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
41 #include "wine/obj_clientserver.h"
42 #include "wine/winbase16.h"
43 #include "wine/wingdi16.h"
44 #include "wine/winuser16.h"
45 #include "ole32_main.h"
47 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(ole);
50 WINE_DECLARE_DEBUG_CHANNEL(accel);
52 #define HICON_16(h32) (LOWORD(h32))
53 #define HICON_32(h16) ((HICON)(ULONG_PTR)(h16))
54 #define HINSTANCE_32(h16) ((HINSTANCE)(ULONG_PTR)(h16))
56 /******************************************************************************
57 * These are static/global variables and internal data structures that the
58 * OLE module uses to maintain it's state.
60 typedef struct tagDropTargetNode
63 IDropTarget* dropTarget;
64 struct tagDropTargetNode* prevDropTarget;
65 struct tagDropTargetNode* nextDropTarget;
68 typedef struct tagTrackerWindowInfo
70 IDataObject* dataObject;
71 IDropSource* dropSource;
78 HWND curDragTargetHWND;
79 IDropTarget* curDragTarget;
82 typedef struct tagOleMenuDescriptor /* OleMenuDescriptor */
84 HWND hwndFrame; /* The containers frame window */
85 HWND hwndActiveObject; /* The active objects window */
86 OLEMENUGROUPWIDTHS mgw; /* OLE menu group widths for the shared menu */
87 HMENU hmenuCombined; /* The combined menu */
88 BOOL bIsServerItem; /* True if the currently open popup belongs to the server */
91 typedef struct tagOleMenuHookItem /* OleMenu hook item in per thread hook list */
93 DWORD tid; /* Thread Id */
94 HANDLE hHeap; /* Heap this is allocated from */
95 HHOOK GetMsg_hHook; /* message hook for WH_GETMESSAGE */
96 HHOOK CallWndProc_hHook; /* message hook for WH_CALLWNDPROC */
97 struct tagOleMenuHookItem *next;
100 static OleMenuHookItem *hook_list;
103 * This is the lock count on the OLE library. It is controlled by the
104 * OLEInitialize/OLEUninitialize methods.
106 static ULONG OLE_moduleLockCount = 0;
109 * Name of our registered window class.
111 static const char OLEDD_DRAGTRACKERCLASS[] = "WineDragDropTracker32";
114 * This is the head of the Drop target container.
116 static DropTargetNode* targetListHead = NULL;
118 /******************************************************************************
119 * These are the prototypes of miscelaneous utility methods
121 static void OLEUTL_ReadRegistryDWORDValue(HKEY regKey, DWORD* pdwValue);
123 /******************************************************************************
124 * These are the prototypes of the utility methods used to manage a shared menu
126 static void OLEMenu_Initialize();
127 static void OLEMenu_UnInitialize();
128 BOOL OLEMenu_InstallHooks( DWORD tid );
129 BOOL OLEMenu_UnInstallHooks( DWORD tid );
130 OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid );
131 static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos );
132 BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor );
133 LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam);
134 LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam);
136 /******************************************************************************
137 * These are the prototypes of the OLE Clipboard initialization methods (in clipboard.c)
139 void OLEClipbrd_UnInitialize();
140 void OLEClipbrd_Initialize();
142 /******************************************************************************
143 * These are the prototypes of the utility methods used for OLE Drag n Drop
145 static void OLEDD_Initialize();
146 static void OLEDD_UnInitialize();
147 static void OLEDD_InsertDropTarget(
148 DropTargetNode* nodeToAdd);
149 static DropTargetNode* OLEDD_ExtractDropTarget(
151 static DropTargetNode* OLEDD_FindDropTarget(
153 static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
158 static void OLEDD_TrackMouseMove(
159 TrackerWindowInfo* trackerInfo,
162 static void OLEDD_TrackStateChange(
163 TrackerWindowInfo* trackerInfo,
166 static DWORD OLEDD_GetButtonState();
169 /******************************************************************************
170 * OleBuildVersion [OLE2.1]
171 * OleBuildVersion [OLE32.84]
173 DWORD WINAPI OleBuildVersion(void)
175 TRACE("Returning version %d, build %d.\n", rmm, rup);
176 return (rmm<<16)+rup;
179 /***********************************************************************
180 * OleInitialize (OLE2.2)
181 * OleInitialize (OLE32.108)
183 HRESULT WINAPI OleInitialize(LPVOID reserved)
187 TRACE("(%p)\n", reserved);
190 * The first duty of the OleInitialize is to initialize the COM libraries.
192 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
195 * If the CoInitializeEx call failed, the OLE libraries can't be
202 * Then, it has to initialize the OLE specific modules.
206 * Object linking and Embedding
207 * In-place activation
209 if (OLE_moduleLockCount==0)
212 * Initialize the libraries.
214 TRACE("() - Initializing the OLE libraries\n");
219 OLEClipbrd_Initialize();
229 OLEMenu_Initialize();
233 * Then, we increase the lock count on the OLE module.
235 OLE_moduleLockCount++;
240 /******************************************************************************
241 * CoGetCurrentProcess [COMPOBJ.34]
242 * CoGetCurrentProcess [OLE32.18]
245 * Is DWORD really the correct return type for this function?
247 DWORD WINAPI CoGetCurrentProcess(void)
249 return GetCurrentProcessId();
252 /******************************************************************************
253 * OleUninitialize [OLE2.3]
254 * OleUninitialize [OLE32.131]
256 void WINAPI OleUninitialize(void)
261 * Decrease the lock count on the OLE module.
263 OLE_moduleLockCount--;
266 * If we hit the bottom of the lock stack, free the libraries.
268 if (OLE_moduleLockCount==0)
271 * Actually free the libraries.
273 TRACE("() - Freeing the last reference count\n");
278 OLEClipbrd_UnInitialize();
283 OLEDD_UnInitialize();
288 OLEMenu_UnInitialize();
292 * Then, uninitialize the COM libraries.
297 /******************************************************************************
298 * CoRegisterMessageFilter [OLE32.38]
300 HRESULT WINAPI CoRegisterMessageFilter(
301 LPMESSAGEFILTER lpMessageFilter, /* [in] Pointer to interface */
302 LPMESSAGEFILTER *lplpMessageFilter /* [out] Indirect pointer to prior instance if non-NULL */
305 if (lplpMessageFilter) {
306 *lplpMessageFilter = NULL;
311 /******************************************************************************
312 * OleInitializeWOW [OLE32.109]
314 HRESULT WINAPI OleInitializeWOW(DWORD x) {
315 FIXME("(0x%08lx),stub!\n",x);
319 /***********************************************************************
320 * RegisterDragDrop (OLE2.35)
322 HRESULT WINAPI RegisterDragDrop16(
324 LPDROPTARGET pDropTarget
326 FIXME("(0x%04x,%p),stub!\n",hwnd,pDropTarget);
330 /***********************************************************************
331 * RegisterDragDrop (OLE32.139)
333 HRESULT WINAPI RegisterDragDrop(
335 LPDROPTARGET pDropTarget)
337 DropTargetNode* dropTargetInfo;
339 TRACE("(%p,%p)\n", hwnd, pDropTarget);
342 * First, check if the window is already registered.
344 dropTargetInfo = OLEDD_FindDropTarget(hwnd);
346 if (dropTargetInfo!=NULL)
347 return DRAGDROP_E_ALREADYREGISTERED;
350 * If it's not there, we can add it. We first create a node for it.
352 dropTargetInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(DropTargetNode));
354 if (dropTargetInfo==NULL)
355 return E_OUTOFMEMORY;
357 dropTargetInfo->hwndTarget = hwnd;
358 dropTargetInfo->prevDropTarget = NULL;
359 dropTargetInfo->nextDropTarget = NULL;
362 * Don't forget that this is an interface pointer, need to nail it down since
363 * we keep a copy of it.
365 dropTargetInfo->dropTarget = pDropTarget;
366 IDropTarget_AddRef(dropTargetInfo->dropTarget);
368 OLEDD_InsertDropTarget(dropTargetInfo);
373 /***********************************************************************
374 * RevokeDragDrop (OLE2.36)
376 HRESULT WINAPI RevokeDragDrop16(
379 FIXME("(0x%04x),stub!\n",hwnd);
383 /***********************************************************************
384 * RevokeDragDrop (OLE32.141)
386 HRESULT WINAPI RevokeDragDrop(
389 DropTargetNode* dropTargetInfo;
391 TRACE("(%p)\n", hwnd);
394 * First, check if the window is already registered.
396 dropTargetInfo = OLEDD_ExtractDropTarget(hwnd);
399 * If it ain't in there, it's an error.
401 if (dropTargetInfo==NULL)
402 return DRAGDROP_E_NOTREGISTERED;
405 * If it's in there, clean-up it's used memory and
408 IDropTarget_Release(dropTargetInfo->dropTarget);
409 HeapFree(GetProcessHeap(), 0, dropTargetInfo);
414 /***********************************************************************
415 * OleRegGetUserType (OLE32.122)
417 * This implementation of OleRegGetUserType ignores the dwFormOfType
418 * parameter and always returns the full name of the object. This is
419 * not too bad since this is the case for many objects because of the
420 * way they are registered.
422 HRESULT WINAPI OleRegGetUserType(
425 LPOLESTR* pszUserType)
435 * Initialize the out parameter.
440 * Build the key name we're looking for
442 sprintf( keyName, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\",
443 clsid->Data1, clsid->Data2, clsid->Data3,
444 clsid->Data4[0], clsid->Data4[1], clsid->Data4[2], clsid->Data4[3],
445 clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7] );
447 TRACE("(%s, %ld, %p)\n", keyName, dwFormOfType, pszUserType);
450 * Open the class id Key
452 hres = RegOpenKeyA(HKEY_CLASSES_ROOT,
456 if (hres != ERROR_SUCCESS)
457 return REGDB_E_CLASSNOTREG;
460 * Retrieve the size of the name string.
464 hres = RegQueryValueExA(clsidKey,
471 if (hres!=ERROR_SUCCESS)
473 RegCloseKey(clsidKey);
474 return REGDB_E_READREGDB;
478 * Allocate a buffer for the registry value.
480 *pszUserType = CoTaskMemAlloc(cbData*2);
482 if (*pszUserType==NULL)
484 RegCloseKey(clsidKey);
485 return E_OUTOFMEMORY;
488 buffer = HeapAlloc(GetProcessHeap(), 0, cbData);
492 RegCloseKey(clsidKey);
493 CoTaskMemFree(*pszUserType);
495 return E_OUTOFMEMORY;
498 hres = RegQueryValueExA(clsidKey,
505 RegCloseKey(clsidKey);
508 if (hres!=ERROR_SUCCESS)
510 CoTaskMemFree(*pszUserType);
513 retVal = REGDB_E_READREGDB;
517 MultiByteToWideChar( CP_ACP, 0, buffer, -1, *pszUserType, cbData /*FIXME*/ );
520 HeapFree(GetProcessHeap(), 0, buffer);
525 /***********************************************************************
526 * DoDragDrop [OLE32.65]
528 HRESULT WINAPI DoDragDrop (
529 IDataObject *pDataObject, /* [in] ptr to the data obj */
530 IDropSource* pDropSource, /* [in] ptr to the source obj */
531 DWORD dwOKEffect, /* [in] effects allowed by the source */
532 DWORD *pdwEffect) /* [out] ptr to effects of the source */
534 TrackerWindowInfo trackerInfo;
535 HWND hwndTrackWindow;
538 TRACE("(DataObject %p, DropSource %p)\n", pDataObject, pDropSource);
541 * Setup the drag n drop tracking window.
543 trackerInfo.dataObject = pDataObject;
544 trackerInfo.dropSource = pDropSource;
545 trackerInfo.dwOKEffect = dwOKEffect;
546 trackerInfo.pdwEffect = pdwEffect;
547 trackerInfo.trackingDone = FALSE;
548 trackerInfo.escPressed = FALSE;
549 trackerInfo.curDragTargetHWND = 0;
550 trackerInfo.curDragTarget = 0;
552 hwndTrackWindow = CreateWindowA(OLEDD_DRAGTRACKERCLASS,
555 CW_USEDEFAULT, CW_USEDEFAULT,
556 CW_USEDEFAULT, CW_USEDEFAULT,
560 (LPVOID)&trackerInfo);
562 if (hwndTrackWindow!=0)
565 * Capture the mouse input
567 SetCapture(hwndTrackWindow);
570 * Pump messages. All mouse input should go the the capture window.
572 while (!trackerInfo.trackingDone && GetMessageA(&msg, 0, 0, 0) )
574 if ( (msg.message >= WM_KEYFIRST) &&
575 (msg.message <= WM_KEYLAST) )
578 * When keyboard messages are sent to windows on this thread, we
579 * want to ignore notify the drop source that the state changed.
580 * in the case of the Escape key, we also notify the drop source
581 * we give it a special meaning.
583 if ( (msg.message==WM_KEYDOWN) &&
584 (msg.wParam==VK_ESCAPE) )
586 trackerInfo.escPressed = TRUE;
590 * Notify the drop source.
592 OLEDD_TrackStateChange(&trackerInfo,
594 OLEDD_GetButtonState());
599 * Dispatch the messages only when it's not a keyboard message.
601 DispatchMessageA(&msg);
606 * Destroy the temporary window.
608 DestroyWindow(hwndTrackWindow);
610 return trackerInfo.returnValue;
616 /***********************************************************************
617 * OleQueryLinkFromData [OLE32.118]
619 HRESULT WINAPI OleQueryLinkFromData(
620 IDataObject* pSrcDataObject)
622 FIXME("(%p),stub!\n", pSrcDataObject);
626 /***********************************************************************
627 * OleRegGetMiscStatus [OLE32.121]
629 HRESULT WINAPI OleRegGetMiscStatus(
641 * Initialize the out parameter.
646 * Build the key name we're looking for
648 sprintf( keyName, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\",
649 clsid->Data1, clsid->Data2, clsid->Data3,
650 clsid->Data4[0], clsid->Data4[1], clsid->Data4[2], clsid->Data4[3],
651 clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7] );
653 TRACE("(%s, %ld, %p)\n", keyName, dwAspect, pdwStatus);
656 * Open the class id Key
658 result = RegOpenKeyA(HKEY_CLASSES_ROOT,
662 if (result != ERROR_SUCCESS)
663 return REGDB_E_CLASSNOTREG;
668 result = RegOpenKeyA(clsidKey,
673 if (result != ERROR_SUCCESS)
675 RegCloseKey(clsidKey);
676 return REGDB_E_READREGDB;
680 * Read the default value
682 OLEUTL_ReadRegistryDWORDValue(miscStatusKey, pdwStatus);
685 * Open the key specific to the requested aspect.
687 sprintf(keyName, "%ld", dwAspect);
689 result = RegOpenKeyA(miscStatusKey,
693 if (result == ERROR_SUCCESS)
695 OLEUTL_ReadRegistryDWORDValue(aspectKey, pdwStatus);
696 RegCloseKey(aspectKey);
702 RegCloseKey(miscStatusKey);
703 RegCloseKey(clsidKey);
708 /******************************************************************************
709 * OleSetContainedObject [OLE32.128]
711 HRESULT WINAPI OleSetContainedObject(
715 IRunnableObject* runnable = NULL;
718 TRACE("(%p,%x), stub!\n", pUnknown, fContained);
720 hres = IUnknown_QueryInterface(pUnknown,
721 &IID_IRunnableObject,
726 hres = IRunnableObject_SetContainedObject(runnable, fContained);
728 IRunnableObject_Release(runnable);
736 /******************************************************************************
737 * OleLoad [OLE32.112]
739 HRESULT WINAPI OleLoad(
742 LPOLECLIENTSITE pClientSite,
745 IPersistStorage* persistStorage = NULL;
746 IOleObject* oleObject = NULL;
750 TRACE("(%p,%p,%p,%p)\n", pStg, riid, pClientSite, ppvObj);
753 * TODO, Conversion ... OleDoAutoConvert
757 * Get the class ID for the object.
759 hres = IStorage_Stat(pStg, &storageInfo, STATFLAG_NONAME);
762 * Now, try and create the handler for the object
764 hres = CoCreateInstance(&storageInfo.clsid,
766 CLSCTX_INPROC_HANDLER,
771 * If that fails, as it will most times, load the default
776 hres = OleCreateDefaultHandler(&storageInfo.clsid,
783 * If we couldn't find a handler... this is bad. Abort the whole thing.
789 * Inform the new object of it's client site.
791 hres = IOleObject_SetClientSite(oleObject, pClientSite);
794 * Initialize the object with it's IPersistStorage interface.
796 hres = IOleObject_QueryInterface(oleObject,
797 &IID_IPersistStorage,
798 (void**)&persistStorage);
802 IPersistStorage_Load(persistStorage, pStg);
804 IPersistStorage_Release(persistStorage);
805 persistStorage = NULL;
809 * Return the requested interface to the caller.
811 hres = IOleObject_QueryInterface(oleObject, riid, ppvObj);
814 * Cleanup interfaces used internally
816 IOleObject_Release(oleObject);
821 /***********************************************************************
822 * OleSave [OLE32.124]
824 HRESULT WINAPI OleSave(
825 LPPERSISTSTORAGE pPS,
832 TRACE("(%p,%p,%x)\n", pPS, pStg, fSameAsLoad);
835 * First, we transfer the class ID (if available)
837 hres = IPersistStorage_GetClassID(pPS, &objectClass);
841 WriteClassStg(pStg, &objectClass);
845 * Then, we ask the object to save itself to the
846 * storage. If it is successful, we commit the storage.
848 hres = IPersistStorage_Save(pPS, pStg, fSameAsLoad);
852 IStorage_Commit(pStg,
860 /******************************************************************************
861 * OleLockRunning [OLE32.114]
863 HRESULT WINAPI OleLockRunning(LPUNKNOWN pUnknown, BOOL fLock, BOOL fLastUnlockCloses)
865 IRunnableObject* runnable = NULL;
868 TRACE("(%p,%x,%x)\n", pUnknown, fLock, fLastUnlockCloses);
870 hres = IUnknown_QueryInterface(pUnknown,
871 &IID_IRunnableObject,
876 hres = IRunnableObject_LockRunning(runnable, fLock, fLastUnlockCloses);
878 IRunnableObject_Release(runnable);
887 /**************************************************************************
888 * Internal methods to manage the shared OLE menu in response to the
889 * OLE***MenuDescriptor API
893 * OLEMenu_Initialize()
895 * Initializes the OLEMENU data structures.
897 static void OLEMenu_Initialize()
902 * OLEMenu_UnInitialize()
904 * Releases the OLEMENU data structures.
906 static void OLEMenu_UnInitialize()
910 /*************************************************************************
911 * OLEMenu_InstallHooks
912 * Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
914 * RETURNS: TRUE if message hooks were succesfully installed
917 BOOL OLEMenu_InstallHooks( DWORD tid )
919 OleMenuHookItem *pHookItem = NULL;
921 /* Create an entry for the hook table */
922 if ( !(pHookItem = HeapAlloc(GetProcessHeap(), 0,
923 sizeof(OleMenuHookItem)) ) )
926 pHookItem->tid = tid;
927 pHookItem->hHeap = GetProcessHeap();
929 /* Install a thread scope message hook for WH_GETMESSAGE */
930 pHookItem->GetMsg_hHook = SetWindowsHookExA( WH_GETMESSAGE, OLEMenu_GetMsgProc,
931 0, GetCurrentThreadId() );
932 if ( !pHookItem->GetMsg_hHook )
935 /* Install a thread scope message hook for WH_CALLWNDPROC */
936 pHookItem->CallWndProc_hHook = SetWindowsHookExA( WH_CALLWNDPROC, OLEMenu_CallWndProc,
937 0, GetCurrentThreadId() );
938 if ( !pHookItem->CallWndProc_hHook )
941 /* Insert the hook table entry */
942 pHookItem->next = hook_list;
943 hook_list = pHookItem;
948 /* Unhook any hooks */
949 if ( pHookItem->GetMsg_hHook )
950 UnhookWindowsHookEx( pHookItem->GetMsg_hHook );
951 if ( pHookItem->CallWndProc_hHook )
952 UnhookWindowsHookEx( pHookItem->CallWndProc_hHook );
953 /* Release the hook table entry */
954 HeapFree(pHookItem->hHeap, 0, pHookItem );
959 /*************************************************************************
960 * OLEMenu_UnInstallHooks
961 * UnInstall thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
963 * RETURNS: TRUE if message hooks were succesfully installed
966 BOOL OLEMenu_UnInstallHooks( DWORD tid )
968 OleMenuHookItem *pHookItem = NULL;
969 OleMenuHookItem **ppHook = &hook_list;
973 if ((*ppHook)->tid == tid)
976 *ppHook = pHookItem->next;
979 ppHook = &(*ppHook)->next;
981 if (!pHookItem) return FALSE;
983 /* Uninstall the hooks installed for this thread */
984 if ( !UnhookWindowsHookEx( pHookItem->GetMsg_hHook ) )
986 if ( !UnhookWindowsHookEx( pHookItem->CallWndProc_hHook ) )
989 /* Release the hook table entry */
990 HeapFree(pHookItem->hHeap, 0, pHookItem );
995 /* Release the hook table entry */
997 HeapFree(pHookItem->hHeap, 0, pHookItem );
1002 /*************************************************************************
1003 * OLEMenu_IsHookInstalled
1004 * Tests if OLEMenu hooks have been installed for a thread
1006 * RETURNS: The pointer and index of the hook table entry for the tid
1007 * NULL and -1 for the index if no hooks were installed for this thread
1009 OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid )
1011 OleMenuHookItem *pHookItem = NULL;
1013 /* Do a simple linear search for an entry whose tid matches ours.
1014 * We really need a map but efficiency is not a concern here. */
1015 for (pHookItem = hook_list; pHookItem; pHookItem = pHookItem->next)
1017 if ( tid == pHookItem->tid )
1024 /***********************************************************************
1025 * OLEMenu_FindMainMenuIndex
1027 * Used by OLEMenu API to find the top level group a menu item belongs to.
1028 * On success pnPos contains the index of the item in the top level menu group
1030 * RETURNS: TRUE if the ID was found, FALSE on failure
1032 static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos )
1036 nItems = GetMenuItemCount( hMainMenu );
1038 for (i = 0; i < nItems; i++)
1042 /* Is the current item a submenu? */
1043 if ( (hsubmenu = GetSubMenu(hMainMenu, i)) )
1045 /* If the handle is the same we're done */
1046 if ( hsubmenu == hPopupMenu )
1052 /* Recursively search without updating pnPos */
1053 else if ( OLEMenu_FindMainMenuIndex( hsubmenu, hPopupMenu, NULL ) )
1065 /***********************************************************************
1066 * OLEMenu_SetIsServerMenu
1068 * Checks whether a popup menu belongs to a shared menu group which is
1069 * owned by the server, and sets the menu descriptor state accordingly.
1070 * All menu messages from these groups should be routed to the server.
1072 * RETURNS: TRUE if the popup menu is part of a server owned group
1073 * FASE if the popup menu is part of a container owned group
1075 BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor )
1077 UINT nPos = 0, nWidth, i;
1079 pOleMenuDescriptor->bIsServerItem = FALSE;
1081 /* Don't bother searching if the popup is the combined menu itself */
1082 if ( hmenu == pOleMenuDescriptor->hmenuCombined )
1085 /* Find the menu item index in the shared OLE menu that this item belongs to */
1086 if ( !OLEMenu_FindMainMenuIndex( pOleMenuDescriptor->hmenuCombined, hmenu, &nPos ) )
1089 /* The group widths array has counts for the number of elements
1090 * in the groups File, Edit, Container, Object, Window, Help.
1091 * The Edit, Object & Help groups belong to the server object
1092 * and the other three belong to the container.
1093 * Loop through the group widths and locate the group we are a member of.
1095 for ( i = 0, nWidth = 0; i < 6; i++ )
1097 nWidth += pOleMenuDescriptor->mgw.width[i];
1098 if ( nPos < nWidth )
1100 /* Odd elements are server menu widths */
1101 pOleMenuDescriptor->bIsServerItem = (i%2) ? TRUE : FALSE;
1106 return pOleMenuDescriptor->bIsServerItem;
1109 /*************************************************************************
1110 * OLEMenu_CallWndProc
1111 * Thread scope WH_CALLWNDPROC hook proc filter function (callback)
1112 * This is invoked from a message hook installed in OleSetMenuDescriptor.
1114 LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam)
1116 LPCWPSTRUCT pMsg = NULL;
1117 HOLEMENU hOleMenu = 0;
1118 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1119 OleMenuHookItem *pHookItem = NULL;
1122 TRACE("%i, %04x, %08x\n", code, wParam, (unsigned)lParam );
1124 /* Check if we're being asked to process the message */
1125 if ( HC_ACTION != code )
1128 /* Retrieve the current message being dispatched from lParam */
1129 pMsg = (LPCWPSTRUCT)lParam;
1131 /* Check if the message is destined for a window we are interested in:
1132 * If the window has an OLEMenu property we may need to dispatch
1133 * the menu message to its active objects window instead. */
1135 hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" );
1139 /* Get the menu descriptor */
1140 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1141 if ( !pOleMenuDescriptor ) /* Bad descriptor! */
1144 /* Process menu messages */
1145 switch( pMsg->message )
1149 /* Reset the menu descriptor state */
1150 pOleMenuDescriptor->bIsServerItem = FALSE;
1152 /* Send this message to the server as well */
1153 SendMessageA( pOleMenuDescriptor->hwndActiveObject,
1154 pMsg->message, pMsg->wParam, pMsg->lParam );
1158 case WM_INITMENUPOPUP:
1160 /* Save the state for whether this is a server owned menu */
1161 OLEMenu_SetIsServerMenu( (HMENU)pMsg->wParam, pOleMenuDescriptor );
1167 fuFlags = HIWORD(pMsg->wParam); /* Get flags */
1168 if ( fuFlags & MF_SYSMENU )
1171 /* Save the state for whether this is a server owned popup menu */
1172 else if ( fuFlags & MF_POPUP )
1173 OLEMenu_SetIsServerMenu( (HMENU)pMsg->lParam, pOleMenuDescriptor );
1180 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) pMsg->lParam;
1181 if ( pMsg->wParam != 0 || lpdis->CtlType != ODT_MENU )
1182 goto NEXTHOOK; /* Not a menu message */
1191 /* If the message was for the server dispatch it accordingly */
1192 if ( pOleMenuDescriptor->bIsServerItem )
1194 SendMessageA( pOleMenuDescriptor->hwndActiveObject,
1195 pMsg->message, pMsg->wParam, pMsg->lParam );
1199 if ( pOleMenuDescriptor )
1200 GlobalUnlock( hOleMenu );
1202 /* Lookup the hook item for the current thread */
1203 if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) )
1205 /* This should never fail!! */
1206 WARN("could not retrieve hHook for current thread!\n" );
1210 /* Pass on the message to the next hooker */
1211 return CallNextHookEx( pHookItem->CallWndProc_hHook, code, wParam, lParam );
1214 /*************************************************************************
1215 * OLEMenu_GetMsgProc
1216 * Thread scope WH_GETMESSAGE hook proc filter function (callback)
1217 * This is invoked from a message hook installed in OleSetMenuDescriptor.
1219 LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam)
1222 HOLEMENU hOleMenu = 0;
1223 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1224 OleMenuHookItem *pHookItem = NULL;
1227 TRACE("%i, %04x, %08x\n", code, wParam, (unsigned)lParam );
1229 /* Check if we're being asked to process a messages */
1230 if ( HC_ACTION != code )
1233 /* Retrieve the current message being dispatched from lParam */
1234 pMsg = (LPMSG)lParam;
1236 /* Check if the message is destined for a window we are interested in:
1237 * If the window has an OLEMenu property we may need to dispatch
1238 * the menu message to its active objects window instead. */
1240 hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" );
1244 /* Process menu messages */
1245 switch( pMsg->message )
1249 wCode = HIWORD(pMsg->wParam); /* Get notification code */
1251 goto NEXTHOOK; /* Not a menu message */
1258 /* Get the menu descriptor */
1259 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1260 if ( !pOleMenuDescriptor ) /* Bad descriptor! */
1263 /* If the message was for the server dispatch it accordingly */
1264 if ( pOleMenuDescriptor->bIsServerItem )
1266 /* Change the hWnd in the message to the active objects hWnd.
1267 * The message loop which reads this message will automatically
1268 * dispatch it to the embedded objects window. */
1269 pMsg->hwnd = pOleMenuDescriptor->hwndActiveObject;
1273 if ( pOleMenuDescriptor )
1274 GlobalUnlock( hOleMenu );
1276 /* Lookup the hook item for the current thread */
1277 if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) )
1279 /* This should never fail!! */
1280 WARN("could not retrieve hHook for current thread!\n" );
1284 /* Pass on the message to the next hooker */
1285 return CallNextHookEx( pHookItem->GetMsg_hHook, code, wParam, lParam );
1288 /***********************************************************************
1289 * OleCreateMenuDescriptor [OLE32.97]
1290 * Creates an OLE menu descriptor for OLE to use when dispatching
1291 * menu messages and commands.
1294 * hmenuCombined - Handle to the objects combined menu
1295 * lpMenuWidths - Pointer to array of 6 LONG's indicating menus per group
1298 HOLEMENU WINAPI OleCreateMenuDescriptor(
1299 HMENU hmenuCombined,
1300 LPOLEMENUGROUPWIDTHS lpMenuWidths)
1303 OleMenuDescriptor *pOleMenuDescriptor;
1306 if ( !hmenuCombined || !lpMenuWidths )
1309 /* Create an OLE menu descriptor */
1310 if ( !(hOleMenu = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
1311 sizeof(OleMenuDescriptor) ) ) )
1314 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1315 if ( !pOleMenuDescriptor )
1318 /* Initialize menu group widths and hmenu */
1319 for ( i = 0; i < 6; i++ )
1320 pOleMenuDescriptor->mgw.width[i] = lpMenuWidths->width[i];
1322 pOleMenuDescriptor->hmenuCombined = hmenuCombined;
1323 pOleMenuDescriptor->bIsServerItem = FALSE;
1324 GlobalUnlock( hOleMenu );
1329 /***********************************************************************
1330 * OleDestroyMenuDescriptor [OLE32.99]
1331 * Destroy the shared menu descriptor
1333 HRESULT WINAPI OleDestroyMenuDescriptor(
1334 HOLEMENU hmenuDescriptor)
1336 if ( hmenuDescriptor )
1337 GlobalFree( hmenuDescriptor );
1341 /***********************************************************************
1342 * OleSetMenuDescriptor [OLE32.129]
1343 * Installs or removes OLE dispatching code for the containers frame window
1344 * FIXME: The lpFrame and lpActiveObject parameters are currently ignored
1345 * OLE should install context sensitive help F1 filtering for the app when
1346 * these are non null.
1349 * hOleMenu Handle to composite menu descriptor
1350 * hwndFrame Handle to containers frame window
1351 * hwndActiveObject Handle to objects in-place activation window
1352 * lpFrame Pointer to IOleInPlaceFrame on containers window
1353 * lpActiveObject Pointer to IOleInPlaceActiveObject on active in-place object
1356 * S_OK - menu installed correctly
1357 * E_FAIL, E_INVALIDARG, E_UNEXPECTED - failure
1359 HRESULT WINAPI OleSetMenuDescriptor(
1362 HWND hwndActiveObject,
1363 LPOLEINPLACEFRAME lpFrame,
1364 LPOLEINPLACEACTIVEOBJECT lpActiveObject)
1366 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1369 if ( !hwndFrame || (hOleMenu && !hwndActiveObject) )
1370 return E_INVALIDARG;
1372 if ( lpFrame || lpActiveObject )
1374 FIXME("(%x, %p, %p, %p, %p), Context sensitive help filtering not implemented!\n",
1375 (unsigned int)hOleMenu,
1382 /* Set up a message hook to intercept the containers frame window messages.
1383 * The message filter is responsible for dispatching menu messages from the
1384 * shared menu which are intended for the object.
1387 if ( hOleMenu ) /* Want to install dispatching code */
1389 /* If OLEMenu hooks are already installed for this thread, fail
1390 * Note: This effectively means that OleSetMenuDescriptor cannot
1391 * be called twice in succession on the same frame window
1392 * without first calling it with a null hOleMenu to uninstall */
1393 if ( OLEMenu_IsHookInstalled( GetCurrentThreadId() ) )
1396 /* Get the menu descriptor */
1397 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1398 if ( !pOleMenuDescriptor )
1399 return E_UNEXPECTED;
1401 /* Update the menu descriptor */
1402 pOleMenuDescriptor->hwndFrame = hwndFrame;
1403 pOleMenuDescriptor->hwndActiveObject = hwndActiveObject;
1405 GlobalUnlock( hOleMenu );
1406 pOleMenuDescriptor = NULL;
1408 /* Add a menu descriptor windows property to the frame window */
1409 SetPropA( hwndFrame, "PROP_OLEMenuDescriptor", hOleMenu );
1411 /* Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC */
1412 if ( !OLEMenu_InstallHooks( GetCurrentThreadId() ) )
1415 else /* Want to uninstall dispatching code */
1417 /* Uninstall the hooks */
1418 if ( !OLEMenu_UnInstallHooks( GetCurrentThreadId() ) )
1421 /* Remove the menu descriptor property from the frame window */
1422 RemovePropA( hwndFrame, "PROP_OLEMenuDescriptor" );
1428 /******************************************************************************
1429 * IsAccelerator [OLE32.75]
1430 * Mostly copied from controls/menu.c TranslateAccelerator implementation
1432 BOOL WINAPI IsAccelerator(HACCEL hAccel, int cAccelEntries, LPMSG lpMsg, WORD* lpwCmd)
1435 LPACCEL16 lpAccelTbl;
1438 if(!lpMsg) return FALSE;
1439 if (!hAccel || !(lpAccelTbl = (LPACCEL16)LockResource16(HACCEL_16(hAccel))))
1441 WARN_(accel)("invalid accel handle=%p\n", hAccel);
1444 if((lpMsg->message != WM_KEYDOWN &&
1445 lpMsg->message != WM_KEYUP &&
1446 lpMsg->message != WM_SYSKEYDOWN &&
1447 lpMsg->message != WM_SYSKEYUP &&
1448 lpMsg->message != WM_CHAR)) return FALSE;
1450 TRACE_(accel)("hAccel=%p, cAccelEntries=%d,"
1451 "msg->hwnd=%p, msg->message=%04x, wParam=%08x, lParam=%08lx\n",
1452 hAccel, cAccelEntries,
1453 lpMsg->hwnd, lpMsg->message, lpMsg->wParam, lpMsg->lParam);
1454 for(i = 0; i < cAccelEntries; i++)
1456 if(lpAccelTbl[i].key != lpMsg->wParam)
1459 if(lpMsg->message == WM_CHAR)
1461 if(!(lpAccelTbl[i].fVirt & FALT) && !(lpAccelTbl[i].fVirt & FVIRTKEY))
1463 TRACE_(accel)("found accel for WM_CHAR: ('%c')\n", lpMsg->wParam & 0xff);
1469 if(lpAccelTbl[i].fVirt & FVIRTKEY)
1472 TRACE_(accel)("found accel for virt_key %04x (scan %04x)\n",
1473 lpMsg->wParam, HIWORD(lpMsg->lParam) & 0xff);
1474 if(GetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT;
1475 if(GetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL;
1476 if(GetKeyState(VK_MENU) & 0x8000) mask |= FALT;
1477 if(mask == (lpAccelTbl[i].fVirt & (FSHIFT | FCONTROL | FALT))) goto found;
1478 TRACE_(accel)("incorrect SHIFT/CTRL/ALT-state\n");
1482 if(!(lpMsg->lParam & 0x01000000)) /* no special_key */
1484 if((lpAccelTbl[i].fVirt & FALT) && (lpMsg->lParam & 0x20000000))
1485 { /* ^^ ALT pressed */
1486 TRACE_(accel)("found accel for Alt-%c\n", lpMsg->wParam & 0xff);
1494 WARN_(accel)("couldn't translate accelerator key\n");
1498 if(lpwCmd) *lpwCmd = lpAccelTbl[i].cmd;
1502 /***********************************************************************
1503 * ReleaseStgMedium [OLE32.140]
1505 void WINAPI ReleaseStgMedium(
1508 switch (pmedium->tymed)
1512 if ( (pmedium->pUnkForRelease==0) &&
1513 (pmedium->u.hGlobal!=0) )
1514 GlobalFree(pmedium->u.hGlobal);
1516 pmedium->u.hGlobal = 0;
1521 if (pmedium->u.lpszFileName!=0)
1523 if (pmedium->pUnkForRelease==0)
1525 DeleteFileW(pmedium->u.lpszFileName);
1528 CoTaskMemFree(pmedium->u.lpszFileName);
1531 pmedium->u.lpszFileName = 0;
1536 if (pmedium->u.pstm!=0)
1538 IStream_Release(pmedium->u.pstm);
1541 pmedium->u.pstm = 0;
1544 case TYMED_ISTORAGE:
1546 if (pmedium->u.pstg!=0)
1548 IStorage_Release(pmedium->u.pstg);
1551 pmedium->u.pstg = 0;
1556 if ( (pmedium->pUnkForRelease==0) &&
1557 (pmedium->u.hGlobal!=0) )
1558 DeleteObject(pmedium->u.hGlobal);
1560 pmedium->u.hGlobal = 0;
1565 if ( (pmedium->pUnkForRelease==0) &&
1566 (pmedium->u.hMetaFilePict!=0) )
1568 LPMETAFILEPICT pMP = GlobalLock(pmedium->u.hGlobal);
1569 DeleteMetaFile(pMP->hMF);
1570 GlobalUnlock(pmedium->u.hGlobal);
1571 GlobalFree(pmedium->u.hGlobal);
1574 pmedium->u.hMetaFilePict = 0;
1579 if ( (pmedium->pUnkForRelease==0) &&
1580 (pmedium->u.hEnhMetaFile!=0) )
1582 DeleteEnhMetaFile(pmedium->u.hEnhMetaFile);
1585 pmedium->u.hEnhMetaFile = 0;
1594 * After cleaning up, the unknown is released
1596 if (pmedium->pUnkForRelease!=0)
1598 IUnknown_Release(pmedium->pUnkForRelease);
1599 pmedium->pUnkForRelease = 0;
1604 * OLEDD_Initialize()
1606 * Initializes the OLE drag and drop data structures.
1608 static void OLEDD_Initialize()
1612 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1613 wndClass.style = CS_GLOBALCLASS;
1614 wndClass.lpfnWndProc = (WNDPROC)OLEDD_DragTrackerWindowProc;
1615 wndClass.cbClsExtra = 0;
1616 wndClass.cbWndExtra = sizeof(TrackerWindowInfo*);
1617 wndClass.hCursor = 0;
1618 wndClass.hbrBackground = 0;
1619 wndClass.lpszClassName = OLEDD_DRAGTRACKERCLASS;
1621 RegisterClassA (&wndClass);
1625 * OLEDD_UnInitialize()
1627 * Releases the OLE drag and drop data structures.
1629 static void OLEDD_UnInitialize()
1632 * Simply empty the list.
1634 while (targetListHead!=NULL)
1636 RevokeDragDrop(targetListHead->hwndTarget);
1641 * OLEDD_InsertDropTarget()
1643 * Insert the target node in the tree.
1645 static void OLEDD_InsertDropTarget(DropTargetNode* nodeToAdd)
1647 DropTargetNode* curNode;
1648 DropTargetNode** parentNodeLink;
1651 * Iterate the tree to find the insertion point.
1653 curNode = targetListHead;
1654 parentNodeLink = &targetListHead;
1656 while (curNode!=NULL)
1658 if (nodeToAdd->hwndTarget<curNode->hwndTarget)
1661 * If the node we want to add has a smaller HWND, go left
1663 parentNodeLink = &curNode->prevDropTarget;
1664 curNode = curNode->prevDropTarget;
1666 else if (nodeToAdd->hwndTarget>curNode->hwndTarget)
1669 * If the node we want to add has a larger HWND, go right
1671 parentNodeLink = &curNode->nextDropTarget;
1672 curNode = curNode->nextDropTarget;
1677 * The item was found in the list. It shouldn't have been there
1685 * If we get here, we have found a spot for our item. The parentNodeLink
1686 * pointer points to the pointer that we have to modify.
1687 * The curNode should be NULL. We just have to establish the link and Voila!
1689 assert(curNode==NULL);
1690 assert(parentNodeLink!=NULL);
1691 assert(*parentNodeLink==NULL);
1693 *parentNodeLink=nodeToAdd;
1697 * OLEDD_ExtractDropTarget()
1699 * Removes the target node from the tree.
1701 static DropTargetNode* OLEDD_ExtractDropTarget(HWND hwndOfTarget)
1703 DropTargetNode* curNode;
1704 DropTargetNode** parentNodeLink;
1707 * Iterate the tree to find the insertion point.
1709 curNode = targetListHead;
1710 parentNodeLink = &targetListHead;
1712 while (curNode!=NULL)
1714 if (hwndOfTarget<curNode->hwndTarget)
1717 * If the node we want to add has a smaller HWND, go left
1719 parentNodeLink = &curNode->prevDropTarget;
1720 curNode = curNode->prevDropTarget;
1722 else if (hwndOfTarget>curNode->hwndTarget)
1725 * If the node we want to add has a larger HWND, go right
1727 parentNodeLink = &curNode->nextDropTarget;
1728 curNode = curNode->nextDropTarget;
1733 * The item was found in the list. Detach it from it's parent and
1734 * re-insert it's kids in the tree.
1736 assert(parentNodeLink!=NULL);
1737 assert(*parentNodeLink==curNode);
1740 * We arbitrately re-attach the left sub-tree to the parent.
1742 *parentNodeLink = curNode->prevDropTarget;
1745 * And we re-insert the right subtree
1747 if (curNode->nextDropTarget!=NULL)
1749 OLEDD_InsertDropTarget(curNode->nextDropTarget);
1753 * The node we found is still a valid node once we complete
1754 * the unlinking of the kids.
1756 curNode->nextDropTarget=NULL;
1757 curNode->prevDropTarget=NULL;
1764 * If we get here, the node is not in the tree
1770 * OLEDD_FindDropTarget()
1772 * Finds information about the drop target.
1774 static DropTargetNode* OLEDD_FindDropTarget(HWND hwndOfTarget)
1776 DropTargetNode* curNode;
1779 * Iterate the tree to find the HWND value.
1781 curNode = targetListHead;
1783 while (curNode!=NULL)
1785 if (hwndOfTarget<curNode->hwndTarget)
1788 * If the node we want to add has a smaller HWND, go left
1790 curNode = curNode->prevDropTarget;
1792 else if (hwndOfTarget>curNode->hwndTarget)
1795 * If the node we want to add has a larger HWND, go right
1797 curNode = curNode->nextDropTarget;
1802 * The item was found in the list.
1809 * If we get here, the item is not in the list
1815 * OLEDD_DragTrackerWindowProc()
1817 * This method is the WindowProcedure of the drag n drop tracking
1818 * window. During a drag n Drop operation, an invisible window is created
1819 * to receive the user input and act upon it. This procedure is in charge
1822 static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
1832 LPCREATESTRUCTA createStruct = (LPCREATESTRUCTA)lParam;
1834 SetWindowLongA(hwnd, 0, (LONG)createStruct->lpCreateParams);
1841 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
1845 * Get the current mouse position in screen coordinates.
1847 mousePos.x = LOWORD(lParam);
1848 mousePos.y = HIWORD(lParam);
1849 ClientToScreen(hwnd, &mousePos);
1852 * Track the movement of the mouse.
1854 OLEDD_TrackMouseMove(trackerInfo, mousePos, wParam);
1861 case WM_LBUTTONDOWN:
1862 case WM_MBUTTONDOWN:
1863 case WM_RBUTTONDOWN:
1865 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
1869 * Get the current mouse position in screen coordinates.
1871 mousePos.x = LOWORD(lParam);
1872 mousePos.y = HIWORD(lParam);
1873 ClientToScreen(hwnd, &mousePos);
1876 * Notify everyone that the button state changed
1877 * TODO: Check if the "escape" key was pressed.
1879 OLEDD_TrackStateChange(trackerInfo, mousePos, wParam);
1886 * This is a window proc after all. Let's call the default.
1888 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1892 * OLEDD_TrackMouseMove()
1894 * This method is invoked while a drag and drop operation is in effect.
1895 * it will generate the appropriate callbacks in the drop source
1896 * and drop target. It will also provide the expected feedback to
1900 * trackerInfo - Pointer to the structure identifying the
1901 * drag & drop operation that is currently
1903 * mousePos - Current position of the mouse in screen
1905 * keyState - Contains the state of the shift keys and the
1906 * mouse buttons (MK_LBUTTON and the like)
1908 static void OLEDD_TrackMouseMove(
1909 TrackerWindowInfo* trackerInfo,
1913 HWND hwndNewTarget = 0;
1917 * Get the handle of the window under the mouse
1919 hwndNewTarget = WindowFromPoint(mousePos);
1922 * Every time, we re-initialize the effects passed to the
1923 * IDropTarget to the effects allowed by the source.
1925 *trackerInfo->pdwEffect = trackerInfo->dwOKEffect;
1928 * If we are hovering over the same target as before, send the
1929 * DragOver notification
1931 if ( (trackerInfo->curDragTarget != 0) &&
1932 (trackerInfo->curDragTargetHWND==hwndNewTarget) )
1934 POINTL mousePosParam;
1937 * The documentation tells me that the coordinate should be in the target
1938 * window's coordinate space. However, the tests I made tell me the
1939 * coordinates should be in screen coordinates.
1941 mousePosParam.x = mousePos.x;
1942 mousePosParam.y = mousePos.y;
1944 IDropTarget_DragOver(trackerInfo->curDragTarget,
1947 trackerInfo->pdwEffect);
1951 DropTargetNode* newDropTargetNode = 0;
1954 * If we changed window, we have to notify our old target and check for
1957 if (trackerInfo->curDragTarget!=0)
1959 IDropTarget_DragLeave(trackerInfo->curDragTarget);
1963 * Make sure we're hovering over a window.
1965 if (hwndNewTarget!=0)
1968 * Find-out if there is a drag target under the mouse
1970 HWND nexttar = hwndNewTarget;
1972 newDropTargetNode = OLEDD_FindDropTarget(nexttar);
1973 } while (!newDropTargetNode && (nexttar = GetParent(nexttar)) != 0);
1974 if(nexttar) hwndNewTarget = nexttar;
1976 trackerInfo->curDragTargetHWND = hwndNewTarget;
1977 trackerInfo->curDragTarget = newDropTargetNode ? newDropTargetNode->dropTarget : 0;
1980 * If there is, notify it that we just dragged-in
1982 if (trackerInfo->curDragTarget!=0)
1984 POINTL mousePosParam;
1987 * The documentation tells me that the coordinate should be in the target
1988 * window's coordinate space. However, the tests I made tell me the
1989 * coordinates should be in screen coordinates.
1991 mousePosParam.x = mousePos.x;
1992 mousePosParam.y = mousePos.y;
1994 IDropTarget_DragEnter(trackerInfo->curDragTarget,
1995 trackerInfo->dataObject,
1998 trackerInfo->pdwEffect);
2004 * The mouse is not over a window so we don't track anything.
2006 trackerInfo->curDragTargetHWND = 0;
2007 trackerInfo->curDragTarget = 0;
2012 * Now that we have done that, we have to tell the source to give
2013 * us feedback on the work being done by the target. If we don't
2014 * have a target, simulate no effect.
2016 if (trackerInfo->curDragTarget==0)
2018 *trackerInfo->pdwEffect = DROPEFFECT_NONE;
2021 hr = IDropSource_GiveFeedback(trackerInfo->dropSource,
2022 *trackerInfo->pdwEffect);
2025 * When we ask for feedback from the drop source, sometimes it will
2026 * do all the necessary work and sometimes it will not handle it
2027 * when that's the case, we must display the standard drag and drop
2030 if (hr==DRAGDROP_S_USEDEFAULTCURSORS)
2032 if (*trackerInfo->pdwEffect & DROPEFFECT_MOVE)
2034 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(1)));
2036 else if (*trackerInfo->pdwEffect & DROPEFFECT_COPY)
2038 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(2)));
2040 else if (*trackerInfo->pdwEffect & DROPEFFECT_LINK)
2042 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(3)));
2046 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(0)));
2052 * OLEDD_TrackStateChange()
2054 * This method is invoked while a drag and drop operation is in effect.
2055 * It is used to notify the drop target/drop source callbacks when
2056 * the state of the keyboard or mouse button change.
2059 * trackerInfo - Pointer to the structure identifying the
2060 * drag & drop operation that is currently
2062 * mousePos - Current position of the mouse in screen
2064 * keyState - Contains the state of the shift keys and the
2065 * mouse buttons (MK_LBUTTON and the like)
2067 static void OLEDD_TrackStateChange(
2068 TrackerWindowInfo* trackerInfo,
2073 * Ask the drop source what to do with the operation.
2075 trackerInfo->returnValue = IDropSource_QueryContinueDrag(
2076 trackerInfo->dropSource,
2077 trackerInfo->escPressed,
2081 * All the return valued will stop the operation except the S_OK
2084 if (trackerInfo->returnValue!=S_OK)
2087 * Make sure the message loop in DoDragDrop stops
2089 trackerInfo->trackingDone = TRUE;
2092 * Release the mouse in case the drop target decides to show a popup
2093 * or a menu or something.
2098 * If we end-up over a target, drop the object in the target or
2099 * inform the target that the operation was cancelled.
2101 if (trackerInfo->curDragTarget!=0)
2103 switch (trackerInfo->returnValue)
2106 * If the source wants us to complete the operation, we tell
2107 * the drop target that we just dropped the object in it.
2109 case DRAGDROP_S_DROP:
2111 POINTL mousePosParam;
2114 * The documentation tells me that the coordinate should be
2115 * in the target window's coordinate space. However, the tests
2116 * I made tell me the coordinates should be in screen coordinates.
2118 mousePosParam.x = mousePos.x;
2119 mousePosParam.y = mousePos.y;
2121 IDropTarget_Drop(trackerInfo->curDragTarget,
2122 trackerInfo->dataObject,
2125 trackerInfo->pdwEffect);
2129 * If the source told us that we should cancel, fool the drop
2130 * target by telling it that the mouse left it's window.
2131 * Also set the drop effect to "NONE" in case the application
2132 * ignores the result of DoDragDrop.
2134 case DRAGDROP_S_CANCEL:
2135 IDropTarget_DragLeave(trackerInfo->curDragTarget);
2136 *trackerInfo->pdwEffect = DROPEFFECT_NONE;
2144 * OLEDD_GetButtonState()
2146 * This method will use the current state of the keyboard to build
2147 * a button state mask equivalent to the one passed in the
2148 * WM_MOUSEMOVE wParam.
2150 static DWORD OLEDD_GetButtonState()
2152 BYTE keyboardState[256];
2155 GetKeyboardState(keyboardState);
2157 if ( (keyboardState[VK_SHIFT] & 0x80) !=0)
2158 keyMask |= MK_SHIFT;
2160 if ( (keyboardState[VK_CONTROL] & 0x80) !=0)
2161 keyMask |= MK_CONTROL;
2163 if ( (keyboardState[VK_LBUTTON] & 0x80) !=0)
2164 keyMask |= MK_LBUTTON;
2166 if ( (keyboardState[VK_RBUTTON] & 0x80) !=0)
2167 keyMask |= MK_RBUTTON;
2169 if ( (keyboardState[VK_MBUTTON] & 0x80) !=0)
2170 keyMask |= MK_MBUTTON;
2176 * OLEDD_GetButtonState()
2178 * This method will read the default value of the registry key in
2179 * parameter and extract a DWORD value from it. The registry key value
2180 * can be in a string key or a DWORD key.
2183 * regKey - Key to read the default value from
2184 * pdwValue - Pointer to the location where the DWORD
2185 * value is returned. This value is not modified
2186 * if the value is not found.
2189 static void OLEUTL_ReadRegistryDWORDValue(
2198 lres = RegQueryValueExA(regKey,
2205 if (lres==ERROR_SUCCESS)
2210 *pdwValue = *(DWORD*)buffer;
2215 *pdwValue = (DWORD)strtoul(buffer, NULL, 10);
2221 /******************************************************************************
2222 * OleMetaFilePictFromIconAndLabel (OLE2.56)
2224 * Returns a global memory handle to a metafile which contains the icon and
2226 * I guess the result of that should look somehow like desktop icons.
2227 * If no hIcon is given, we load the icon via lpszSourceFile and iIconIndex.
2228 * This code might be wrong at some places.
2230 HGLOBAL16 WINAPI OleMetaFilePictFromIconAndLabel16(
2232 LPCOLESTR16 lpszLabel,
2233 LPCOLESTR16 lpszSourceFile,
2240 FIXME("(%04x, '%s', '%s', %d): incorrect metrics, please try to correct them !\n\n\n", hIcon, lpszLabel, lpszSourceFile, iIconIndex);
2243 if (lpszSourceFile) {
2244 HINSTANCE16 hInstance = LoadLibrary16(lpszSourceFile);
2246 /* load the icon at index from lpszSourceFile */
2247 hIcon = HICON_16(LoadIconA(HINSTANCE_32(hInstance), (LPCSTR)(DWORD)iIconIndex));
2248 FreeLibrary16(hInstance);
2253 hdc = CreateMetaFileA(NULL);
2254 DrawIcon(hdc, 0, 0, HICON_32(hIcon)); /* FIXME */
2255 TextOutA(hdc, 0, 0, lpszLabel, 1); /* FIXME */
2256 hmf = GlobalAlloc16(0, sizeof(METAFILEPICT16));
2257 mf = (METAFILEPICT16 *)GlobalLock16(hmf);
2258 mf->mm = MM_ANISOTROPIC;
2259 mf->xExt = 20; /* FIXME: bogus */
2260 mf->yExt = 20; /* dito */
2261 mf->hMF = CloseMetaFile16(HDC_16(hdc));
2265 /******************************************************************************
2266 * DllDebugObjectRPCHook (OLE32.62)
2267 * turns on and off internal debugging, pointer is only used on macintosh
2270 BOOL WINAPI DllDebugObjectRPCHook(BOOL b, void *dummy)