Make cdrom.c compile on FreeBSD (FreeBSD does not seem to have *SEEK,
[wine/dcerpc.git] / ole / ole2.c
blob9f05278df06b659da39705af01ea7794761bdc58
1 /*
2 * OLE2 library
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1999 Francis Beaudet
6 */
8 #include <assert.h>
10 #include "winuser.h"
11 #include "winerror.h"
12 #include "ole2.h"
13 #include "process.h"
14 #include "wine/obj_clientserver.h"
15 #include "debug.h"
16 #include "ole2ver.h"
18 /******************************************************************************
19 * These are static/global variables and internal data structures that the
20 * OLE module uses to maintain it's state.
22 typedef struct tagDropTargetNode
24 HWND hwndTarget;
25 IDropTarget* dropTarget;
26 struct tagDropTargetNode* prevDropTarget;
27 struct tagDropTargetNode* nextDropTarget;
28 } DropTargetNode;
30 typedef struct tagTrackerWindowInfo
32 IDataObject* dataObject;
33 IDropSource* dropSource;
34 DWORD dwOKEffect;
35 DWORD* pdwEffect;
36 BOOL trackingDone;
37 HRESULT returnValue;
39 BOOL escPressed;
40 HWND curDragTargetHWND;
41 IDropTarget* curDragTarget;
42 } TrackerWindowInfo;
45 * This is the lock count on the OLE library. It is controlled by the
46 * OLEInitialize/OLEUninitialize methods.
48 static ULONG OLE_moduleLockCount = 0;
51 * Name of our registered window class.
53 static const char OLEDD_DRAGTRACKERCLASS[] = "WineDragDropTracker32";
56 * This is the head of the Drop target container.
58 static DropTargetNode* targetListHead = NULL;
60 /******************************************************************************
61 * These are the prototypes of the utility methods used for OLE Drag n Drop
63 static void OLEDD_Initialize();
64 static void OLEDD_UnInitialize();
65 static void OLEDD_InsertDropTarget(
66 DropTargetNode* nodeToAdd);
67 static DropTargetNode* OLEDD_ExtractDropTarget(
68 HWND hwndOfTarget);
69 static DropTargetNode* OLEDD_FindDropTarget(
70 HWND hwndOfTarget);
71 static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
72 HWND hwnd,
73 UINT uMsg,
74 WPARAM wParam,
75 LPARAM lParam);
76 static void OLEDD_TrackMouseMove(
77 TrackerWindowInfo* trackerInfo,
78 POINT mousePos,
79 DWORD keyState);
80 static void OLEDD_TrackStateChange(
81 TrackerWindowInfo* trackerInfo,
82 POINT mousePos,
83 DWORD keyState);
84 static DWORD OLEDD_GetButtonState();
87 /******************************************************************************
88 * OleBuildVersion [OLE2.1]
90 DWORD WINAPI OleBuildVersion(void)
92 TRACE(ole,"(void)\n");
93 return (rmm<<16)+rup;
96 /***********************************************************************
97 * OleInitialize (OLE2.2) (OLE32.108)
99 HRESULT WINAPI OleInitialize(LPVOID reserved)
101 HRESULT hr;
103 TRACE(ole, "(%p)\n", reserved);
106 * The first duty of the OleInitialize is to initialize the COM libraries.
108 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
111 * If the CoInitializeEx call failed, the OLE libraries can't be
112 * initialized.
114 if (FAILED(hr))
115 return hr;
118 * Then, it has to initialize the OLE specific modules.
119 * This includes:
120 * Clipboard
121 * Drag and Drop
122 * Object linking and Embedding
123 * In-place activation
125 if (OLE_moduleLockCount==0)
128 * Initialize the libraries.
130 TRACE(ole, "() - Initializing the OLE libraries\n");
133 * Drag and Drop
135 OLEDD_Initialize();
139 * Then, we increase the lock count on the OLE module.
141 OLE_moduleLockCount++;
143 return hr;
146 /******************************************************************************
147 * CoGetCurrentProcess [COMPOBJ.34] [OLE2.2][OLE32.108]
149 * NOTES
150 * Is DWORD really the correct return type for this function?
152 DWORD WINAPI CoGetCurrentProcess(void) {
153 return (DWORD)PROCESS_Current();
156 /******************************************************************************
157 * OleUninitialize [OLE2.3] [OLE32.131]
159 void WINAPI OleUninitialize(void)
161 TRACE(ole, "()\n");
164 * Decrease the lock count on the OLE module.
166 OLE_moduleLockCount--;
169 * If we hit the bottom of the lock stack, free the libraries.
171 if (OLE_moduleLockCount==0)
174 * Actually free the libraries.
176 TRACE(ole, "() - Freeing the last reference count\n");
179 * Drag and Drop
181 OLEDD_UnInitialize();
185 * Then, uninitialize the COM libraries.
187 CoUninitialize();
190 /***********************************************************************
191 * OleFlushClipboard [OLE2.76]
193 HRESULT WINAPI OleFlushClipboard16(void)
195 return S_OK;
198 /***********************************************************************
199 * OleSetClipboard [OLE32.127]
201 HRESULT WINAPI OleSetClipboard(LPVOID pDataObj)
203 FIXME(ole,"(%p), stub!\n", pDataObj);
204 return S_OK;
207 /******************************************************************************
208 * CoRegisterMessageFilter32 [OLE32.38]
210 HRESULT WINAPI CoRegisterMessageFilter(
211 LPMESSAGEFILTER lpMessageFilter, /* Pointer to interface */
212 LPMESSAGEFILTER *lplpMessageFilter /* Indirect pointer to prior instance if non-NULL */
214 FIXME(ole,"stub\n");
215 if (lplpMessageFilter) {
216 *lplpMessageFilter = NULL;
218 return S_OK;
221 /******************************************************************************
222 * OleInitializeWOW [OLE32.109]
224 HRESULT WINAPI OleInitializeWOW(DWORD x) {
225 FIXME(ole,"(0x%08lx),stub!\n",x);
226 return 0;
229 /***********************************************************************
230 * RegisterDragDrop16 (OLE2.35)
232 HRESULT WINAPI RegisterDragDrop16(
233 HWND16 hwnd,
234 LPDROPTARGET pDropTarget
236 FIXME(ole,"(0x%04x,%p),stub!\n",hwnd,pDropTarget);
237 return S_OK;
240 /***********************************************************************
241 * RegisterDragDrop32 (OLE32.139)
243 HRESULT WINAPI RegisterDragDrop(
244 HWND hwnd,
245 LPDROPTARGET pDropTarget)
247 DropTargetNode* dropTargetInfo;
249 TRACE(ole,"(0x%x,%p)\n", hwnd, pDropTarget);
252 * First, check if the window is already registered.
254 dropTargetInfo = OLEDD_FindDropTarget(hwnd);
256 if (dropTargetInfo!=NULL)
257 return DRAGDROP_E_ALREADYREGISTERED;
260 * If it's not there, we can add it. We first create a node for it.
262 dropTargetInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(DropTargetNode));
264 if (dropTargetInfo==NULL)
265 return E_OUTOFMEMORY;
267 dropTargetInfo->hwndTarget = hwnd;
268 dropTargetInfo->prevDropTarget = NULL;
269 dropTargetInfo->nextDropTarget = NULL;
272 * Don't forget that this is an interface pointer, need to nail it down since
273 * we keep a copy of it.
275 dropTargetInfo->dropTarget = pDropTarget;
276 IDropTarget_AddRef(dropTargetInfo->dropTarget);
278 OLEDD_InsertDropTarget(dropTargetInfo);
280 return S_OK;
283 /***********************************************************************
284 * RevokeDragDrop16 (OLE2.36)
286 HRESULT WINAPI RevokeDragDrop16(
287 HWND16 hwnd
289 FIXME(ole,"(0x%04x),stub!\n",hwnd);
290 return S_OK;
293 /***********************************************************************
294 * RevokeDragDrop32 (OLE32.141)
296 HRESULT WINAPI RevokeDragDrop(
297 HWND hwnd)
299 DropTargetNode* dropTargetInfo;
301 TRACE(ole,"(0x%x)\n", hwnd);
304 * First, check if the window is already registered.
306 dropTargetInfo = OLEDD_ExtractDropTarget(hwnd);
309 * If it ain't in there, it's an error.
311 if (dropTargetInfo==NULL)
312 return DRAGDROP_E_NOTREGISTERED;
315 * If it's in there, clean-up it's used memory and
316 * references
318 IDropTarget_Release(dropTargetInfo->dropTarget);
319 HeapFree(GetProcessHeap(), 0, dropTargetInfo);
321 return S_OK;
324 /***********************************************************************
325 * OleRegGetUserType (OLE32.122)
327 HRESULT WINAPI OleRegGetUserType(
328 REFCLSID clsid,
329 DWORD dwFormOfType,
330 LPOLESTR* pszUserType)
332 FIXME(ole,",stub!\n");
333 return S_OK;
336 /***********************************************************************
337 * DoDragDrop32 [OLE32.65]
339 HRESULT WINAPI DoDragDrop (
340 IDataObject *pDataObject, /* ptr to the data obj */
341 IDropSource* pDropSource, /* ptr to the source obj */
342 DWORD dwOKEffect, /* effects allowed by the source */
343 DWORD *pdwEffect) /* ptr to effects of the source */
345 TrackerWindowInfo trackerInfo;
346 HWND hwndTrackWindow;
347 MSG msg;
349 TRACE(ole,"(DataObject %p, DropSource %p)\n", pDataObject, pDropSource);
352 * Setup the drag n drop tracking window.
354 trackerInfo.dataObject = pDataObject;
355 trackerInfo.dropSource = pDropSource;
356 trackerInfo.dwOKEffect = dwOKEffect;
357 trackerInfo.pdwEffect = pdwEffect;
358 trackerInfo.trackingDone = FALSE;
359 trackerInfo.escPressed = FALSE;
360 trackerInfo.curDragTargetHWND = 0;
361 trackerInfo.curDragTarget = 0;
363 hwndTrackWindow = CreateWindowA(OLEDD_DRAGTRACKERCLASS,
364 "TrackerWindow",
365 WS_POPUP,
366 CW_USEDEFAULT, CW_USEDEFAULT,
367 CW_USEDEFAULT, CW_USEDEFAULT,
371 (LPVOID)&trackerInfo);
373 if (hwndTrackWindow!=0)
376 * Capture the mouse input
378 SetCapture(hwndTrackWindow);
381 * Pump messages. All mouse input should go the the capture window.
383 while (!trackerInfo.trackingDone && GetMessageA(&msg, 0, 0, 0) )
385 if ( (msg.message >= WM_KEYFIRST) &&
386 (msg.message <= WM_KEYFIRST) )
389 * When keyboard messages are sent to windows on this thread, we
390 * want to ignore notify the drop source that the state changed.
391 * in the case of the Escape key, we also notify the drop source
392 * we give it a special meaning.
394 if ( (msg.message==WM_KEYDOWN) &&
395 (msg.wParam==VK_ESCAPE) )
397 trackerInfo.escPressed = TRUE;
401 * Notify the drop source.
403 OLEDD_TrackStateChange(&trackerInfo,
404 msg.pt,
405 OLEDD_GetButtonState());
407 else
410 * Dispatch the messages only when it's not a keyboard message.
412 DispatchMessageA(&msg);
417 * Destroy the temporary window.
419 DestroyWindow(hwndTrackWindow);
421 return trackerInfo.returnValue;
424 return E_FAIL;
427 /***********************************************************************
428 * OleQueryLinkFromData32 [OLE32.118]
430 HRESULT WINAPI OleQueryLinkFromData32(
431 IDataObject* pSrcDataObject)
433 FIXME(ole,"(%p),stub!\n", pSrcDataObject);
434 return S_OK;
437 /***********************************************************************
438 * OleRegGetMiscStatus32 [OLE32.121]
440 HRESULT WINAPI OleRegGetMiscStatus32(
441 REFCLSID clsid,
442 DWORD dwAspect,
443 DWORD* pdwStatus)
445 FIXME(ole,"(),stub!\n");
446 return REGDB_E_CLASSNOTREG;
449 /***********************************************************************
450 * OleGetClipboard32 [OLE32.105]
452 HRESULT WINAPI OleGetClipboard32(
453 IDataObject** ppDataObj)
455 FIXME(ole,"(%p),stub!\n", ppDataObj);
457 if (ppDataObj)
458 *ppDataObj=0;
460 return E_FAIL;
463 /***********************************************************************
464 * OleCreateMenuDescriptor [OLE32.97]
466 HOLEMENU WINAPI OleCreateMenuDescriptor(
467 HMENU hmenuCombined,
468 LPOLEMENUGROUPWIDTHS lpMenuWidths)
470 FIXME(ole,"(%x,%p),stub!\n", hmenuCombined, lpMenuWidths);
472 return NULL;
475 /***********************************************************************
476 * OleDestroyMenuDescriptor [OLE32.99]
478 HRESULT WINAPI OleDestroyMenuDescriptor(
479 HOLEMENU hmenuDescriptor)
481 FIXME(ole,"(%x),stub!\n", (unsigned int)hmenuDescriptor);
482 return S_OK;
485 /***********************************************************************
486 * OleSetMenuDescriptor [OLE32.129]
488 HRESULT WINAPI OleSetMenuDescriptor(
489 HOLEMENU hmenuDescriptor,
490 HWND hwndFrame,
491 HWND hwndActiveObject,
492 LPOLEINPLACEFRAME lpFrame,
493 LPOLEINPLACEACTIVEOBJECT lpActiveObject)
495 FIXME(ole,"(%x, %x, %x, %p, %p),stub!\n",
496 (unsigned int)hmenuDescriptor,
497 hwndFrame,
498 hwndActiveObject,
499 lpFrame,
500 lpActiveObject);
502 return E_FAIL;
505 /***********************************************************************
506 * ReleaseStgMedium [OLE32.140]
508 void WINAPI ReleaseStgMedium(
509 STGMEDIUM* pmedium)
511 switch (pmedium->tymed)
513 case TYMED_HGLOBAL:
515 if ( (pmedium->pUnkForRelease==0) &&
516 (pmedium->u.hGlobal!=0) )
517 GlobalFree(pmedium->u.hGlobal);
519 pmedium->u.hGlobal = 0;
520 break;
522 case TYMED_FILE:
524 if (pmedium->u.lpszFileName!=0)
526 if (pmedium->pUnkForRelease==0)
528 DeleteFileW(pmedium->u.lpszFileName);
531 CoTaskMemFree(pmedium->u.lpszFileName);
534 pmedium->u.lpszFileName = 0;
535 break;
537 case TYMED_ISTREAM:
539 if (pmedium->u.pstm!=0)
541 IStream_Release(pmedium->u.pstm);
544 pmedium->u.pstm = 0;
545 break;
547 case TYMED_ISTORAGE:
549 if (pmedium->u.pstg!=0)
551 IStorage_Release(pmedium->u.pstg);
554 pmedium->u.pstg = 0;
555 break;
557 case TYMED_GDI:
559 if ( (pmedium->pUnkForRelease==0) &&
560 (pmedium->u.hGlobal!=0) )
561 DeleteObject(pmedium->u.hGlobal);
563 pmedium->u.hGlobal = 0;
564 break;
566 case TYMED_MFPICT:
568 if ( (pmedium->pUnkForRelease==0) &&
569 (pmedium->u.hMetaFilePict!=0) )
571 DeleteMetaFile(pmedium->u.hMetaFilePict);
572 GlobalFree(pmedium->u.hMetaFilePict);
575 pmedium->u.hMetaFilePict = 0;
576 break;
578 case TYMED_ENHMF:
580 if ( (pmedium->pUnkForRelease==0) &&
581 (pmedium->u.hEnhMetaFile!=0) )
583 DeleteEnhMetaFile(pmedium->u.hEnhMetaFile);
586 pmedium->u.hEnhMetaFile = 0;
587 break;
589 case TYMED_NULL:
590 default:
591 break;
595 * After cleaning up, the unknown is released
597 if (pmedium->pUnkForRelease!=0)
599 IUnknown_Release(pmedium->pUnkForRelease);
600 pmedium->pUnkForRelease = 0;
604 /***
605 * OLEDD_Initialize()
607 * Initializes the OLE drag and drop data structures.
609 static void OLEDD_Initialize()
611 WNDCLASSA wndClass;
613 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
614 wndClass.style = CS_GLOBALCLASS;
615 wndClass.lpfnWndProc = (WNDPROC)OLEDD_DragTrackerWindowProc;
616 wndClass.cbClsExtra = 0;
617 wndClass.cbWndExtra = sizeof(TrackerWindowInfo*);
618 wndClass.hCursor = 0;
619 wndClass.hbrBackground = 0;
620 wndClass.lpszClassName = OLEDD_DRAGTRACKERCLASS;
622 RegisterClassA (&wndClass);
625 /***
626 * OLEDD_UnInitialize()
628 * Releases the OLE drag and drop data structures.
630 static void OLEDD_UnInitialize()
633 * Simply empty the list.
635 while (targetListHead!=NULL)
637 RevokeDragDrop(targetListHead->hwndTarget);
641 /***
642 * OLEDD_InsertDropTarget()
644 * Insert the target node in the tree.
646 static void OLEDD_InsertDropTarget(DropTargetNode* nodeToAdd)
648 DropTargetNode* curNode;
649 DropTargetNode** parentNodeLink;
652 * Iterate the tree to find the insertion point.
654 curNode = targetListHead;
655 parentNodeLink = &targetListHead;
657 while (curNode!=NULL)
659 if (nodeToAdd->hwndTarget<curNode->hwndTarget)
662 * If the node we want to add has a smaller HWND, go left
664 parentNodeLink = &curNode->prevDropTarget;
665 curNode = curNode->prevDropTarget;
667 else if (nodeToAdd->hwndTarget>curNode->hwndTarget)
670 * If the node we want to add has a larger HWND, go right
672 parentNodeLink = &curNode->nextDropTarget;
673 curNode = curNode->nextDropTarget;
675 else
678 * The item was found in the list. It shouldn't have been there
680 assert(FALSE);
681 return;
686 * If we get here, we have found a spot for our item. The parentNodeLink
687 * pointer points to the pointer that we have to modify.
688 * The curNode should be NULL. We just have to establish the link and Voila!
690 assert(curNode==NULL);
691 assert(parentNodeLink!=NULL);
692 assert(*parentNodeLink==NULL);
694 *parentNodeLink=nodeToAdd;
697 /***
698 * OLEDD_ExtractDropTarget()
700 * Removes the target node from the tree.
702 static DropTargetNode* OLEDD_ExtractDropTarget(HWND hwndOfTarget)
704 DropTargetNode* curNode;
705 DropTargetNode** parentNodeLink;
708 * Iterate the tree to find the insertion point.
710 curNode = targetListHead;
711 parentNodeLink = &targetListHead;
713 while (curNode!=NULL)
715 if (hwndOfTarget<curNode->hwndTarget)
718 * If the node we want to add has a smaller HWND, go left
720 parentNodeLink = &curNode->prevDropTarget;
721 curNode = curNode->prevDropTarget;
723 else if (hwndOfTarget>curNode->hwndTarget)
726 * If the node we want to add has a larger HWND, go right
728 parentNodeLink = &curNode->nextDropTarget;
729 curNode = curNode->nextDropTarget;
731 else
734 * The item was found in the list. Detach it from it's parent and
735 * re-insert it's kids in the tree.
737 assert(parentNodeLink!=NULL);
738 assert(*parentNodeLink==curNode);
741 * We arbitrately re-attach the left sub-tree to the parent.
743 *parentNodeLink = curNode->prevDropTarget;
746 * And we re-insert the right subtree
748 if (curNode->nextDropTarget!=NULL)
750 OLEDD_InsertDropTarget(curNode->nextDropTarget);
754 * The node we found is still a valid node once we complete
755 * the unlinking of the kids.
757 curNode->nextDropTarget=NULL;
758 curNode->prevDropTarget=NULL;
760 return curNode;
765 * If we get here, the node is not in the tree
767 return NULL;
770 /***
771 * OLEDD_FindDropTarget()
773 * Finds information about the drop target.
775 static DropTargetNode* OLEDD_FindDropTarget(HWND hwndOfTarget)
777 DropTargetNode* curNode;
780 * Iterate the tree to find the HWND value.
782 curNode = targetListHead;
784 while (curNode!=NULL)
786 if (hwndOfTarget<curNode->hwndTarget)
789 * If the node we want to add has a smaller HWND, go left
791 curNode = curNode->prevDropTarget;
793 else if (hwndOfTarget>curNode->hwndTarget)
796 * If the node we want to add has a larger HWND, go right
798 curNode = curNode->nextDropTarget;
800 else
803 * The item was found in the list.
805 return curNode;
810 * If we get here, the item is not in the list
812 return NULL;
815 /***
816 * OLEDD_DragTrackerWindowProc()
818 * This method is the WindowProcedure of the drag n drop tracking
819 * window. During a drag n Drop operation, an invisible window is created
820 * to receive the user input and act upon it. This procedure is in charge
821 * of this behavior.
823 static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
824 HWND hwnd,
825 UINT uMsg,
826 WPARAM wParam,
827 LPARAM lParam)
829 switch (uMsg)
831 case WM_CREATE:
833 LPCREATESTRUCTA createStruct = (LPCREATESTRUCTA)lParam;
835 SetWindowLongA(hwnd, 0, (LONG)createStruct->lpCreateParams);
838 break;
840 case WM_MOUSEMOVE:
842 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
843 POINT mousePos;
846 * Get the current mouse position in screen coordinates.
848 mousePos.x = LOWORD(lParam);
849 mousePos.y = HIWORD(lParam);
850 ClientToScreen(hwnd, &mousePos);
853 * Track the movement of the mouse.
855 OLEDD_TrackMouseMove(trackerInfo, mousePos, wParam);
857 break;
859 case WM_LBUTTONUP:
860 case WM_MBUTTONUP:
861 case WM_RBUTTONUP:
862 case WM_LBUTTONDOWN:
863 case WM_MBUTTONDOWN:
864 case WM_RBUTTONDOWN:
866 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
867 POINT mousePos;
870 * Get the current mouse position in screen coordinates.
872 mousePos.x = LOWORD(lParam);
873 mousePos.y = HIWORD(lParam);
874 ClientToScreen(hwnd, &mousePos);
877 * Notify everyone that the button state changed
878 * TODO: Check if the "escape" key was pressed.
880 OLEDD_TrackStateChange(trackerInfo, mousePos, wParam);
882 break;
887 * This is a window proc after all. Let's call the default.
889 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
892 /***
893 * OLEDD_TrackMouseMove()
895 * This method is invoked while a drag and drop operation is in effect.
896 * it will generate the appropriate callbacks in the drop source
897 * and drop target. It will also provide the expected feedback to
898 * the user.
900 * params:
901 * trackerInfo - Pointer to the structure identifying the
902 * drag & drop operation that is currently
903 * active.
904 * mousePos - Current position of the mouse in screen
905 * coordinates.
906 * keyState - Contains the state of the shift keys and the
907 * mouse buttons (MK_LBUTTON and the like)
909 static void OLEDD_TrackMouseMove(
910 TrackerWindowInfo* trackerInfo,
911 POINT mousePos,
912 DWORD keyState)
914 HWND hwndNewTarget = 0;
915 HRESULT hr = S_OK;
918 * Get the handle of the window under the mouse
920 hwndNewTarget = WindowFromPoint(mousePos);
923 * If we are hovering over the same target as before, send the
924 * DragOver notification
926 if ( (trackerInfo->curDragTarget != 0) &&
927 (trackerInfo->curDragTargetHWND==hwndNewTarget) )
929 POINTL mousePosParam;
932 * The documentation tells me that the coordinate should be in the target
933 * window's coordinate space. However, the tests I made tell me the
934 * coordinates should be in screen coordinates.
936 mousePosParam.x = mousePos.x;
937 mousePosParam.y = mousePos.y;
939 IDropTarget_DragOver(trackerInfo->curDragTarget,
940 keyState,
941 mousePosParam,
942 trackerInfo->pdwEffect);
944 else
946 DropTargetNode* newDropTargetNode = 0;
949 * If we changed window, we have to notify our old target and check for
950 * the new one.
952 if (trackerInfo->curDragTarget!=0)
954 IDropTarget_DragLeave(trackerInfo->curDragTarget);
958 * Make sure we're hovering over a window.
960 if (hwndNewTarget!=0)
963 * Find-out if there is a drag target under the mouse
965 newDropTargetNode = OLEDD_FindDropTarget(hwndNewTarget);
967 trackerInfo->curDragTargetHWND = hwndNewTarget;
968 trackerInfo->curDragTarget = newDropTargetNode ? newDropTargetNode->dropTarget : 0;
971 * If there is, notify it that we just dragged-in
973 if (trackerInfo->curDragTarget!=0)
975 POINTL mousePosParam;
978 * The documentation tells me that the coordinate should be in the target
979 * window's coordinate space. However, the tests I made tell me the
980 * coordinates should be in screen coordinates.
982 mousePosParam.x = mousePos.x;
983 mousePosParam.y = mousePos.y;
985 IDropTarget_DragEnter(trackerInfo->curDragTarget,
986 trackerInfo->dataObject,
987 keyState,
988 mousePosParam,
989 trackerInfo->pdwEffect);
992 else
995 * The mouse is not over a window so we don't track anything.
997 trackerInfo->curDragTargetHWND = 0;
998 trackerInfo->curDragTarget = 0;
1003 * Now that we have done that, we have to tell the source to give
1004 * us feedback on the work being done by the target. If we don't
1005 * have a target, simulate no effect.
1007 if (trackerInfo->curDragTarget==0)
1009 *trackerInfo->pdwEffect = DROPEFFECT_NONE;
1012 hr = IDropSource_GiveFeedback(trackerInfo->dropSource,
1013 *trackerInfo->pdwEffect);
1016 * When we ask for feedback from the drop source, sometimes it will
1017 * do all the necessary work and sometimes it will not handle it
1018 * when that's the case, we must display the standard drag and drop
1019 * cursors.
1021 if (hr==DRAGDROP_S_USEDEFAULTCURSORS)
1023 if ( (*trackerInfo->pdwEffect & DROPEFFECT_MOVE) ||
1024 (*trackerInfo->pdwEffect & DROPEFFECT_COPY) ||
1025 (*trackerInfo->pdwEffect & DROPEFFECT_LINK) )
1027 SetCursor(LoadCursorA(0, IDC_SIZEALLA));
1029 else
1031 SetCursor(LoadCursorA(0, IDC_NOA));
1036 /***
1037 * OLEDD_TrackStateChange()
1039 * This method is invoked while a drag and drop operation is in effect.
1040 * It is used to notify the drop target/drop source callbacks when
1041 * the state of the keyboard or mouse button change.
1043 * params:
1044 * trackerInfo - Pointer to the structure identifying the
1045 * drag & drop operation that is currently
1046 * active.
1047 * mousePos - Current position of the mouse in screen
1048 * coordinates.
1049 * keyState - Contains the state of the shift keys and the
1050 * mouse buttons (MK_LBUTTON and the like)
1052 static void OLEDD_TrackStateChange(
1053 TrackerWindowInfo* trackerInfo,
1054 POINT mousePos,
1055 DWORD keyState)
1058 * Ask the drop source what to do with the operation.
1060 trackerInfo->returnValue = IDropSource_QueryContinueDrag(
1061 trackerInfo->dropSource,
1062 trackerInfo->escPressed,
1063 keyState);
1066 * All the return valued will stop the operation except the S_OK
1067 * return value.
1069 if (trackerInfo->returnValue!=S_OK)
1072 * Make sure the message loop in DoDragDrop stops
1074 trackerInfo->trackingDone = TRUE;
1077 * Release the mouse in case the drop target decides to show a popup
1078 * or a menu or something.
1080 ReleaseCapture();
1083 * If we end-up over a target, drop the object in the target or
1084 * inform the target that the operation was cancelled.
1086 if (trackerInfo->curDragTarget!=0)
1088 switch (trackerInfo->returnValue)
1091 * If the source wants us to complete the operation, we tell
1092 * the drop target that we just dropped the object in it.
1094 case DRAGDROP_S_DROP:
1096 POINTL mousePosParam;
1099 * The documentation tells me that the coordinate should be
1100 * in the target window's coordinate space. However, the tests
1101 * I made tell me the coordinates should be in screen coordinates.
1103 mousePosParam.x = mousePos.x;
1104 mousePosParam.y = mousePos.y;
1106 IDropTarget_Drop(trackerInfo->curDragTarget,
1107 trackerInfo->dataObject,
1108 keyState,
1109 mousePosParam,
1110 trackerInfo->pdwEffect);
1111 break;
1114 * If the source told us that we should cancel, fool the drop
1115 * target by telling it that the mouse left it's window.
1117 case DRAGDROP_S_CANCEL:
1118 IDropTarget_DragLeave(trackerInfo->curDragTarget);
1119 break;
1125 /***
1126 * OLEDD_GetButtonState()
1128 * This method will use the current state of the keyboard to build
1129 * a button state mask equivalent to the one passed in the
1130 * WM_MOUSEMOVE wParam.
1132 static DWORD OLEDD_GetButtonState()
1134 BYTE keyboardState[256];
1135 DWORD keyMask = 0;
1137 GetKeyboardState(keyboardState);
1139 if ( (keyboardState[VK_SHIFT] & 0x80) !=0)
1140 keyMask |= MK_SHIFT;
1142 if ( (keyboardState[VK_CONTROL] & 0x80) !=0)
1143 keyMask |= MK_CONTROL;
1145 if ( (keyboardState[VK_LBUTTON] & 0x80) !=0)
1146 keyMask |= MK_LBUTTON;
1148 if ( (keyboardState[VK_RBUTTON] & 0x80) !=0)
1149 keyMask |= MK_RBUTTON;
1151 if ( (keyboardState[VK_MBUTTON] & 0x80) !=0)
1152 keyMask |= MK_MBUTTON;
1154 return keyMask;