4 * Copyright 1995 Martin von Loewis
5 * Copyright 1999 Francis Beaudet
14 #include "wine/obj_clientserver.h"
17 /******************************************************************************
18 * These are static/global variables and internal data structures that the
19 * OLE module uses to maintain it's state.
21 typedef struct tagDropTargetNode
24 IDropTarget* dropTarget;
25 struct tagDropTargetNode* prevDropTarget;
26 struct tagDropTargetNode* nextDropTarget;
29 typedef struct tagTrackerWindowInfo
31 IDataObject* dataObject;
32 IDropSource* dropSource;
39 HWND curDragTargetHWND;
40 IDropTarget* curDragTarget;
44 * This is the lock count on the OLE library. It is controlled by the
45 * OLEInitialize/OLEUninitialize methods.
47 static ULONG OLE_moduleLockCount = 0;
50 * Name of our registered window class.
52 static const char OLEDD_DRAGTRACKERCLASS[] = "WineDragDropTracker32";
55 * This is the head of the Drop target container.
57 static DropTargetNode* targetListHead = NULL;
59 /******************************************************************************
60 * These are the prototypes of the utility methods used for OLE Drag n Drop
62 static void OLEDD_Initialize();
63 static void OLEDD_UnInitialize();
64 static void OLEDD_InsertDropTarget(
65 DropTargetNode* nodeToAdd);
66 static DropTargetNode* OLEDD_ExtractDropTarget(
68 static DropTargetNode* OLEDD_FindDropTarget(
70 static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
75 static void OLEDD_TrackMouseMove(
76 TrackerWindowInfo* trackerInfo,
79 static void OLEDD_TrackStateChange(
80 TrackerWindowInfo* trackerInfo,
83 static DWORD OLEDD_GetButtonState();
86 /******************************************************************************
87 * OleBuildVersion [OLE2.1]
89 DWORD WINAPI OleBuildVersion(void)
91 TRACE(ole,"(void)\n");
95 /***********************************************************************
96 * OleInitialize (OLE2.2) (OLE32.108)
98 HRESULT WINAPI OleInitialize(LPVOID reserved)
102 TRACE(ole, "(%p)\n", reserved);
105 * The first duty of the OleInitialize is to initialize the COM libraries.
107 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
110 * If the CoInitializeEx call failed, the OLE libraries can't be
117 * Then, it has to initialize the OLE specific modules.
121 * Object linking and Embedding
122 * In-place activation
124 if (OLE_moduleLockCount==0)
127 * Initialize the libraries.
129 TRACE(ole, "() - Initializing the OLE libraries\n");
138 * Then, we increase the lock count on the OLE module.
140 OLE_moduleLockCount++;
145 /******************************************************************************
146 * CoGetCurrentProcess [COMPOBJ.34] [OLE2.2][OLE32.108]
149 * Is DWORD really the correct return type for this function?
151 DWORD WINAPI CoGetCurrentProcess(void) {
152 return (DWORD)PROCESS_Current();
155 /******************************************************************************
156 * OleUninitialize [OLE2.3] [OLE32.131]
158 void WINAPI OleUninitialize(void)
163 * Decrease the lock count on the OLE module.
165 OLE_moduleLockCount--;
168 * If we hit the bottom of the lock stack, free the libraries.
170 if (OLE_moduleLockCount==0)
173 * Actually free the libraries.
175 TRACE(ole, "() - Freeing the last reference count\n");
180 OLEDD_UnInitialize();
184 * Then, uninitialize the COM libraries.
189 /***********************************************************************
190 * OleFlushClipboard [OLE2.76]
192 HRESULT WINAPI OleFlushClipboard16(void)
197 /***********************************************************************
198 * OleSetClipboard [OLE32.127]
200 HRESULT WINAPI OleSetClipboard(LPVOID pDataObj)
202 FIXME(ole,"(%p), stub!\n", pDataObj);
206 /******************************************************************************
207 * CoRegisterMessageFilter32 [OLE32.38]
209 HRESULT WINAPI CoRegisterMessageFilter(
210 LPMESSAGEFILTER lpMessageFilter, /* Pointer to interface */
211 LPMESSAGEFILTER *lplpMessageFilter /* Indirect pointer to prior instance if non-NULL */
214 if (lplpMessageFilter) {
215 *lplpMessageFilter = NULL;
220 /******************************************************************************
221 * OleInitializeWOW [OLE32.109]
223 HRESULT WINAPI OleInitializeWOW(DWORD x) {
224 FIXME(ole,"(0x%08lx),stub!\n",x);
228 /***********************************************************************
229 * RegisterDragDrop16 (OLE2.35)
231 HRESULT WINAPI RegisterDragDrop16(
233 LPDROPTARGET pDropTarget
235 FIXME(ole,"(0x%04x,%p),stub!\n",hwnd,pDropTarget);
239 /***********************************************************************
240 * RegisterDragDrop32 (OLE32.139)
242 HRESULT WINAPI RegisterDragDrop(
244 LPDROPTARGET pDropTarget)
246 DropTargetNode* dropTargetInfo;
248 TRACE(ole,"(0x%x,%p)\n", hwnd, pDropTarget);
251 * First, check if the window is already registered.
253 dropTargetInfo = OLEDD_FindDropTarget(hwnd);
255 if (dropTargetInfo!=NULL)
256 return DRAGDROP_E_ALREADYREGISTERED;
259 * If it's not there, we can add it. We first create a node for it.
261 dropTargetInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(DropTargetNode));
263 if (dropTargetInfo==NULL)
264 return E_OUTOFMEMORY;
266 dropTargetInfo->hwndTarget = hwnd;
267 dropTargetInfo->prevDropTarget = NULL;
268 dropTargetInfo->nextDropTarget = NULL;
271 * Don't forget that this is an interface pointer, need to nail it down since
272 * we keep a copy of it.
274 dropTargetInfo->dropTarget = pDropTarget;
275 IDropTarget_AddRef(dropTargetInfo->dropTarget);
277 OLEDD_InsertDropTarget(dropTargetInfo);
282 /***********************************************************************
283 * RevokeDragDrop16 (OLE2.36)
285 HRESULT WINAPI RevokeDragDrop16(
288 FIXME(ole,"(0x%04x),stub!\n",hwnd);
292 /***********************************************************************
293 * RevokeDragDrop32 (OLE32.141)
295 HRESULT WINAPI RevokeDragDrop(
298 DropTargetNode* dropTargetInfo;
300 TRACE(ole,"(0x%x)\n", hwnd);
303 * First, check if the window is already registered.
305 dropTargetInfo = OLEDD_ExtractDropTarget(hwnd);
308 * If it ain't in there, it's an error.
310 if (dropTargetInfo==NULL)
311 return DRAGDROP_E_NOTREGISTERED;
314 * If it's in there, clean-up it's used memory and
317 IDropTarget_Release(dropTargetInfo->dropTarget);
318 HeapFree(GetProcessHeap(), 0, dropTargetInfo);
323 /***********************************************************************
324 * OleRegGetUserType (OLE32.122)
326 HRESULT WINAPI OleRegGetUserType(
329 LPOLESTR* pszUserType)
331 FIXME(ole,",stub!\n");
335 /***********************************************************************
336 * DoDragDrop32 [OLE32.65]
338 HRESULT WINAPI DoDragDrop (
339 IDataObject *pDataObject, /* ptr to the data obj */
340 IDropSource* pDropSource, /* ptr to the source obj */
341 DWORD dwOKEffect, /* effects allowed by the source */
342 DWORD *pdwEffect) /* ptr to effects of the source */
344 TrackerWindowInfo trackerInfo;
345 HWND hwndTrackWindow;
348 TRACE(ole,"(DataObject %p, DropSource %p)\n", pDataObject, pDropSource);
351 * Setup the drag n drop tracking window.
353 trackerInfo.dataObject = pDataObject;
354 trackerInfo.dropSource = pDropSource;
355 trackerInfo.dwOKEffect = dwOKEffect;
356 trackerInfo.pdwEffect = pdwEffect;
357 trackerInfo.trackingDone = FALSE;
358 trackerInfo.escPressed = FALSE;
359 trackerInfo.curDragTargetHWND = 0;
360 trackerInfo.curDragTarget = 0;
362 hwndTrackWindow = CreateWindowA(OLEDD_DRAGTRACKERCLASS,
365 CW_USEDEFAULT, CW_USEDEFAULT,
366 CW_USEDEFAULT, CW_USEDEFAULT,
370 (LPVOID)&trackerInfo);
372 if (hwndTrackWindow!=0)
375 * Capture the mouse input
377 SetCapture(hwndTrackWindow);
380 * Pump messages. All mouse input should go the the capture window.
382 while (!trackerInfo.trackingDone && GetMessageA(&msg, 0, 0, 0) )
384 if ( (msg.message >= WM_KEYFIRST) &&
385 (msg.message <= WM_KEYFIRST) )
388 * When keyboard messages are sent to windows on this thread, we
389 * want to ignore notify the drop source that the state changed.
390 * in the case of the Escape key, we also notify the drop source
391 * we give it a special meaning.
393 if ( (msg.message==WM_KEYDOWN) &&
394 (msg.wParam==VK_ESCAPE) )
396 trackerInfo.escPressed = TRUE;
400 * Notify the drop source.
402 OLEDD_TrackStateChange(&trackerInfo,
404 OLEDD_GetButtonState());
409 * Dispatch the messages only when it's not a keyboard message.
411 DispatchMessageA(&msg);
416 * Destroy the temporary window.
418 DestroyWindow(hwndTrackWindow);
420 return trackerInfo.returnValue;
426 /***********************************************************************
427 * OleQueryLinkFromData32 [OLE32.118]
429 HRESULT WINAPI OleQueryLinkFromData32(
430 IDataObject* pSrcDataObject)
432 FIXME(ole,"(%p),stub!\n", pSrcDataObject);
436 /***********************************************************************
437 * OleRegGetMiscStatus32 [OLE32.121]
439 HRESULT WINAPI OleRegGetMiscStatus32(
444 FIXME(ole,"(),stub!\n");
445 return REGDB_E_CLASSNOTREG;
448 /***********************************************************************
449 * OleGetClipboard32 [OLE32.105]
451 HRESULT WINAPI OleGetClipboard32(
452 IDataObject** ppDataObj)
454 FIXME(ole,"(%p),stub!\n", ppDataObj);
462 /***********************************************************************
463 * OleCreateMenuDescriptor [OLE32.97]
465 HOLEMENU WINAPI OleCreateMenuDescriptor(
467 LPOLEMENUGROUPWIDTHS lpMenuWidths)
469 FIXME(ole,"(%x,%p),stub!\n", hmenuCombined, lpMenuWidths);
474 /***********************************************************************
475 * OleDestroyMenuDescriptor [OLE32.99]
477 void WINAPI OleDestroyMenuDescriptor(
478 HOLEMENU hmenuDescriptor)
480 FIXME(ole,"(%x),stub!\n", (unsigned int)hmenuDescriptor);
483 /***********************************************************************
484 * OleSetMenuDescriptor [OLE32.129]
486 HRESULT WINAPI OleSetMenuDescriptor(
487 HOLEMENU hmenuDescriptor,
489 HWND hwndActiveObject,
490 LPOLEINPLACEFRAME lpFrame,
491 LPOLEINPLACEACTIVEOBJECT lpActiveObject)
493 FIXME(ole,"(%x, %x, %x, %p, %p),stub!\n",
494 (unsigned int)hmenuDescriptor,
503 /***********************************************************************
504 * ReleaseStgMedium [OLE32.140]
506 void WINAPI ReleaseStgMedium(
509 switch (pmedium->tymed)
513 if ( (pmedium->pUnkForRelease==0) &&
514 (pmedium->u.hGlobal!=0) )
515 GlobalFree(pmedium->u.hGlobal);
517 pmedium->u.hGlobal = 0;
522 if (pmedium->u.lpszFileName!=0)
524 if (pmedium->pUnkForRelease==0)
526 DeleteFileW(pmedium->u.lpszFileName);
529 CoTaskMemFree(pmedium->u.lpszFileName);
532 pmedium->u.lpszFileName = 0;
537 if (pmedium->u.pstm!=0)
539 IStream_Release(pmedium->u.pstm);
547 if (pmedium->u.pstg!=0)
549 IStorage_Release(pmedium->u.pstg);
557 if ( (pmedium->pUnkForRelease==0) &&
558 (pmedium->u.hGlobal!=0) )
559 DeleteObject(pmedium->u.hGlobal);
561 pmedium->u.hGlobal = 0;
566 if ( (pmedium->pUnkForRelease==0) &&
567 (pmedium->u.hMetaFilePict!=0) )
569 DeleteMetaFile(pmedium->u.hMetaFilePict);
570 GlobalFree(pmedium->u.hMetaFilePict);
573 pmedium->u.hMetaFilePict = 0;
578 if ( (pmedium->pUnkForRelease==0) &&
579 (pmedium->u.hEnhMetaFile!=0) )
581 DeleteEnhMetaFile(pmedium->u.hEnhMetaFile);
584 pmedium->u.hEnhMetaFile = 0;
593 * After cleaning up, the unknown is released
595 if (pmedium->pUnkForRelease!=0)
597 IUnknown_Release(pmedium->pUnkForRelease);
598 pmedium->pUnkForRelease = 0;
605 * Initializes the OLE drag and drop data structures.
607 static void OLEDD_Initialize()
611 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
612 wndClass.style = CS_GLOBALCLASS;
613 wndClass.lpfnWndProc = (WNDPROC)OLEDD_DragTrackerWindowProc;
614 wndClass.cbClsExtra = 0;
615 wndClass.cbWndExtra = sizeof(TrackerWindowInfo*);
616 wndClass.hCursor = 0;
617 wndClass.hbrBackground = 0;
618 wndClass.lpszClassName = OLEDD_DRAGTRACKERCLASS;
620 RegisterClassA (&wndClass);
624 * OLEDD_UnInitialize()
626 * Releases the OLE drag and drop data structures.
628 static void OLEDD_UnInitialize()
631 * Simply empty the list.
633 while (targetListHead!=NULL)
635 RevokeDragDrop(targetListHead->hwndTarget);
640 * OLEDD_InsertDropTarget()
642 * Insert the target node in the tree.
644 static void OLEDD_InsertDropTarget(DropTargetNode* nodeToAdd)
646 DropTargetNode* curNode;
647 DropTargetNode** parentNodeLink;
650 * Iterate the tree to find the insertion point.
652 curNode = targetListHead;
653 parentNodeLink = &targetListHead;
655 while (curNode!=NULL)
657 if (nodeToAdd->hwndTarget<curNode->hwndTarget)
660 * If the node we want to add has a smaller HWND, go left
662 parentNodeLink = &curNode->prevDropTarget;
663 curNode = curNode->prevDropTarget;
665 else if (nodeToAdd->hwndTarget>curNode->hwndTarget)
668 * If the node we want to add has a larger HWND, go right
670 parentNodeLink = &curNode->nextDropTarget;
671 curNode = curNode->nextDropTarget;
676 * The item was found in the list. It shouldn't have been there
684 * If we get here, we have found a spot for our item. The parentNodeLink
685 * pointer points to the pointer that we have to modify.
686 * The curNode should be NULL. We just have to establish the link and Voila!
688 assert(curNode==NULL);
689 assert(parentNodeLink!=NULL);
690 assert(*parentNodeLink==NULL);
692 *parentNodeLink=nodeToAdd;
696 * OLEDD_ExtractDropTarget()
698 * Removes the target node from the tree.
700 static DropTargetNode* OLEDD_ExtractDropTarget(HWND hwndOfTarget)
702 DropTargetNode* curNode;
703 DropTargetNode** parentNodeLink;
706 * Iterate the tree to find the insertion point.
708 curNode = targetListHead;
709 parentNodeLink = &targetListHead;
711 while (curNode!=NULL)
713 if (hwndOfTarget<curNode->hwndTarget)
716 * If the node we want to add has a smaller HWND, go left
718 parentNodeLink = &curNode->prevDropTarget;
719 curNode = curNode->prevDropTarget;
721 else if (hwndOfTarget>curNode->hwndTarget)
724 * If the node we want to add has a larger HWND, go right
726 parentNodeLink = &curNode->nextDropTarget;
727 curNode = curNode->nextDropTarget;
732 * The item was found in the list. Detach it from it's parent and
733 * re-insert it's kids in the tree.
735 assert(parentNodeLink!=NULL);
736 assert(*parentNodeLink==curNode);
739 * We arbitrately re-attach the left sub-tree to the parent.
741 *parentNodeLink = curNode->prevDropTarget;
744 * And we re-insert the right subtree
746 if (curNode->nextDropTarget!=NULL)
748 OLEDD_InsertDropTarget(curNode->nextDropTarget);
752 * The node we found is still a valid node once we complete
753 * the unlinking of the kids.
755 curNode->nextDropTarget=NULL;
756 curNode->prevDropTarget=NULL;
763 * If we get here, the node is not in the tree
769 * OLEDD_FindDropTarget()
771 * Finds information about the drop target.
773 static DropTargetNode* OLEDD_FindDropTarget(HWND hwndOfTarget)
775 DropTargetNode* curNode;
778 * Iterate the tree to find the HWND value.
780 curNode = targetListHead;
782 while (curNode!=NULL)
784 if (hwndOfTarget<curNode->hwndTarget)
787 * If the node we want to add has a smaller HWND, go left
789 curNode = curNode->prevDropTarget;
791 else if (hwndOfTarget>curNode->hwndTarget)
794 * If the node we want to add has a larger HWND, go right
796 curNode = curNode->nextDropTarget;
801 * The item was found in the list.
808 * If we get here, the item is not in the list
814 * OLEDD_DragTrackerWindowProc()
816 * This method is the WindowProcedure of the drag n drop tracking
817 * window. During a drag n Drop operation, an invisible window is created
818 * to receive the user input and act upon it. This procedure is in charge
821 static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
831 LPCREATESTRUCTA createStruct = (LPCREATESTRUCTA)lParam;
833 SetWindowLongA(hwnd, 0, (LONG)createStruct->lpCreateParams);
840 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
844 * Get the current mouse position in screen coordinates.
846 mousePos.x = LOWORD(lParam);
847 mousePos.y = HIWORD(lParam);
848 ClientToScreen(hwnd, &mousePos);
851 * Track the movement of the mouse.
853 OLEDD_TrackMouseMove(trackerInfo, mousePos, wParam);
864 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
868 * Get the current mouse position in screen coordinates.
870 mousePos.x = LOWORD(lParam);
871 mousePos.y = HIWORD(lParam);
872 ClientToScreen(hwnd, &mousePos);
875 * Notify everyone that the button state changed
876 * TODO: Check if the "escape" key was pressed.
878 OLEDD_TrackStateChange(trackerInfo, mousePos, wParam);
885 * This is a window proc after all. Let's call the default.
887 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
891 * OLEDD_TrackMouseMove()
893 * This method is invoked while a drag and drop operation is in effect.
894 * it will generate the appropriate callbacks in the drop source
895 * and drop target. It will also provide the expected feedback to
899 * trackerInfo - Pointer to the structure identifying the
900 * drag & drop operation that is currently
902 * mousePos - Current position of the mouse in screen
904 * keyState - Contains the state of the shift keys and the
905 * mouse buttons (MK_LBUTTON and the like)
907 static void OLEDD_TrackMouseMove(
908 TrackerWindowInfo* trackerInfo,
912 HWND hwndNewTarget = 0;
916 * Get the handle of the window under the mouse
918 hwndNewTarget = WindowFromPoint(mousePos);
921 * If we are hovering over the same target as before, send the
922 * DragOver notification
924 if ( (trackerInfo->curDragTarget != 0) &&
925 (trackerInfo->curDragTargetHWND==hwndNewTarget) )
927 POINTL mousePosParam;
930 * The documentation tells me that the coordinate should be in the target
931 * window's coordinate space. However, the tests I made tell me the
932 * coordinates should be in screen coordinates.
934 mousePosParam.x = mousePos.x;
935 mousePosParam.y = mousePos.y;
937 IDropTarget_DragOver(trackerInfo->curDragTarget,
940 trackerInfo->pdwEffect);
944 DropTargetNode* newDropTargetNode = 0;
947 * If we changed window, we have to notify our old target and check for
950 if (trackerInfo->curDragTarget!=0)
952 IDropTarget_DragLeave(trackerInfo->curDragTarget);
956 * Make sure we're hovering over a window.
958 if (hwndNewTarget!=0)
961 * Find-out if there is a drag target under the mouse
963 newDropTargetNode = OLEDD_FindDropTarget(hwndNewTarget);
965 trackerInfo->curDragTargetHWND = hwndNewTarget;
966 trackerInfo->curDragTarget = newDropTargetNode ? newDropTargetNode->dropTarget : 0;
969 * If there is, notify it that we just dragged-in
971 if (trackerInfo->curDragTarget!=0)
973 POINTL mousePosParam;
976 * The documentation tells me that the coordinate should be in the target
977 * window's coordinate space. However, the tests I made tell me the
978 * coordinates should be in screen coordinates.
980 mousePosParam.x = mousePos.x;
981 mousePosParam.y = mousePos.y;
983 IDropTarget_DragEnter(trackerInfo->curDragTarget,
984 trackerInfo->dataObject,
987 trackerInfo->pdwEffect);
993 * The mouse is not over a window so we don't track anything.
995 trackerInfo->curDragTargetHWND = 0;
996 trackerInfo->curDragTarget = 0;
1001 * Now that we have done that, we have to tell the source to give
1002 * us feedback on the work being done by the target. If we don't
1003 * have a target, simulate no effect.
1005 if (trackerInfo->curDragTarget==0)
1007 *trackerInfo->pdwEffect = DROPEFFECT_NONE;
1010 hr = IDropSource_GiveFeedback(trackerInfo->dropSource,
1011 *trackerInfo->pdwEffect);
1014 * When we ask for feedback from the drop source, sometimes it will
1015 * do all the necessary work and sometimes it will not handle it
1016 * when that's the case, we must display the standard drag and drop
1019 if (hr==DRAGDROP_S_USEDEFAULTCURSORS)
1021 if ( (*trackerInfo->pdwEffect & DROPEFFECT_MOVE) ||
1022 (*trackerInfo->pdwEffect & DROPEFFECT_COPY) ||
1023 (*trackerInfo->pdwEffect & DROPEFFECT_LINK) )
1025 SetCursor(LoadCursorA(0, IDC_SIZEALLA));
1029 SetCursor(LoadCursorA(0, IDC_NOA));
1035 * OLEDD_TrackStateChange()
1037 * This method is invoked while a drag and drop operation is in effect.
1038 * It is used to notify the drop target/drop source callbacks when
1039 * the state of the keyboard or mouse button change.
1042 * trackerInfo - Pointer to the structure identifying the
1043 * drag & drop operation that is currently
1045 * mousePos - Current position of the mouse in screen
1047 * keyState - Contains the state of the shift keys and the
1048 * mouse buttons (MK_LBUTTON and the like)
1050 static void OLEDD_TrackStateChange(
1051 TrackerWindowInfo* trackerInfo,
1056 * Ask the drop source what to do with the operation.
1058 trackerInfo->returnValue = IDropSource_QueryContinueDrag(
1059 trackerInfo->dropSource,
1060 trackerInfo->escPressed,
1064 * All the return valued will stop the operation except the S_OK
1067 if (trackerInfo->returnValue!=S_OK)
1070 * Make sure the message loop in DoDragDrop stops
1072 trackerInfo->trackingDone = TRUE;
1075 * Release the mouse in case the drop target decides to show a popup
1076 * or a menu or something.
1081 * If we end-up over a target, drop the object in the target or
1082 * inform the target that the operation was cancelled.
1084 if (trackerInfo->curDragTarget!=0)
1086 switch (trackerInfo->returnValue)
1089 * If the source wants us to complete the operation, we tell
1090 * the drop target that we just dropped the object in it.
1092 case DRAGDROP_S_DROP:
1094 POINTL mousePosParam;
1097 * The documentation tells me that the coordinate should be
1098 * in the target window's coordinate space. However, the tests
1099 * I made tell me the coordinates should be in screen coordinates.
1101 mousePosParam.x = mousePos.x;
1102 mousePosParam.y = mousePos.y;
1104 IDropTarget_Drop(trackerInfo->curDragTarget,
1105 trackerInfo->dataObject,
1108 trackerInfo->pdwEffect);
1112 * If the source told us that we should cancel, fool the drop
1113 * target by telling it that the mouse left it's window.
1115 case DRAGDROP_S_CANCEL:
1116 IDropTarget_DragLeave(trackerInfo->curDragTarget);
1124 * OLEDD_GetButtonState()
1126 * This method will use the current state of the keyboard to build
1127 * a button state mask equivalent to the one passed in the
1128 * WM_MOUSEMOVE wParam.
1130 static DWORD OLEDD_GetButtonState()
1132 BYTE keyboardState[256];
1135 GetKeyboardState(keyboardState);
1137 if ( (keyboardState[VK_SHIFT] & 0x80) !=0)
1138 keyMask |= MK_SHIFT;
1140 if ( (keyboardState[VK_CONTROL] & 0x80) !=0)
1141 keyMask |= MK_CONTROL;
1143 if ( (keyboardState[VK_LBUTTON] & 0x80) !=0)
1144 keyMask |= MK_LBUTTON;
1146 if ( (keyboardState[VK_RBUTTON] & 0x80) !=0)
1147 keyMask |= MK_RBUTTON;
1149 if ( (keyboardState[VK_MBUTTON] & 0x80) !=0)
1150 keyMask |= MK_MBUTTON;