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))
55 /******************************************************************************
56 * These are static/global variables and internal data structures that the
57 * OLE module uses to maintain it's state.
59 typedef struct tagDropTargetNode
62 IDropTarget* dropTarget;
63 struct tagDropTargetNode* prevDropTarget;
64 struct tagDropTargetNode* nextDropTarget;
67 typedef struct tagTrackerWindowInfo
69 IDataObject* dataObject;
70 IDropSource* dropSource;
77 HWND curDragTargetHWND;
78 IDropTarget* curDragTarget;
81 typedef struct tagOleMenuDescriptor /* OleMenuDescriptor */
83 HWND hwndFrame; /* The containers frame window */
84 HWND hwndActiveObject; /* The active objects window */
85 OLEMENUGROUPWIDTHS mgw; /* OLE menu group widths for the shared menu */
86 HMENU hmenuCombined; /* The combined menu */
87 BOOL bIsServerItem; /* True if the currently open popup belongs to the server */
90 typedef struct tagOleMenuHookItem /* OleMenu hook item in per thread hook list */
92 DWORD tid; /* Thread Id */
93 HANDLE hHeap; /* Heap this is allocated from */
94 HHOOK GetMsg_hHook; /* message hook for WH_GETMESSAGE */
95 HHOOK CallWndProc_hHook; /* message hook for WH_CALLWNDPROC */
96 struct tagOleMenuHookItem *next;
99 static OleMenuHookItem *hook_list;
102 * This is the lock count on the OLE library. It is controlled by the
103 * OLEInitialize/OLEUninitialize methods.
105 static ULONG OLE_moduleLockCount = 0;
108 * Name of our registered window class.
110 static const char OLEDD_DRAGTRACKERCLASS[] = "WineDragDropTracker32";
113 * This is the head of the Drop target container.
115 static DropTargetNode* targetListHead = NULL;
117 /******************************************************************************
118 * These are the prototypes of miscelaneous utility methods
120 static void OLEUTL_ReadRegistryDWORDValue(HKEY regKey, DWORD* pdwValue);
122 /******************************************************************************
123 * These are the prototypes of the utility methods used to manage a shared menu
125 static void OLEMenu_Initialize();
126 static void OLEMenu_UnInitialize();
127 BOOL OLEMenu_InstallHooks( DWORD tid );
128 BOOL OLEMenu_UnInstallHooks( DWORD tid );
129 OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid );
130 static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos );
131 BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor );
132 LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam);
133 LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam);
135 /******************************************************************************
136 * These are the prototypes of the OLE Clipboard initialization methods (in clipboard.c)
138 void OLEClipbrd_UnInitialize();
139 void OLEClipbrd_Initialize();
141 /******************************************************************************
142 * These are the prototypes of the utility methods used for OLE Drag n Drop
144 static void OLEDD_Initialize();
145 static void OLEDD_UnInitialize();
146 static void OLEDD_InsertDropTarget(
147 DropTargetNode* nodeToAdd);
148 static DropTargetNode* OLEDD_ExtractDropTarget(
150 static DropTargetNode* OLEDD_FindDropTarget(
152 static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
157 static void OLEDD_TrackMouseMove(
158 TrackerWindowInfo* trackerInfo,
161 static void OLEDD_TrackStateChange(
162 TrackerWindowInfo* trackerInfo,
165 static DWORD OLEDD_GetButtonState();
168 /******************************************************************************
169 * OleBuildVersion [OLE2.1]
170 * OleBuildVersion [OLE32.84]
172 DWORD WINAPI OleBuildVersion(void)
174 TRACE("Returning version %d, build %d.\n", rmm, rup);
175 return (rmm<<16)+rup;
178 /***********************************************************************
179 * OleInitialize (OLE2.2)
180 * OleInitialize (OLE32.108)
182 HRESULT WINAPI OleInitialize(LPVOID reserved)
186 TRACE("(%p)\n", reserved);
189 * The first duty of the OleInitialize is to initialize the COM libraries.
191 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
194 * If the CoInitializeEx call failed, the OLE libraries can't be
201 * Then, it has to initialize the OLE specific modules.
205 * Object linking and Embedding
206 * In-place activation
208 if (OLE_moduleLockCount==0)
211 * Initialize the libraries.
213 TRACE("() - Initializing the OLE libraries\n");
218 OLEClipbrd_Initialize();
228 OLEMenu_Initialize();
232 * Then, we increase the lock count on the OLE module.
234 OLE_moduleLockCount++;
239 /******************************************************************************
240 * CoGetCurrentProcess [COMPOBJ.34]
241 * CoGetCurrentProcess [OLE32.18]
244 * Is DWORD really the correct return type for this function?
246 DWORD WINAPI CoGetCurrentProcess(void)
248 return GetCurrentProcessId();
251 /******************************************************************************
252 * OleUninitialize [OLE2.3]
253 * OleUninitialize [OLE32.131]
255 void WINAPI OleUninitialize(void)
260 * Decrease the lock count on the OLE module.
262 OLE_moduleLockCount--;
265 * If we hit the bottom of the lock stack, free the libraries.
267 if (OLE_moduleLockCount==0)
270 * Actually free the libraries.
272 TRACE("() - Freeing the last reference count\n");
277 OLEClipbrd_UnInitialize();
282 OLEDD_UnInitialize();
287 OLEMenu_UnInitialize();
291 * Then, uninitialize the COM libraries.
296 /******************************************************************************
297 * CoRegisterMessageFilter [OLE32.38]
299 HRESULT WINAPI CoRegisterMessageFilter(
300 LPMESSAGEFILTER lpMessageFilter, /* [in] Pointer to interface */
301 LPMESSAGEFILTER *lplpMessageFilter /* [out] Indirect pointer to prior instance if non-NULL */
304 if (lplpMessageFilter) {
305 *lplpMessageFilter = NULL;
310 /******************************************************************************
311 * OleInitializeWOW [OLE32.109]
313 HRESULT WINAPI OleInitializeWOW(DWORD x) {
314 FIXME("(0x%08lx),stub!\n",x);
318 /***********************************************************************
319 * RegisterDragDrop (OLE2.35)
321 HRESULT WINAPI RegisterDragDrop16(
323 LPDROPTARGET pDropTarget
325 FIXME("(0x%04x,%p),stub!\n",hwnd,pDropTarget);
329 /***********************************************************************
330 * RegisterDragDrop (OLE32.139)
332 HRESULT WINAPI RegisterDragDrop(
334 LPDROPTARGET pDropTarget)
336 DropTargetNode* dropTargetInfo;
338 TRACE("(0x%x,%p)\n", hwnd, pDropTarget);
341 * First, check if the window is already registered.
343 dropTargetInfo = OLEDD_FindDropTarget(hwnd);
345 if (dropTargetInfo!=NULL)
346 return DRAGDROP_E_ALREADYREGISTERED;
349 * If it's not there, we can add it. We first create a node for it.
351 dropTargetInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(DropTargetNode));
353 if (dropTargetInfo==NULL)
354 return E_OUTOFMEMORY;
356 dropTargetInfo->hwndTarget = hwnd;
357 dropTargetInfo->prevDropTarget = NULL;
358 dropTargetInfo->nextDropTarget = NULL;
361 * Don't forget that this is an interface pointer, need to nail it down since
362 * we keep a copy of it.
364 dropTargetInfo->dropTarget = pDropTarget;
365 IDropTarget_AddRef(dropTargetInfo->dropTarget);
367 OLEDD_InsertDropTarget(dropTargetInfo);
372 /***********************************************************************
373 * RevokeDragDrop (OLE2.36)
375 HRESULT WINAPI RevokeDragDrop16(
378 FIXME("(0x%04x),stub!\n",hwnd);
382 /***********************************************************************
383 * RevokeDragDrop (OLE32.141)
385 HRESULT WINAPI RevokeDragDrop(
388 DropTargetNode* dropTargetInfo;
390 TRACE("(0x%x)\n", hwnd);
393 * First, check if the window is already registered.
395 dropTargetInfo = OLEDD_ExtractDropTarget(hwnd);
398 * If it ain't in there, it's an error.
400 if (dropTargetInfo==NULL)
401 return DRAGDROP_E_NOTREGISTERED;
404 * If it's in there, clean-up it's used memory and
407 IDropTarget_Release(dropTargetInfo->dropTarget);
408 HeapFree(GetProcessHeap(), 0, dropTargetInfo);
413 /***********************************************************************
414 * OleRegGetUserType (OLE32.122)
416 * This implementation of OleRegGetUserType ignores the dwFormOfType
417 * parameter and always returns the full name of the object. This is
418 * not too bad since this is the case for many objects because of the
419 * way they are registered.
421 HRESULT WINAPI OleRegGetUserType(
424 LPOLESTR* pszUserType)
434 * Initialize the out parameter.
439 * Build the key name we're looking for
441 sprintf( keyName, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\",
442 clsid->Data1, clsid->Data2, clsid->Data3,
443 clsid->Data4[0], clsid->Data4[1], clsid->Data4[2], clsid->Data4[3],
444 clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7] );
446 TRACE("(%s, %ld, %p)\n", keyName, dwFormOfType, pszUserType);
449 * Open the class id Key
451 hres = RegOpenKeyA(HKEY_CLASSES_ROOT,
455 if (hres != ERROR_SUCCESS)
456 return REGDB_E_CLASSNOTREG;
459 * Retrieve the size of the name string.
463 hres = RegQueryValueExA(clsidKey,
470 if (hres!=ERROR_SUCCESS)
472 RegCloseKey(clsidKey);
473 return REGDB_E_READREGDB;
477 * Allocate a buffer for the registry value.
479 *pszUserType = CoTaskMemAlloc(cbData*2);
481 if (*pszUserType==NULL)
483 RegCloseKey(clsidKey);
484 return E_OUTOFMEMORY;
487 buffer = HeapAlloc(GetProcessHeap(), 0, cbData);
491 RegCloseKey(clsidKey);
492 CoTaskMemFree(*pszUserType);
494 return E_OUTOFMEMORY;
497 hres = RegQueryValueExA(clsidKey,
504 RegCloseKey(clsidKey);
507 if (hres!=ERROR_SUCCESS)
509 CoTaskMemFree(*pszUserType);
512 retVal = REGDB_E_READREGDB;
516 MultiByteToWideChar( CP_ACP, 0, buffer, -1, *pszUserType, cbData /*FIXME*/ );
519 HeapFree(GetProcessHeap(), 0, buffer);
524 /***********************************************************************
525 * DoDragDrop [OLE32.65]
527 HRESULT WINAPI DoDragDrop (
528 IDataObject *pDataObject, /* [in] ptr to the data obj */
529 IDropSource* pDropSource, /* [in] ptr to the source obj */
530 DWORD dwOKEffect, /* [in] effects allowed by the source */
531 DWORD *pdwEffect) /* [out] ptr to effects of the source */
533 TrackerWindowInfo trackerInfo;
534 HWND hwndTrackWindow;
537 TRACE("(DataObject %p, DropSource %p)\n", pDataObject, pDropSource);
540 * Setup the drag n drop tracking window.
542 trackerInfo.dataObject = pDataObject;
543 trackerInfo.dropSource = pDropSource;
544 trackerInfo.dwOKEffect = dwOKEffect;
545 trackerInfo.pdwEffect = pdwEffect;
546 trackerInfo.trackingDone = FALSE;
547 trackerInfo.escPressed = FALSE;
548 trackerInfo.curDragTargetHWND = 0;
549 trackerInfo.curDragTarget = 0;
551 hwndTrackWindow = CreateWindowA(OLEDD_DRAGTRACKERCLASS,
554 CW_USEDEFAULT, CW_USEDEFAULT,
555 CW_USEDEFAULT, CW_USEDEFAULT,
559 (LPVOID)&trackerInfo);
561 if (hwndTrackWindow!=0)
564 * Capture the mouse input
566 SetCapture(hwndTrackWindow);
569 * Pump messages. All mouse input should go the the capture window.
571 while (!trackerInfo.trackingDone && GetMessageA(&msg, 0, 0, 0) )
573 if ( (msg.message >= WM_KEYFIRST) &&
574 (msg.message <= WM_KEYLAST) )
577 * When keyboard messages are sent to windows on this thread, we
578 * want to ignore notify the drop source that the state changed.
579 * in the case of the Escape key, we also notify the drop source
580 * we give it a special meaning.
582 if ( (msg.message==WM_KEYDOWN) &&
583 (msg.wParam==VK_ESCAPE) )
585 trackerInfo.escPressed = TRUE;
589 * Notify the drop source.
591 OLEDD_TrackStateChange(&trackerInfo,
593 OLEDD_GetButtonState());
598 * Dispatch the messages only when it's not a keyboard message.
600 DispatchMessageA(&msg);
605 * Destroy the temporary window.
607 DestroyWindow(hwndTrackWindow);
609 return trackerInfo.returnValue;
615 /***********************************************************************
616 * OleQueryLinkFromData [OLE32.118]
618 HRESULT WINAPI OleQueryLinkFromData(
619 IDataObject* pSrcDataObject)
621 FIXME("(%p),stub!\n", pSrcDataObject);
625 /***********************************************************************
626 * OleRegGetMiscStatus [OLE32.121]
628 HRESULT WINAPI OleRegGetMiscStatus(
640 * Initialize the out parameter.
645 * Build the key name we're looking for
647 sprintf( keyName, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\",
648 clsid->Data1, clsid->Data2, clsid->Data3,
649 clsid->Data4[0], clsid->Data4[1], clsid->Data4[2], clsid->Data4[3],
650 clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7] );
652 TRACE("(%s, %ld, %p)\n", keyName, dwAspect, pdwStatus);
655 * Open the class id Key
657 result = RegOpenKeyA(HKEY_CLASSES_ROOT,
661 if (result != ERROR_SUCCESS)
662 return REGDB_E_CLASSNOTREG;
667 result = RegOpenKeyA(clsidKey,
672 if (result != ERROR_SUCCESS)
674 RegCloseKey(clsidKey);
675 return REGDB_E_READREGDB;
679 * Read the default value
681 OLEUTL_ReadRegistryDWORDValue(miscStatusKey, pdwStatus);
684 * Open the key specific to the requested aspect.
686 sprintf(keyName, "%ld", dwAspect);
688 result = RegOpenKeyA(miscStatusKey,
692 if (result == ERROR_SUCCESS)
694 OLEUTL_ReadRegistryDWORDValue(aspectKey, pdwStatus);
695 RegCloseKey(aspectKey);
701 RegCloseKey(miscStatusKey);
702 RegCloseKey(clsidKey);
707 /******************************************************************************
708 * OleSetContainedObject [OLE32.128]
710 HRESULT WINAPI OleSetContainedObject(
714 IRunnableObject* runnable = NULL;
717 TRACE("(%p,%x), stub!\n", pUnknown, fContained);
719 hres = IUnknown_QueryInterface(pUnknown,
720 &IID_IRunnableObject,
725 hres = IRunnableObject_SetContainedObject(runnable, fContained);
727 IRunnableObject_Release(runnable);
735 /******************************************************************************
736 * OleLoad [OLE32.112]
738 HRESULT WINAPI OleLoad(
741 LPOLECLIENTSITE pClientSite,
744 IPersistStorage* persistStorage = NULL;
745 IOleObject* oleObject = NULL;
749 TRACE("(%p,%p,%p,%p)\n", pStg, riid, pClientSite, ppvObj);
752 * TODO, Conversion ... OleDoAutoConvert
756 * Get the class ID for the object.
758 hres = IStorage_Stat(pStg, &storageInfo, STATFLAG_NONAME);
761 * Now, try and create the handler for the object
763 hres = CoCreateInstance(&storageInfo.clsid,
765 CLSCTX_INPROC_HANDLER,
770 * If that fails, as it will most times, load the default
775 hres = OleCreateDefaultHandler(&storageInfo.clsid,
782 * If we couldn't find a handler... this is bad. Abort the whole thing.
788 * Inform the new object of it's client site.
790 hres = IOleObject_SetClientSite(oleObject, pClientSite);
793 * Initialize the object with it's IPersistStorage interface.
795 hres = IOleObject_QueryInterface(oleObject,
796 &IID_IPersistStorage,
797 (void**)&persistStorage);
801 IPersistStorage_Load(persistStorage, pStg);
803 IPersistStorage_Release(persistStorage);
804 persistStorage = NULL;
808 * Return the requested interface to the caller.
810 hres = IOleObject_QueryInterface(oleObject, riid, ppvObj);
813 * Cleanup interfaces used internally
815 IOleObject_Release(oleObject);
820 /***********************************************************************
821 * OleSave [OLE32.124]
823 HRESULT WINAPI OleSave(
824 LPPERSISTSTORAGE pPS,
831 TRACE("(%p,%p,%x)\n", pPS, pStg, fSameAsLoad);
834 * First, we transfer the class ID (if available)
836 hres = IPersistStorage_GetClassID(pPS, &objectClass);
840 WriteClassStg(pStg, &objectClass);
844 * Then, we ask the object to save itself to the
845 * storage. If it is successful, we commit the storage.
847 hres = IPersistStorage_Save(pPS, pStg, fSameAsLoad);
851 IStorage_Commit(pStg,
859 /******************************************************************************
860 * OleLockRunning [OLE32.114]
862 HRESULT WINAPI OleLockRunning(LPUNKNOWN pUnknown, BOOL fLock, BOOL fLastUnlockCloses)
864 IRunnableObject* runnable = NULL;
867 TRACE("(%p,%x,%x)\n", pUnknown, fLock, fLastUnlockCloses);
869 hres = IUnknown_QueryInterface(pUnknown,
870 &IID_IRunnableObject,
875 hres = IRunnableObject_LockRunning(runnable, fLock, fLastUnlockCloses);
877 IRunnableObject_Release(runnable);
886 /**************************************************************************
887 * Internal methods to manage the shared OLE menu in response to the
888 * OLE***MenuDescriptor API
892 * OLEMenu_Initialize()
894 * Initializes the OLEMENU data structures.
896 static void OLEMenu_Initialize()
901 * OLEMenu_UnInitialize()
903 * Releases the OLEMENU data structures.
905 static void OLEMenu_UnInitialize()
909 /*************************************************************************
910 * OLEMenu_InstallHooks
911 * Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
913 * RETURNS: TRUE if message hooks were succesfully installed
916 BOOL OLEMenu_InstallHooks( DWORD tid )
918 OleMenuHookItem *pHookItem = NULL;
920 /* Create an entry for the hook table */
921 if ( !(pHookItem = HeapAlloc(GetProcessHeap(), 0,
922 sizeof(OleMenuHookItem)) ) )
925 pHookItem->tid = tid;
926 pHookItem->hHeap = GetProcessHeap();
928 /* Install a thread scope message hook for WH_GETMESSAGE */
929 pHookItem->GetMsg_hHook = SetWindowsHookExA( WH_GETMESSAGE, OLEMenu_GetMsgProc,
930 0, GetCurrentThreadId() );
931 if ( !pHookItem->GetMsg_hHook )
934 /* Install a thread scope message hook for WH_CALLWNDPROC */
935 pHookItem->CallWndProc_hHook = SetWindowsHookExA( WH_CALLWNDPROC, OLEMenu_CallWndProc,
936 0, GetCurrentThreadId() );
937 if ( !pHookItem->CallWndProc_hHook )
940 /* Insert the hook table entry */
941 pHookItem->next = hook_list;
942 hook_list = pHookItem;
947 /* Unhook any hooks */
948 if ( pHookItem->GetMsg_hHook )
949 UnhookWindowsHookEx( pHookItem->GetMsg_hHook );
950 if ( pHookItem->CallWndProc_hHook )
951 UnhookWindowsHookEx( pHookItem->CallWndProc_hHook );
952 /* Release the hook table entry */
953 HeapFree(pHookItem->hHeap, 0, pHookItem );
958 /*************************************************************************
959 * OLEMenu_UnInstallHooks
960 * UnInstall thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
962 * RETURNS: TRUE if message hooks were succesfully installed
965 BOOL OLEMenu_UnInstallHooks( DWORD tid )
967 OleMenuHookItem *pHookItem = NULL;
968 OleMenuHookItem **ppHook = &hook_list;
972 if ((*ppHook)->tid == tid)
975 *ppHook = pHookItem->next;
978 ppHook = &(*ppHook)->next;
980 if (!pHookItem) return FALSE;
982 /* Uninstall the hooks installed for this thread */
983 if ( !UnhookWindowsHookEx( pHookItem->GetMsg_hHook ) )
985 if ( !UnhookWindowsHookEx( pHookItem->CallWndProc_hHook ) )
988 /* Release the hook table entry */
989 HeapFree(pHookItem->hHeap, 0, pHookItem );
994 /* Release the hook table entry */
996 HeapFree(pHookItem->hHeap, 0, pHookItem );
1001 /*************************************************************************
1002 * OLEMenu_IsHookInstalled
1003 * Tests if OLEMenu hooks have been installed for a thread
1005 * RETURNS: The pointer and index of the hook table entry for the tid
1006 * NULL and -1 for the index if no hooks were installed for this thread
1008 OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid )
1010 OleMenuHookItem *pHookItem = NULL;
1012 /* Do a simple linear search for an entry whose tid matches ours.
1013 * We really need a map but efficiency is not a concern here. */
1014 for (pHookItem = hook_list; pHookItem; pHookItem = pHookItem->next)
1016 if ( tid == pHookItem->tid )
1023 /***********************************************************************
1024 * OLEMenu_FindMainMenuIndex
1026 * Used by OLEMenu API to find the top level group a menu item belongs to.
1027 * On success pnPos contains the index of the item in the top level menu group
1029 * RETURNS: TRUE if the ID was found, FALSE on failure
1031 static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos )
1035 nItems = GetMenuItemCount( hMainMenu );
1037 for (i = 0; i < nItems; i++)
1041 /* Is the current item a submenu? */
1042 if ( (hsubmenu = GetSubMenu(hMainMenu, i)) )
1044 /* If the handle is the same we're done */
1045 if ( hsubmenu == hPopupMenu )
1051 /* Recursively search without updating pnPos */
1052 else if ( OLEMenu_FindMainMenuIndex( hsubmenu, hPopupMenu, NULL ) )
1064 /***********************************************************************
1065 * OLEMenu_SetIsServerMenu
1067 * Checks whether a popup menu belongs to a shared menu group which is
1068 * owned by the server, and sets the menu descriptor state accordingly.
1069 * All menu messages from these groups should be routed to the server.
1071 * RETURNS: TRUE if the popup menu is part of a server owned group
1072 * FASE if the popup menu is part of a container owned group
1074 BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor )
1076 UINT nPos = 0, nWidth, i;
1078 pOleMenuDescriptor->bIsServerItem = FALSE;
1080 /* Don't bother searching if the popup is the combined menu itself */
1081 if ( hmenu == pOleMenuDescriptor->hmenuCombined )
1084 /* Find the menu item index in the shared OLE menu that this item belongs to */
1085 if ( !OLEMenu_FindMainMenuIndex( pOleMenuDescriptor->hmenuCombined, hmenu, &nPos ) )
1088 /* The group widths array has counts for the number of elements
1089 * in the groups File, Edit, Container, Object, Window, Help.
1090 * The Edit, Object & Help groups belong to the server object
1091 * and the other three belong to the container.
1092 * Loop through the group widths and locate the group we are a member of.
1094 for ( i = 0, nWidth = 0; i < 6; i++ )
1096 nWidth += pOleMenuDescriptor->mgw.width[i];
1097 if ( nPos < nWidth )
1099 /* Odd elements are server menu widths */
1100 pOleMenuDescriptor->bIsServerItem = (i%2) ? TRUE : FALSE;
1105 return pOleMenuDescriptor->bIsServerItem;
1108 /*************************************************************************
1109 * OLEMenu_CallWndProc
1110 * Thread scope WH_CALLWNDPROC hook proc filter function (callback)
1111 * This is invoked from a message hook installed in OleSetMenuDescriptor.
1113 LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam)
1115 LPCWPSTRUCT pMsg = NULL;
1116 HOLEMENU hOleMenu = 0;
1117 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1118 OleMenuHookItem *pHookItem = NULL;
1121 TRACE("%i, %04x, %08x\n", code, wParam, (unsigned)lParam );
1123 /* Check if we're being asked to process the message */
1124 if ( HC_ACTION != code )
1127 /* Retrieve the current message being dispatched from lParam */
1128 pMsg = (LPCWPSTRUCT)lParam;
1130 /* Check if the message is destined for a window we are interested in:
1131 * If the window has an OLEMenu property we may need to dispatch
1132 * the menu message to its active objects window instead. */
1134 hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" );
1138 /* Get the menu descriptor */
1139 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1140 if ( !pOleMenuDescriptor ) /* Bad descriptor! */
1143 /* Process menu messages */
1144 switch( pMsg->message )
1148 /* Reset the menu descriptor state */
1149 pOleMenuDescriptor->bIsServerItem = FALSE;
1151 /* Send this message to the server as well */
1152 SendMessageA( pOleMenuDescriptor->hwndActiveObject,
1153 pMsg->message, pMsg->wParam, pMsg->lParam );
1157 case WM_INITMENUPOPUP:
1159 /* Save the state for whether this is a server owned menu */
1160 OLEMenu_SetIsServerMenu( (HMENU)pMsg->wParam, pOleMenuDescriptor );
1166 fuFlags = HIWORD(pMsg->wParam); /* Get flags */
1167 if ( fuFlags & MF_SYSMENU )
1170 /* Save the state for whether this is a server owned popup menu */
1171 else if ( fuFlags & MF_POPUP )
1172 OLEMenu_SetIsServerMenu( (HMENU)pMsg->lParam, pOleMenuDescriptor );
1179 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) pMsg->lParam;
1180 if ( pMsg->wParam != 0 || lpdis->CtlType != ODT_MENU )
1181 goto NEXTHOOK; /* Not a menu message */
1190 /* If the message was for the server dispatch it accordingly */
1191 if ( pOleMenuDescriptor->bIsServerItem )
1193 SendMessageA( pOleMenuDescriptor->hwndActiveObject,
1194 pMsg->message, pMsg->wParam, pMsg->lParam );
1198 if ( pOleMenuDescriptor )
1199 GlobalUnlock( hOleMenu );
1201 /* Lookup the hook item for the current thread */
1202 if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) )
1204 /* This should never fail!! */
1205 WARN("could not retrieve hHook for current thread!\n" );
1209 /* Pass on the message to the next hooker */
1210 return CallNextHookEx( pHookItem->CallWndProc_hHook, code, wParam, lParam );
1213 /*************************************************************************
1214 * OLEMenu_GetMsgProc
1215 * Thread scope WH_GETMESSAGE hook proc filter function (callback)
1216 * This is invoked from a message hook installed in OleSetMenuDescriptor.
1218 LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam)
1221 HOLEMENU hOleMenu = 0;
1222 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1223 OleMenuHookItem *pHookItem = NULL;
1226 TRACE("%i, %04x, %08x\n", code, wParam, (unsigned)lParam );
1228 /* Check if we're being asked to process a messages */
1229 if ( HC_ACTION != code )
1232 /* Retrieve the current message being dispatched from lParam */
1233 pMsg = (LPMSG)lParam;
1235 /* Check if the message is destined for a window we are interested in:
1236 * If the window has an OLEMenu property we may need to dispatch
1237 * the menu message to its active objects window instead. */
1239 hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" );
1243 /* Process menu messages */
1244 switch( pMsg->message )
1248 wCode = HIWORD(pMsg->wParam); /* Get notification code */
1250 goto NEXTHOOK; /* Not a menu message */
1257 /* Get the menu descriptor */
1258 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1259 if ( !pOleMenuDescriptor ) /* Bad descriptor! */
1262 /* If the message was for the server dispatch it accordingly */
1263 if ( pOleMenuDescriptor->bIsServerItem )
1265 /* Change the hWnd in the message to the active objects hWnd.
1266 * The message loop which reads this message will automatically
1267 * dispatch it to the embedded objects window. */
1268 pMsg->hwnd = pOleMenuDescriptor->hwndActiveObject;
1272 if ( pOleMenuDescriptor )
1273 GlobalUnlock( hOleMenu );
1275 /* Lookup the hook item for the current thread */
1276 if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) )
1278 /* This should never fail!! */
1279 WARN("could not retrieve hHook for current thread!\n" );
1283 /* Pass on the message to the next hooker */
1284 return CallNextHookEx( pHookItem->GetMsg_hHook, code, wParam, lParam );
1287 /***********************************************************************
1288 * OleCreateMenuDescriptor [OLE32.97]
1289 * Creates an OLE menu descriptor for OLE to use when dispatching
1290 * menu messages and commands.
1293 * hmenuCombined - Handle to the objects combined menu
1294 * lpMenuWidths - Pointer to array of 6 LONG's indicating menus per group
1297 HOLEMENU WINAPI OleCreateMenuDescriptor(
1298 HMENU hmenuCombined,
1299 LPOLEMENUGROUPWIDTHS lpMenuWidths)
1302 OleMenuDescriptor *pOleMenuDescriptor;
1305 if ( !hmenuCombined || !lpMenuWidths )
1308 /* Create an OLE menu descriptor */
1309 if ( !(hOleMenu = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
1310 sizeof(OleMenuDescriptor) ) ) )
1313 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1314 if ( !pOleMenuDescriptor )
1317 /* Initialize menu group widths and hmenu */
1318 for ( i = 0; i < 6; i++ )
1319 pOleMenuDescriptor->mgw.width[i] = lpMenuWidths->width[i];
1321 pOleMenuDescriptor->hmenuCombined = hmenuCombined;
1322 pOleMenuDescriptor->bIsServerItem = FALSE;
1323 GlobalUnlock( hOleMenu );
1328 /***********************************************************************
1329 * OleDestroyMenuDescriptor [OLE32.99]
1330 * Destroy the shared menu descriptor
1332 HRESULT WINAPI OleDestroyMenuDescriptor(
1333 HOLEMENU hmenuDescriptor)
1335 if ( hmenuDescriptor )
1336 GlobalFree( hmenuDescriptor );
1340 /***********************************************************************
1341 * OleSetMenuDescriptor [OLE32.129]
1342 * Installs or removes OLE dispatching code for the containers frame window
1343 * FIXME: The lpFrame and lpActiveObject parameters are currently ignored
1344 * OLE should install context sensitive help F1 filtering for the app when
1345 * these are non null.
1348 * hOleMenu Handle to composite menu descriptor
1349 * hwndFrame Handle to containers frame window
1350 * hwndActiveObject Handle to objects in-place activation window
1351 * lpFrame Pointer to IOleInPlaceFrame on containers window
1352 * lpActiveObject Pointer to IOleInPlaceActiveObject on active in-place object
1355 * S_OK - menu installed correctly
1356 * E_FAIL, E_INVALIDARG, E_UNEXPECTED - failure
1358 HRESULT WINAPI OleSetMenuDescriptor(
1361 HWND hwndActiveObject,
1362 LPOLEINPLACEFRAME lpFrame,
1363 LPOLEINPLACEACTIVEOBJECT lpActiveObject)
1365 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1368 if ( !hwndFrame || (hOleMenu && !hwndActiveObject) )
1369 return E_INVALIDARG;
1371 if ( lpFrame || lpActiveObject )
1373 FIXME("(%x, %x, %x, %p, %p), Context sensitive help filtering not implemented!\n",
1374 (unsigned int)hOleMenu,
1381 /* Set up a message hook to intercept the containers frame window messages.
1382 * The message filter is responsible for dispatching menu messages from the
1383 * shared menu which are intended for the object.
1386 if ( hOleMenu ) /* Want to install dispatching code */
1388 /* If OLEMenu hooks are already installed for this thread, fail
1389 * Note: This effectively means that OleSetMenuDescriptor cannot
1390 * be called twice in succession on the same frame window
1391 * without first calling it with a null hOleMenu to uninstall */
1392 if ( OLEMenu_IsHookInstalled( GetCurrentThreadId() ) )
1395 /* Get the menu descriptor */
1396 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1397 if ( !pOleMenuDescriptor )
1398 return E_UNEXPECTED;
1400 /* Update the menu descriptor */
1401 pOleMenuDescriptor->hwndFrame = hwndFrame;
1402 pOleMenuDescriptor->hwndActiveObject = hwndActiveObject;
1404 GlobalUnlock( hOleMenu );
1405 pOleMenuDescriptor = NULL;
1407 /* Add a menu descriptor windows property to the frame window */
1408 SetPropA( hwndFrame, "PROP_OLEMenuDescriptor", hOleMenu );
1410 /* Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC */
1411 if ( !OLEMenu_InstallHooks( GetCurrentThreadId() ) )
1414 else /* Want to uninstall dispatching code */
1416 /* Uninstall the hooks */
1417 if ( !OLEMenu_UnInstallHooks( GetCurrentThreadId() ) )
1420 /* Remove the menu descriptor property from the frame window */
1421 RemovePropA( hwndFrame, "PROP_OLEMenuDescriptor" );
1427 /******************************************************************************
1428 * IsAccelerator [OLE32.75]
1429 * Mostly copied from controls/menu.c TranslateAccelerator implementation
1431 BOOL WINAPI IsAccelerator(HACCEL hAccel, int cAccelEntries, LPMSG lpMsg, WORD* lpwCmd)
1434 LPACCEL16 lpAccelTbl;
1437 if(!lpMsg) return FALSE;
1438 if (!hAccel || !(lpAccelTbl = (LPACCEL16)LockResource16(HACCEL_16(hAccel))))
1440 WARN_(accel)("invalid accel handle=%04x\n", hAccel);
1443 if((lpMsg->message != WM_KEYDOWN &&
1444 lpMsg->message != WM_KEYUP &&
1445 lpMsg->message != WM_SYSKEYDOWN &&
1446 lpMsg->message != WM_SYSKEYUP &&
1447 lpMsg->message != WM_CHAR)) return FALSE;
1449 TRACE_(accel)("hAccel=%04x, cAccelEntries=%d,"
1450 "msg->hwnd=%04x, msg->message=%04x, wParam=%08x, lParam=%08lx\n",
1451 hAccel, cAccelEntries,
1452 lpMsg->hwnd, lpMsg->message, lpMsg->wParam, lpMsg->lParam);
1453 for(i = 0; i < cAccelEntries; i++)
1455 if(lpAccelTbl[i].key != lpMsg->wParam)
1458 if(lpMsg->message == WM_CHAR)
1460 if(!(lpAccelTbl[i].fVirt & FALT) && !(lpAccelTbl[i].fVirt & FVIRTKEY))
1462 TRACE_(accel)("found accel for WM_CHAR: ('%c')\n", lpMsg->wParam & 0xff);
1468 if(lpAccelTbl[i].fVirt & FVIRTKEY)
1471 TRACE_(accel)("found accel for virt_key %04x (scan %04x)\n",
1472 lpMsg->wParam, HIWORD(lpMsg->lParam) & 0xff);
1473 if(GetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT;
1474 if(GetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL;
1475 if(GetKeyState(VK_MENU) & 0x8000) mask |= FALT;
1476 if(mask == (lpAccelTbl[i].fVirt & (FSHIFT | FCONTROL | FALT))) goto found;
1477 TRACE_(accel)("incorrect SHIFT/CTRL/ALT-state\n");
1481 if(!(lpMsg->lParam & 0x01000000)) /* no special_key */
1483 if((lpAccelTbl[i].fVirt & FALT) && (lpMsg->lParam & 0x20000000))
1484 { /* ^^ ALT pressed */
1485 TRACE_(accel)("found accel for Alt-%c\n", lpMsg->wParam & 0xff);
1493 WARN_(accel)("couldn't translate accelerator key\n");
1497 if(lpwCmd) *lpwCmd = lpAccelTbl[i].cmd;
1501 /***********************************************************************
1502 * ReleaseStgMedium [OLE32.140]
1504 void WINAPI ReleaseStgMedium(
1507 switch (pmedium->tymed)
1511 if ( (pmedium->pUnkForRelease==0) &&
1512 (pmedium->u.hGlobal!=0) )
1513 GlobalFree(pmedium->u.hGlobal);
1515 pmedium->u.hGlobal = 0;
1520 if (pmedium->u.lpszFileName!=0)
1522 if (pmedium->pUnkForRelease==0)
1524 DeleteFileW(pmedium->u.lpszFileName);
1527 CoTaskMemFree(pmedium->u.lpszFileName);
1530 pmedium->u.lpszFileName = 0;
1535 if (pmedium->u.pstm!=0)
1537 IStream_Release(pmedium->u.pstm);
1540 pmedium->u.pstm = 0;
1543 case TYMED_ISTORAGE:
1545 if (pmedium->u.pstg!=0)
1547 IStorage_Release(pmedium->u.pstg);
1550 pmedium->u.pstg = 0;
1555 if ( (pmedium->pUnkForRelease==0) &&
1556 (pmedium->u.hGlobal!=0) )
1557 DeleteObject(pmedium->u.hGlobal);
1559 pmedium->u.hGlobal = 0;
1564 if ( (pmedium->pUnkForRelease==0) &&
1565 (pmedium->u.hMetaFilePict!=0) )
1567 LPMETAFILEPICT pMP = GlobalLock(pmedium->u.hGlobal);
1568 DeleteMetaFile(pMP->hMF);
1569 GlobalUnlock(pmedium->u.hGlobal);
1570 GlobalFree(pmedium->u.hGlobal);
1573 pmedium->u.hMetaFilePict = 0;
1578 if ( (pmedium->pUnkForRelease==0) &&
1579 (pmedium->u.hEnhMetaFile!=0) )
1581 DeleteEnhMetaFile(pmedium->u.hEnhMetaFile);
1584 pmedium->u.hEnhMetaFile = 0;
1593 * After cleaning up, the unknown is released
1595 if (pmedium->pUnkForRelease!=0)
1597 IUnknown_Release(pmedium->pUnkForRelease);
1598 pmedium->pUnkForRelease = 0;
1603 * OLEDD_Initialize()
1605 * Initializes the OLE drag and drop data structures.
1607 static void OLEDD_Initialize()
1611 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1612 wndClass.style = CS_GLOBALCLASS;
1613 wndClass.lpfnWndProc = (WNDPROC)OLEDD_DragTrackerWindowProc;
1614 wndClass.cbClsExtra = 0;
1615 wndClass.cbWndExtra = sizeof(TrackerWindowInfo*);
1616 wndClass.hCursor = 0;
1617 wndClass.hbrBackground = 0;
1618 wndClass.lpszClassName = OLEDD_DRAGTRACKERCLASS;
1620 RegisterClassA (&wndClass);
1624 * OLEDD_UnInitialize()
1626 * Releases the OLE drag and drop data structures.
1628 static void OLEDD_UnInitialize()
1631 * Simply empty the list.
1633 while (targetListHead!=NULL)
1635 RevokeDragDrop(targetListHead->hwndTarget);
1640 * OLEDD_InsertDropTarget()
1642 * Insert the target node in the tree.
1644 static void OLEDD_InsertDropTarget(DropTargetNode* nodeToAdd)
1646 DropTargetNode* curNode;
1647 DropTargetNode** parentNodeLink;
1650 * Iterate the tree to find the insertion point.
1652 curNode = targetListHead;
1653 parentNodeLink = &targetListHead;
1655 while (curNode!=NULL)
1657 if (nodeToAdd->hwndTarget<curNode->hwndTarget)
1660 * If the node we want to add has a smaller HWND, go left
1662 parentNodeLink = &curNode->prevDropTarget;
1663 curNode = curNode->prevDropTarget;
1665 else if (nodeToAdd->hwndTarget>curNode->hwndTarget)
1668 * If the node we want to add has a larger HWND, go right
1670 parentNodeLink = &curNode->nextDropTarget;
1671 curNode = curNode->nextDropTarget;
1676 * The item was found in the list. It shouldn't have been there
1684 * If we get here, we have found a spot for our item. The parentNodeLink
1685 * pointer points to the pointer that we have to modify.
1686 * The curNode should be NULL. We just have to establish the link and Voila!
1688 assert(curNode==NULL);
1689 assert(parentNodeLink!=NULL);
1690 assert(*parentNodeLink==NULL);
1692 *parentNodeLink=nodeToAdd;
1696 * OLEDD_ExtractDropTarget()
1698 * Removes the target node from the tree.
1700 static DropTargetNode* OLEDD_ExtractDropTarget(HWND hwndOfTarget)
1702 DropTargetNode* curNode;
1703 DropTargetNode** parentNodeLink;
1706 * Iterate the tree to find the insertion point.
1708 curNode = targetListHead;
1709 parentNodeLink = &targetListHead;
1711 while (curNode!=NULL)
1713 if (hwndOfTarget<curNode->hwndTarget)
1716 * If the node we want to add has a smaller HWND, go left
1718 parentNodeLink = &curNode->prevDropTarget;
1719 curNode = curNode->prevDropTarget;
1721 else if (hwndOfTarget>curNode->hwndTarget)
1724 * If the node we want to add has a larger HWND, go right
1726 parentNodeLink = &curNode->nextDropTarget;
1727 curNode = curNode->nextDropTarget;
1732 * The item was found in the list. Detach it from it's parent and
1733 * re-insert it's kids in the tree.
1735 assert(parentNodeLink!=NULL);
1736 assert(*parentNodeLink==curNode);
1739 * We arbitrately re-attach the left sub-tree to the parent.
1741 *parentNodeLink = curNode->prevDropTarget;
1744 * And we re-insert the right subtree
1746 if (curNode->nextDropTarget!=NULL)
1748 OLEDD_InsertDropTarget(curNode->nextDropTarget);
1752 * The node we found is still a valid node once we complete
1753 * the unlinking of the kids.
1755 curNode->nextDropTarget=NULL;
1756 curNode->prevDropTarget=NULL;
1763 * If we get here, the node is not in the tree
1769 * OLEDD_FindDropTarget()
1771 * Finds information about the drop target.
1773 static DropTargetNode* OLEDD_FindDropTarget(HWND hwndOfTarget)
1775 DropTargetNode* curNode;
1778 * Iterate the tree to find the HWND value.
1780 curNode = targetListHead;
1782 while (curNode!=NULL)
1784 if (hwndOfTarget<curNode->hwndTarget)
1787 * If the node we want to add has a smaller HWND, go left
1789 curNode = curNode->prevDropTarget;
1791 else if (hwndOfTarget>curNode->hwndTarget)
1794 * If the node we want to add has a larger HWND, go right
1796 curNode = curNode->nextDropTarget;
1801 * The item was found in the list.
1808 * If we get here, the item is not in the list
1814 * OLEDD_DragTrackerWindowProc()
1816 * This method is the WindowProcedure of the drag n drop tracking
1817 * window. During a drag n Drop operation, an invisible window is created
1818 * to receive the user input and act upon it. This procedure is in charge
1821 static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
1831 LPCREATESTRUCTA createStruct = (LPCREATESTRUCTA)lParam;
1833 SetWindowLongA(hwnd, 0, (LONG)createStruct->lpCreateParams);
1840 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
1844 * Get the current mouse position in screen coordinates.
1846 mousePos.x = LOWORD(lParam);
1847 mousePos.y = HIWORD(lParam);
1848 ClientToScreen(hwnd, &mousePos);
1851 * Track the movement of the mouse.
1853 OLEDD_TrackMouseMove(trackerInfo, mousePos, wParam);
1860 case WM_LBUTTONDOWN:
1861 case WM_MBUTTONDOWN:
1862 case WM_RBUTTONDOWN:
1864 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
1868 * Get the current mouse position in screen coordinates.
1870 mousePos.x = LOWORD(lParam);
1871 mousePos.y = HIWORD(lParam);
1872 ClientToScreen(hwnd, &mousePos);
1875 * Notify everyone that the button state changed
1876 * TODO: Check if the "escape" key was pressed.
1878 OLEDD_TrackStateChange(trackerInfo, mousePos, wParam);
1885 * This is a window proc after all. Let's call the default.
1887 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1891 * OLEDD_TrackMouseMove()
1893 * This method is invoked while a drag and drop operation is in effect.
1894 * it will generate the appropriate callbacks in the drop source
1895 * and drop target. It will also provide the expected feedback to
1899 * trackerInfo - Pointer to the structure identifying the
1900 * drag & drop operation that is currently
1902 * mousePos - Current position of the mouse in screen
1904 * keyState - Contains the state of the shift keys and the
1905 * mouse buttons (MK_LBUTTON and the like)
1907 static void OLEDD_TrackMouseMove(
1908 TrackerWindowInfo* trackerInfo,
1912 HWND hwndNewTarget = 0;
1916 * Get the handle of the window under the mouse
1918 hwndNewTarget = WindowFromPoint(mousePos);
1921 * Every time, we re-initialize the effects passed to the
1922 * IDropTarget to the effects allowed by the source.
1924 *trackerInfo->pdwEffect = trackerInfo->dwOKEffect;
1927 * If we are hovering over the same target as before, send the
1928 * DragOver notification
1930 if ( (trackerInfo->curDragTarget != 0) &&
1931 (trackerInfo->curDragTargetHWND==hwndNewTarget) )
1933 POINTL mousePosParam;
1936 * The documentation tells me that the coordinate should be in the target
1937 * window's coordinate space. However, the tests I made tell me the
1938 * coordinates should be in screen coordinates.
1940 mousePosParam.x = mousePos.x;
1941 mousePosParam.y = mousePos.y;
1943 IDropTarget_DragOver(trackerInfo->curDragTarget,
1946 trackerInfo->pdwEffect);
1950 DropTargetNode* newDropTargetNode = 0;
1953 * If we changed window, we have to notify our old target and check for
1956 if (trackerInfo->curDragTarget!=0)
1958 IDropTarget_DragLeave(trackerInfo->curDragTarget);
1962 * Make sure we're hovering over a window.
1964 if (hwndNewTarget!=0)
1967 * Find-out if there is a drag target under the mouse
1969 HWND nexttar = hwndNewTarget;
1971 newDropTargetNode = OLEDD_FindDropTarget(nexttar);
1972 } while (!newDropTargetNode && (nexttar = GetParent(nexttar)) != 0);
1973 if(nexttar) hwndNewTarget = nexttar;
1975 trackerInfo->curDragTargetHWND = hwndNewTarget;
1976 trackerInfo->curDragTarget = newDropTargetNode ? newDropTargetNode->dropTarget : 0;
1979 * If there is, notify it that we just dragged-in
1981 if (trackerInfo->curDragTarget!=0)
1983 POINTL mousePosParam;
1986 * The documentation tells me that the coordinate should be in the target
1987 * window's coordinate space. However, the tests I made tell me the
1988 * coordinates should be in screen coordinates.
1990 mousePosParam.x = mousePos.x;
1991 mousePosParam.y = mousePos.y;
1993 IDropTarget_DragEnter(trackerInfo->curDragTarget,
1994 trackerInfo->dataObject,
1997 trackerInfo->pdwEffect);
2003 * The mouse is not over a window so we don't track anything.
2005 trackerInfo->curDragTargetHWND = 0;
2006 trackerInfo->curDragTarget = 0;
2011 * Now that we have done that, we have to tell the source to give
2012 * us feedback on the work being done by the target. If we don't
2013 * have a target, simulate no effect.
2015 if (trackerInfo->curDragTarget==0)
2017 *trackerInfo->pdwEffect = DROPEFFECT_NONE;
2020 hr = IDropSource_GiveFeedback(trackerInfo->dropSource,
2021 *trackerInfo->pdwEffect);
2024 * When we ask for feedback from the drop source, sometimes it will
2025 * do all the necessary work and sometimes it will not handle it
2026 * when that's the case, we must display the standard drag and drop
2029 if (hr==DRAGDROP_S_USEDEFAULTCURSORS)
2031 if (*trackerInfo->pdwEffect & DROPEFFECT_MOVE)
2033 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(1)));
2035 else if (*trackerInfo->pdwEffect & DROPEFFECT_COPY)
2037 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(2)));
2039 else if (*trackerInfo->pdwEffect & DROPEFFECT_LINK)
2041 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(3)));
2045 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(0)));
2051 * OLEDD_TrackStateChange()
2053 * This method is invoked while a drag and drop operation is in effect.
2054 * It is used to notify the drop target/drop source callbacks when
2055 * the state of the keyboard or mouse button change.
2058 * trackerInfo - Pointer to the structure identifying the
2059 * drag & drop operation that is currently
2061 * mousePos - Current position of the mouse in screen
2063 * keyState - Contains the state of the shift keys and the
2064 * mouse buttons (MK_LBUTTON and the like)
2066 static void OLEDD_TrackStateChange(
2067 TrackerWindowInfo* trackerInfo,
2072 * Ask the drop source what to do with the operation.
2074 trackerInfo->returnValue = IDropSource_QueryContinueDrag(
2075 trackerInfo->dropSource,
2076 trackerInfo->escPressed,
2080 * All the return valued will stop the operation except the S_OK
2083 if (trackerInfo->returnValue!=S_OK)
2086 * Make sure the message loop in DoDragDrop stops
2088 trackerInfo->trackingDone = TRUE;
2091 * Release the mouse in case the drop target decides to show a popup
2092 * or a menu or something.
2097 * If we end-up over a target, drop the object in the target or
2098 * inform the target that the operation was cancelled.
2100 if (trackerInfo->curDragTarget!=0)
2102 switch (trackerInfo->returnValue)
2105 * If the source wants us to complete the operation, we tell
2106 * the drop target that we just dropped the object in it.
2108 case DRAGDROP_S_DROP:
2110 POINTL mousePosParam;
2113 * The documentation tells me that the coordinate should be
2114 * in the target window's coordinate space. However, the tests
2115 * I made tell me the coordinates should be in screen coordinates.
2117 mousePosParam.x = mousePos.x;
2118 mousePosParam.y = mousePos.y;
2120 IDropTarget_Drop(trackerInfo->curDragTarget,
2121 trackerInfo->dataObject,
2124 trackerInfo->pdwEffect);
2128 * If the source told us that we should cancel, fool the drop
2129 * target by telling it that the mouse left it's window.
2130 * Also set the drop effect to "NONE" in case the application
2131 * ignores the result of DoDragDrop.
2133 case DRAGDROP_S_CANCEL:
2134 IDropTarget_DragLeave(trackerInfo->curDragTarget);
2135 *trackerInfo->pdwEffect = DROPEFFECT_NONE;
2143 * OLEDD_GetButtonState()
2145 * This method will use the current state of the keyboard to build
2146 * a button state mask equivalent to the one passed in the
2147 * WM_MOUSEMOVE wParam.
2149 static DWORD OLEDD_GetButtonState()
2151 BYTE keyboardState[256];
2154 GetKeyboardState(keyboardState);
2156 if ( (keyboardState[VK_SHIFT] & 0x80) !=0)
2157 keyMask |= MK_SHIFT;
2159 if ( (keyboardState[VK_CONTROL] & 0x80) !=0)
2160 keyMask |= MK_CONTROL;
2162 if ( (keyboardState[VK_LBUTTON] & 0x80) !=0)
2163 keyMask |= MK_LBUTTON;
2165 if ( (keyboardState[VK_RBUTTON] & 0x80) !=0)
2166 keyMask |= MK_RBUTTON;
2168 if ( (keyboardState[VK_MBUTTON] & 0x80) !=0)
2169 keyMask |= MK_MBUTTON;
2175 * OLEDD_GetButtonState()
2177 * This method will read the default value of the registry key in
2178 * parameter and extract a DWORD value from it. The registry key value
2179 * can be in a string key or a DWORD key.
2182 * regKey - Key to read the default value from
2183 * pdwValue - Pointer to the location where the DWORD
2184 * value is returned. This value is not modified
2185 * if the value is not found.
2188 static void OLEUTL_ReadRegistryDWORDValue(
2197 lres = RegQueryValueExA(regKey,
2204 if (lres==ERROR_SUCCESS)
2209 *pdwValue = *(DWORD*)buffer;
2214 *pdwValue = (DWORD)strtoul(buffer, NULL, 10);
2220 /******************************************************************************
2221 * OleMetaFilePictFromIconAndLabel (OLE2.56)
2223 * Returns a global memory handle to a metafile which contains the icon and
2225 * I guess the result of that should look somehow like desktop icons.
2226 * If no hIcon is given, we load the icon via lpszSourceFile and iIconIndex.
2227 * This code might be wrong at some places.
2229 HGLOBAL16 WINAPI OleMetaFilePictFromIconAndLabel16(
2231 LPCOLESTR16 lpszLabel,
2232 LPCOLESTR16 lpszSourceFile,
2239 FIXME("(%04x, '%s', '%s', %d): incorrect metrics, please try to correct them !\n\n\n", hIcon, lpszLabel, lpszSourceFile, iIconIndex);
2242 if (lpszSourceFile) {
2243 HINSTANCE16 hInstance = LoadLibrary16(lpszSourceFile);
2245 /* load the icon at index from lpszSourceFile */
2246 hIcon = HICON_16(LoadIconA(hInstance, (LPCSTR)(DWORD)iIconIndex));
2247 FreeLibrary16(hInstance);
2249 return (HGLOBAL)NULL;
2252 hdc = CreateMetaFileA(NULL);
2253 DrawIcon(hdc, 0, 0, HICON_32(hIcon)); /* FIXME */
2254 TextOutA(hdc, 0, 0, lpszLabel, 1); /* FIXME */
2255 hmf = GlobalAlloc16(0, sizeof(METAFILEPICT16));
2256 mf = (METAFILEPICT16 *)GlobalLock16(hmf);
2257 mf->mm = MM_ANISOTROPIC;
2258 mf->xExt = 20; /* FIXME: bogus */
2259 mf->yExt = 20; /* dito */
2260 mf->hMF = CloseMetaFile16(HDC_16(hdc));
2264 /******************************************************************************
2265 * DllDebugObjectRPCHook (OLE32.62)
2266 * turns on and off internal debugging, pointer is only used on macintosh
2269 BOOL WINAPI DllDebugObjectRPCHook(BOOL b, void *dummy)