5 * Copyright 1995 Martin von Loewis
6 * Copyright 1999 Francis Beaudet
7 * Copyright 1999 Noel Borthwick
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
43 #include "wine/winbase16.h"
44 #include "wine/wingdi16.h"
45 #include "wine/winuser16.h"
46 #include "ole32_main.h"
48 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(ole);
51 WINE_DECLARE_DEBUG_CHANNEL(accel);
53 #define HICON_16(h32) (LOWORD(h32))
54 #define HICON_32(h16) ((HICON)(ULONG_PTR)(h16))
55 #define HINSTANCE_32(h16) ((HINSTANCE)(ULONG_PTR)(h16))
57 /******************************************************************************
58 * These are static/global variables and internal data structures that the
59 * OLE module uses to maintain it's state.
61 typedef struct tagDropTargetNode
64 IDropTarget* dropTarget;
65 struct tagDropTargetNode* prevDropTarget;
66 struct tagDropTargetNode* nextDropTarget;
69 typedef struct tagTrackerWindowInfo
71 IDataObject* dataObject;
72 IDropSource* dropSource;
79 HWND curDragTargetHWND;
80 IDropTarget* curDragTarget;
83 typedef struct tagOleMenuDescriptor /* OleMenuDescriptor */
85 HWND hwndFrame; /* The containers frame window */
86 HWND hwndActiveObject; /* The active objects window */
87 OLEMENUGROUPWIDTHS mgw; /* OLE menu group widths for the shared menu */
88 HMENU hmenuCombined; /* The combined menu */
89 BOOL bIsServerItem; /* True if the currently open popup belongs to the server */
92 typedef struct tagOleMenuHookItem /* OleMenu hook item in per thread hook list */
94 DWORD tid; /* Thread Id */
95 HANDLE hHeap; /* Heap this is allocated from */
96 HHOOK GetMsg_hHook; /* message hook for WH_GETMESSAGE */
97 HHOOK CallWndProc_hHook; /* message hook for WH_CALLWNDPROC */
98 struct tagOleMenuHookItem *next;
101 static OleMenuHookItem *hook_list;
104 * This is the lock count on the OLE library. It is controlled by the
105 * OLEInitialize/OLEUninitialize methods.
107 static ULONG OLE_moduleLockCount = 0;
110 * Name of our registered window class.
112 static const char OLEDD_DRAGTRACKERCLASS[] = "WineDragDropTracker32";
115 * This is the head of the Drop target container.
117 static DropTargetNode* targetListHead = NULL;
119 /******************************************************************************
120 * These are the prototypes of miscelaneous utility methods
122 static void OLEUTL_ReadRegistryDWORDValue(HKEY regKey, DWORD* pdwValue);
124 /******************************************************************************
125 * These are the prototypes of the utility methods used to manage a shared menu
127 static void OLEMenu_Initialize();
128 static void OLEMenu_UnInitialize();
129 BOOL OLEMenu_InstallHooks( DWORD tid );
130 BOOL OLEMenu_UnInstallHooks( DWORD tid );
131 OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid );
132 static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos );
133 BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor );
134 LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam);
135 LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam);
137 /******************************************************************************
138 * These are the prototypes of the OLE Clipboard initialization methods (in clipboard.c)
140 void OLEClipbrd_UnInitialize();
141 void OLEClipbrd_Initialize();
143 /******************************************************************************
144 * These are the prototypes of the utility methods used for OLE Drag n Drop
146 static void OLEDD_Initialize();
147 static void OLEDD_UnInitialize();
148 static void OLEDD_InsertDropTarget(
149 DropTargetNode* nodeToAdd);
150 static DropTargetNode* OLEDD_ExtractDropTarget(
152 static DropTargetNode* OLEDD_FindDropTarget(
154 static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
159 static void OLEDD_TrackMouseMove(
160 TrackerWindowInfo* trackerInfo,
163 static void OLEDD_TrackStateChange(
164 TrackerWindowInfo* trackerInfo,
167 static DWORD OLEDD_GetButtonState();
170 /******************************************************************************
171 * OleBuildVersion [OLE2.1]
172 * OleBuildVersion [OLE32.84]
174 DWORD WINAPI OleBuildVersion(void)
176 TRACE("Returning version %d, build %d.\n", rmm, rup);
177 return (rmm<<16)+rup;
180 /***********************************************************************
181 * OleInitialize (OLE2.2)
182 * OleInitialize (OLE32.108)
184 HRESULT WINAPI OleInitialize(LPVOID reserved)
188 TRACE("(%p)\n", reserved);
191 * The first duty of the OleInitialize is to initialize the COM libraries.
193 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
196 * If the CoInitializeEx call failed, the OLE libraries can't be
203 * Then, it has to initialize the OLE specific modules.
207 * Object linking and Embedding
208 * In-place activation
210 if (OLE_moduleLockCount==0)
213 * Initialize the libraries.
215 TRACE("() - Initializing the OLE libraries\n");
220 OLEClipbrd_Initialize();
230 OLEMenu_Initialize();
234 * Then, we increase the lock count on the OLE module.
236 OLE_moduleLockCount++;
241 /******************************************************************************
242 * CoGetCurrentProcess [COMPOBJ.34]
243 * CoGetCurrentProcess [OLE32.18]
246 * Is DWORD really the correct return type for this function?
248 DWORD WINAPI CoGetCurrentProcess(void)
250 return GetCurrentProcessId();
253 /******************************************************************************
254 * OleUninitialize [OLE2.3]
255 * OleUninitialize [OLE32.131]
257 void WINAPI OleUninitialize(void)
262 * Decrease the lock count on the OLE module.
264 OLE_moduleLockCount--;
267 * If we hit the bottom of the lock stack, free the libraries.
269 if (OLE_moduleLockCount==0)
272 * Actually free the libraries.
274 TRACE("() - Freeing the last reference count\n");
279 OLEClipbrd_UnInitialize();
284 OLEDD_UnInitialize();
289 OLEMenu_UnInitialize();
293 * Then, uninitialize the COM libraries.
298 /******************************************************************************
299 * CoRegisterMessageFilter [OLE32.38]
301 HRESULT WINAPI CoRegisterMessageFilter(
302 LPMESSAGEFILTER lpMessageFilter, /* [in] Pointer to interface */
303 LPMESSAGEFILTER *lplpMessageFilter /* [out] Indirect pointer to prior instance if non-NULL */
306 if (lplpMessageFilter) {
307 *lplpMessageFilter = NULL;
312 /******************************************************************************
313 * OleInitializeWOW [OLE32.109]
315 HRESULT WINAPI OleInitializeWOW(DWORD x) {
316 FIXME("(0x%08lx),stub!\n",x);
320 /***********************************************************************
321 * RegisterDragDrop (OLE2.35)
323 HRESULT WINAPI RegisterDragDrop16(
325 LPDROPTARGET pDropTarget
327 FIXME("(0x%04x,%p),stub!\n",hwnd,pDropTarget);
331 /***********************************************************************
332 * RegisterDragDrop (OLE32.139)
334 HRESULT WINAPI RegisterDragDrop(
336 LPDROPTARGET pDropTarget)
338 DropTargetNode* dropTargetInfo;
340 TRACE("(%p,%p)\n", hwnd, pDropTarget);
343 * First, check if the window is already registered.
345 dropTargetInfo = OLEDD_FindDropTarget(hwnd);
347 if (dropTargetInfo!=NULL)
348 return DRAGDROP_E_ALREADYREGISTERED;
351 * If it's not there, we can add it. We first create a node for it.
353 dropTargetInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(DropTargetNode));
355 if (dropTargetInfo==NULL)
356 return E_OUTOFMEMORY;
358 dropTargetInfo->hwndTarget = hwnd;
359 dropTargetInfo->prevDropTarget = NULL;
360 dropTargetInfo->nextDropTarget = NULL;
363 * Don't forget that this is an interface pointer, need to nail it down since
364 * we keep a copy of it.
366 dropTargetInfo->dropTarget = pDropTarget;
367 IDropTarget_AddRef(dropTargetInfo->dropTarget);
369 OLEDD_InsertDropTarget(dropTargetInfo);
374 /***********************************************************************
375 * RevokeDragDrop (OLE2.36)
377 HRESULT WINAPI RevokeDragDrop16(
380 FIXME("(0x%04x),stub!\n",hwnd);
384 /***********************************************************************
385 * RevokeDragDrop (OLE32.141)
387 HRESULT WINAPI RevokeDragDrop(
390 DropTargetNode* dropTargetInfo;
392 TRACE("(%p)\n", hwnd);
395 * First, check if the window is already registered.
397 dropTargetInfo = OLEDD_ExtractDropTarget(hwnd);
400 * If it ain't in there, it's an error.
402 if (dropTargetInfo==NULL)
403 return DRAGDROP_E_NOTREGISTERED;
406 * If it's in there, clean-up it's used memory and
409 IDropTarget_Release(dropTargetInfo->dropTarget);
410 HeapFree(GetProcessHeap(), 0, dropTargetInfo);
415 /***********************************************************************
416 * OleRegGetUserType (OLE32.122)
418 * This implementation of OleRegGetUserType ignores the dwFormOfType
419 * parameter and always returns the full name of the object. This is
420 * not too bad since this is the case for many objects because of the
421 * way they are registered.
423 HRESULT WINAPI OleRegGetUserType(
426 LPOLESTR* pszUserType)
436 * Initialize the out parameter.
441 * Build the key name we're looking for
443 sprintf( keyName, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\",
444 clsid->Data1, clsid->Data2, clsid->Data3,
445 clsid->Data4[0], clsid->Data4[1], clsid->Data4[2], clsid->Data4[3],
446 clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7] );
448 TRACE("(%s, %ld, %p)\n", keyName, dwFormOfType, pszUserType);
451 * Open the class id Key
453 hres = RegOpenKeyA(HKEY_CLASSES_ROOT,
457 if (hres != ERROR_SUCCESS)
458 return REGDB_E_CLASSNOTREG;
461 * Retrieve the size of the name string.
465 hres = RegQueryValueExA(clsidKey,
472 if (hres!=ERROR_SUCCESS)
474 RegCloseKey(clsidKey);
475 return REGDB_E_READREGDB;
479 * Allocate a buffer for the registry value.
481 *pszUserType = CoTaskMemAlloc(cbData*2);
483 if (*pszUserType==NULL)
485 RegCloseKey(clsidKey);
486 return E_OUTOFMEMORY;
489 buffer = HeapAlloc(GetProcessHeap(), 0, cbData);
493 RegCloseKey(clsidKey);
494 CoTaskMemFree(*pszUserType);
496 return E_OUTOFMEMORY;
499 hres = RegQueryValueExA(clsidKey,
506 RegCloseKey(clsidKey);
509 if (hres!=ERROR_SUCCESS)
511 CoTaskMemFree(*pszUserType);
514 retVal = REGDB_E_READREGDB;
518 MultiByteToWideChar( CP_ACP, 0, buffer, -1, *pszUserType, cbData /*FIXME*/ );
521 HeapFree(GetProcessHeap(), 0, buffer);
526 /***********************************************************************
527 * DoDragDrop [OLE32.65]
529 HRESULT WINAPI DoDragDrop (
530 IDataObject *pDataObject, /* [in] ptr to the data obj */
531 IDropSource* pDropSource, /* [in] ptr to the source obj */
532 DWORD dwOKEffect, /* [in] effects allowed by the source */
533 DWORD *pdwEffect) /* [out] ptr to effects of the source */
535 TrackerWindowInfo trackerInfo;
536 HWND hwndTrackWindow;
539 TRACE("(DataObject %p, DropSource %p)\n", pDataObject, pDropSource);
542 * Setup the drag n drop tracking window.
544 if (!IsValidInterface((LPUNKNOWN)pDropSource))
547 trackerInfo.dataObject = pDataObject;
548 trackerInfo.dropSource = pDropSource;
549 trackerInfo.dwOKEffect = dwOKEffect;
550 trackerInfo.pdwEffect = pdwEffect;
551 trackerInfo.trackingDone = FALSE;
552 trackerInfo.escPressed = FALSE;
553 trackerInfo.curDragTargetHWND = 0;
554 trackerInfo.curDragTarget = 0;
556 hwndTrackWindow = CreateWindowA(OLEDD_DRAGTRACKERCLASS,
559 CW_USEDEFAULT, CW_USEDEFAULT,
560 CW_USEDEFAULT, CW_USEDEFAULT,
564 (LPVOID)&trackerInfo);
566 if (hwndTrackWindow!=0)
569 * Capture the mouse input
571 SetCapture(hwndTrackWindow);
574 * Pump messages. All mouse input should go the the capture window.
576 while (!trackerInfo.trackingDone && GetMessageA(&msg, 0, 0, 0) )
578 if ( (msg.message >= WM_KEYFIRST) &&
579 (msg.message <= WM_KEYLAST) )
582 * When keyboard messages are sent to windows on this thread, we
583 * want to ignore notify the drop source that the state changed.
584 * in the case of the Escape key, we also notify the drop source
585 * we give it a special meaning.
587 if ( (msg.message==WM_KEYDOWN) &&
588 (msg.wParam==VK_ESCAPE) )
590 trackerInfo.escPressed = TRUE;
594 * Notify the drop source.
596 OLEDD_TrackStateChange(&trackerInfo,
598 OLEDD_GetButtonState());
603 * Dispatch the messages only when it's not a keyboard message.
605 DispatchMessageA(&msg);
610 * Destroy the temporary window.
612 DestroyWindow(hwndTrackWindow);
614 return trackerInfo.returnValue;
620 /***********************************************************************
621 * OleQueryLinkFromData [OLE32.118]
623 HRESULT WINAPI OleQueryLinkFromData(
624 IDataObject* pSrcDataObject)
626 FIXME("(%p),stub!\n", pSrcDataObject);
630 /***********************************************************************
631 * OleRegGetMiscStatus [OLE32.121]
633 HRESULT WINAPI OleRegGetMiscStatus(
645 * Initialize the out parameter.
650 * Build the key name we're looking for
652 sprintf( keyName, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\",
653 clsid->Data1, clsid->Data2, clsid->Data3,
654 clsid->Data4[0], clsid->Data4[1], clsid->Data4[2], clsid->Data4[3],
655 clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7] );
657 TRACE("(%s, %ld, %p)\n", keyName, dwAspect, pdwStatus);
660 * Open the class id Key
662 result = RegOpenKeyA(HKEY_CLASSES_ROOT,
666 if (result != ERROR_SUCCESS)
667 return REGDB_E_CLASSNOTREG;
672 result = RegOpenKeyA(clsidKey,
677 if (result != ERROR_SUCCESS)
679 RegCloseKey(clsidKey);
680 return REGDB_E_READREGDB;
684 * Read the default value
686 OLEUTL_ReadRegistryDWORDValue(miscStatusKey, pdwStatus);
689 * Open the key specific to the requested aspect.
691 sprintf(keyName, "%ld", dwAspect);
693 result = RegOpenKeyA(miscStatusKey,
697 if (result == ERROR_SUCCESS)
699 OLEUTL_ReadRegistryDWORDValue(aspectKey, pdwStatus);
700 RegCloseKey(aspectKey);
706 RegCloseKey(miscStatusKey);
707 RegCloseKey(clsidKey);
712 /******************************************************************************
713 * OleSetContainedObject [OLE32.128]
715 HRESULT WINAPI OleSetContainedObject(
719 IRunnableObject* runnable = NULL;
722 TRACE("(%p,%x), stub!\n", pUnknown, fContained);
724 hres = IUnknown_QueryInterface(pUnknown,
725 &IID_IRunnableObject,
730 hres = IRunnableObject_SetContainedObject(runnable, fContained);
732 IRunnableObject_Release(runnable);
740 /******************************************************************************
741 * OleLoad [OLE32.112]
743 HRESULT WINAPI OleLoad(
746 LPOLECLIENTSITE pClientSite,
749 IPersistStorage* persistStorage = NULL;
750 IOleObject* oleObject = NULL;
754 TRACE("(%p,%p,%p,%p)\n", pStg, riid, pClientSite, ppvObj);
757 * TODO, Conversion ... OleDoAutoConvert
761 * Get the class ID for the object.
763 hres = IStorage_Stat(pStg, &storageInfo, STATFLAG_NONAME);
766 * Now, try and create the handler for the object
768 hres = CoCreateInstance(&storageInfo.clsid,
770 CLSCTX_INPROC_HANDLER,
775 * If that fails, as it will most times, load the default
780 hres = OleCreateDefaultHandler(&storageInfo.clsid,
787 * If we couldn't find a handler... this is bad. Abort the whole thing.
793 * Inform the new object of it's client site.
795 hres = IOleObject_SetClientSite(oleObject, pClientSite);
798 * Initialize the object with it's IPersistStorage interface.
800 hres = IOleObject_QueryInterface(oleObject,
801 &IID_IPersistStorage,
802 (void**)&persistStorage);
806 IPersistStorage_Load(persistStorage, pStg);
808 IPersistStorage_Release(persistStorage);
809 persistStorage = NULL;
813 * Return the requested interface to the caller.
815 hres = IOleObject_QueryInterface(oleObject, riid, ppvObj);
818 * Cleanup interfaces used internally
820 IOleObject_Release(oleObject);
825 /***********************************************************************
826 * OleSave [OLE32.124]
828 HRESULT WINAPI OleSave(
829 LPPERSISTSTORAGE pPS,
836 TRACE("(%p,%p,%x)\n", pPS, pStg, fSameAsLoad);
839 * First, we transfer the class ID (if available)
841 hres = IPersistStorage_GetClassID(pPS, &objectClass);
845 WriteClassStg(pStg, &objectClass);
849 * Then, we ask the object to save itself to the
850 * storage. If it is successful, we commit the storage.
852 hres = IPersistStorage_Save(pPS, pStg, fSameAsLoad);
856 IStorage_Commit(pStg,
864 /******************************************************************************
865 * OleLockRunning [OLE32.114]
867 HRESULT WINAPI OleLockRunning(LPUNKNOWN pUnknown, BOOL fLock, BOOL fLastUnlockCloses)
869 IRunnableObject* runnable = NULL;
872 TRACE("(%p,%x,%x)\n", pUnknown, fLock, fLastUnlockCloses);
874 hres = IUnknown_QueryInterface(pUnknown,
875 &IID_IRunnableObject,
880 hres = IRunnableObject_LockRunning(runnable, fLock, fLastUnlockCloses);
882 IRunnableObject_Release(runnable);
891 /**************************************************************************
892 * Internal methods to manage the shared OLE menu in response to the
893 * OLE***MenuDescriptor API
897 * OLEMenu_Initialize()
899 * Initializes the OLEMENU data structures.
901 static void OLEMenu_Initialize()
906 * OLEMenu_UnInitialize()
908 * Releases the OLEMENU data structures.
910 static void OLEMenu_UnInitialize()
914 /*************************************************************************
915 * OLEMenu_InstallHooks
916 * Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
918 * RETURNS: TRUE if message hooks were succesfully installed
921 BOOL OLEMenu_InstallHooks( DWORD tid )
923 OleMenuHookItem *pHookItem = NULL;
925 /* Create an entry for the hook table */
926 if ( !(pHookItem = HeapAlloc(GetProcessHeap(), 0,
927 sizeof(OleMenuHookItem)) ) )
930 pHookItem->tid = tid;
931 pHookItem->hHeap = GetProcessHeap();
933 /* Install a thread scope message hook for WH_GETMESSAGE */
934 pHookItem->GetMsg_hHook = SetWindowsHookExA( WH_GETMESSAGE, OLEMenu_GetMsgProc,
935 0, GetCurrentThreadId() );
936 if ( !pHookItem->GetMsg_hHook )
939 /* Install a thread scope message hook for WH_CALLWNDPROC */
940 pHookItem->CallWndProc_hHook = SetWindowsHookExA( WH_CALLWNDPROC, OLEMenu_CallWndProc,
941 0, GetCurrentThreadId() );
942 if ( !pHookItem->CallWndProc_hHook )
945 /* Insert the hook table entry */
946 pHookItem->next = hook_list;
947 hook_list = pHookItem;
952 /* Unhook any hooks */
953 if ( pHookItem->GetMsg_hHook )
954 UnhookWindowsHookEx( pHookItem->GetMsg_hHook );
955 if ( pHookItem->CallWndProc_hHook )
956 UnhookWindowsHookEx( pHookItem->CallWndProc_hHook );
957 /* Release the hook table entry */
958 HeapFree(pHookItem->hHeap, 0, pHookItem );
963 /*************************************************************************
964 * OLEMenu_UnInstallHooks
965 * UnInstall thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
967 * RETURNS: TRUE if message hooks were succesfully installed
970 BOOL OLEMenu_UnInstallHooks( DWORD tid )
972 OleMenuHookItem *pHookItem = NULL;
973 OleMenuHookItem **ppHook = &hook_list;
977 if ((*ppHook)->tid == tid)
980 *ppHook = pHookItem->next;
983 ppHook = &(*ppHook)->next;
985 if (!pHookItem) return FALSE;
987 /* Uninstall the hooks installed for this thread */
988 if ( !UnhookWindowsHookEx( pHookItem->GetMsg_hHook ) )
990 if ( !UnhookWindowsHookEx( pHookItem->CallWndProc_hHook ) )
993 /* Release the hook table entry */
994 HeapFree(pHookItem->hHeap, 0, pHookItem );
999 /* Release the hook table entry */
1001 HeapFree(pHookItem->hHeap, 0, pHookItem );
1006 /*************************************************************************
1007 * OLEMenu_IsHookInstalled
1008 * Tests if OLEMenu hooks have been installed for a thread
1010 * RETURNS: The pointer and index of the hook table entry for the tid
1011 * NULL and -1 for the index if no hooks were installed for this thread
1013 OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid )
1015 OleMenuHookItem *pHookItem = NULL;
1017 /* Do a simple linear search for an entry whose tid matches ours.
1018 * We really need a map but efficiency is not a concern here. */
1019 for (pHookItem = hook_list; pHookItem; pHookItem = pHookItem->next)
1021 if ( tid == pHookItem->tid )
1028 /***********************************************************************
1029 * OLEMenu_FindMainMenuIndex
1031 * Used by OLEMenu API to find the top level group a menu item belongs to.
1032 * On success pnPos contains the index of the item in the top level menu group
1034 * RETURNS: TRUE if the ID was found, FALSE on failure
1036 static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos )
1040 nItems = GetMenuItemCount( hMainMenu );
1042 for (i = 0; i < nItems; i++)
1046 /* Is the current item a submenu? */
1047 if ( (hsubmenu = GetSubMenu(hMainMenu, i)) )
1049 /* If the handle is the same we're done */
1050 if ( hsubmenu == hPopupMenu )
1056 /* Recursively search without updating pnPos */
1057 else if ( OLEMenu_FindMainMenuIndex( hsubmenu, hPopupMenu, NULL ) )
1069 /***********************************************************************
1070 * OLEMenu_SetIsServerMenu
1072 * Checks whether a popup menu belongs to a shared menu group which is
1073 * owned by the server, and sets the menu descriptor state accordingly.
1074 * All menu messages from these groups should be routed to the server.
1076 * RETURNS: TRUE if the popup menu is part of a server owned group
1077 * FASE if the popup menu is part of a container owned group
1079 BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor )
1081 UINT nPos = 0, nWidth, i;
1083 pOleMenuDescriptor->bIsServerItem = FALSE;
1085 /* Don't bother searching if the popup is the combined menu itself */
1086 if ( hmenu == pOleMenuDescriptor->hmenuCombined )
1089 /* Find the menu item index in the shared OLE menu that this item belongs to */
1090 if ( !OLEMenu_FindMainMenuIndex( pOleMenuDescriptor->hmenuCombined, hmenu, &nPos ) )
1093 /* The group widths array has counts for the number of elements
1094 * in the groups File, Edit, Container, Object, Window, Help.
1095 * The Edit, Object & Help groups belong to the server object
1096 * and the other three belong to the container.
1097 * Loop through the group widths and locate the group we are a member of.
1099 for ( i = 0, nWidth = 0; i < 6; i++ )
1101 nWidth += pOleMenuDescriptor->mgw.width[i];
1102 if ( nPos < nWidth )
1104 /* Odd elements are server menu widths */
1105 pOleMenuDescriptor->bIsServerItem = (i%2) ? TRUE : FALSE;
1110 return pOleMenuDescriptor->bIsServerItem;
1113 /*************************************************************************
1114 * OLEMenu_CallWndProc
1115 * Thread scope WH_CALLWNDPROC hook proc filter function (callback)
1116 * This is invoked from a message hook installed in OleSetMenuDescriptor.
1118 LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam)
1120 LPCWPSTRUCT pMsg = NULL;
1121 HOLEMENU hOleMenu = 0;
1122 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1123 OleMenuHookItem *pHookItem = NULL;
1126 TRACE("%i, %04x, %08x\n", code, wParam, (unsigned)lParam );
1128 /* Check if we're being asked to process the message */
1129 if ( HC_ACTION != code )
1132 /* Retrieve the current message being dispatched from lParam */
1133 pMsg = (LPCWPSTRUCT)lParam;
1135 /* Check if the message is destined for a window we are interested in:
1136 * If the window has an OLEMenu property we may need to dispatch
1137 * the menu message to its active objects window instead. */
1139 hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" );
1143 /* Get the menu descriptor */
1144 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1145 if ( !pOleMenuDescriptor ) /* Bad descriptor! */
1148 /* Process menu messages */
1149 switch( pMsg->message )
1153 /* Reset the menu descriptor state */
1154 pOleMenuDescriptor->bIsServerItem = FALSE;
1156 /* Send this message to the server as well */
1157 SendMessageA( pOleMenuDescriptor->hwndActiveObject,
1158 pMsg->message, pMsg->wParam, pMsg->lParam );
1162 case WM_INITMENUPOPUP:
1164 /* Save the state for whether this is a server owned menu */
1165 OLEMenu_SetIsServerMenu( (HMENU)pMsg->wParam, pOleMenuDescriptor );
1171 fuFlags = HIWORD(pMsg->wParam); /* Get flags */
1172 if ( fuFlags & MF_SYSMENU )
1175 /* Save the state for whether this is a server owned popup menu */
1176 else if ( fuFlags & MF_POPUP )
1177 OLEMenu_SetIsServerMenu( (HMENU)pMsg->lParam, pOleMenuDescriptor );
1184 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) pMsg->lParam;
1185 if ( pMsg->wParam != 0 || lpdis->CtlType != ODT_MENU )
1186 goto NEXTHOOK; /* Not a menu message */
1195 /* If the message was for the server dispatch it accordingly */
1196 if ( pOleMenuDescriptor->bIsServerItem )
1198 SendMessageA( pOleMenuDescriptor->hwndActiveObject,
1199 pMsg->message, pMsg->wParam, pMsg->lParam );
1203 if ( pOleMenuDescriptor )
1204 GlobalUnlock( hOleMenu );
1206 /* Lookup the hook item for the current thread */
1207 if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) )
1209 /* This should never fail!! */
1210 WARN("could not retrieve hHook for current thread!\n" );
1214 /* Pass on the message to the next hooker */
1215 return CallNextHookEx( pHookItem->CallWndProc_hHook, code, wParam, lParam );
1218 /*************************************************************************
1219 * OLEMenu_GetMsgProc
1220 * Thread scope WH_GETMESSAGE hook proc filter function (callback)
1221 * This is invoked from a message hook installed in OleSetMenuDescriptor.
1223 LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam)
1226 HOLEMENU hOleMenu = 0;
1227 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1228 OleMenuHookItem *pHookItem = NULL;
1231 TRACE("%i, %04x, %08x\n", code, wParam, (unsigned)lParam );
1233 /* Check if we're being asked to process a messages */
1234 if ( HC_ACTION != code )
1237 /* Retrieve the current message being dispatched from lParam */
1238 pMsg = (LPMSG)lParam;
1240 /* Check if the message is destined for a window we are interested in:
1241 * If the window has an OLEMenu property we may need to dispatch
1242 * the menu message to its active objects window instead. */
1244 hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" );
1248 /* Process menu messages */
1249 switch( pMsg->message )
1253 wCode = HIWORD(pMsg->wParam); /* Get notification code */
1255 goto NEXTHOOK; /* Not a menu message */
1262 /* Get the menu descriptor */
1263 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1264 if ( !pOleMenuDescriptor ) /* Bad descriptor! */
1267 /* If the message was for the server dispatch it accordingly */
1268 if ( pOleMenuDescriptor->bIsServerItem )
1270 /* Change the hWnd in the message to the active objects hWnd.
1271 * The message loop which reads this message will automatically
1272 * dispatch it to the embedded objects window. */
1273 pMsg->hwnd = pOleMenuDescriptor->hwndActiveObject;
1277 if ( pOleMenuDescriptor )
1278 GlobalUnlock( hOleMenu );
1280 /* Lookup the hook item for the current thread */
1281 if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) )
1283 /* This should never fail!! */
1284 WARN("could not retrieve hHook for current thread!\n" );
1288 /* Pass on the message to the next hooker */
1289 return CallNextHookEx( pHookItem->GetMsg_hHook, code, wParam, lParam );
1292 /***********************************************************************
1293 * OleCreateMenuDescriptor [OLE32.97]
1294 * Creates an OLE menu descriptor for OLE to use when dispatching
1295 * menu messages and commands.
1298 * hmenuCombined - Handle to the objects combined menu
1299 * lpMenuWidths - Pointer to array of 6 LONG's indicating menus per group
1302 HOLEMENU WINAPI OleCreateMenuDescriptor(
1303 HMENU hmenuCombined,
1304 LPOLEMENUGROUPWIDTHS lpMenuWidths)
1307 OleMenuDescriptor *pOleMenuDescriptor;
1310 if ( !hmenuCombined || !lpMenuWidths )
1313 /* Create an OLE menu descriptor */
1314 if ( !(hOleMenu = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
1315 sizeof(OleMenuDescriptor) ) ) )
1318 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1319 if ( !pOleMenuDescriptor )
1322 /* Initialize menu group widths and hmenu */
1323 for ( i = 0; i < 6; i++ )
1324 pOleMenuDescriptor->mgw.width[i] = lpMenuWidths->width[i];
1326 pOleMenuDescriptor->hmenuCombined = hmenuCombined;
1327 pOleMenuDescriptor->bIsServerItem = FALSE;
1328 GlobalUnlock( hOleMenu );
1333 /***********************************************************************
1334 * OleDestroyMenuDescriptor [OLE32.99]
1335 * Destroy the shared menu descriptor
1337 HRESULT WINAPI OleDestroyMenuDescriptor(
1338 HOLEMENU hmenuDescriptor)
1340 if ( hmenuDescriptor )
1341 GlobalFree( hmenuDescriptor );
1345 /***********************************************************************
1346 * OleSetMenuDescriptor [OLE32.129]
1347 * Installs or removes OLE dispatching code for the containers frame window
1348 * FIXME: The lpFrame and lpActiveObject parameters are currently ignored
1349 * OLE should install context sensitive help F1 filtering for the app when
1350 * these are non null.
1353 * hOleMenu Handle to composite menu descriptor
1354 * hwndFrame Handle to containers frame window
1355 * hwndActiveObject Handle to objects in-place activation window
1356 * lpFrame Pointer to IOleInPlaceFrame on containers window
1357 * lpActiveObject Pointer to IOleInPlaceActiveObject on active in-place object
1360 * S_OK - menu installed correctly
1361 * E_FAIL, E_INVALIDARG, E_UNEXPECTED - failure
1363 HRESULT WINAPI OleSetMenuDescriptor(
1366 HWND hwndActiveObject,
1367 LPOLEINPLACEFRAME lpFrame,
1368 LPOLEINPLACEACTIVEOBJECT lpActiveObject)
1370 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1373 if ( !hwndFrame || (hOleMenu && !hwndActiveObject) )
1374 return E_INVALIDARG;
1376 if ( lpFrame || lpActiveObject )
1378 FIXME("(%x, %p, %p, %p, %p), Context sensitive help filtering not implemented!\n",
1379 (unsigned int)hOleMenu,
1386 /* Set up a message hook to intercept the containers frame window messages.
1387 * The message filter is responsible for dispatching menu messages from the
1388 * shared menu which are intended for the object.
1391 if ( hOleMenu ) /* Want to install dispatching code */
1393 /* If OLEMenu hooks are already installed for this thread, fail
1394 * Note: This effectively means that OleSetMenuDescriptor cannot
1395 * be called twice in succession on the same frame window
1396 * without first calling it with a null hOleMenu to uninstall */
1397 if ( OLEMenu_IsHookInstalled( GetCurrentThreadId() ) )
1400 /* Get the menu descriptor */
1401 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1402 if ( !pOleMenuDescriptor )
1403 return E_UNEXPECTED;
1405 /* Update the menu descriptor */
1406 pOleMenuDescriptor->hwndFrame = hwndFrame;
1407 pOleMenuDescriptor->hwndActiveObject = hwndActiveObject;
1409 GlobalUnlock( hOleMenu );
1410 pOleMenuDescriptor = NULL;
1412 /* Add a menu descriptor windows property to the frame window */
1413 SetPropA( hwndFrame, "PROP_OLEMenuDescriptor", hOleMenu );
1415 /* Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC */
1416 if ( !OLEMenu_InstallHooks( GetCurrentThreadId() ) )
1419 else /* Want to uninstall dispatching code */
1421 /* Uninstall the hooks */
1422 if ( !OLEMenu_UnInstallHooks( GetCurrentThreadId() ) )
1425 /* Remove the menu descriptor property from the frame window */
1426 RemovePropA( hwndFrame, "PROP_OLEMenuDescriptor" );
1432 /******************************************************************************
1433 * IsAccelerator [OLE32.75]
1434 * Mostly copied from controls/menu.c TranslateAccelerator implementation
1436 BOOL WINAPI IsAccelerator(HACCEL hAccel, int cAccelEntries, LPMSG lpMsg, WORD* lpwCmd)
1439 LPACCEL16 lpAccelTbl;
1442 if(!lpMsg) return FALSE;
1443 if (!hAccel || !(lpAccelTbl = (LPACCEL16)LockResource16(HACCEL_16(hAccel))))
1445 WARN_(accel)("invalid accel handle=%p\n", hAccel);
1448 if((lpMsg->message != WM_KEYDOWN &&
1449 lpMsg->message != WM_KEYUP &&
1450 lpMsg->message != WM_SYSKEYDOWN &&
1451 lpMsg->message != WM_SYSKEYUP &&
1452 lpMsg->message != WM_CHAR)) return FALSE;
1454 TRACE_(accel)("hAccel=%p, cAccelEntries=%d,"
1455 "msg->hwnd=%p, msg->message=%04x, wParam=%08x, lParam=%08lx\n",
1456 hAccel, cAccelEntries,
1457 lpMsg->hwnd, lpMsg->message, lpMsg->wParam, lpMsg->lParam);
1458 for(i = 0; i < cAccelEntries; i++)
1460 if(lpAccelTbl[i].key != lpMsg->wParam)
1463 if(lpMsg->message == WM_CHAR)
1465 if(!(lpAccelTbl[i].fVirt & FALT) && !(lpAccelTbl[i].fVirt & FVIRTKEY))
1467 TRACE_(accel)("found accel for WM_CHAR: ('%c')\n", lpMsg->wParam & 0xff);
1473 if(lpAccelTbl[i].fVirt & FVIRTKEY)
1476 TRACE_(accel)("found accel for virt_key %04x (scan %04x)\n",
1477 lpMsg->wParam, HIWORD(lpMsg->lParam) & 0xff);
1478 if(GetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT;
1479 if(GetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL;
1480 if(GetKeyState(VK_MENU) & 0x8000) mask |= FALT;
1481 if(mask == (lpAccelTbl[i].fVirt & (FSHIFT | FCONTROL | FALT))) goto found;
1482 TRACE_(accel)("incorrect SHIFT/CTRL/ALT-state\n");
1486 if(!(lpMsg->lParam & 0x01000000)) /* no special_key */
1488 if((lpAccelTbl[i].fVirt & FALT) && (lpMsg->lParam & 0x20000000))
1489 { /* ^^ ALT pressed */
1490 TRACE_(accel)("found accel for Alt-%c\n", lpMsg->wParam & 0xff);
1498 WARN_(accel)("couldn't translate accelerator key\n");
1502 if(lpwCmd) *lpwCmd = lpAccelTbl[i].cmd;
1506 /***********************************************************************
1507 * ReleaseStgMedium [OLE32.140]
1509 void WINAPI ReleaseStgMedium(
1512 switch (pmedium->tymed)
1516 if ( (pmedium->pUnkForRelease==0) &&
1517 (pmedium->u.hGlobal!=0) )
1518 GlobalFree(pmedium->u.hGlobal);
1523 if (pmedium->u.lpszFileName!=0)
1525 if (pmedium->pUnkForRelease==0)
1527 DeleteFileW(pmedium->u.lpszFileName);
1530 CoTaskMemFree(pmedium->u.lpszFileName);
1536 if (pmedium->u.pstm!=0)
1538 IStream_Release(pmedium->u.pstm);
1542 case TYMED_ISTORAGE:
1544 if (pmedium->u.pstg!=0)
1546 IStorage_Release(pmedium->u.pstg);
1552 if ( (pmedium->pUnkForRelease==0) &&
1553 (pmedium->u.hBitmap!=0) )
1554 DeleteObject(pmedium->u.hBitmap);
1559 if ( (pmedium->pUnkForRelease==0) &&
1560 (pmedium->u.hMetaFilePict!=0) )
1562 LPMETAFILEPICT pMP = GlobalLock(pmedium->u.hMetaFilePict);
1563 DeleteMetaFile(pMP->hMF);
1564 GlobalUnlock(pmedium->u.hMetaFilePict);
1565 GlobalFree(pmedium->u.hMetaFilePict);
1571 if ( (pmedium->pUnkForRelease==0) &&
1572 (pmedium->u.hEnhMetaFile!=0) )
1574 DeleteEnhMetaFile(pmedium->u.hEnhMetaFile);
1582 pmedium->tymed=TYMED_NULL;
1585 * After cleaning up, the unknown is released
1587 if (pmedium->pUnkForRelease!=0)
1589 IUnknown_Release(pmedium->pUnkForRelease);
1590 pmedium->pUnkForRelease = 0;
1595 * OLEDD_Initialize()
1597 * Initializes the OLE drag and drop data structures.
1599 static void OLEDD_Initialize()
1603 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1604 wndClass.style = CS_GLOBALCLASS;
1605 wndClass.lpfnWndProc = (WNDPROC)OLEDD_DragTrackerWindowProc;
1606 wndClass.cbClsExtra = 0;
1607 wndClass.cbWndExtra = sizeof(TrackerWindowInfo*);
1608 wndClass.hCursor = 0;
1609 wndClass.hbrBackground = 0;
1610 wndClass.lpszClassName = OLEDD_DRAGTRACKERCLASS;
1612 RegisterClassA (&wndClass);
1616 * OLEDD_UnInitialize()
1618 * Releases the OLE drag and drop data structures.
1620 static void OLEDD_UnInitialize()
1623 * Simply empty the list.
1625 while (targetListHead!=NULL)
1627 RevokeDragDrop(targetListHead->hwndTarget);
1632 * OLEDD_InsertDropTarget()
1634 * Insert the target node in the tree.
1636 static void OLEDD_InsertDropTarget(DropTargetNode* nodeToAdd)
1638 DropTargetNode* curNode;
1639 DropTargetNode** parentNodeLink;
1642 * Iterate the tree to find the insertion point.
1644 curNode = targetListHead;
1645 parentNodeLink = &targetListHead;
1647 while (curNode!=NULL)
1649 if (nodeToAdd->hwndTarget<curNode->hwndTarget)
1652 * If the node we want to add has a smaller HWND, go left
1654 parentNodeLink = &curNode->prevDropTarget;
1655 curNode = curNode->prevDropTarget;
1657 else if (nodeToAdd->hwndTarget>curNode->hwndTarget)
1660 * If the node we want to add has a larger HWND, go right
1662 parentNodeLink = &curNode->nextDropTarget;
1663 curNode = curNode->nextDropTarget;
1668 * The item was found in the list. It shouldn't have been there
1676 * If we get here, we have found a spot for our item. The parentNodeLink
1677 * pointer points to the pointer that we have to modify.
1678 * The curNode should be NULL. We just have to establish the link and Voila!
1680 assert(curNode==NULL);
1681 assert(parentNodeLink!=NULL);
1682 assert(*parentNodeLink==NULL);
1684 *parentNodeLink=nodeToAdd;
1688 * OLEDD_ExtractDropTarget()
1690 * Removes the target node from the tree.
1692 static DropTargetNode* OLEDD_ExtractDropTarget(HWND hwndOfTarget)
1694 DropTargetNode* curNode;
1695 DropTargetNode** parentNodeLink;
1698 * Iterate the tree to find the insertion point.
1700 curNode = targetListHead;
1701 parentNodeLink = &targetListHead;
1703 while (curNode!=NULL)
1705 if (hwndOfTarget<curNode->hwndTarget)
1708 * If the node we want to add has a smaller HWND, go left
1710 parentNodeLink = &curNode->prevDropTarget;
1711 curNode = curNode->prevDropTarget;
1713 else if (hwndOfTarget>curNode->hwndTarget)
1716 * If the node we want to add has a larger HWND, go right
1718 parentNodeLink = &curNode->nextDropTarget;
1719 curNode = curNode->nextDropTarget;
1724 * The item was found in the list. Detach it from it's parent and
1725 * re-insert it's kids in the tree.
1727 assert(parentNodeLink!=NULL);
1728 assert(*parentNodeLink==curNode);
1731 * We arbitrately re-attach the left sub-tree to the parent.
1733 *parentNodeLink = curNode->prevDropTarget;
1736 * And we re-insert the right subtree
1738 if (curNode->nextDropTarget!=NULL)
1740 OLEDD_InsertDropTarget(curNode->nextDropTarget);
1744 * The node we found is still a valid node once we complete
1745 * the unlinking of the kids.
1747 curNode->nextDropTarget=NULL;
1748 curNode->prevDropTarget=NULL;
1755 * If we get here, the node is not in the tree
1761 * OLEDD_FindDropTarget()
1763 * Finds information about the drop target.
1765 static DropTargetNode* OLEDD_FindDropTarget(HWND hwndOfTarget)
1767 DropTargetNode* curNode;
1770 * Iterate the tree to find the HWND value.
1772 curNode = targetListHead;
1774 while (curNode!=NULL)
1776 if (hwndOfTarget<curNode->hwndTarget)
1779 * If the node we want to add has a smaller HWND, go left
1781 curNode = curNode->prevDropTarget;
1783 else if (hwndOfTarget>curNode->hwndTarget)
1786 * If the node we want to add has a larger HWND, go right
1788 curNode = curNode->nextDropTarget;
1793 * The item was found in the list.
1800 * If we get here, the item is not in the list
1806 * OLEDD_DragTrackerWindowProc()
1808 * This method is the WindowProcedure of the drag n drop tracking
1809 * window. During a drag n Drop operation, an invisible window is created
1810 * to receive the user input and act upon it. This procedure is in charge
1813 static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
1823 LPCREATESTRUCTA createStruct = (LPCREATESTRUCTA)lParam;
1825 SetWindowLongA(hwnd, 0, (LONG)createStruct->lpCreateParams);
1832 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
1836 * Get the current mouse position in screen coordinates.
1838 mousePos.x = LOWORD(lParam);
1839 mousePos.y = HIWORD(lParam);
1840 ClientToScreen(hwnd, &mousePos);
1843 * Track the movement of the mouse.
1845 OLEDD_TrackMouseMove(trackerInfo, mousePos, wParam);
1852 case WM_LBUTTONDOWN:
1853 case WM_MBUTTONDOWN:
1854 case WM_RBUTTONDOWN:
1856 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
1860 * Get the current mouse position in screen coordinates.
1862 mousePos.x = LOWORD(lParam);
1863 mousePos.y = HIWORD(lParam);
1864 ClientToScreen(hwnd, &mousePos);
1867 * Notify everyone that the button state changed
1868 * TODO: Check if the "escape" key was pressed.
1870 OLEDD_TrackStateChange(trackerInfo, mousePos, wParam);
1877 * This is a window proc after all. Let's call the default.
1879 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1883 * OLEDD_TrackMouseMove()
1885 * This method is invoked while a drag and drop operation is in effect.
1886 * it will generate the appropriate callbacks in the drop source
1887 * and drop target. It will also provide the expected feedback to
1891 * trackerInfo - Pointer to the structure identifying the
1892 * drag & drop operation that is currently
1894 * mousePos - Current position of the mouse in screen
1896 * keyState - Contains the state of the shift keys and the
1897 * mouse buttons (MK_LBUTTON and the like)
1899 static void OLEDD_TrackMouseMove(
1900 TrackerWindowInfo* trackerInfo,
1904 HWND hwndNewTarget = 0;
1908 * Get the handle of the window under the mouse
1910 hwndNewTarget = WindowFromPoint(mousePos);
1913 * Every time, we re-initialize the effects passed to the
1914 * IDropTarget to the effects allowed by the source.
1916 *trackerInfo->pdwEffect = trackerInfo->dwOKEffect;
1919 * If we are hovering over the same target as before, send the
1920 * DragOver notification
1922 if ( (trackerInfo->curDragTarget != 0) &&
1923 (trackerInfo->curDragTargetHWND==hwndNewTarget) )
1925 POINTL mousePosParam;
1928 * The documentation tells me that the coordinate should be in the target
1929 * window's coordinate space. However, the tests I made tell me the
1930 * coordinates should be in screen coordinates.
1932 mousePosParam.x = mousePos.x;
1933 mousePosParam.y = mousePos.y;
1935 IDropTarget_DragOver(trackerInfo->curDragTarget,
1938 trackerInfo->pdwEffect);
1942 DropTargetNode* newDropTargetNode = 0;
1945 * If we changed window, we have to notify our old target and check for
1948 if (trackerInfo->curDragTarget!=0)
1950 IDropTarget_DragLeave(trackerInfo->curDragTarget);
1954 * Make sure we're hovering over a window.
1956 if (hwndNewTarget!=0)
1959 * Find-out if there is a drag target under the mouse
1961 HWND nexttar = hwndNewTarget;
1963 newDropTargetNode = OLEDD_FindDropTarget(nexttar);
1964 } while (!newDropTargetNode && (nexttar = GetParent(nexttar)) != 0);
1965 if(nexttar) hwndNewTarget = nexttar;
1967 trackerInfo->curDragTargetHWND = hwndNewTarget;
1968 trackerInfo->curDragTarget = newDropTargetNode ? newDropTargetNode->dropTarget : 0;
1971 * If there is, notify it that we just dragged-in
1973 if (trackerInfo->curDragTarget!=0)
1975 POINTL mousePosParam;
1978 * The documentation tells me that the coordinate should be in the target
1979 * window's coordinate space. However, the tests I made tell me the
1980 * coordinates should be in screen coordinates.
1982 mousePosParam.x = mousePos.x;
1983 mousePosParam.y = mousePos.y;
1985 IDropTarget_DragEnter(trackerInfo->curDragTarget,
1986 trackerInfo->dataObject,
1989 trackerInfo->pdwEffect);
1995 * The mouse is not over a window so we don't track anything.
1997 trackerInfo->curDragTargetHWND = 0;
1998 trackerInfo->curDragTarget = 0;
2003 * Now that we have done that, we have to tell the source to give
2004 * us feedback on the work being done by the target. If we don't
2005 * have a target, simulate no effect.
2007 if (trackerInfo->curDragTarget==0)
2009 *trackerInfo->pdwEffect = DROPEFFECT_NONE;
2012 hr = IDropSource_GiveFeedback(trackerInfo->dropSource,
2013 *trackerInfo->pdwEffect);
2016 * When we ask for feedback from the drop source, sometimes it will
2017 * do all the necessary work and sometimes it will not handle it
2018 * when that's the case, we must display the standard drag and drop
2021 if (hr==DRAGDROP_S_USEDEFAULTCURSORS)
2023 if (*trackerInfo->pdwEffect & DROPEFFECT_MOVE)
2025 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(1)));
2027 else if (*trackerInfo->pdwEffect & DROPEFFECT_COPY)
2029 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(2)));
2031 else if (*trackerInfo->pdwEffect & DROPEFFECT_LINK)
2033 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(3)));
2037 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(0)));
2043 * OLEDD_TrackStateChange()
2045 * This method is invoked while a drag and drop operation is in effect.
2046 * It is used to notify the drop target/drop source callbacks when
2047 * the state of the keyboard or mouse button change.
2050 * trackerInfo - Pointer to the structure identifying the
2051 * drag & drop operation that is currently
2053 * mousePos - Current position of the mouse in screen
2055 * keyState - Contains the state of the shift keys and the
2056 * mouse buttons (MK_LBUTTON and the like)
2058 static void OLEDD_TrackStateChange(
2059 TrackerWindowInfo* trackerInfo,
2064 * Ask the drop source what to do with the operation.
2066 trackerInfo->returnValue = IDropSource_QueryContinueDrag(
2067 trackerInfo->dropSource,
2068 trackerInfo->escPressed,
2072 * All the return valued will stop the operation except the S_OK
2075 if (trackerInfo->returnValue!=S_OK)
2078 * Make sure the message loop in DoDragDrop stops
2080 trackerInfo->trackingDone = TRUE;
2083 * Release the mouse in case the drop target decides to show a popup
2084 * or a menu or something.
2089 * If we end-up over a target, drop the object in the target or
2090 * inform the target that the operation was cancelled.
2092 if (trackerInfo->curDragTarget!=0)
2094 switch (trackerInfo->returnValue)
2097 * If the source wants us to complete the operation, we tell
2098 * the drop target that we just dropped the object in it.
2100 case DRAGDROP_S_DROP:
2102 POINTL mousePosParam;
2105 * The documentation tells me that the coordinate should be
2106 * in the target window's coordinate space. However, the tests
2107 * I made tell me the coordinates should be in screen coordinates.
2109 mousePosParam.x = mousePos.x;
2110 mousePosParam.y = mousePos.y;
2112 IDropTarget_Drop(trackerInfo->curDragTarget,
2113 trackerInfo->dataObject,
2116 trackerInfo->pdwEffect);
2120 * If the source told us that we should cancel, fool the drop
2121 * target by telling it that the mouse left it's window.
2122 * Also set the drop effect to "NONE" in case the application
2123 * ignores the result of DoDragDrop.
2125 case DRAGDROP_S_CANCEL:
2126 IDropTarget_DragLeave(trackerInfo->curDragTarget);
2127 *trackerInfo->pdwEffect = DROPEFFECT_NONE;
2135 * OLEDD_GetButtonState()
2137 * This method will use the current state of the keyboard to build
2138 * a button state mask equivalent to the one passed in the
2139 * WM_MOUSEMOVE wParam.
2141 static DWORD OLEDD_GetButtonState()
2143 BYTE keyboardState[256];
2146 GetKeyboardState(keyboardState);
2148 if ( (keyboardState[VK_SHIFT] & 0x80) !=0)
2149 keyMask |= MK_SHIFT;
2151 if ( (keyboardState[VK_CONTROL] & 0x80) !=0)
2152 keyMask |= MK_CONTROL;
2154 if ( (keyboardState[VK_LBUTTON] & 0x80) !=0)
2155 keyMask |= MK_LBUTTON;
2157 if ( (keyboardState[VK_RBUTTON] & 0x80) !=0)
2158 keyMask |= MK_RBUTTON;
2160 if ( (keyboardState[VK_MBUTTON] & 0x80) !=0)
2161 keyMask |= MK_MBUTTON;
2167 * OLEDD_GetButtonState()
2169 * This method will read the default value of the registry key in
2170 * parameter and extract a DWORD value from it. The registry key value
2171 * can be in a string key or a DWORD key.
2174 * regKey - Key to read the default value from
2175 * pdwValue - Pointer to the location where the DWORD
2176 * value is returned. This value is not modified
2177 * if the value is not found.
2180 static void OLEUTL_ReadRegistryDWORDValue(
2189 lres = RegQueryValueExA(regKey,
2196 if (lres==ERROR_SUCCESS)
2201 *pdwValue = *(DWORD*)buffer;
2206 *pdwValue = (DWORD)strtoul(buffer, NULL, 10);
2212 /******************************************************************************
2213 * OleMetaFilePictFromIconAndLabel (OLE2.56)
2215 * Returns a global memory handle to a metafile which contains the icon and
2217 * I guess the result of that should look somehow like desktop icons.
2218 * If no hIcon is given, we load the icon via lpszSourceFile and iIconIndex.
2219 * This code might be wrong at some places.
2221 HGLOBAL16 WINAPI OleMetaFilePictFromIconAndLabel16(
2223 LPCOLESTR16 lpszLabel,
2224 LPCOLESTR16 lpszSourceFile,
2231 FIXME("(%04x, '%s', '%s', %d): incorrect metrics, please try to correct them !\n\n\n", hIcon, lpszLabel, lpszSourceFile, iIconIndex);
2234 if (lpszSourceFile) {
2235 HINSTANCE16 hInstance = LoadLibrary16(lpszSourceFile);
2237 /* load the icon at index from lpszSourceFile */
2238 hIcon = HICON_16(LoadIconA(HINSTANCE_32(hInstance), (LPCSTR)(DWORD)iIconIndex));
2239 FreeLibrary16(hInstance);
2244 hdc = CreateMetaFileA(NULL);
2245 DrawIcon(hdc, 0, 0, HICON_32(hIcon)); /* FIXME */
2246 TextOutA(hdc, 0, 0, lpszLabel, 1); /* FIXME */
2247 hmf = GlobalAlloc16(0, sizeof(METAFILEPICT16));
2248 mf = (METAFILEPICT16 *)GlobalLock16(hmf);
2249 mf->mm = MM_ANISOTROPIC;
2250 mf->xExt = 20; /* FIXME: bogus */
2251 mf->yExt = 20; /* dito */
2252 mf->hMF = CloseMetaFile16(HDC_16(hdc));
2256 /******************************************************************************
2257 * DllDebugObjectRPCHook (OLE32.62)
2258 * turns on and off internal debugging, pointer is only used on macintosh
2261 BOOL WINAPI DllDebugObjectRPCHook(BOOL b, void *dummy)