4 * Copyright 1995 Martin von Loewis
5 * Copyright 1999 Francis Beaudet
6 * Copyright 1999 Noel Borthwick
21 #include "wine/obj_clientserver.h"
22 #include "wine/winbase16.h"
23 #include "wine/wingdi16.h"
24 #include "debugtools.h"
28 DEFAULT_DEBUG_CHANNEL(ole);
30 /******************************************************************************
31 * These are static/global variables and internal data structures that the
32 * OLE module uses to maintain it's state.
34 typedef struct tagDropTargetNode
37 IDropTarget* dropTarget;
38 struct tagDropTargetNode* prevDropTarget;
39 struct tagDropTargetNode* nextDropTarget;
42 typedef struct tagTrackerWindowInfo
44 IDataObject* dataObject;
45 IDropSource* dropSource;
52 HWND curDragTargetHWND;
53 IDropTarget* curDragTarget;
56 typedef struct tagOleMenuDescriptor /* OleMenuDescriptor */
58 HWND hwndFrame; /* The containers frame window */
59 HWND hwndActiveObject; /* The active objects window */
60 OLEMENUGROUPWIDTHS mgw; /* OLE menu group widths for the shared menu */
61 HMENU hmenuCombined; /* The combined menu */
62 BOOL bIsServerItem; /* True if the currently open popup belongs to the server */
65 typedef struct tagOleMenuHookItem /* OleMenu hook item in per thread hook list */
67 DWORD tid; /* Thread Id */
68 HANDLE hHeap; /* Heap this is allocated from */
69 HHOOK GetMsg_hHook; /* message hook for WH_GETMESSAGE */
70 HHOOK CallWndProc_hHook; /* message hook for WH_CALLWNDPROC */
71 struct tagOleMenuHookItem *next;
74 static OleMenuHookItem *hook_list;
77 * This is the lock count on the OLE library. It is controlled by the
78 * OLEInitialize/OLEUninitialize methods.
80 static ULONG OLE_moduleLockCount = 0;
83 * Name of our registered window class.
85 static const char OLEDD_DRAGTRACKERCLASS[] = "WineDragDropTracker32";
88 * This is the head of the Drop target container.
90 static DropTargetNode* targetListHead = NULL;
92 /******************************************************************************
93 * These are the prototypes of miscelaneous utility methods
95 static void OLEUTL_ReadRegistryDWORDValue(HKEY regKey, DWORD* pdwValue);
97 /******************************************************************************
98 * These are the prototypes of the utility methods used to manage a shared menu
100 static void OLEMenu_Initialize();
101 static void OLEMenu_UnInitialize();
102 BOOL OLEMenu_InstallHooks( DWORD tid );
103 BOOL OLEMenu_UnInstallHooks( DWORD tid );
104 OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid );
105 static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos );
106 BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor );
107 LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam);
108 LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam);
110 /******************************************************************************
111 * These are the prototypes of the OLE Clipboard initialization methods (in clipboard.c)
113 void OLEClipbrd_UnInitialize();
114 void OLEClipbrd_Initialize();
116 /******************************************************************************
117 * These are the prototypes of the utility methods used for OLE Drag n Drop
119 static void OLEDD_Initialize();
120 static void OLEDD_UnInitialize();
121 static void OLEDD_InsertDropTarget(
122 DropTargetNode* nodeToAdd);
123 static DropTargetNode* OLEDD_ExtractDropTarget(
125 static DropTargetNode* OLEDD_FindDropTarget(
127 static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
132 static void OLEDD_TrackMouseMove(
133 TrackerWindowInfo* trackerInfo,
136 static void OLEDD_TrackStateChange(
137 TrackerWindowInfo* trackerInfo,
140 static DWORD OLEDD_GetButtonState();
143 /******************************************************************************
144 * OleBuildVersion [OLE2.1]
146 DWORD WINAPI OleBuildVersion(void)
148 TRACE("Returning version %d, build %d.\n", rmm, rup);
149 return (rmm<<16)+rup;
152 /***********************************************************************
153 * OleInitialize (OLE2.2) (OLE32.108)
155 HRESULT WINAPI OleInitialize(LPVOID reserved)
159 TRACE("(%p)\n", reserved);
162 * The first duty of the OleInitialize is to initialize the COM libraries.
164 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
167 * If the CoInitializeEx call failed, the OLE libraries can't be
174 * Then, it has to initialize the OLE specific modules.
178 * Object linking and Embedding
179 * In-place activation
181 if (OLE_moduleLockCount==0)
184 * Initialize the libraries.
186 TRACE("() - Initializing the OLE libraries\n");
191 OLEClipbrd_Initialize();
201 OLEMenu_Initialize();
205 * Then, we increase the lock count on the OLE module.
207 OLE_moduleLockCount++;
212 /******************************************************************************
213 * CoGetCurrentProcess [COMPOBJ.34] [OLE2.2][OLE32.108]
216 * Is DWORD really the correct return type for this function?
218 DWORD WINAPI CoGetCurrentProcess(void) {
219 return (DWORD)PROCESS_Current();
222 /******************************************************************************
223 * OleUninitialize [OLE2.3] [OLE32.131]
225 void WINAPI OleUninitialize(void)
230 * Decrease the lock count on the OLE module.
232 OLE_moduleLockCount--;
235 * If we hit the bottom of the lock stack, free the libraries.
237 if (OLE_moduleLockCount==0)
240 * Actually free the libraries.
242 TRACE("() - Freeing the last reference count\n");
247 OLEClipbrd_UnInitialize();
252 OLEDD_UnInitialize();
257 OLEMenu_UnInitialize();
261 * Then, uninitialize the COM libraries.
266 /******************************************************************************
267 * CoRegisterMessageFilter [OLE32.38]
269 HRESULT WINAPI CoRegisterMessageFilter(
270 LPMESSAGEFILTER lpMessageFilter, /* Pointer to interface */
271 LPMESSAGEFILTER *lplpMessageFilter /* Indirect pointer to prior instance if non-NULL */
274 if (lplpMessageFilter) {
275 *lplpMessageFilter = NULL;
280 /******************************************************************************
281 * OleInitializeWOW [OLE32.109]
283 HRESULT WINAPI OleInitializeWOW(DWORD x) {
284 FIXME("(0x%08lx),stub!\n",x);
288 /***********************************************************************
289 * RegisterDragDrop16 (OLE2.35)
291 HRESULT WINAPI RegisterDragDrop16(
293 LPDROPTARGET pDropTarget
295 FIXME("(0x%04x,%p),stub!\n",hwnd,pDropTarget);
299 /***********************************************************************
300 * RegisterDragDrop (OLE32.139)
302 HRESULT WINAPI RegisterDragDrop(
304 LPDROPTARGET pDropTarget)
306 DropTargetNode* dropTargetInfo;
308 TRACE("(0x%x,%p)\n", hwnd, pDropTarget);
311 * First, check if the window is already registered.
313 dropTargetInfo = OLEDD_FindDropTarget(hwnd);
315 if (dropTargetInfo!=NULL)
316 return DRAGDROP_E_ALREADYREGISTERED;
319 * If it's not there, we can add it. We first create a node for it.
321 dropTargetInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(DropTargetNode));
323 if (dropTargetInfo==NULL)
324 return E_OUTOFMEMORY;
326 dropTargetInfo->hwndTarget = hwnd;
327 dropTargetInfo->prevDropTarget = NULL;
328 dropTargetInfo->nextDropTarget = NULL;
331 * Don't forget that this is an interface pointer, need to nail it down since
332 * we keep a copy of it.
334 dropTargetInfo->dropTarget = pDropTarget;
335 IDropTarget_AddRef(dropTargetInfo->dropTarget);
337 OLEDD_InsertDropTarget(dropTargetInfo);
342 /***********************************************************************
343 * RevokeDragDrop16 (OLE2.36)
345 HRESULT WINAPI RevokeDragDrop16(
348 FIXME("(0x%04x),stub!\n",hwnd);
352 /***********************************************************************
353 * RevokeDragDrop (OLE32.141)
355 HRESULT WINAPI RevokeDragDrop(
358 DropTargetNode* dropTargetInfo;
360 TRACE("(0x%x)\n", hwnd);
363 * First, check if the window is already registered.
365 dropTargetInfo = OLEDD_ExtractDropTarget(hwnd);
368 * If it ain't in there, it's an error.
370 if (dropTargetInfo==NULL)
371 return DRAGDROP_E_NOTREGISTERED;
374 * If it's in there, clean-up it's used memory and
377 IDropTarget_Release(dropTargetInfo->dropTarget);
378 HeapFree(GetProcessHeap(), 0, dropTargetInfo);
383 /***********************************************************************
384 * OleRegGetUserType (OLE32.122)
386 * This implementation of OleRegGetUserType ignores the dwFormOfType
387 * parameter and always returns the full name of the object. This is
388 * not too bad since this is the case for many objects because of the
389 * way they are registered.
391 HRESULT WINAPI OleRegGetUserType(
394 LPOLESTR* pszUserType)
405 * Initialize the out parameter.
410 * Build the key name we're looking for
412 WINE_StringFromCLSID((LPCLSID)clsid, xclsid);
414 strcpy(keyName, "CLSID\\");
415 strcat(keyName, xclsid);
416 strcat(keyName, "\\");
418 TRACE("(%s, %ld, %p)\n", keyName, dwFormOfType, pszUserType);
421 * Open the class id Key
423 hres = RegOpenKeyA(HKEY_CLASSES_ROOT,
427 if (hres != ERROR_SUCCESS)
428 return REGDB_E_CLASSNOTREG;
431 * Retrieve the size of the name string.
435 hres = RegQueryValueExA(clsidKey,
442 if (hres!=ERROR_SUCCESS)
444 RegCloseKey(clsidKey);
445 return REGDB_E_READREGDB;
449 * Allocate a buffer for the registry value.
451 *pszUserType = CoTaskMemAlloc(cbData*2);
453 if (*pszUserType==NULL)
455 RegCloseKey(clsidKey);
456 return E_OUTOFMEMORY;
459 buffer = HeapAlloc(GetProcessHeap(), 0, cbData);
463 RegCloseKey(clsidKey);
464 CoTaskMemFree(*pszUserType);
466 return E_OUTOFMEMORY;
469 hres = RegQueryValueExA(clsidKey,
476 RegCloseKey(clsidKey);
479 if (hres!=ERROR_SUCCESS)
481 CoTaskMemFree(*pszUserType);
484 retVal = REGDB_E_READREGDB;
488 lstrcpyAtoW(*pszUserType, buffer);
491 HeapFree(GetProcessHeap(), 0, buffer);
496 /***********************************************************************
497 * DoDragDrop [OLE32.65]
499 HRESULT WINAPI DoDragDrop (
500 IDataObject *pDataObject, /* ptr to the data obj */
501 IDropSource* pDropSource, /* ptr to the source obj */
502 DWORD dwOKEffect, /* effects allowed by the source */
503 DWORD *pdwEffect) /* ptr to effects of the source */
505 TrackerWindowInfo trackerInfo;
506 HWND hwndTrackWindow;
509 TRACE("(DataObject %p, DropSource %p)\n", pDataObject, pDropSource);
512 * Setup the drag n drop tracking window.
514 trackerInfo.dataObject = pDataObject;
515 trackerInfo.dropSource = pDropSource;
516 trackerInfo.dwOKEffect = dwOKEffect;
517 trackerInfo.pdwEffect = pdwEffect;
518 trackerInfo.trackingDone = FALSE;
519 trackerInfo.escPressed = FALSE;
520 trackerInfo.curDragTargetHWND = 0;
521 trackerInfo.curDragTarget = 0;
523 hwndTrackWindow = CreateWindowA(OLEDD_DRAGTRACKERCLASS,
526 CW_USEDEFAULT, CW_USEDEFAULT,
527 CW_USEDEFAULT, CW_USEDEFAULT,
531 (LPVOID)&trackerInfo);
533 if (hwndTrackWindow!=0)
536 * Capture the mouse input
538 SetCapture(hwndTrackWindow);
541 * Pump messages. All mouse input should go the the capture window.
543 while (!trackerInfo.trackingDone && GetMessageA(&msg, 0, 0, 0) )
545 if ( (msg.message >= WM_KEYFIRST) &&
546 (msg.message <= WM_KEYFIRST) )
549 * When keyboard messages are sent to windows on this thread, we
550 * want to ignore notify the drop source that the state changed.
551 * in the case of the Escape key, we also notify the drop source
552 * we give it a special meaning.
554 if ( (msg.message==WM_KEYDOWN) &&
555 (msg.wParam==VK_ESCAPE) )
557 trackerInfo.escPressed = TRUE;
561 * Notify the drop source.
563 OLEDD_TrackStateChange(&trackerInfo,
565 OLEDD_GetButtonState());
570 * Dispatch the messages only when it's not a keyboard message.
572 DispatchMessageA(&msg);
577 * Destroy the temporary window.
579 DestroyWindow(hwndTrackWindow);
581 return trackerInfo.returnValue;
587 /***********************************************************************
588 * OleQueryLinkFromData [OLE32.118]
590 HRESULT WINAPI OleQueryLinkFromData(
591 IDataObject* pSrcDataObject)
593 FIXME("(%p),stub!\n", pSrcDataObject);
597 /***********************************************************************
598 * OleRegGetMiscStatus [OLE32.121]
600 HRESULT WINAPI OleRegGetMiscStatus(
613 * Initialize the out parameter.
618 * Build the key name we're looking for
620 WINE_StringFromCLSID((LPCLSID)clsid, xclsid);
622 strcpy(keyName, "CLSID\\");
623 strcat(keyName, xclsid);
624 strcat(keyName, "\\");
626 TRACE("(%s, %ld, %p)\n", keyName, dwAspect, pdwStatus);
629 * Open the class id Key
631 result = RegOpenKeyA(HKEY_CLASSES_ROOT,
635 if (result != ERROR_SUCCESS)
636 return REGDB_E_CLASSNOTREG;
641 result = RegOpenKeyA(clsidKey,
646 if (result != ERROR_SUCCESS)
648 RegCloseKey(clsidKey);
649 return REGDB_E_READREGDB;
653 * Read the default value
655 OLEUTL_ReadRegistryDWORDValue(miscStatusKey, pdwStatus);
658 * Open the key specific to the requested aspect.
660 sprintf(keyName, "%ld", dwAspect);
662 result = RegOpenKeyA(miscStatusKey,
666 if (result == ERROR_SUCCESS)
668 OLEUTL_ReadRegistryDWORDValue(aspectKey, pdwStatus);
669 RegCloseKey(aspectKey);
675 RegCloseKey(miscStatusKey);
676 RegCloseKey(clsidKey);
681 /******************************************************************************
682 * OleSetContainedObject [OLE32.128]
684 HRESULT WINAPI OleSetContainedObject(
688 IRunnableObject* runnable = NULL;
691 TRACE("(%p,%x), stub!\n", pUnknown, fContained);
693 hres = IUnknown_QueryInterface(pUnknown,
694 &IID_IRunnableObject,
699 hres = IRunnableObject_SetContainedObject(runnable, fContained);
701 IRunnableObject_Release(runnable);
709 /******************************************************************************
710 * OleLoad [OLE32.112]
712 HRESULT WINAPI OleLoad(
715 LPOLECLIENTSITE pClientSite,
718 IPersistStorage* persistStorage = NULL;
719 IOleObject* oleObject = NULL;
723 TRACE("(%p,%p,%p,%p)\n", pStg, riid, pClientSite, ppvObj);
726 * TODO, Conversion ... OleDoAutoConvert
730 * Get the class ID for the object.
732 hres = IStorage_Stat(pStg, &storageInfo, STATFLAG_NONAME);
735 * Now, try and create the handler for the object
737 hres = CoCreateInstance(&storageInfo.clsid,
739 CLSCTX_INPROC_HANDLER,
744 * If that fails, as it will most times, load the default
749 hres = OleCreateDefaultHandler(&storageInfo.clsid,
756 * If we couldn't find a handler... this is bad. Abort the whole thing.
762 * Inform the new object of it's client site.
764 hres = IOleObject_SetClientSite(oleObject, pClientSite);
767 * Initialize the object with it's IPersistStorage interface.
769 hres = IOleObject_QueryInterface(oleObject,
770 &IID_IPersistStorage,
771 (void**)&persistStorage);
775 IPersistStorage_Load(persistStorage, pStg);
777 IPersistStorage_Release(persistStorage);
778 persistStorage = NULL;
782 * Return the requested interface to the caller.
784 hres = IOleObject_QueryInterface(oleObject, riid, ppvObj);
787 * Cleanup interfaces used internally
789 IOleObject_Release(oleObject);
794 /***********************************************************************
795 * OleSave [OLE32.124]
797 HRESULT WINAPI OleSave(
798 LPPERSISTSTORAGE pPS,
805 TRACE("(%p,%p,%x)\n", pPS, pStg, fSameAsLoad);
808 * First, we transfer the class ID (if available)
810 hres = IPersistStorage_GetClassID(pPS, &objectClass);
814 WriteClassStg(pStg, &objectClass);
818 * Then, we ask the object to save itself to the
819 * storage. If it is successful, we commit the storage.
821 hres = IPersistStorage_Save(pPS, pStg, fSameAsLoad);
825 IStorage_Commit(pStg,
833 /**************************************************************************
834 * Internal methods to manage the shared OLE menu in response to the
835 * OLE***MenuDescriptor API
839 * OLEMenu_Initialize()
841 * Initializes the OLEMENU data structures.
843 static void OLEMenu_Initialize()
848 * OLEMenu_UnInitialize()
850 * Releases the OLEMENU data structures.
852 static void OLEMenu_UnInitialize()
856 /*************************************************************************
857 * OLEMenu_InstallHooks
858 * Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
860 * RETURNS: TRUE if message hooks were succesfully installed
863 BOOL OLEMenu_InstallHooks( DWORD tid )
865 OleMenuHookItem *pHookItem = NULL;
867 /* Create an entry for the hook table */
868 if ( !(pHookItem = HeapAlloc(GetProcessHeap(), 0,
869 sizeof(OleMenuHookItem)) ) )
872 pHookItem->tid = tid;
873 pHookItem->hHeap = GetProcessHeap();
875 /* Install a thread scope message hook for WH_GETMESSAGE */
876 pHookItem->GetMsg_hHook = SetWindowsHookExA( WH_GETMESSAGE, OLEMenu_GetMsgProc,
877 0, GetCurrentThreadId() );
878 if ( !pHookItem->GetMsg_hHook )
881 /* Install a thread scope message hook for WH_CALLWNDPROC */
882 pHookItem->CallWndProc_hHook = SetWindowsHookExA( WH_CALLWNDPROC, OLEMenu_CallWndProc,
883 0, GetCurrentThreadId() );
884 if ( !pHookItem->CallWndProc_hHook )
887 /* Insert the hook table entry */
888 pHookItem->next = hook_list;
889 hook_list = pHookItem;
894 /* Unhook any hooks */
895 if ( pHookItem->GetMsg_hHook )
896 UnhookWindowsHookEx( pHookItem->GetMsg_hHook );
897 if ( pHookItem->CallWndProc_hHook )
898 UnhookWindowsHookEx( pHookItem->CallWndProc_hHook );
899 /* Release the hook table entry */
900 HeapFree(pHookItem->hHeap, 0, pHookItem );
905 /*************************************************************************
906 * OLEMenu_UnInstallHooks
907 * UnInstall thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
909 * RETURNS: TRUE if message hooks were succesfully installed
912 BOOL OLEMenu_UnInstallHooks( DWORD tid )
914 OleMenuHookItem *pHookItem = NULL;
915 OleMenuHookItem **ppHook = &hook_list;
919 if ((*ppHook)->tid == tid)
922 *ppHook = pHookItem->next;
925 ppHook = &(*ppHook)->next;
927 if (!pHookItem) return FALSE;
929 /* Uninstall the hooks installed for this thread */
930 if ( !UnhookWindowsHookEx( pHookItem->GetMsg_hHook ) )
932 if ( !UnhookWindowsHookEx( pHookItem->CallWndProc_hHook ) )
935 /* Release the hook table entry */
936 HeapFree(pHookItem->hHeap, 0, pHookItem );
941 /* Release the hook table entry */
943 HeapFree(pHookItem->hHeap, 0, pHookItem );
948 /*************************************************************************
949 * OLEMenu_IsHookInstalled
950 * Tests if OLEMenu hooks have been installed for a thread
952 * RETURNS: The pointer and index of the hook table entry for the tid
953 * NULL and -1 for the index if no hooks were installed for this thread
955 OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid )
957 OleMenuHookItem *pHookItem = NULL;
959 /* Do a simple linear search for an entry whose tid matches ours.
960 * We really need a map but efficiency is not a concern here. */
961 for (pHookItem = hook_list; pHookItem; pHookItem = pHookItem->next)
963 if ( tid == pHookItem->tid )
970 /***********************************************************************
971 * OLEMenu_FindMainMenuIndex
973 * Used by OLEMenu API to find the top level group a menu item belongs to.
974 * On success pnPos contains the index of the item in the top level menu group
976 * RETURNS: TRUE if the ID was found, FALSE on failure
978 static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos )
982 nItems = GetMenuItemCount( hMainMenu );
984 for (i = 0; i < nItems; i++)
988 /* Is the current item a submenu? */
989 if ( (hsubmenu = GetSubMenu(hMainMenu, i)) )
991 /* If the handle is the same we're done */
992 if ( hsubmenu == hPopupMenu )
998 /* Recursively search without updating pnPos */
999 else if ( OLEMenu_FindMainMenuIndex( hsubmenu, hPopupMenu, NULL ) )
1011 /***********************************************************************
1012 * OLEMenu_SetIsServerMenu
1014 * Checks whether a popup menu belongs to a shared menu group which is
1015 * owned by the server, and sets the menu descriptor state accordingly.
1016 * All menu messages from these groups should be routed to the server.
1018 * RETURNS: TRUE if the popup menu is part of a server owned group
1019 * FASE if the popup menu is part of a container owned group
1021 BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor )
1023 UINT nPos = 0, nWidth, i;
1025 pOleMenuDescriptor->bIsServerItem = FALSE;
1027 /* Don't bother searching if the popup is the combined menu itself */
1028 if ( hmenu == pOleMenuDescriptor->hmenuCombined )
1031 /* Find the menu item index in the shared OLE menu that this item belongs to */
1032 if ( !OLEMenu_FindMainMenuIndex( pOleMenuDescriptor->hmenuCombined, hmenu, &nPos ) )
1035 /* The group widths array has counts for the number of elements
1036 * in the groups File, Edit, Container, Object, Window, Help.
1037 * The Edit, Object & Help groups belong to the server object
1038 * and the other three belong to the container.
1039 * Loop thru the group widths and locate the group we are a member of.
1041 for ( i = 0, nWidth = 0; i < 6; i++ )
1043 nWidth += pOleMenuDescriptor->mgw.width[i];
1044 if ( nPos < nWidth )
1046 /* Odd elements are server menu widths */
1047 pOleMenuDescriptor->bIsServerItem = (i%2) ? TRUE : FALSE;
1052 return pOleMenuDescriptor->bIsServerItem;
1055 /*************************************************************************
1056 * OLEMenu_CallWndProc
1057 * Thread scope WH_CALLWNDPROC hook proc filter function (callback)
1058 * This is invoked from a message hook installed in OleSetMenuDescriptor.
1060 LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam)
1062 LPCWPSTRUCT pMsg = NULL;
1063 HOLEMENU hOleMenu = 0;
1064 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1065 OleMenuHookItem *pHookItem = NULL;
1068 TRACE("%i, %04x, %08x\n", code, wParam, (unsigned)lParam );
1070 /* Check if we're being asked to process the message */
1071 if ( HC_ACTION != code )
1074 /* Retrieve the current message being dispatched from lParam */
1075 pMsg = (LPCWPSTRUCT)lParam;
1077 /* Check if the message is destined for a window we are interested in:
1078 * If the window has an OLEMenu property we may need to dispatch
1079 * the menu message to its active objects window instead. */
1081 hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" );
1085 /* Get the menu descriptor */
1086 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1087 if ( !pOleMenuDescriptor ) /* Bad descriptor! */
1090 /* Process menu messages */
1091 switch( pMsg->message )
1095 /* Reset the menu descriptor state */
1096 pOleMenuDescriptor->bIsServerItem = FALSE;
1098 /* Send this message to the server as well */
1099 SendMessageA( pOleMenuDescriptor->hwndActiveObject,
1100 pMsg->message, pMsg->wParam, pMsg->lParam );
1104 case WM_INITMENUPOPUP:
1106 /* Save the state for whether this is a server owned menu */
1107 OLEMenu_SetIsServerMenu( (HMENU)pMsg->wParam, pOleMenuDescriptor );
1113 fuFlags = HIWORD(pMsg->wParam); /* Get flags */
1114 if ( fuFlags & MF_SYSMENU )
1117 /* Save the state for whether this is a server owned popup menu */
1118 else if ( fuFlags & MF_POPUP )
1119 OLEMenu_SetIsServerMenu( (HMENU)pMsg->lParam, pOleMenuDescriptor );
1126 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) pMsg->lParam;
1127 if ( pMsg->wParam != 0 || lpdis->CtlType != ODT_MENU )
1128 goto NEXTHOOK; /* Not a menu message */
1137 /* If the message was for the server dispatch it accordingly */
1138 if ( pOleMenuDescriptor->bIsServerItem )
1140 SendMessageA( pOleMenuDescriptor->hwndActiveObject,
1141 pMsg->message, pMsg->wParam, pMsg->lParam );
1145 if ( pOleMenuDescriptor )
1146 GlobalUnlock( hOleMenu );
1148 /* Lookup the hook item for the current thread */
1149 if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) )
1151 /* This should never fail!! */
1152 WARN("could not retrieve hHook for current thread!\n" );
1156 /* Pass on the message to the next hooker */
1157 return CallNextHookEx( pHookItem->CallWndProc_hHook, code, wParam, lParam );
1160 /*************************************************************************
1161 * OLEMenu_GetMsgProc
1162 * Thread scope WH_GETMESSAGE hook proc filter function (callback)
1163 * This is invoked from a message hook installed in OleSetMenuDescriptor.
1165 LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam)
1168 HOLEMENU hOleMenu = 0;
1169 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1170 OleMenuHookItem *pHookItem = NULL;
1173 TRACE("%i, %04x, %08x\n", code, wParam, (unsigned)lParam );
1175 /* Check if we're being asked to process a messages */
1176 if ( HC_ACTION != code )
1179 /* Retrieve the current message being dispatched from lParam */
1180 pMsg = (LPMSG)lParam;
1182 /* Check if the message is destined for a window we are interested in:
1183 * If the window has an OLEMenu property we may need to dispatch
1184 * the menu message to its active objects window instead. */
1186 hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" );
1190 /* Process menu messages */
1191 switch( pMsg->message )
1195 wCode = HIWORD(pMsg->wParam); /* Get notification code */
1197 goto NEXTHOOK; /* Not a menu message */
1204 /* Get the menu descriptor */
1205 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1206 if ( !pOleMenuDescriptor ) /* Bad descriptor! */
1209 /* If the message was for the server dispatch it accordingly */
1210 if ( pOleMenuDescriptor->bIsServerItem )
1212 /* Change the hWnd in the message to the active objects hWnd.
1213 * The message loop which reads this message will automatically
1214 * dispatch it to the embedded objects window. */
1215 pMsg->hwnd = pOleMenuDescriptor->hwndActiveObject;
1219 if ( pOleMenuDescriptor )
1220 GlobalUnlock( hOleMenu );
1222 /* Lookup the hook item for the current thread */
1223 if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) )
1225 /* This should never fail!! */
1226 WARN("could not retrieve hHook for current thread!\n" );
1230 /* Pass on the message to the next hooker */
1231 return CallNextHookEx( pHookItem->GetMsg_hHook, code, wParam, lParam );
1234 /***********************************************************************
1235 * OleCreateMenuDescriptor [OLE32.97]
1236 * Creates an OLE menu descriptor for OLE to use when dispatching
1237 * menu messages and commands.
1240 * hmenuCombined - Handle to the objects combined menu
1241 * lpMenuWidths - Pointer to array of 6 LONG's indicating menus per group
1244 HOLEMENU WINAPI OleCreateMenuDescriptor(
1245 HMENU hmenuCombined,
1246 LPOLEMENUGROUPWIDTHS lpMenuWidths)
1249 OleMenuDescriptor *pOleMenuDescriptor;
1252 if ( !hmenuCombined || !lpMenuWidths )
1255 /* Create an OLE menu descriptor */
1256 if ( !(hOleMenu = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
1257 sizeof(OleMenuDescriptor) ) ) )
1260 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1261 if ( !pOleMenuDescriptor )
1264 /* Initialize menu group widths and hmenu */
1265 for ( i = 0; i < 6; i++ )
1266 pOleMenuDescriptor->mgw.width[i] = lpMenuWidths->width[i];
1268 pOleMenuDescriptor->hmenuCombined = hmenuCombined;
1269 pOleMenuDescriptor->bIsServerItem = FALSE;
1270 GlobalUnlock( hOleMenu );
1275 /***********************************************************************
1276 * OleDestroyMenuDescriptor [OLE32.99]
1277 * Destroy the shared menu descriptor
1279 HRESULT WINAPI OleDestroyMenuDescriptor(
1280 HOLEMENU hmenuDescriptor)
1282 if ( hmenuDescriptor )
1283 GlobalFree( hmenuDescriptor );
1287 /***********************************************************************
1288 * OleSetMenuDescriptor [OLE32.129]
1289 * Installs or removes OLE dispatching code for the containers frame window
1290 * FIXME: The lpFrame and lpActiveObject parameters are currently ignored
1291 * OLE should install context sensitive help F1 filtering for the app when
1292 * these are non null.
1295 * hOleMenu Handle to composite menu descriptor
1296 * hwndFrame Handle to containers frame window
1297 * hwndActiveObject Handle to objects in-place activation window
1298 * lpFrame Pointer to IOleInPlaceFrame on containers window
1299 * lpActiveObject Pointer to IOleInPlaceActiveObject on active in-place object
1302 * S_OK - menu installed correctly
1303 * E_FAIL, E_INVALIDARG, E_UNEXPECTED - failure
1305 HRESULT WINAPI OleSetMenuDescriptor(
1308 HWND hwndActiveObject,
1309 LPOLEINPLACEFRAME lpFrame,
1310 LPOLEINPLACEACTIVEOBJECT lpActiveObject)
1312 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1315 if ( !hwndFrame || (hOleMenu && !hwndActiveObject) )
1316 return E_INVALIDARG;
1318 if ( lpFrame || lpActiveObject )
1320 FIXME("(%x, %x, %x, %p, %p), Context sensitive help filtering not implemented!\n",
1321 (unsigned int)hOleMenu,
1328 /* Set up a message hook to intercept the containers frame window messages.
1329 * The message filter is responsible for dispatching menu messages from the
1330 * shared menu which are intended for the object.
1333 if ( hOleMenu ) /* Want to install dispatching code */
1335 /* If OLEMenu hooks are already installed for this thread, fail
1336 * Note: This effectively means that OleSetMenuDescriptor cannot
1337 * be called twice in succession on the same frame window
1338 * without first calling it with a null hOleMenu to uninstall */
1339 if ( OLEMenu_IsHookInstalled( GetCurrentThreadId() ) )
1342 /* Get the menu descriptor */
1343 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1344 if ( !pOleMenuDescriptor )
1345 return E_UNEXPECTED;
1347 /* Update the menu descriptor */
1348 pOleMenuDescriptor->hwndFrame = hwndFrame;
1349 pOleMenuDescriptor->hwndActiveObject = hwndActiveObject;
1351 GlobalUnlock( hOleMenu );
1352 pOleMenuDescriptor = NULL;
1354 /* Add a menu descriptor windows property to the frame window */
1355 SetPropA( hwndFrame, "PROP_OLEMenuDescriptor", hOleMenu );
1357 /* Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC */
1358 if ( !OLEMenu_InstallHooks( GetCurrentThreadId() ) )
1361 else /* Want to uninstall dispatching code */
1363 /* Uninstall the hooks */
1364 if ( !OLEMenu_UnInstallHooks( GetCurrentThreadId() ) )
1367 /* Remove the menu descriptor property from the frame window */
1368 RemovePropA( hwndFrame, "PROP_OLEMenuDescriptor" );
1374 /***********************************************************************
1375 * ReleaseStgMedium [OLE32.140]
1377 void WINAPI ReleaseStgMedium(
1380 switch (pmedium->tymed)
1384 if ( (pmedium->pUnkForRelease==0) &&
1385 (pmedium->u.hGlobal!=0) )
1386 GlobalFree(pmedium->u.hGlobal);
1388 pmedium->u.hGlobal = 0;
1393 if (pmedium->u.lpszFileName!=0)
1395 if (pmedium->pUnkForRelease==0)
1397 DeleteFileW(pmedium->u.lpszFileName);
1400 CoTaskMemFree(pmedium->u.lpszFileName);
1403 pmedium->u.lpszFileName = 0;
1408 if (pmedium->u.pstm!=0)
1410 IStream_Release(pmedium->u.pstm);
1413 pmedium->u.pstm = 0;
1416 case TYMED_ISTORAGE:
1418 if (pmedium->u.pstg!=0)
1420 IStorage_Release(pmedium->u.pstg);
1423 pmedium->u.pstg = 0;
1428 if ( (pmedium->pUnkForRelease==0) &&
1429 (pmedium->u.hGlobal!=0) )
1430 DeleteObject(pmedium->u.hGlobal);
1432 pmedium->u.hGlobal = 0;
1437 if ( (pmedium->pUnkForRelease==0) &&
1438 (pmedium->u.hMetaFilePict!=0) )
1440 DeleteMetaFile(pmedium->u.hMetaFilePict);
1441 GlobalFree(pmedium->u.hMetaFilePict);
1444 pmedium->u.hMetaFilePict = 0;
1449 if ( (pmedium->pUnkForRelease==0) &&
1450 (pmedium->u.hEnhMetaFile!=0) )
1452 DeleteEnhMetaFile(pmedium->u.hEnhMetaFile);
1455 pmedium->u.hEnhMetaFile = 0;
1464 * After cleaning up, the unknown is released
1466 if (pmedium->pUnkForRelease!=0)
1468 IUnknown_Release(pmedium->pUnkForRelease);
1469 pmedium->pUnkForRelease = 0;
1474 * OLEDD_Initialize()
1476 * Initializes the OLE drag and drop data structures.
1478 static void OLEDD_Initialize()
1482 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1483 wndClass.style = CS_GLOBALCLASS;
1484 wndClass.lpfnWndProc = (WNDPROC)OLEDD_DragTrackerWindowProc;
1485 wndClass.cbClsExtra = 0;
1486 wndClass.cbWndExtra = sizeof(TrackerWindowInfo*);
1487 wndClass.hCursor = 0;
1488 wndClass.hbrBackground = 0;
1489 wndClass.lpszClassName = OLEDD_DRAGTRACKERCLASS;
1491 RegisterClassA (&wndClass);
1495 * OLEDD_UnInitialize()
1497 * Releases the OLE drag and drop data structures.
1499 static void OLEDD_UnInitialize()
1502 * Simply empty the list.
1504 while (targetListHead!=NULL)
1506 RevokeDragDrop(targetListHead->hwndTarget);
1511 * OLEDD_InsertDropTarget()
1513 * Insert the target node in the tree.
1515 static void OLEDD_InsertDropTarget(DropTargetNode* nodeToAdd)
1517 DropTargetNode* curNode;
1518 DropTargetNode** parentNodeLink;
1521 * Iterate the tree to find the insertion point.
1523 curNode = targetListHead;
1524 parentNodeLink = &targetListHead;
1526 while (curNode!=NULL)
1528 if (nodeToAdd->hwndTarget<curNode->hwndTarget)
1531 * If the node we want to add has a smaller HWND, go left
1533 parentNodeLink = &curNode->prevDropTarget;
1534 curNode = curNode->prevDropTarget;
1536 else if (nodeToAdd->hwndTarget>curNode->hwndTarget)
1539 * If the node we want to add has a larger HWND, go right
1541 parentNodeLink = &curNode->nextDropTarget;
1542 curNode = curNode->nextDropTarget;
1547 * The item was found in the list. It shouldn't have been there
1555 * If we get here, we have found a spot for our item. The parentNodeLink
1556 * pointer points to the pointer that we have to modify.
1557 * The curNode should be NULL. We just have to establish the link and Voila!
1559 assert(curNode==NULL);
1560 assert(parentNodeLink!=NULL);
1561 assert(*parentNodeLink==NULL);
1563 *parentNodeLink=nodeToAdd;
1567 * OLEDD_ExtractDropTarget()
1569 * Removes the target node from the tree.
1571 static DropTargetNode* OLEDD_ExtractDropTarget(HWND hwndOfTarget)
1573 DropTargetNode* curNode;
1574 DropTargetNode** parentNodeLink;
1577 * Iterate the tree to find the insertion point.
1579 curNode = targetListHead;
1580 parentNodeLink = &targetListHead;
1582 while (curNode!=NULL)
1584 if (hwndOfTarget<curNode->hwndTarget)
1587 * If the node we want to add has a smaller HWND, go left
1589 parentNodeLink = &curNode->prevDropTarget;
1590 curNode = curNode->prevDropTarget;
1592 else if (hwndOfTarget>curNode->hwndTarget)
1595 * If the node we want to add has a larger HWND, go right
1597 parentNodeLink = &curNode->nextDropTarget;
1598 curNode = curNode->nextDropTarget;
1603 * The item was found in the list. Detach it from it's parent and
1604 * re-insert it's kids in the tree.
1606 assert(parentNodeLink!=NULL);
1607 assert(*parentNodeLink==curNode);
1610 * We arbitrately re-attach the left sub-tree to the parent.
1612 *parentNodeLink = curNode->prevDropTarget;
1615 * And we re-insert the right subtree
1617 if (curNode->nextDropTarget!=NULL)
1619 OLEDD_InsertDropTarget(curNode->nextDropTarget);
1623 * The node we found is still a valid node once we complete
1624 * the unlinking of the kids.
1626 curNode->nextDropTarget=NULL;
1627 curNode->prevDropTarget=NULL;
1634 * If we get here, the node is not in the tree
1640 * OLEDD_FindDropTarget()
1642 * Finds information about the drop target.
1644 static DropTargetNode* OLEDD_FindDropTarget(HWND hwndOfTarget)
1646 DropTargetNode* curNode;
1649 * Iterate the tree to find the HWND value.
1651 curNode = targetListHead;
1653 while (curNode!=NULL)
1655 if (hwndOfTarget<curNode->hwndTarget)
1658 * If the node we want to add has a smaller HWND, go left
1660 curNode = curNode->prevDropTarget;
1662 else if (hwndOfTarget>curNode->hwndTarget)
1665 * If the node we want to add has a larger HWND, go right
1667 curNode = curNode->nextDropTarget;
1672 * The item was found in the list.
1679 * If we get here, the item is not in the list
1685 * OLEDD_DragTrackerWindowProc()
1687 * This method is the WindowProcedure of the drag n drop tracking
1688 * window. During a drag n Drop operation, an invisible window is created
1689 * to receive the user input and act upon it. This procedure is in charge
1692 static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
1702 LPCREATESTRUCTA createStruct = (LPCREATESTRUCTA)lParam;
1704 SetWindowLongA(hwnd, 0, (LONG)createStruct->lpCreateParams);
1711 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
1715 * Get the current mouse position in screen coordinates.
1717 mousePos.x = LOWORD(lParam);
1718 mousePos.y = HIWORD(lParam);
1719 ClientToScreen(hwnd, &mousePos);
1722 * Track the movement of the mouse.
1724 OLEDD_TrackMouseMove(trackerInfo, mousePos, wParam);
1731 case WM_LBUTTONDOWN:
1732 case WM_MBUTTONDOWN:
1733 case WM_RBUTTONDOWN:
1735 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
1739 * Get the current mouse position in screen coordinates.
1741 mousePos.x = LOWORD(lParam);
1742 mousePos.y = HIWORD(lParam);
1743 ClientToScreen(hwnd, &mousePos);
1746 * Notify everyone that the button state changed
1747 * TODO: Check if the "escape" key was pressed.
1749 OLEDD_TrackStateChange(trackerInfo, mousePos, wParam);
1756 * This is a window proc after all. Let's call the default.
1758 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1762 * OLEDD_TrackMouseMove()
1764 * This method is invoked while a drag and drop operation is in effect.
1765 * it will generate the appropriate callbacks in the drop source
1766 * and drop target. It will also provide the expected feedback to
1770 * trackerInfo - Pointer to the structure identifying the
1771 * drag & drop operation that is currently
1773 * mousePos - Current position of the mouse in screen
1775 * keyState - Contains the state of the shift keys and the
1776 * mouse buttons (MK_LBUTTON and the like)
1778 static void OLEDD_TrackMouseMove(
1779 TrackerWindowInfo* trackerInfo,
1783 HWND hwndNewTarget = 0;
1787 * Get the handle of the window under the mouse
1789 hwndNewTarget = WindowFromPoint(mousePos);
1792 * Every time, we re-initialize the effects passed to the
1793 * IDropTarget to the effects allowed by the source.
1795 *trackerInfo->pdwEffect = trackerInfo->dwOKEffect;
1798 * If we are hovering over the same target as before, send the
1799 * DragOver notification
1801 if ( (trackerInfo->curDragTarget != 0) &&
1802 (trackerInfo->curDragTargetHWND==hwndNewTarget) )
1804 POINTL mousePosParam;
1807 * The documentation tells me that the coordinate should be in the target
1808 * window's coordinate space. However, the tests I made tell me the
1809 * coordinates should be in screen coordinates.
1811 mousePosParam.x = mousePos.x;
1812 mousePosParam.y = mousePos.y;
1814 IDropTarget_DragOver(trackerInfo->curDragTarget,
1817 trackerInfo->pdwEffect);
1821 DropTargetNode* newDropTargetNode = 0;
1824 * If we changed window, we have to notify our old target and check for
1827 if (trackerInfo->curDragTarget!=0)
1829 IDropTarget_DragLeave(trackerInfo->curDragTarget);
1833 * Make sure we're hovering over a window.
1835 if (hwndNewTarget!=0)
1838 * Find-out if there is a drag target under the mouse
1840 newDropTargetNode = OLEDD_FindDropTarget(hwndNewTarget);
1842 trackerInfo->curDragTargetHWND = hwndNewTarget;
1843 trackerInfo->curDragTarget = newDropTargetNode ? newDropTargetNode->dropTarget : 0;
1846 * If there is, notify it that we just dragged-in
1848 if (trackerInfo->curDragTarget!=0)
1850 POINTL mousePosParam;
1853 * The documentation tells me that the coordinate should be in the target
1854 * window's coordinate space. However, the tests I made tell me the
1855 * coordinates should be in screen coordinates.
1857 mousePosParam.x = mousePos.x;
1858 mousePosParam.y = mousePos.y;
1860 IDropTarget_DragEnter(trackerInfo->curDragTarget,
1861 trackerInfo->dataObject,
1864 trackerInfo->pdwEffect);
1870 * The mouse is not over a window so we don't track anything.
1872 trackerInfo->curDragTargetHWND = 0;
1873 trackerInfo->curDragTarget = 0;
1878 * Now that we have done that, we have to tell the source to give
1879 * us feedback on the work being done by the target. If we don't
1880 * have a target, simulate no effect.
1882 if (trackerInfo->curDragTarget==0)
1884 *trackerInfo->pdwEffect = DROPEFFECT_NONE;
1887 hr = IDropSource_GiveFeedback(trackerInfo->dropSource,
1888 *trackerInfo->pdwEffect);
1891 * When we ask for feedback from the drop source, sometimes it will
1892 * do all the necessary work and sometimes it will not handle it
1893 * when that's the case, we must display the standard drag and drop
1896 if (hr==DRAGDROP_S_USEDEFAULTCURSORS)
1898 if ( (*trackerInfo->pdwEffect & DROPEFFECT_MOVE) ||
1899 (*trackerInfo->pdwEffect & DROPEFFECT_COPY) ||
1900 (*trackerInfo->pdwEffect & DROPEFFECT_LINK) )
1902 SetCursor(LoadCursorA(0, IDC_SIZEALLA));
1906 SetCursor(LoadCursorA(0, IDC_NOA));
1912 * OLEDD_TrackStateChange()
1914 * This method is invoked while a drag and drop operation is in effect.
1915 * It is used to notify the drop target/drop source callbacks when
1916 * the state of the keyboard or mouse button change.
1919 * trackerInfo - Pointer to the structure identifying the
1920 * drag & drop operation that is currently
1922 * mousePos - Current position of the mouse in screen
1924 * keyState - Contains the state of the shift keys and the
1925 * mouse buttons (MK_LBUTTON and the like)
1927 static void OLEDD_TrackStateChange(
1928 TrackerWindowInfo* trackerInfo,
1933 * Ask the drop source what to do with the operation.
1935 trackerInfo->returnValue = IDropSource_QueryContinueDrag(
1936 trackerInfo->dropSource,
1937 trackerInfo->escPressed,
1941 * All the return valued will stop the operation except the S_OK
1944 if (trackerInfo->returnValue!=S_OK)
1947 * Make sure the message loop in DoDragDrop stops
1949 trackerInfo->trackingDone = TRUE;
1952 * Release the mouse in case the drop target decides to show a popup
1953 * or a menu or something.
1958 * If we end-up over a target, drop the object in the target or
1959 * inform the target that the operation was cancelled.
1961 if (trackerInfo->curDragTarget!=0)
1963 switch (trackerInfo->returnValue)
1966 * If the source wants us to complete the operation, we tell
1967 * the drop target that we just dropped the object in it.
1969 case DRAGDROP_S_DROP:
1971 POINTL mousePosParam;
1974 * The documentation tells me that the coordinate should be
1975 * in the target window's coordinate space. However, the tests
1976 * I made tell me the coordinates should be in screen coordinates.
1978 mousePosParam.x = mousePos.x;
1979 mousePosParam.y = mousePos.y;
1981 IDropTarget_Drop(trackerInfo->curDragTarget,
1982 trackerInfo->dataObject,
1985 trackerInfo->pdwEffect);
1989 * If the source told us that we should cancel, fool the drop
1990 * target by telling it that the mouse left it's window.
1991 * Also set the drop effect to "NONE" in case the application
1992 * ignores the result of DoDragDrop.
1994 case DRAGDROP_S_CANCEL:
1995 IDropTarget_DragLeave(trackerInfo->curDragTarget);
1996 *trackerInfo->pdwEffect = DROPEFFECT_NONE;
2004 * OLEDD_GetButtonState()
2006 * This method will use the current state of the keyboard to build
2007 * a button state mask equivalent to the one passed in the
2008 * WM_MOUSEMOVE wParam.
2010 static DWORD OLEDD_GetButtonState()
2012 BYTE keyboardState[256];
2015 GetKeyboardState(keyboardState);
2017 if ( (keyboardState[VK_SHIFT] & 0x80) !=0)
2018 keyMask |= MK_SHIFT;
2020 if ( (keyboardState[VK_CONTROL] & 0x80) !=0)
2021 keyMask |= MK_CONTROL;
2023 if ( (keyboardState[VK_LBUTTON] & 0x80) !=0)
2024 keyMask |= MK_LBUTTON;
2026 if ( (keyboardState[VK_RBUTTON] & 0x80) !=0)
2027 keyMask |= MK_RBUTTON;
2029 if ( (keyboardState[VK_MBUTTON] & 0x80) !=0)
2030 keyMask |= MK_MBUTTON;
2036 * OLEDD_GetButtonState()
2038 * This method will read the default value of the registry key in
2039 * parameter and extract a DWORD value from it. The registry key value
2040 * can be in a string key or a DWORD key.
2043 * regKey - Key to read the default value from
2044 * pdwValue - Pointer to the location where the DWORD
2045 * value is returned. This value is not modified
2046 * if the value is not found.
2049 static void OLEUTL_ReadRegistryDWORDValue(
2058 lres = RegQueryValueExA(regKey,
2065 if (lres==ERROR_SUCCESS)
2070 *pdwValue = *(DWORD*)buffer;
2075 *pdwValue = (DWORD)strtoul(buffer, NULL, 10);
2081 /******************************************************************************
2082 * OleMetaFilePictFromIconAndLabel
2084 * Returns a global memory handle to a metafile which contains the icon and
2086 * I guess the result of that should look somehow like desktop icons.
2087 * If no hIcon is given, we load the icon via lpszSourceFile and iIconIndex.
2088 * This code might be wrong at some places.
2090 HGLOBAL16 WINAPI OleMetaFilePictFromIconAndLabel16(
2092 LPCOLESTR16 lpszLabel,
2093 LPCOLESTR16 lpszSourceFile,
2100 FIXME("(%04x, '%s', '%s', %d): incorrect metrics, please try to correct them !\n\n\n", hIcon, lpszLabel, lpszSourceFile, iIconIndex);
2103 if (lpszSourceFile) {
2104 HINSTANCE16 hInstance = LoadLibrary16(lpszSourceFile);
2106 /* load the icon at index from lpszSourceFile */
2107 hIcon = (HICON16)LoadIconA(hInstance, (LPCSTR)(DWORD)iIconIndex);
2108 FreeLibrary16(hInstance);
2110 return (HGLOBAL)NULL;
2113 hdc = CreateMetaFile16(NULL);
2114 DrawIcon(hdc, 0, 0, hIcon); /* FIXME */
2115 TextOut16(hdc, 0, 0, lpszLabel, 1); /* FIXME */
2116 hmf = GlobalAlloc16(0, sizeof(METAFILEPICT16));
2117 mf = (METAFILEPICT16 *)GlobalLock16(hmf);
2118 mf->mm = MM_ANISOTROPIC;
2119 mf->xExt = 20; /* FIXME: bogus */
2120 mf->yExt = 20; /* dito */
2121 mf->hMF = CloseMetaFile16(hdc);