xref: /reactos/dll/win32/ole32/ole2.c (revision 0f5d91b7)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  *	OLE2 library
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * Copyright 1995 Martin von Loewis
5c2c66affSColin Finck  * Copyright 1999 Francis Beaudet
6c2c66affSColin Finck  * Copyright 1999 Noel Borthwick
7c2c66affSColin Finck  * Copyright 1999, 2000 Marcus Meissner
8c2c66affSColin Finck  * Copyright 2005 Juan Lang
9c2c66affSColin Finck  * Copyright 2011 Adam Martinson for CodeWeavers
10c2c66affSColin Finck  *
11c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
12c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
13c2c66affSColin Finck  * License as published by the Free Software Foundation; either
14c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
15c2c66affSColin Finck  *
16c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
17c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19c2c66affSColin Finck  * Lesser General Public License for more details.
20c2c66affSColin Finck  *
21c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
22c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
23c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24c2c66affSColin Finck  */
25c2c66affSColin Finck 
26c0f90872SAmine Khaldi #include <assert.h>
27c0f90872SAmine Khaldi #include <stdlib.h>
28c0f90872SAmine Khaldi #include <stdarg.h>
29c0f90872SAmine Khaldi #include <stdio.h>
30c0f90872SAmine Khaldi #include <string.h>
31c0f90872SAmine Khaldi 
32c0f90872SAmine Khaldi #define COBJMACROS
33c0f90872SAmine Khaldi #define NONAMELESSUNION
34c0f90872SAmine Khaldi 
35c0f90872SAmine Khaldi #include "windef.h"
36c0f90872SAmine Khaldi #include "winbase.h"
37c0f90872SAmine Khaldi #include "winerror.h"
38c0f90872SAmine Khaldi #include "wingdi.h"
39c0f90872SAmine Khaldi #include "winuser.h"
40c0f90872SAmine Khaldi #include "winnls.h"
41c0f90872SAmine Khaldi #include "winreg.h"
42c0f90872SAmine Khaldi #include "ole2.h"
43c0f90872SAmine Khaldi #include "ole2ver.h"
44c0f90872SAmine Khaldi 
45c0f90872SAmine Khaldi #include "compobj_private.h"
46c2c66affSColin Finck #include "olestd.h"
47c0f90872SAmine Khaldi #include "wine/list.h"
48c0f90872SAmine Khaldi 
49c0f90872SAmine Khaldi #include "wine/debug.h"
50c2c66affSColin Finck 
51c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(ole);
52c2c66affSColin Finck WINE_DECLARE_DEBUG_CHANNEL(accel);
53c2c66affSColin Finck 
54c2c66affSColin Finck /******************************************************************************
55c2c66affSColin Finck  * These are static/global variables and internal data structures that the
56c2c66affSColin Finck  * OLE module uses to maintain its state.
57c2c66affSColin Finck  */
58c2c66affSColin Finck typedef struct tagTrackerWindowInfo
59c2c66affSColin Finck {
60c2c66affSColin Finck   IDataObject* dataObject;
61c2c66affSColin Finck   IDropSource* dropSource;
62c2c66affSColin Finck   DWORD        dwOKEffect;
63c2c66affSColin Finck   DWORD*       pdwEffect;
64c2c66affSColin Finck   BOOL       trackingDone;
65c2c66affSColin Finck   HRESULT      returnValue;
66c2c66affSColin Finck 
67c2c66affSColin Finck   BOOL       escPressed;
68c2c66affSColin Finck   HWND       curTargetHWND;	/* window the mouse is hovering over */
69c2c66affSColin Finck   IDropTarget* curDragTarget;
70332ca5f5SKatayama Hirofumi MZ #ifdef __REACTOS__
71332ca5f5SKatayama Hirofumi MZ   HWND       accepterHWND;
72332ca5f5SKatayama Hirofumi MZ #endif
73c2c66affSColin Finck   POINTL     curMousePos;       /* current position of the mouse in screen coordinates */
74c2c66affSColin Finck   DWORD      dwKeyState;        /* current state of the shift and ctrl keys and the mouse buttons */
75c2c66affSColin Finck } TrackerWindowInfo;
76c2c66affSColin Finck 
77c2c66affSColin Finck typedef struct tagOleMenuDescriptor  /* OleMenuDescriptor */
78c2c66affSColin Finck {
79c2c66affSColin Finck   HWND               hwndFrame;         /* The containers frame window */
80c2c66affSColin Finck   HWND               hwndActiveObject;  /* The active objects window */
81c2c66affSColin Finck   OLEMENUGROUPWIDTHS mgw;               /* OLE menu group widths for the shared menu */
82c2c66affSColin Finck   HMENU              hmenuCombined;     /* The combined menu */
83c2c66affSColin Finck   BOOL               bIsServerItem;     /* True if the currently open popup belongs to the server */
84c2c66affSColin Finck } OleMenuDescriptor;
85c2c66affSColin Finck 
86c2c66affSColin Finck typedef struct tagOleMenuHookItem   /* OleMenu hook item in per thread hook list */
87c2c66affSColin Finck {
88c2c66affSColin Finck   DWORD tid;                /* Thread Id  */
89c2c66affSColin Finck   HANDLE hHeap;             /* Heap this is allocated from */
90c2c66affSColin Finck   HHOOK GetMsg_hHook;       /* message hook for WH_GETMESSAGE */
91c2c66affSColin Finck   HHOOK CallWndProc_hHook;  /* message hook for WH_CALLWNDPROC */
92c2c66affSColin Finck   struct tagOleMenuHookItem *next;
93c2c66affSColin Finck } OleMenuHookItem;
94c2c66affSColin Finck 
95c2c66affSColin Finck static OleMenuHookItem *hook_list;
96c2c66affSColin Finck 
97c2c66affSColin Finck /*
98c2c66affSColin Finck  * This is the lock count on the OLE library. It is controlled by the
99c2c66affSColin Finck  * OLEInitialize/OLEUninitialize methods.
100c2c66affSColin Finck  */
101c2c66affSColin Finck static LONG OLE_moduleLockCount = 0;
102c2c66affSColin Finck 
103c2c66affSColin Finck /*
104c2c66affSColin Finck  * Name of our registered window class.
105c2c66affSColin Finck  */
106c2c66affSColin Finck static const WCHAR OLEDD_DRAGTRACKERCLASS[] =
107c2c66affSColin Finck   {'W','i','n','e','D','r','a','g','D','r','o','p','T','r','a','c','k','e','r','3','2',0};
108c2c66affSColin Finck 
109c2c66affSColin Finck /*
110c2c66affSColin Finck  * Name of menu descriptor property.
111c2c66affSColin Finck  */
112c2c66affSColin Finck static const WCHAR prop_olemenuW[] =
113c2c66affSColin Finck   {'P','R','O','P','_','O','L','E','M','e','n','u','D','e','s','c','r','i','p','t','o','r',0};
114c2c66affSColin Finck 
115c2c66affSColin Finck /* property to store IDropTarget pointer */
116c2c66affSColin Finck static const WCHAR prop_oledroptarget[] =
117c2c66affSColin Finck   {'O','l','e','D','r','o','p','T','a','r','g','e','t','I','n','t','e','r','f','a','c','e',0};
118c2c66affSColin Finck 
119c2c66affSColin Finck /* property to store Marshalled IDropTarget pointer */
120c2c66affSColin Finck static const WCHAR prop_marshalleddroptarget[] =
121c2c66affSColin Finck   {'W','i','n','e','M','a','r','s','h','a','l','l','e','d','D','r','o','p','T','a','r','g','e','t',0};
122c2c66affSColin Finck 
123c2c66affSColin Finck static const WCHAR emptyW[] = { 0 };
124c2c66affSColin Finck 
125c2c66affSColin Finck /******************************************************************************
126c2c66affSColin Finck  * These are the prototypes of miscellaneous utility methods
127c2c66affSColin Finck  */
128c2c66affSColin Finck static void OLEUTL_ReadRegistryDWORDValue(HKEY regKey, DWORD* pdwValue);
129c2c66affSColin Finck 
130c2c66affSColin Finck /******************************************************************************
131c2c66affSColin Finck  * These are the prototypes of the utility methods used to manage a shared menu
132c2c66affSColin Finck  */
133c2c66affSColin Finck static void OLEMenu_Initialize(void);
134c2c66affSColin Finck static void OLEMenu_UnInitialize(void);
135c2c66affSColin Finck static BOOL OLEMenu_InstallHooks( DWORD tid );
136c2c66affSColin Finck static BOOL OLEMenu_UnInstallHooks( DWORD tid );
137c2c66affSColin Finck static OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid );
138c2c66affSColin Finck static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos );
139c2c66affSColin Finck static BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor );
140c2c66affSColin Finck static LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam);
141c2c66affSColin Finck static LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam);
142c2c66affSColin Finck 
143c2c66affSColin Finck /******************************************************************************
144c2c66affSColin Finck  * These are the prototypes of the OLE Clipboard initialization methods (in clipboard.c)
145c2c66affSColin Finck  */
146c2c66affSColin Finck extern void OLEClipbrd_UnInitialize(void);
147c2c66affSColin Finck extern void OLEClipbrd_Initialize(void);
148c2c66affSColin Finck 
149c2c66affSColin Finck /******************************************************************************
150c2c66affSColin Finck  * These are the prototypes of the utility methods used for OLE Drag n Drop
151c2c66affSColin Finck  */
152c2c66affSColin Finck static void OLEDD_Initialize(void);
153c2c66affSColin Finck static LRESULT WINAPI  OLEDD_DragTrackerWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
154c2c66affSColin Finck static void OLEDD_TrackStateChange(TrackerWindowInfo* trackerInfo);
155c2c66affSColin Finck static DWORD OLEDD_GetButtonState(void);
156c2c66affSColin Finck 
157c2c66affSColin Finck /******************************************************************************
158c2c66affSColin Finck  *		OleBuildVersion [OLE32.@]
159c2c66affSColin Finck  */
OleBuildVersion(void)160c2c66affSColin Finck DWORD WINAPI OleBuildVersion(void)
161c2c66affSColin Finck {
162c2c66affSColin Finck     TRACE("Returning version %d, build %d.\n", rmm, rup);
163c2c66affSColin Finck     return (rmm<<16)+rup;
164c2c66affSColin Finck }
165c2c66affSColin Finck 
166c2c66affSColin Finck /***********************************************************************
167c2c66affSColin Finck  *           OleInitialize       (OLE32.@)
168c2c66affSColin Finck  */
OleInitialize(LPVOID reserved)169c2c66affSColin Finck HRESULT WINAPI DECLSPEC_HOTPATCH OleInitialize(LPVOID reserved)
170c2c66affSColin Finck {
171c2c66affSColin Finck   HRESULT hr;
172c2c66affSColin Finck 
173c2c66affSColin Finck   TRACE("(%p)\n", reserved);
174c2c66affSColin Finck 
175c2c66affSColin Finck   /*
176c2c66affSColin Finck    * The first duty of the OleInitialize is to initialize the COM libraries.
177c2c66affSColin Finck    */
178c2c66affSColin Finck   hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
179c2c66affSColin Finck 
180c2c66affSColin Finck   /*
181c2c66affSColin Finck    * If the CoInitializeEx call failed, the OLE libraries can't be
182c2c66affSColin Finck    * initialized.
183c2c66affSColin Finck    */
184c2c66affSColin Finck   if (FAILED(hr))
185c2c66affSColin Finck     return hr;
186c2c66affSColin Finck 
187c2c66affSColin Finck   if (!COM_CurrentInfo()->ole_inits)
188c2c66affSColin Finck     hr = S_OK;
189c2c66affSColin Finck   else
190c2c66affSColin Finck     hr = S_FALSE;
191c2c66affSColin Finck 
192c2c66affSColin Finck   /*
193c2c66affSColin Finck    * Then, it has to initialize the OLE specific modules.
194c2c66affSColin Finck    * This includes:
195c2c66affSColin Finck    *     Clipboard
196c2c66affSColin Finck    *     Drag and Drop
197c2c66affSColin Finck    *     Object linking and Embedding
198c2c66affSColin Finck    *     In-place activation
199c2c66affSColin Finck    */
200c2c66affSColin Finck   if (!COM_CurrentInfo()->ole_inits++ &&
201c2c66affSColin Finck       InterlockedIncrement(&OLE_moduleLockCount) == 1)
202c2c66affSColin Finck   {
203c2c66affSColin Finck     /*
204c2c66affSColin Finck      * Initialize the libraries.
205c2c66affSColin Finck      */
206c2c66affSColin Finck     TRACE("() - Initializing the OLE libraries\n");
207c2c66affSColin Finck 
208c2c66affSColin Finck     /*
209c2c66affSColin Finck      * OLE Clipboard
210c2c66affSColin Finck      */
211c2c66affSColin Finck     OLEClipbrd_Initialize();
212c2c66affSColin Finck 
213c2c66affSColin Finck     /*
214c2c66affSColin Finck      * Drag and Drop
215c2c66affSColin Finck      */
216c2c66affSColin Finck     OLEDD_Initialize();
217c2c66affSColin Finck 
218c2c66affSColin Finck     /*
219c2c66affSColin Finck      * OLE shared menu
220c2c66affSColin Finck      */
221c2c66affSColin Finck     OLEMenu_Initialize();
222c2c66affSColin Finck   }
223c2c66affSColin Finck 
224c2c66affSColin Finck   return hr;
225c2c66affSColin Finck }
226c2c66affSColin Finck 
227c2c66affSColin Finck /******************************************************************************
228c2c66affSColin Finck  *		OleUninitialize	[OLE32.@]
229c2c66affSColin Finck  */
OleUninitialize(void)230c2c66affSColin Finck void WINAPI DECLSPEC_HOTPATCH OleUninitialize(void)
231c2c66affSColin Finck {
232c2c66affSColin Finck   TRACE("()\n");
233c2c66affSColin Finck 
234c2c66affSColin Finck   if (COM_CurrentInfo()->ole_inits == 0)
235c2c66affSColin Finck   {
236c2c66affSColin Finck     WARN("ole_inits is already 0\n");
237c2c66affSColin Finck     return ;
238c2c66affSColin Finck   }
239c2c66affSColin Finck   /*
240c2c66affSColin Finck    * If we hit the bottom of the lock stack, free the libraries.
241c2c66affSColin Finck    */
242c2c66affSColin Finck   if (!--COM_CurrentInfo()->ole_inits && !InterlockedDecrement(&OLE_moduleLockCount))
243c2c66affSColin Finck   {
244c2c66affSColin Finck     /*
245c2c66affSColin Finck      * Actually free the libraries.
246c2c66affSColin Finck      */
247c2c66affSColin Finck     TRACE("() - Freeing the last reference count\n");
248c2c66affSColin Finck 
249c2c66affSColin Finck     /*
250c2c66affSColin Finck      * OLE Clipboard
251c2c66affSColin Finck      */
252c2c66affSColin Finck     OLEClipbrd_UnInitialize();
253c2c66affSColin Finck 
254c2c66affSColin Finck     /*
255c2c66affSColin Finck      * OLE shared menu
256c2c66affSColin Finck      */
257c2c66affSColin Finck     OLEMenu_UnInitialize();
258c2c66affSColin Finck   }
259c2c66affSColin Finck 
260c2c66affSColin Finck   /*
261c2c66affSColin Finck    * Then, uninitialize the COM libraries.
262c2c66affSColin Finck    */
263c2c66affSColin Finck   CoUninitialize();
264c2c66affSColin Finck }
265c2c66affSColin Finck 
266c2c66affSColin Finck /******************************************************************************
267c2c66affSColin Finck  *		OleInitializeWOW	[OLE32.@]
268c2c66affSColin Finck  */
OleInitializeWOW(DWORD x,DWORD y)269c2c66affSColin Finck HRESULT WINAPI OleInitializeWOW(DWORD x, DWORD y) {
270c2c66affSColin Finck         FIXME("(0x%08x, 0x%08x),stub!\n",x, y);
271c2c66affSColin Finck         return 0;
272c2c66affSColin Finck }
273c2c66affSColin Finck 
274c2c66affSColin Finck /*************************************************************
275c2c66affSColin Finck  *           get_droptarget_handle
276c2c66affSColin Finck  *
277c2c66affSColin Finck  * Retrieve a handle to the map containing the marshalled IDropTarget.
278c2c66affSColin Finck  * This handle belongs to the process that called RegisterDragDrop.
279c2c66affSColin Finck  * See get_droptarget_local_handle().
280c2c66affSColin Finck  */
get_droptarget_handle(HWND hwnd)281c2c66affSColin Finck static inline HANDLE get_droptarget_handle(HWND hwnd)
282c2c66affSColin Finck {
283c2c66affSColin Finck     return GetPropW(hwnd, prop_marshalleddroptarget);
284c2c66affSColin Finck }
285c2c66affSColin Finck 
286c2c66affSColin Finck /*************************************************************
287c2c66affSColin Finck  *           is_droptarget
288c2c66affSColin Finck  *
289c2c66affSColin Finck  * Is the window a droptarget.
290c2c66affSColin Finck  */
is_droptarget(HWND hwnd)291c2c66affSColin Finck static inline BOOL is_droptarget(HWND hwnd)
292c2c66affSColin Finck {
293c2c66affSColin Finck     return get_droptarget_handle(hwnd) != 0;
294c2c66affSColin Finck }
295c2c66affSColin Finck 
296332ca5f5SKatayama Hirofumi MZ #ifdef __REACTOS__
is_acceptfiles(HWND hwnd)297332ca5f5SKatayama Hirofumi MZ static inline BOOL is_acceptfiles(HWND hwnd)
298332ca5f5SKatayama Hirofumi MZ {
299332ca5f5SKatayama Hirofumi MZ     return !!(GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES);
300332ca5f5SKatayama Hirofumi MZ }
301332ca5f5SKatayama Hirofumi MZ #endif
302c2c66affSColin Finck /*************************************************************
303c2c66affSColin Finck  *           get_droptarget_local_handle
304c2c66affSColin Finck  *
305c2c66affSColin Finck  * Retrieve a handle to the map containing the marshalled IDropTarget.
306c2c66affSColin Finck  * The handle should be closed when finished with.
307c2c66affSColin Finck  */
get_droptarget_local_handle(HWND hwnd)308c2c66affSColin Finck static HANDLE get_droptarget_local_handle(HWND hwnd)
309c2c66affSColin Finck {
310c2c66affSColin Finck     HANDLE handle, local_handle = 0;
311c2c66affSColin Finck 
312c2c66affSColin Finck     handle = get_droptarget_handle(hwnd);
313c2c66affSColin Finck 
314c2c66affSColin Finck     if(handle)
315c2c66affSColin Finck     {
316c2c66affSColin Finck         DWORD pid;
317c2c66affSColin Finck         HANDLE process;
318c2c66affSColin Finck 
319c2c66affSColin Finck         GetWindowThreadProcessId(hwnd, &pid);
320c2c66affSColin Finck         process = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid);
321c2c66affSColin Finck         if(process)
322c2c66affSColin Finck         {
323c2c66affSColin Finck             DuplicateHandle(process, handle, GetCurrentProcess(), &local_handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
324c2c66affSColin Finck             CloseHandle(process);
325c2c66affSColin Finck         }
326c2c66affSColin Finck     }
327c2c66affSColin Finck     return local_handle;
328c2c66affSColin Finck }
329c2c66affSColin Finck 
330c2c66affSColin Finck /***********************************************************************
331c2c66affSColin Finck  *     create_map_from_stream
332c2c66affSColin Finck  *
333c2c66affSColin Finck  * Helper for RegisterDragDrop.  Creates a file mapping object
334c2c66affSColin Finck  * with the contents of the provided stream.  The stream must
335c2c66affSColin Finck  * be a global memory backed stream.
336c2c66affSColin Finck  */
create_map_from_stream(IStream * stream,HANDLE * map)337c2c66affSColin Finck static HRESULT create_map_from_stream(IStream *stream, HANDLE *map)
338c2c66affSColin Finck {
339c2c66affSColin Finck     HGLOBAL hmem;
340c2c66affSColin Finck     DWORD size;
341c2c66affSColin Finck     HRESULT hr;
342c2c66affSColin Finck     void *data;
343c2c66affSColin Finck 
344c2c66affSColin Finck     hr = GetHGlobalFromStream(stream, &hmem);
345c2c66affSColin Finck     if(FAILED(hr)) return hr;
346c2c66affSColin Finck 
347c2c66affSColin Finck     size = GlobalSize(hmem);
348c2c66affSColin Finck     *map = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, NULL);
349c2c66affSColin Finck     if(!*map) return E_OUTOFMEMORY;
350c2c66affSColin Finck 
351c2c66affSColin Finck     data = MapViewOfFile(*map, FILE_MAP_WRITE, 0, 0, size);
352c2c66affSColin Finck     memcpy(data, GlobalLock(hmem), size);
353c2c66affSColin Finck     GlobalUnlock(hmem);
354c2c66affSColin Finck     UnmapViewOfFile(data);
355c2c66affSColin Finck     return S_OK;
356c2c66affSColin Finck }
357c2c66affSColin Finck 
358c2c66affSColin Finck /***********************************************************************
359c2c66affSColin Finck  *     create_stream_from_map
360c2c66affSColin Finck  *
361c2c66affSColin Finck  * Creates a stream from the provided map.
362c2c66affSColin Finck  */
create_stream_from_map(HANDLE map,IStream ** stream)363c2c66affSColin Finck static HRESULT create_stream_from_map(HANDLE map, IStream **stream)
364c2c66affSColin Finck {
365c2c66affSColin Finck     HRESULT hr = E_OUTOFMEMORY;
366c2c66affSColin Finck     HGLOBAL hmem;
367c2c66affSColin Finck     void *data;
368c2c66affSColin Finck     MEMORY_BASIC_INFORMATION info;
369c2c66affSColin Finck 
370c2c66affSColin Finck     data = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
371c2c66affSColin Finck     if(!data) return hr;
372c2c66affSColin Finck 
373c2c66affSColin Finck     VirtualQuery(data, &info, sizeof(info));
374c2c66affSColin Finck     TRACE("size %d\n", (int)info.RegionSize);
375c2c66affSColin Finck 
376c2c66affSColin Finck     hmem = GlobalAlloc(GMEM_MOVEABLE, info.RegionSize);
377c2c66affSColin Finck     if(hmem)
378c2c66affSColin Finck     {
379c2c66affSColin Finck         memcpy(GlobalLock(hmem), data, info.RegionSize);
380c2c66affSColin Finck         GlobalUnlock(hmem);
381c2c66affSColin Finck         hr = CreateStreamOnHGlobal(hmem, TRUE, stream);
382c2c66affSColin Finck     }
383c2c66affSColin Finck     UnmapViewOfFile(data);
384c2c66affSColin Finck     return hr;
385c2c66affSColin Finck }
386c2c66affSColin Finck 
387c2c66affSColin Finck /* This is to work around apps which break COM rules by not implementing
388c2c66affSColin Finck  * IDropTarget::QueryInterface().  Windows doesn't expose this because it
389c2c66affSColin Finck  * doesn't call CoMarshallInterface() in RegisterDragDrop().
390c2c66affSColin Finck  * The wrapper is only used internally, and only exists for the life of
391c2c66affSColin Finck  * the marshal.  We don't want to hold a ref on the app provided target
392c2c66affSColin Finck  * as some apps destroy this prior to CoUninitialize without calling
393c2c66affSColin Finck  * RevokeDragDrop.  The only (long-term) ref is held by the window prop. */
394c2c66affSColin Finck typedef struct {
395c2c66affSColin Finck     IDropTarget IDropTarget_iface;
396c2c66affSColin Finck     HWND hwnd;
397c2c66affSColin Finck     LONG refs;
398c2c66affSColin Finck } DropTargetWrapper;
399c2c66affSColin Finck 
impl_from_IDropTarget(IDropTarget * iface)400c2c66affSColin Finck static inline DropTargetWrapper* impl_from_IDropTarget(IDropTarget* iface)
401c2c66affSColin Finck {
402c2c66affSColin Finck     return CONTAINING_RECORD(iface, DropTargetWrapper, IDropTarget_iface);
403c2c66affSColin Finck }
404c2c66affSColin Finck 
DropTargetWrapper_QueryInterface(IDropTarget * iface,REFIID riid,void ** ppvObject)405c2c66affSColin Finck static HRESULT WINAPI DropTargetWrapper_QueryInterface(IDropTarget* iface,
406c2c66affSColin Finck                                                        REFIID riid,
407c2c66affSColin Finck                                                        void** ppvObject)
408c2c66affSColin Finck {
409c2c66affSColin Finck     DropTargetWrapper* This = impl_from_IDropTarget(iface);
410c2c66affSColin Finck     if (IsEqualIID(riid, &IID_IUnknown) ||
411c2c66affSColin Finck         IsEqualIID(riid, &IID_IDropTarget))
412c2c66affSColin Finck     {
413c2c66affSColin Finck         IDropTarget_AddRef(&This->IDropTarget_iface);
414c2c66affSColin Finck         *ppvObject = &This->IDropTarget_iface;
415c2c66affSColin Finck         return S_OK;
416c2c66affSColin Finck     }
417c2c66affSColin Finck     *ppvObject = NULL;
418c2c66affSColin Finck     return E_NOINTERFACE;
419c2c66affSColin Finck }
420c2c66affSColin Finck 
DropTargetWrapper_AddRef(IDropTarget * iface)421c2c66affSColin Finck static ULONG WINAPI DropTargetWrapper_AddRef(IDropTarget* iface)
422c2c66affSColin Finck {
423c2c66affSColin Finck     DropTargetWrapper* This = impl_from_IDropTarget(iface);
424c2c66affSColin Finck     return InterlockedIncrement(&This->refs);
425c2c66affSColin Finck }
426c2c66affSColin Finck 
DropTargetWrapper_Release(IDropTarget * iface)427c2c66affSColin Finck static ULONG WINAPI DropTargetWrapper_Release(IDropTarget* iface)
428c2c66affSColin Finck {
429c2c66affSColin Finck     DropTargetWrapper* This = impl_from_IDropTarget(iface);
430c2c66affSColin Finck     ULONG refs = InterlockedDecrement(&This->refs);
431c2c66affSColin Finck     if (!refs) HeapFree(GetProcessHeap(), 0, This);
432c2c66affSColin Finck     return refs;
433c2c66affSColin Finck }
434c2c66affSColin Finck 
get_target_from_wrapper(IDropTarget * wrapper,IDropTarget ** target)435c2c66affSColin Finck static inline HRESULT get_target_from_wrapper( IDropTarget *wrapper, IDropTarget **target )
436c2c66affSColin Finck {
437c2c66affSColin Finck     DropTargetWrapper* This = impl_from_IDropTarget( wrapper );
438c2c66affSColin Finck     *target = GetPropW( This->hwnd, prop_oledroptarget );
439c2c66affSColin Finck     if (!*target) return DRAGDROP_E_NOTREGISTERED;
440c2c66affSColin Finck     IDropTarget_AddRef( *target );
441c2c66affSColin Finck     return S_OK;
442c2c66affSColin Finck }
443c2c66affSColin Finck 
DropTargetWrapper_DragEnter(IDropTarget * iface,IDataObject * pDataObj,DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)444c2c66affSColin Finck static HRESULT WINAPI DropTargetWrapper_DragEnter(IDropTarget* iface,
445c2c66affSColin Finck                                                   IDataObject* pDataObj,
446c2c66affSColin Finck                                                   DWORD grfKeyState,
447c2c66affSColin Finck                                                   POINTL pt,
448c2c66affSColin Finck                                                   DWORD* pdwEffect)
449c2c66affSColin Finck {
450c2c66affSColin Finck     IDropTarget *target;
451c2c66affSColin Finck     HRESULT r = get_target_from_wrapper( iface, &target );
452c2c66affSColin Finck 
453c2c66affSColin Finck     if (SUCCEEDED( r ))
454c2c66affSColin Finck     {
455c2c66affSColin Finck         r = IDropTarget_DragEnter( target, pDataObj, grfKeyState, pt, pdwEffect );
456c2c66affSColin Finck         IDropTarget_Release( target );
457c2c66affSColin Finck     }
458c2c66affSColin Finck     return r;
459c2c66affSColin Finck }
460c2c66affSColin Finck 
DropTargetWrapper_DragOver(IDropTarget * iface,DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)461c2c66affSColin Finck static HRESULT WINAPI DropTargetWrapper_DragOver(IDropTarget* iface,
462c2c66affSColin Finck                                                  DWORD grfKeyState,
463c2c66affSColin Finck                                                  POINTL pt,
464c2c66affSColin Finck                                                  DWORD* pdwEffect)
465c2c66affSColin Finck {
466c2c66affSColin Finck     IDropTarget *target;
467c2c66affSColin Finck     HRESULT r = get_target_from_wrapper( iface, &target );
468c2c66affSColin Finck 
469c2c66affSColin Finck     if (SUCCEEDED( r ))
470c2c66affSColin Finck     {
471c2c66affSColin Finck         r = IDropTarget_DragOver( target, grfKeyState, pt, pdwEffect );
472c2c66affSColin Finck         IDropTarget_Release( target );
473c2c66affSColin Finck     }
474c2c66affSColin Finck     return r;
475c2c66affSColin Finck }
476c2c66affSColin Finck 
DropTargetWrapper_DragLeave(IDropTarget * iface)477c2c66affSColin Finck static HRESULT WINAPI DropTargetWrapper_DragLeave(IDropTarget* iface)
478c2c66affSColin Finck {
479c2c66affSColin Finck     IDropTarget *target;
480c2c66affSColin Finck     HRESULT r = get_target_from_wrapper( iface, &target );
481c2c66affSColin Finck 
482c2c66affSColin Finck     if (SUCCEEDED( r ))
483c2c66affSColin Finck     {
484c2c66affSColin Finck         r = IDropTarget_DragLeave( target );
485c2c66affSColin Finck         IDropTarget_Release( target );
486c2c66affSColin Finck     }
487c2c66affSColin Finck     return r;
488c2c66affSColin Finck }
489c2c66affSColin Finck 
DropTargetWrapper_Drop(IDropTarget * iface,IDataObject * pDataObj,DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)490c2c66affSColin Finck static HRESULT WINAPI DropTargetWrapper_Drop(IDropTarget* iface,
491c2c66affSColin Finck                                              IDataObject* pDataObj,
492c2c66affSColin Finck                                              DWORD grfKeyState,
493c2c66affSColin Finck                                              POINTL pt,
494c2c66affSColin Finck                                              DWORD* pdwEffect)
495c2c66affSColin Finck {
496c2c66affSColin Finck     IDropTarget *target;
497c2c66affSColin Finck     HRESULT r = get_target_from_wrapper( iface, &target );
498c2c66affSColin Finck 
499c2c66affSColin Finck     if (SUCCEEDED( r ))
500c2c66affSColin Finck     {
501c2c66affSColin Finck         r = IDropTarget_Drop( target, pDataObj, grfKeyState, pt, pdwEffect );
502c2c66affSColin Finck         IDropTarget_Release( target );
503c2c66affSColin Finck     }
504c2c66affSColin Finck     return r;
505c2c66affSColin Finck }
506c2c66affSColin Finck 
507c2c66affSColin Finck static const IDropTargetVtbl DropTargetWrapperVTbl =
508c2c66affSColin Finck {
509c2c66affSColin Finck     DropTargetWrapper_QueryInterface,
510c2c66affSColin Finck     DropTargetWrapper_AddRef,
511c2c66affSColin Finck     DropTargetWrapper_Release,
512c2c66affSColin Finck     DropTargetWrapper_DragEnter,
513c2c66affSColin Finck     DropTargetWrapper_DragOver,
514c2c66affSColin Finck     DropTargetWrapper_DragLeave,
515c2c66affSColin Finck     DropTargetWrapper_Drop
516c2c66affSColin Finck };
517c2c66affSColin Finck 
WrapDropTarget(HWND hwnd)518c2c66affSColin Finck static IDropTarget* WrapDropTarget( HWND hwnd )
519c2c66affSColin Finck {
520c2c66affSColin Finck     DropTargetWrapper* This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
521c2c66affSColin Finck 
522c2c66affSColin Finck     if (This)
523c2c66affSColin Finck     {
524c2c66affSColin Finck         This->IDropTarget_iface.lpVtbl = &DropTargetWrapperVTbl;
525c2c66affSColin Finck         This->hwnd = hwnd;
526c2c66affSColin Finck         This->refs = 1;
527c2c66affSColin Finck     }
528c2c66affSColin Finck     return &This->IDropTarget_iface;
529c2c66affSColin Finck }
530c2c66affSColin Finck 
531c2c66affSColin Finck /***********************************************************************
532c2c66affSColin Finck  *     get_droptarget_pointer
533c2c66affSColin Finck  *
534c2c66affSColin Finck  * Retrieves the marshalled IDropTarget from the window.
535c2c66affSColin Finck  */
get_droptarget_pointer(HWND hwnd)536c2c66affSColin Finck static IDropTarget* get_droptarget_pointer(HWND hwnd)
537c2c66affSColin Finck {
538c2c66affSColin Finck     IDropTarget *droptarget = NULL;
539c2c66affSColin Finck     HANDLE map;
540c2c66affSColin Finck     IStream *stream;
541c2c66affSColin Finck 
542c2c66affSColin Finck     map = get_droptarget_local_handle(hwnd);
543c2c66affSColin Finck     if(!map) return NULL;
544c2c66affSColin Finck 
545c2c66affSColin Finck     if(SUCCEEDED(create_stream_from_map(map, &stream)))
546c2c66affSColin Finck     {
547c2c66affSColin Finck         CoUnmarshalInterface(stream, &IID_IDropTarget, (void**)&droptarget);
548c2c66affSColin Finck         IStream_Release(stream);
549c2c66affSColin Finck     }
550c2c66affSColin Finck     CloseHandle(map);
551c2c66affSColin Finck     return droptarget;
552c2c66affSColin Finck }
553c2c66affSColin Finck 
554c2c66affSColin Finck /***********************************************************************
555c2c66affSColin Finck  *           RegisterDragDrop (OLE32.@)
556c2c66affSColin Finck  */
RegisterDragDrop(HWND hwnd,LPDROPTARGET pDropTarget)557c2c66affSColin Finck HRESULT WINAPI RegisterDragDrop(HWND hwnd, LPDROPTARGET pDropTarget)
558c2c66affSColin Finck {
559c2c66affSColin Finck   DWORD pid = 0;
560c2c66affSColin Finck   HRESULT hr;
561c2c66affSColin Finck   IStream *stream;
562c2c66affSColin Finck   HANDLE map;
563c2c66affSColin Finck   IDropTarget *wrapper;
564c2c66affSColin Finck 
565c2c66affSColin Finck   TRACE("(%p,%p)\n", hwnd, pDropTarget);
566c2c66affSColin Finck 
567c2c66affSColin Finck   if (!COM_CurrentApt())
568c2c66affSColin Finck   {
569c2c66affSColin Finck     ERR("COM not initialized\n");
570c2c66affSColin Finck     return E_OUTOFMEMORY;
571c2c66affSColin Finck   }
572c2c66affSColin Finck 
573c2c66affSColin Finck   if (!pDropTarget)
574c2c66affSColin Finck     return E_INVALIDARG;
575c2c66affSColin Finck 
576c2c66affSColin Finck   if (!IsWindow(hwnd))
577c2c66affSColin Finck   {
578c2c66affSColin Finck     ERR("invalid hwnd %p\n", hwnd);
579c2c66affSColin Finck     return DRAGDROP_E_INVALIDHWND;
580c2c66affSColin Finck   }
581c2c66affSColin Finck 
582c2c66affSColin Finck   /* block register for other processes windows */
583c2c66affSColin Finck   GetWindowThreadProcessId(hwnd, &pid);
584c2c66affSColin Finck   if (pid != GetCurrentProcessId())
585c2c66affSColin Finck   {
586c2c66affSColin Finck     FIXME("register for another process windows is disabled\n");
587c2c66affSColin Finck     return DRAGDROP_E_INVALIDHWND;
588c2c66affSColin Finck   }
589c2c66affSColin Finck 
590c2c66affSColin Finck   /* check if the window is already registered */
591c2c66affSColin Finck   if (is_droptarget(hwnd))
592c2c66affSColin Finck     return DRAGDROP_E_ALREADYREGISTERED;
593c2c66affSColin Finck 
594c2c66affSColin Finck   /*
595c2c66affSColin Finck    * Marshal the drop target pointer into a shared memory map and
596c2c66affSColin Finck    * store the map's handle in a Wine specific window prop.  We also
597c2c66affSColin Finck    * store the drop target pointer itself in the
598c2c66affSColin Finck    * "OleDropTargetInterface" prop for compatibility with Windows.
599c2c66affSColin Finck    */
600c2c66affSColin Finck 
601c2c66affSColin Finck   hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
602c2c66affSColin Finck   if(FAILED(hr)) return hr;
603c2c66affSColin Finck 
604c2c66affSColin Finck   /* IDropTarget::QueryInterface() shouldn't be called, some (broken) apps depend on this. */
605c2c66affSColin Finck   wrapper = WrapDropTarget( hwnd );
606c2c66affSColin Finck   if(!wrapper)
607c2c66affSColin Finck   {
608c2c66affSColin Finck     IStream_Release(stream);
609c2c66affSColin Finck     return E_OUTOFMEMORY;
610c2c66affSColin Finck   }
611c2c66affSColin Finck   hr = CoMarshalInterface(stream, &IID_IDropTarget, (IUnknown*)wrapper, MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
612c2c66affSColin Finck   IDropTarget_Release(wrapper);
613c2c66affSColin Finck 
614c2c66affSColin Finck   if(SUCCEEDED(hr))
615c2c66affSColin Finck   {
616c2c66affSColin Finck     hr = create_map_from_stream(stream, &map);
617c2c66affSColin Finck     if(SUCCEEDED(hr))
618c2c66affSColin Finck     {
619c2c66affSColin Finck       IDropTarget_AddRef(pDropTarget);
620c2c66affSColin Finck       SetPropW(hwnd, prop_oledroptarget, pDropTarget);
621c2c66affSColin Finck       SetPropW(hwnd, prop_marshalleddroptarget, map);
622c2c66affSColin Finck     }
623c2c66affSColin Finck     else
624c2c66affSColin Finck     {
625c2c66affSColin Finck       LARGE_INTEGER zero;
626c2c66affSColin Finck       zero.QuadPart = 0;
627c2c66affSColin Finck       IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
628c2c66affSColin Finck       CoReleaseMarshalData(stream);
629c2c66affSColin Finck     }
630c2c66affSColin Finck   }
631c2c66affSColin Finck   IStream_Release(stream);
632c2c66affSColin Finck 
633c2c66affSColin Finck   return hr;
634c2c66affSColin Finck }
635c2c66affSColin Finck 
636c2c66affSColin Finck /***********************************************************************
637c2c66affSColin Finck  *           RevokeDragDrop (OLE32.@)
638c2c66affSColin Finck  */
RevokeDragDrop(HWND hwnd)639c2c66affSColin Finck HRESULT WINAPI RevokeDragDrop(HWND hwnd)
640c2c66affSColin Finck {
641c2c66affSColin Finck   HANDLE map;
642c2c66affSColin Finck   IStream *stream;
643c2c66affSColin Finck   IDropTarget *drop_target;
644c2c66affSColin Finck   HRESULT hr;
645c2c66affSColin Finck 
646c2c66affSColin Finck   TRACE("(%p)\n", hwnd);
647c2c66affSColin Finck 
648c2c66affSColin Finck   if (!IsWindow(hwnd))
649c2c66affSColin Finck   {
650c2c66affSColin Finck     ERR("invalid hwnd %p\n", hwnd);
651c2c66affSColin Finck     return DRAGDROP_E_INVALIDHWND;
652c2c66affSColin Finck   }
653c2c66affSColin Finck 
654c2c66affSColin Finck   /* no registration data */
655c2c66affSColin Finck   if (!(map = get_droptarget_handle(hwnd)))
656c2c66affSColin Finck     return DRAGDROP_E_NOTREGISTERED;
657c2c66affSColin Finck 
658c2c66affSColin Finck   drop_target = GetPropW(hwnd, prop_oledroptarget);
659c2c66affSColin Finck   if(drop_target) IDropTarget_Release(drop_target);
660c2c66affSColin Finck 
661c2c66affSColin Finck   RemovePropW(hwnd, prop_oledroptarget);
662c2c66affSColin Finck   RemovePropW(hwnd, prop_marshalleddroptarget);
663c2c66affSColin Finck 
664c2c66affSColin Finck   hr = create_stream_from_map(map, &stream);
665c2c66affSColin Finck   if(SUCCEEDED(hr))
666c2c66affSColin Finck   {
667c2c66affSColin Finck       CoReleaseMarshalData(stream);
668c2c66affSColin Finck       IStream_Release(stream);
669c2c66affSColin Finck   }
670c2c66affSColin Finck   CloseHandle(map);
671c2c66affSColin Finck 
672c2c66affSColin Finck   return hr;
673c2c66affSColin Finck }
674c2c66affSColin Finck 
675c2c66affSColin Finck /***********************************************************************
676c2c66affSColin Finck  *           OleRegGetUserType (OLE32.@)
677c2c66affSColin Finck  */
OleRegGetUserType(REFCLSID clsid,DWORD form,LPOLESTR * usertype)678c2c66affSColin Finck HRESULT WINAPI OleRegGetUserType(REFCLSID clsid, DWORD form, LPOLESTR *usertype)
679c2c66affSColin Finck {
680c2c66affSColin Finck   static const WCHAR auxusertypeW[] = {'A','u','x','U','s','e','r','T','y','p','e','\\','%','d',0};
681c2c66affSColin Finck   DWORD valuetype, valuelen;
682c2c66affSColin Finck   WCHAR auxkeynameW[16];
683c2c66affSColin Finck   HKEY    usertypekey;
684c2c66affSColin Finck   HRESULT hres;
685c2c66affSColin Finck   LONG    ret;
686c2c66affSColin Finck 
687c2c66affSColin Finck   TRACE("(%s, %u, %p)\n", debugstr_guid(clsid), form, usertype);
688c2c66affSColin Finck 
689c2c66affSColin Finck   if (!usertype)
690c2c66affSColin Finck     return E_INVALIDARG;
691c2c66affSColin Finck 
692c2c66affSColin Finck   *usertype = NULL;
693c2c66affSColin Finck 
694c2c66affSColin Finck   /* Return immediately if it's not registered. */
695c2c66affSColin Finck   hres = COM_OpenKeyForCLSID(clsid, NULL, KEY_READ, &usertypekey);
696c2c66affSColin Finck   if (FAILED(hres))
697c2c66affSColin Finck     return hres;
698c2c66affSColin Finck 
699c2c66affSColin Finck   valuelen = 0;
700c2c66affSColin Finck 
701c2c66affSColin Finck   /* Try additional types if requested. If they don't exist fall back to USERCLASSTYPE_FULL. */
702c2c66affSColin Finck   if (form != USERCLASSTYPE_FULL)
703c2c66affSColin Finck   {
704c2c66affSColin Finck     HKEY auxkey;
705c2c66affSColin Finck 
706*0f5d91b7SAmine Khaldi     swprintf(auxkeynameW, auxusertypeW, form);
707c2c66affSColin Finck     if (COM_OpenKeyForCLSID(clsid, auxkeynameW, KEY_READ, &auxkey) == S_OK)
708c2c66affSColin Finck     {
709c2c66affSColin Finck       if (!RegQueryValueExW(auxkey, emptyW, NULL, &valuetype, NULL, &valuelen) && valuelen)
710c2c66affSColin Finck       {
711c2c66affSColin Finck         RegCloseKey(usertypekey);
712c2c66affSColin Finck         usertypekey = auxkey;
713c2c66affSColin Finck       }
714c2c66affSColin Finck       else
715c2c66affSColin Finck         RegCloseKey(auxkey);
716c2c66affSColin Finck     }
717c2c66affSColin Finck   }
718c2c66affSColin Finck 
719c2c66affSColin Finck   valuelen = 0;
720c2c66affSColin Finck   if (RegQueryValueExW(usertypekey, emptyW, NULL, &valuetype, NULL, &valuelen))
721c2c66affSColin Finck   {
722c2c66affSColin Finck     RegCloseKey(usertypekey);
723c2c66affSColin Finck     return REGDB_E_READREGDB;
724c2c66affSColin Finck   }
725c2c66affSColin Finck 
726c2c66affSColin Finck   *usertype = CoTaskMemAlloc(valuelen);
727c2c66affSColin Finck   if (!*usertype)
728c2c66affSColin Finck   {
729c2c66affSColin Finck     RegCloseKey(usertypekey);
730c2c66affSColin Finck     return E_OUTOFMEMORY;
731c2c66affSColin Finck   }
732c2c66affSColin Finck 
733c2c66affSColin Finck   ret = RegQueryValueExW(usertypekey,
734c2c66affSColin Finck 			  emptyW,
735c2c66affSColin Finck 			  NULL,
736c2c66affSColin Finck 			  &valuetype,
737c2c66affSColin Finck 			  (LPBYTE)*usertype,
738c2c66affSColin Finck 			  &valuelen);
739c2c66affSColin Finck   RegCloseKey(usertypekey);
740c2c66affSColin Finck   if (ret != ERROR_SUCCESS)
741c2c66affSColin Finck   {
742c2c66affSColin Finck     CoTaskMemFree(*usertype);
743c2c66affSColin Finck     *usertype = NULL;
744c2c66affSColin Finck     return REGDB_E_READREGDB;
745c2c66affSColin Finck   }
746c2c66affSColin Finck 
747c2c66affSColin Finck   return S_OK;
748c2c66affSColin Finck }
749c2c66affSColin Finck 
750c2c66affSColin Finck /***********************************************************************
751c2c66affSColin Finck  * DoDragDrop [OLE32.@]
752c2c66affSColin Finck  */
DoDragDrop(IDataObject * pDataObject,IDropSource * pDropSource,DWORD dwOKEffect,DWORD * pdwEffect)753c2c66affSColin Finck HRESULT WINAPI DoDragDrop (
754c2c66affSColin Finck   IDataObject *pDataObject,  /* [in] ptr to the data obj           */
755c2c66affSColin Finck   IDropSource* pDropSource,  /* [in] ptr to the source obj         */
756c2c66affSColin Finck   DWORD       dwOKEffect,    /* [in] effects allowed by the source */
757c2c66affSColin Finck   DWORD       *pdwEffect)    /* [out] ptr to effects of the source */
758c2c66affSColin Finck {
759c2c66affSColin Finck   static const WCHAR trackerW[] = {'T','r','a','c','k','e','r','W','i','n','d','o','w',0};
760c2c66affSColin Finck   TrackerWindowInfo trackerInfo;
761c2c66affSColin Finck   HWND            hwndTrackWindow;
762c2c66affSColin Finck   MSG             msg;
763c2c66affSColin Finck 
764c2c66affSColin Finck   TRACE("(%p, %p, %08x, %p)\n", pDataObject, pDropSource, dwOKEffect, pdwEffect);
765c2c66affSColin Finck 
766c2c66affSColin Finck   if (!pDataObject || !pDropSource || !pdwEffect)
767c2c66affSColin Finck       return E_INVALIDARG;
768c2c66affSColin Finck 
769c2c66affSColin Finck   /*
770c2c66affSColin Finck    * Setup the drag n drop tracking window.
771c2c66affSColin Finck    */
772c2c66affSColin Finck 
773c2c66affSColin Finck   trackerInfo.dataObject        = pDataObject;
774c2c66affSColin Finck   trackerInfo.dropSource        = pDropSource;
775c2c66affSColin Finck   trackerInfo.dwOKEffect        = dwOKEffect;
776c2c66affSColin Finck   trackerInfo.pdwEffect         = pdwEffect;
777c2c66affSColin Finck   trackerInfo.trackingDone      = FALSE;
778c2c66affSColin Finck   trackerInfo.escPressed        = FALSE;
779c2c66affSColin Finck   trackerInfo.curTargetHWND     = 0;
780c2c66affSColin Finck   trackerInfo.curDragTarget     = 0;
781332ca5f5SKatayama Hirofumi MZ #ifdef __REACTOS__
782332ca5f5SKatayama Hirofumi MZ   trackerInfo.accepterHWND      = NULL;
783332ca5f5SKatayama Hirofumi MZ #endif
784c2c66affSColin Finck 
785c2c66affSColin Finck   hwndTrackWindow = CreateWindowW(OLEDD_DRAGTRACKERCLASS, trackerW,
786c2c66affSColin Finck                                   WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT,
787c2c66affSColin Finck                                   CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, 0,
788c2c66affSColin Finck                                   &trackerInfo);
789c2c66affSColin Finck 
790c2c66affSColin Finck   if (hwndTrackWindow)
791c2c66affSColin Finck   {
792c2c66affSColin Finck     /*
793c2c66affSColin Finck      * Capture the mouse input
794c2c66affSColin Finck      */
795c2c66affSColin Finck     SetCapture(hwndTrackWindow);
796c2c66affSColin Finck 
797c2c66affSColin Finck     msg.message = 0;
798c2c66affSColin Finck 
799c2c66affSColin Finck     /*
800c2c66affSColin Finck      * Pump messages. All mouse input should go to the capture window.
801c2c66affSColin Finck      */
802c2c66affSColin Finck     while (!trackerInfo.trackingDone && GetMessageW(&msg, 0, 0, 0) )
803c2c66affSColin Finck     {
804c2c66affSColin Finck       trackerInfo.curMousePos.x = msg.pt.x;
805c2c66affSColin Finck       trackerInfo.curMousePos.y = msg.pt.y;
806c2c66affSColin Finck       trackerInfo.dwKeyState = OLEDD_GetButtonState();
807c2c66affSColin Finck 
808c2c66affSColin Finck       if ( (msg.message >= WM_KEYFIRST) &&
809c2c66affSColin Finck 	   (msg.message <= WM_KEYLAST) )
810c2c66affSColin Finck       {
811c2c66affSColin Finck 	/*
812c2c66affSColin Finck 	 * When keyboard messages are sent to windows on this thread, we
813c2c66affSColin Finck 	 * want to ignore notify the drop source that the state changed.
814c2c66affSColin Finck 	 * in the case of the Escape key, we also notify the drop source
815c2c66affSColin Finck 	 * we give it a special meaning.
816c2c66affSColin Finck 	 */
817c2c66affSColin Finck 	if ( (msg.message==WM_KEYDOWN) &&
818c2c66affSColin Finck 	     (msg.wParam==VK_ESCAPE) )
819c2c66affSColin Finck 	{
820c2c66affSColin Finck 	  trackerInfo.escPressed = TRUE;
821c2c66affSColin Finck 	}
822c2c66affSColin Finck 
823c2c66affSColin Finck 	/*
824c2c66affSColin Finck 	 * Notify the drop source.
825c2c66affSColin Finck 	 */
826c2c66affSColin Finck         OLEDD_TrackStateChange(&trackerInfo);
827c2c66affSColin Finck       }
828c2c66affSColin Finck       else
829c2c66affSColin Finck       {
830c2c66affSColin Finck 	/*
831c2c66affSColin Finck 	 * Dispatch the messages only when it's not a keyboard message.
832c2c66affSColin Finck 	 */
833c2c66affSColin Finck 	DispatchMessageW(&msg);
834c2c66affSColin Finck       }
835c2c66affSColin Finck     }
836c2c66affSColin Finck 
837c2c66affSColin Finck     /* re-post the quit message to outer message loop */
838c2c66affSColin Finck     if (msg.message == WM_QUIT)
839c2c66affSColin Finck         PostQuitMessage(msg.wParam);
840c2c66affSColin Finck     /*
841c2c66affSColin Finck      * Destroy the temporary window.
842c2c66affSColin Finck      */
843c2c66affSColin Finck     DestroyWindow(hwndTrackWindow);
844c2c66affSColin Finck 
845c2c66affSColin Finck     return trackerInfo.returnValue;
846c2c66affSColin Finck   }
847c2c66affSColin Finck 
848c2c66affSColin Finck   return E_FAIL;
849c2c66affSColin Finck }
850c2c66affSColin Finck 
851c2c66affSColin Finck /***********************************************************************
852c2c66affSColin Finck  * OleQueryLinkFromData [OLE32.@]
853c2c66affSColin Finck  */
OleQueryLinkFromData(IDataObject * pSrcDataObject)854c2c66affSColin Finck HRESULT WINAPI OleQueryLinkFromData(
855c2c66affSColin Finck   IDataObject* pSrcDataObject)
856c2c66affSColin Finck {
857c2c66affSColin Finck   FIXME("(%p),stub!\n", pSrcDataObject);
858c2c66affSColin Finck   return S_FALSE;
859c2c66affSColin Finck }
860c2c66affSColin Finck 
861c2c66affSColin Finck /***********************************************************************
862c2c66affSColin Finck  * OleRegGetMiscStatus [OLE32.@]
863c2c66affSColin Finck  */
OleRegGetMiscStatus(REFCLSID clsid,DWORD dwAspect,DWORD * pdwStatus)864c2c66affSColin Finck HRESULT WINAPI OleRegGetMiscStatus(
865c2c66affSColin Finck   REFCLSID clsid,
866c2c66affSColin Finck   DWORD    dwAspect,
867c2c66affSColin Finck   DWORD*   pdwStatus)
868c2c66affSColin Finck {
869c2c66affSColin Finck   static const WCHAR miscstatusW[] = {'M','i','s','c','S','t','a','t','u','s',0};
870c2c66affSColin Finck   static const WCHAR dfmtW[] = {'%','d',0};
871c2c66affSColin Finck   WCHAR   keyName[16];
872c2c66affSColin Finck   HKEY    miscStatusKey;
873c2c66affSColin Finck   HKEY    aspectKey;
874c2c66affSColin Finck   LONG    result;
875c2c66affSColin Finck   HRESULT hr;
876c2c66affSColin Finck 
877c2c66affSColin Finck   TRACE("(%s, %d, %p)\n", debugstr_guid(clsid), dwAspect, pdwStatus);
878c2c66affSColin Finck 
879c2c66affSColin Finck   if (!pdwStatus) return E_INVALIDARG;
880c2c66affSColin Finck 
881c2c66affSColin Finck   *pdwStatus = 0;
882c2c66affSColin Finck 
883c2c66affSColin Finck   if (actctx_get_miscstatus(clsid, dwAspect, pdwStatus)) return S_OK;
884c2c66affSColin Finck 
885c2c66affSColin Finck   hr = COM_OpenKeyForCLSID(clsid, miscstatusW, KEY_READ, &miscStatusKey);
886c2c66affSColin Finck   if (FAILED(hr))
887c2c66affSColin Finck     /* missing key is not a failure */
888c2c66affSColin Finck     return hr == REGDB_E_KEYMISSING ? S_OK : hr;
889c2c66affSColin Finck 
890c2c66affSColin Finck   OLEUTL_ReadRegistryDWORDValue(miscStatusKey, pdwStatus);
891c2c66affSColin Finck 
892c2c66affSColin Finck   /*
893c2c66affSColin Finck    * Open the key specific to the requested aspect.
894c2c66affSColin Finck    */
895*0f5d91b7SAmine Khaldi   swprintf(keyName, dfmtW, dwAspect);
896c2c66affSColin Finck 
897c2c66affSColin Finck   result = open_classes_key(miscStatusKey, keyName, KEY_READ, &aspectKey);
898c2c66affSColin Finck   if (result == ERROR_SUCCESS)
899c2c66affSColin Finck   {
900c2c66affSColin Finck     OLEUTL_ReadRegistryDWORDValue(aspectKey, pdwStatus);
901c2c66affSColin Finck     RegCloseKey(aspectKey);
902c2c66affSColin Finck   }
903c2c66affSColin Finck 
904c2c66affSColin Finck   RegCloseKey(miscStatusKey);
905c2c66affSColin Finck   return S_OK;
906c2c66affSColin Finck }
907c2c66affSColin Finck 
908c2c66affSColin Finck static HRESULT EnumOLEVERB_Construct(HKEY hkeyVerb, ULONG index, IEnumOLEVERB **ppenum);
909c2c66affSColin Finck 
910c2c66affSColin Finck typedef struct
911c2c66affSColin Finck {
912c2c66affSColin Finck     IEnumOLEVERB IEnumOLEVERB_iface;
913c2c66affSColin Finck     LONG ref;
914c2c66affSColin Finck 
915c2c66affSColin Finck     HKEY hkeyVerb;
916c2c66affSColin Finck     ULONG index;
917c2c66affSColin Finck } EnumOLEVERB;
918c2c66affSColin Finck 
impl_from_IEnumOLEVERB(IEnumOLEVERB * iface)919c2c66affSColin Finck static inline EnumOLEVERB *impl_from_IEnumOLEVERB(IEnumOLEVERB *iface)
920c2c66affSColin Finck {
921c2c66affSColin Finck     return CONTAINING_RECORD(iface, EnumOLEVERB, IEnumOLEVERB_iface);
922c2c66affSColin Finck }
923c2c66affSColin Finck 
EnumOLEVERB_QueryInterface(IEnumOLEVERB * iface,REFIID riid,void ** ppv)924c2c66affSColin Finck static HRESULT WINAPI EnumOLEVERB_QueryInterface(
925c2c66affSColin Finck     IEnumOLEVERB *iface, REFIID riid, void **ppv)
926c2c66affSColin Finck {
927c2c66affSColin Finck     TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
928c2c66affSColin Finck     if (IsEqualIID(riid, &IID_IUnknown) ||
929c2c66affSColin Finck         IsEqualIID(riid, &IID_IEnumOLEVERB))
930c2c66affSColin Finck     {
931c2c66affSColin Finck         IEnumOLEVERB_AddRef(iface);
932c2c66affSColin Finck         *ppv = iface;
933c2c66affSColin Finck         return S_OK;
934c2c66affSColin Finck     }
935c2c66affSColin Finck     return E_NOINTERFACE;
936c2c66affSColin Finck }
937c2c66affSColin Finck 
EnumOLEVERB_AddRef(IEnumOLEVERB * iface)938c2c66affSColin Finck static ULONG WINAPI EnumOLEVERB_AddRef(
939c2c66affSColin Finck     IEnumOLEVERB *iface)
940c2c66affSColin Finck {
941c2c66affSColin Finck     EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);
942c2c66affSColin Finck     TRACE("()\n");
943c2c66affSColin Finck     return InterlockedIncrement(&This->ref);
944c2c66affSColin Finck }
945c2c66affSColin Finck 
EnumOLEVERB_Release(IEnumOLEVERB * iface)946c2c66affSColin Finck static ULONG WINAPI EnumOLEVERB_Release(
947c2c66affSColin Finck     IEnumOLEVERB *iface)
948c2c66affSColin Finck {
949c2c66affSColin Finck     EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);
950c2c66affSColin Finck     LONG refs = InterlockedDecrement(&This->ref);
951c2c66affSColin Finck     TRACE("()\n");
952c2c66affSColin Finck     if (!refs)
953c2c66affSColin Finck     {
954c2c66affSColin Finck         RegCloseKey(This->hkeyVerb);
955c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, This);
956c2c66affSColin Finck     }
957c2c66affSColin Finck     return refs;
958c2c66affSColin Finck }
959c2c66affSColin Finck 
EnumOLEVERB_Next(IEnumOLEVERB * iface,ULONG celt,LPOLEVERB rgelt,ULONG * pceltFetched)960c2c66affSColin Finck static HRESULT WINAPI EnumOLEVERB_Next(
961c2c66affSColin Finck     IEnumOLEVERB *iface, ULONG celt, LPOLEVERB rgelt,
962c2c66affSColin Finck     ULONG *pceltFetched)
963c2c66affSColin Finck {
964c2c66affSColin Finck     EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);
965c2c66affSColin Finck     HRESULT hr = S_OK;
966c2c66affSColin Finck 
967c2c66affSColin Finck     TRACE("(%d, %p, %p)\n", celt, rgelt, pceltFetched);
968c2c66affSColin Finck 
969c2c66affSColin Finck     if (pceltFetched)
970c2c66affSColin Finck         *pceltFetched = 0;
971c2c66affSColin Finck 
972c2c66affSColin Finck     for (; celt; celt--, rgelt++)
973c2c66affSColin Finck     {
974c2c66affSColin Finck         WCHAR wszSubKey[20];
975c2c66affSColin Finck         LONG cbData;
976c2c66affSColin Finck         LPWSTR pwszOLEVERB;
977c2c66affSColin Finck         LPWSTR pwszMenuFlags;
978c2c66affSColin Finck         LPWSTR pwszAttribs;
979aeea2943SAmine Khaldi         LONG res = RegEnumKeyW(This->hkeyVerb, This->index, wszSubKey, ARRAY_SIZE(wszSubKey));
980c2c66affSColin Finck         if (res == ERROR_NO_MORE_ITEMS)
981c2c66affSColin Finck         {
982c2c66affSColin Finck             hr = S_FALSE;
983c2c66affSColin Finck             break;
984c2c66affSColin Finck         }
985c2c66affSColin Finck         else if (res != ERROR_SUCCESS)
986c2c66affSColin Finck         {
987c2c66affSColin Finck             ERR("RegEnumKeyW failed with error %d\n", res);
988c2c66affSColin Finck             hr = REGDB_E_READREGDB;
989c2c66affSColin Finck             break;
990c2c66affSColin Finck         }
991c2c66affSColin Finck         res = RegQueryValueW(This->hkeyVerb, wszSubKey, NULL, &cbData);
992c2c66affSColin Finck         if (res != ERROR_SUCCESS)
993c2c66affSColin Finck         {
994c2c66affSColin Finck             ERR("RegQueryValueW failed with error %d\n", res);
995c2c66affSColin Finck             hr = REGDB_E_READREGDB;
996c2c66affSColin Finck             break;
997c2c66affSColin Finck         }
998c2c66affSColin Finck         pwszOLEVERB = CoTaskMemAlloc(cbData);
999c2c66affSColin Finck         if (!pwszOLEVERB)
1000c2c66affSColin Finck         {
1001c2c66affSColin Finck             hr = E_OUTOFMEMORY;
1002c2c66affSColin Finck             break;
1003c2c66affSColin Finck         }
1004c2c66affSColin Finck         res = RegQueryValueW(This->hkeyVerb, wszSubKey, pwszOLEVERB, &cbData);
1005c2c66affSColin Finck         if (res != ERROR_SUCCESS)
1006c2c66affSColin Finck         {
1007c2c66affSColin Finck             ERR("RegQueryValueW failed with error %d\n", res);
1008c2c66affSColin Finck             hr = REGDB_E_READREGDB;
1009c2c66affSColin Finck             CoTaskMemFree(pwszOLEVERB);
1010c2c66affSColin Finck             break;
1011c2c66affSColin Finck         }
1012c2c66affSColin Finck 
1013c2c66affSColin Finck         TRACE("verb string: %s\n", debugstr_w(pwszOLEVERB));
1014*0f5d91b7SAmine Khaldi         pwszMenuFlags = wcschr(pwszOLEVERB, ',');
1015c2c66affSColin Finck         if (!pwszMenuFlags)
1016c2c66affSColin Finck         {
1017c2c66affSColin Finck             hr = OLEOBJ_E_INVALIDVERB;
1018c2c66affSColin Finck             CoTaskMemFree(pwszOLEVERB);
1019c2c66affSColin Finck             break;
1020c2c66affSColin Finck         }
1021c2c66affSColin Finck         /* nul terminate the name string and advance to first character */
1022c2c66affSColin Finck         *pwszMenuFlags = '\0';
1023c2c66affSColin Finck         pwszMenuFlags++;
1024*0f5d91b7SAmine Khaldi         pwszAttribs = wcschr(pwszMenuFlags, ',');
1025c2c66affSColin Finck         if (!pwszAttribs)
1026c2c66affSColin Finck         {
1027c2c66affSColin Finck             hr = OLEOBJ_E_INVALIDVERB;
1028c2c66affSColin Finck             CoTaskMemFree(pwszOLEVERB);
1029c2c66affSColin Finck             break;
1030c2c66affSColin Finck         }
1031c2c66affSColin Finck         /* nul terminate the menu string and advance to first character */
1032c2c66affSColin Finck         *pwszAttribs = '\0';
1033c2c66affSColin Finck         pwszAttribs++;
1034c2c66affSColin Finck 
1035c2c66affSColin Finck         /* fill out structure for this verb */
1036*0f5d91b7SAmine Khaldi         rgelt->lVerb = wcstol(wszSubKey, NULL, 10);
1037c2c66affSColin Finck         rgelt->lpszVerbName = pwszOLEVERB; /* user should free */
1038*0f5d91b7SAmine Khaldi         rgelt->fuFlags = wcstol(pwszMenuFlags, NULL, 10);
1039*0f5d91b7SAmine Khaldi         rgelt->grfAttribs = wcstol(pwszAttribs, NULL, 10);
1040c2c66affSColin Finck 
1041c2c66affSColin Finck         if (pceltFetched)
1042c2c66affSColin Finck             (*pceltFetched)++;
1043c2c66affSColin Finck         This->index++;
1044c2c66affSColin Finck     }
1045c2c66affSColin Finck     return hr;
1046c2c66affSColin Finck }
1047c2c66affSColin Finck 
EnumOLEVERB_Skip(IEnumOLEVERB * iface,ULONG celt)1048c2c66affSColin Finck static HRESULT WINAPI EnumOLEVERB_Skip(
1049c2c66affSColin Finck     IEnumOLEVERB *iface, ULONG celt)
1050c2c66affSColin Finck {
1051c2c66affSColin Finck     EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);
1052c2c66affSColin Finck 
1053c2c66affSColin Finck     TRACE("(%d)\n", celt);
1054c2c66affSColin Finck 
1055c2c66affSColin Finck     This->index += celt;
1056c2c66affSColin Finck     return S_OK;
1057c2c66affSColin Finck }
1058c2c66affSColin Finck 
EnumOLEVERB_Reset(IEnumOLEVERB * iface)1059c2c66affSColin Finck static HRESULT WINAPI EnumOLEVERB_Reset(
1060c2c66affSColin Finck     IEnumOLEVERB *iface)
1061c2c66affSColin Finck {
1062c2c66affSColin Finck     EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);
1063c2c66affSColin Finck 
1064c2c66affSColin Finck     TRACE("()\n");
1065c2c66affSColin Finck 
1066c2c66affSColin Finck     This->index = 0;
1067c2c66affSColin Finck     return S_OK;
1068c2c66affSColin Finck }
1069c2c66affSColin Finck 
EnumOLEVERB_Clone(IEnumOLEVERB * iface,IEnumOLEVERB ** ppenum)1070c2c66affSColin Finck static HRESULT WINAPI EnumOLEVERB_Clone(
1071c2c66affSColin Finck     IEnumOLEVERB *iface,
1072c2c66affSColin Finck     IEnumOLEVERB **ppenum)
1073c2c66affSColin Finck {
1074c2c66affSColin Finck     EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);
1075c2c66affSColin Finck     HKEY hkeyVerb;
1076c2c66affSColin Finck     TRACE("(%p)\n", ppenum);
1077c2c66affSColin Finck     if (!DuplicateHandle(GetCurrentProcess(), This->hkeyVerb, GetCurrentProcess(), (HANDLE *)&hkeyVerb, 0, FALSE, DUPLICATE_SAME_ACCESS))
1078c2c66affSColin Finck         return HRESULT_FROM_WIN32(GetLastError());
1079c2c66affSColin Finck     return EnumOLEVERB_Construct(hkeyVerb, This->index, ppenum);
1080c2c66affSColin Finck }
1081c2c66affSColin Finck 
1082c2c66affSColin Finck static const IEnumOLEVERBVtbl EnumOLEVERB_VTable =
1083c2c66affSColin Finck {
1084c2c66affSColin Finck     EnumOLEVERB_QueryInterface,
1085c2c66affSColin Finck     EnumOLEVERB_AddRef,
1086c2c66affSColin Finck     EnumOLEVERB_Release,
1087c2c66affSColin Finck     EnumOLEVERB_Next,
1088c2c66affSColin Finck     EnumOLEVERB_Skip,
1089c2c66affSColin Finck     EnumOLEVERB_Reset,
1090c2c66affSColin Finck     EnumOLEVERB_Clone
1091c2c66affSColin Finck };
1092c2c66affSColin Finck 
EnumOLEVERB_Construct(HKEY hkeyVerb,ULONG index,IEnumOLEVERB ** ppenum)1093c2c66affSColin Finck static HRESULT EnumOLEVERB_Construct(HKEY hkeyVerb, ULONG index, IEnumOLEVERB **ppenum)
1094c2c66affSColin Finck {
1095c2c66affSColin Finck     EnumOLEVERB *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1096c2c66affSColin Finck     if (!This)
1097c2c66affSColin Finck     {
1098c2c66affSColin Finck         RegCloseKey(hkeyVerb);
1099c2c66affSColin Finck         return E_OUTOFMEMORY;
1100c2c66affSColin Finck     }
1101c2c66affSColin Finck     This->IEnumOLEVERB_iface.lpVtbl = &EnumOLEVERB_VTable;
1102c2c66affSColin Finck     This->ref = 1;
1103c2c66affSColin Finck     This->index = index;
1104c2c66affSColin Finck     This->hkeyVerb = hkeyVerb;
1105c2c66affSColin Finck     *ppenum = &This->IEnumOLEVERB_iface;
1106c2c66affSColin Finck     return S_OK;
1107c2c66affSColin Finck }
1108c2c66affSColin Finck 
1109c2c66affSColin Finck /***********************************************************************
1110c2c66affSColin Finck  *           OleRegEnumVerbs    [OLE32.@]
1111c2c66affSColin Finck  *
1112c2c66affSColin Finck  * Enumerates verbs associated with a class stored in the registry.
1113c2c66affSColin Finck  *
1114c2c66affSColin Finck  * PARAMS
1115c2c66affSColin Finck  *  clsid  [I] Class ID to enumerate the verbs for.
1116c2c66affSColin Finck  *  ppenum [O] Enumerator.
1117c2c66affSColin Finck  *
1118c2c66affSColin Finck  * RETURNS
1119c2c66affSColin Finck  *  S_OK: Success.
1120c2c66affSColin Finck  *  REGDB_E_CLASSNOTREG: The specified class does not have a key in the registry.
1121c2c66affSColin Finck  *  REGDB_E_READREGDB: The class key could not be opened for some other reason.
1122c2c66affSColin Finck  *  OLE_E_REGDB_KEY: The Verb subkey for the class is not present.
1123c2c66affSColin Finck  *  OLEOBJ_E_NOVERBS: The Verb subkey for the class is empty.
1124c2c66affSColin Finck  */
OleRegEnumVerbs(REFCLSID clsid,LPENUMOLEVERB * ppenum)1125c2c66affSColin Finck HRESULT WINAPI OleRegEnumVerbs (REFCLSID clsid, LPENUMOLEVERB* ppenum)
1126c2c66affSColin Finck {
1127c2c66affSColin Finck     LONG res;
1128c2c66affSColin Finck     HKEY hkeyVerb;
1129c2c66affSColin Finck     DWORD dwSubKeys;
1130c2c66affSColin Finck     static const WCHAR wszVerb[] = {'V','e','r','b',0};
1131c2c66affSColin Finck 
1132c2c66affSColin Finck     TRACE("(%s, %p)\n", debugstr_guid(clsid), ppenum);
1133c2c66affSColin Finck 
1134c2c66affSColin Finck     res = COM_OpenKeyForCLSID(clsid, wszVerb, KEY_READ, &hkeyVerb);
1135c2c66affSColin Finck     if (FAILED(res))
1136c2c66affSColin Finck     {
1137c2c66affSColin Finck         if (res == REGDB_E_CLASSNOTREG)
1138c2c66affSColin Finck             ERR("CLSID %s not registered\n", debugstr_guid(clsid));
1139c2c66affSColin Finck         else if (res == REGDB_E_KEYMISSING)
1140c2c66affSColin Finck             ERR("no Verbs key for class %s\n", debugstr_guid(clsid));
1141c2c66affSColin Finck         else
1142c2c66affSColin Finck             ERR("failed to open Verbs key for CLSID %s with error %d\n",
1143c2c66affSColin Finck                 debugstr_guid(clsid), res);
1144c2c66affSColin Finck         return res;
1145c2c66affSColin Finck     }
1146c2c66affSColin Finck 
1147c2c66affSColin Finck     res = RegQueryInfoKeyW(hkeyVerb, NULL, NULL, NULL, &dwSubKeys, NULL,
1148c2c66affSColin Finck                           NULL, NULL, NULL, NULL, NULL, NULL);
1149c2c66affSColin Finck     if (res != ERROR_SUCCESS)
1150c2c66affSColin Finck     {
1151c2c66affSColin Finck         ERR("failed to get subkey count with error %d\n", GetLastError());
1152c2c66affSColin Finck         return REGDB_E_READREGDB;
1153c2c66affSColin Finck     }
1154c2c66affSColin Finck 
1155c2c66affSColin Finck     if (!dwSubKeys)
1156c2c66affSColin Finck     {
1157c2c66affSColin Finck         WARN("class %s has no verbs\n", debugstr_guid(clsid));
1158c2c66affSColin Finck         RegCloseKey(hkeyVerb);
1159c2c66affSColin Finck         return OLEOBJ_E_NOVERBS;
1160c2c66affSColin Finck     }
1161c2c66affSColin Finck 
1162c2c66affSColin Finck     return EnumOLEVERB_Construct(hkeyVerb, 0, ppenum);
1163c2c66affSColin Finck }
1164c2c66affSColin Finck 
1165c2c66affSColin Finck /******************************************************************************
1166c2c66affSColin Finck  *              OleSetContainedObject        [OLE32.@]
1167c2c66affSColin Finck  */
OleSetContainedObject(LPUNKNOWN pUnknown,BOOL fContained)1168c2c66affSColin Finck HRESULT WINAPI OleSetContainedObject(
1169c2c66affSColin Finck   LPUNKNOWN pUnknown,
1170c2c66affSColin Finck   BOOL      fContained)
1171c2c66affSColin Finck {
1172c2c66affSColin Finck   IRunnableObject* runnable = NULL;
1173c2c66affSColin Finck   HRESULT          hres;
1174c2c66affSColin Finck 
1175c2c66affSColin Finck   TRACE("(%p,%x)\n", pUnknown, fContained);
1176c2c66affSColin Finck 
1177c2c66affSColin Finck   hres = IUnknown_QueryInterface(pUnknown,
1178c2c66affSColin Finck 				 &IID_IRunnableObject,
1179c2c66affSColin Finck 				 (void**)&runnable);
1180c2c66affSColin Finck 
1181c2c66affSColin Finck   if (SUCCEEDED(hres))
1182c2c66affSColin Finck   {
1183c2c66affSColin Finck     hres = IRunnableObject_SetContainedObject(runnable, fContained);
1184c2c66affSColin Finck 
1185c2c66affSColin Finck     IRunnableObject_Release(runnable);
1186c2c66affSColin Finck 
1187c2c66affSColin Finck     return hres;
1188c2c66affSColin Finck   }
1189c2c66affSColin Finck 
1190c2c66affSColin Finck   return S_OK;
1191c2c66affSColin Finck }
1192c2c66affSColin Finck 
1193c2c66affSColin Finck /******************************************************************************
1194c2c66affSColin Finck  *              OleRun        [OLE32.@]
1195c2c66affSColin Finck  *
1196c2c66affSColin Finck  * Set the OLE object to the running state.
1197c2c66affSColin Finck  *
1198c2c66affSColin Finck  * PARAMS
1199c2c66affSColin Finck  *  pUnknown [I] OLE object to run.
1200c2c66affSColin Finck  *
1201c2c66affSColin Finck  * RETURNS
1202c2c66affSColin Finck  *  Success: S_OK.
1203c2c66affSColin Finck  *  Failure: Any HRESULT code.
1204c2c66affSColin Finck  */
OleRun(LPUNKNOWN pUnknown)1205c2c66affSColin Finck HRESULT WINAPI DECLSPEC_HOTPATCH OleRun(LPUNKNOWN pUnknown)
1206c2c66affSColin Finck {
1207c2c66affSColin Finck     IRunnableObject *runable;
1208c2c66affSColin Finck     HRESULT hres;
1209c2c66affSColin Finck 
1210c2c66affSColin Finck     TRACE("(%p)\n", pUnknown);
1211c2c66affSColin Finck 
1212c2c66affSColin Finck     hres = IUnknown_QueryInterface(pUnknown, &IID_IRunnableObject, (void**)&runable);
1213c2c66affSColin Finck     if (FAILED(hres))
1214c2c66affSColin Finck         return S_OK; /* Appears to return no error. */
1215c2c66affSColin Finck 
1216c2c66affSColin Finck     hres = IRunnableObject_Run(runable, NULL);
1217c2c66affSColin Finck     IRunnableObject_Release(runable);
1218c2c66affSColin Finck     return hres;
1219c2c66affSColin Finck }
1220c2c66affSColin Finck 
1221c2c66affSColin Finck /******************************************************************************
1222c2c66affSColin Finck  *              OleLoad        [OLE32.@]
1223c2c66affSColin Finck  */
OleLoad(LPSTORAGE pStg,REFIID riid,LPOLECLIENTSITE pClientSite,LPVOID * ppvObj)1224c2c66affSColin Finck HRESULT WINAPI OleLoad(
1225c2c66affSColin Finck   LPSTORAGE       pStg,
1226c2c66affSColin Finck   REFIID          riid,
1227c2c66affSColin Finck   LPOLECLIENTSITE pClientSite,
1228c2c66affSColin Finck   LPVOID*         ppvObj)
1229c2c66affSColin Finck {
1230c2c66affSColin Finck   IPersistStorage* persistStorage = NULL;
1231c2c66affSColin Finck   IUnknown*        pUnk;
1232c2c66affSColin Finck   IOleObject*      pOleObject      = NULL;
1233c2c66affSColin Finck   STATSTG          storageInfo;
1234c2c66affSColin Finck   HRESULT          hres;
1235c2c66affSColin Finck 
1236c2c66affSColin Finck   TRACE("(%p, %s, %p, %p)\n", pStg, debugstr_guid(riid), pClientSite, ppvObj);
1237c2c66affSColin Finck 
1238c2c66affSColin Finck   *ppvObj = NULL;
1239c2c66affSColin Finck 
1240c2c66affSColin Finck   /*
1241c2c66affSColin Finck    * TODO, Conversion ... OleDoAutoConvert
1242c2c66affSColin Finck    */
1243c2c66affSColin Finck 
1244c2c66affSColin Finck   /*
1245c2c66affSColin Finck    * Get the class ID for the object.
1246c2c66affSColin Finck    */
1247c2c66affSColin Finck   hres = IStorage_Stat(pStg, &storageInfo, STATFLAG_NONAME);
1248c2c66affSColin Finck   if (FAILED(hres))
1249c2c66affSColin Finck     return hres;
1250c2c66affSColin Finck 
1251c2c66affSColin Finck   /*
1252c2c66affSColin Finck    * Now, try and create the handler for the object
1253c2c66affSColin Finck    */
1254c2c66affSColin Finck   hres = CoCreateInstance(&storageInfo.clsid,
1255c2c66affSColin Finck 			  NULL,
1256c2c66affSColin Finck 			  CLSCTX_INPROC_HANDLER|CLSCTX_INPROC_SERVER,
1257c2c66affSColin Finck 			  riid,
1258c2c66affSColin Finck 			  (void**)&pUnk);
1259c2c66affSColin Finck 
1260c2c66affSColin Finck   /*
1261c2c66affSColin Finck    * If that fails, as it will most times, load the default
1262c2c66affSColin Finck    * OLE handler.
1263c2c66affSColin Finck    */
1264c2c66affSColin Finck   if (FAILED(hres))
1265c2c66affSColin Finck   {
1266c2c66affSColin Finck     hres = OleCreateDefaultHandler(&storageInfo.clsid,
1267c2c66affSColin Finck 				   NULL,
1268c2c66affSColin Finck 				   riid,
1269c2c66affSColin Finck 				   (void**)&pUnk);
1270c2c66affSColin Finck   }
1271c2c66affSColin Finck 
1272c2c66affSColin Finck   /*
1273c2c66affSColin Finck    * If we couldn't find a handler... this is bad. Abort the whole thing.
1274c2c66affSColin Finck    */
1275c2c66affSColin Finck   if (FAILED(hres))
1276c2c66affSColin Finck     return hres;
1277c2c66affSColin Finck 
1278c2c66affSColin Finck   if (pClientSite)
1279c2c66affSColin Finck   {
1280c2c66affSColin Finck     hres = IUnknown_QueryInterface(pUnk, &IID_IOleObject, (void **)&pOleObject);
1281c2c66affSColin Finck     if (SUCCEEDED(hres))
1282c2c66affSColin Finck     {
1283c2c66affSColin Finck         DWORD dwStatus;
1284c2c66affSColin Finck         hres = IOleObject_GetMiscStatus(pOleObject, DVASPECT_CONTENT, &dwStatus);
1285c2c66affSColin Finck     }
1286c2c66affSColin Finck   }
1287c2c66affSColin Finck 
1288c2c66affSColin Finck   /*
1289c2c66affSColin Finck    * Initialize the object with its IPersistStorage interface.
1290c2c66affSColin Finck    */
1291c2c66affSColin Finck   hres = IUnknown_QueryInterface(pUnk, &IID_IPersistStorage, (void**)&persistStorage);
1292c2c66affSColin Finck   if (SUCCEEDED(hres))
1293c2c66affSColin Finck   {
1294c2c66affSColin Finck     hres = IPersistStorage_Load(persistStorage, pStg);
1295c2c66affSColin Finck 
1296c2c66affSColin Finck     IPersistStorage_Release(persistStorage);
1297c2c66affSColin Finck     persistStorage = NULL;
1298c2c66affSColin Finck   }
1299c2c66affSColin Finck 
1300c2c66affSColin Finck   if (SUCCEEDED(hres) && pClientSite)
1301c2c66affSColin Finck     /*
1302c2c66affSColin Finck      * Inform the new object of its client site.
1303c2c66affSColin Finck      */
1304c2c66affSColin Finck     hres = IOleObject_SetClientSite(pOleObject, pClientSite);
1305c2c66affSColin Finck 
1306c2c66affSColin Finck   /*
1307c2c66affSColin Finck    * Cleanup interfaces used internally
1308c2c66affSColin Finck    */
1309c2c66affSColin Finck   if (pOleObject)
1310c2c66affSColin Finck     IOleObject_Release(pOleObject);
1311c2c66affSColin Finck 
1312c2c66affSColin Finck   if (SUCCEEDED(hres))
1313c2c66affSColin Finck   {
1314c2c66affSColin Finck     IOleLink *pOleLink;
1315c2c66affSColin Finck     HRESULT hres1;
1316c2c66affSColin Finck     hres1 = IUnknown_QueryInterface(pUnk, &IID_IOleLink, (void **)&pOleLink);
1317c2c66affSColin Finck     if (SUCCEEDED(hres1))
1318c2c66affSColin Finck     {
1319c2c66affSColin Finck       FIXME("handle OLE link\n");
1320c2c66affSColin Finck       IOleLink_Release(pOleLink);
1321c2c66affSColin Finck     }
1322c2c66affSColin Finck   }
1323c2c66affSColin Finck 
1324c2c66affSColin Finck   if (FAILED(hres))
1325c2c66affSColin Finck   {
1326c2c66affSColin Finck     IUnknown_Release(pUnk);
1327c2c66affSColin Finck     pUnk = NULL;
1328c2c66affSColin Finck   }
1329c2c66affSColin Finck 
1330c2c66affSColin Finck   *ppvObj = pUnk;
1331c2c66affSColin Finck 
1332c2c66affSColin Finck   return hres;
1333c2c66affSColin Finck }
1334c2c66affSColin Finck 
1335c2c66affSColin Finck /***********************************************************************
1336c2c66affSColin Finck  *           OleSave     [OLE32.@]
1337c2c66affSColin Finck  */
OleSave(LPPERSISTSTORAGE pPS,LPSTORAGE pStg,BOOL fSameAsLoad)1338c2c66affSColin Finck HRESULT WINAPI OleSave(
1339c2c66affSColin Finck   LPPERSISTSTORAGE pPS,
1340c2c66affSColin Finck   LPSTORAGE        pStg,
1341c2c66affSColin Finck   BOOL             fSameAsLoad)
1342c2c66affSColin Finck {
1343c2c66affSColin Finck   HRESULT hres;
1344c2c66affSColin Finck   CLSID   objectClass;
1345c2c66affSColin Finck 
1346c2c66affSColin Finck   TRACE("(%p,%p,%x)\n", pPS, pStg, fSameAsLoad);
1347c2c66affSColin Finck 
1348c2c66affSColin Finck   /*
1349c2c66affSColin Finck    * First, we transfer the class ID (if available)
1350c2c66affSColin Finck    */
1351c2c66affSColin Finck   hres = IPersistStorage_GetClassID(pPS, &objectClass);
1352c2c66affSColin Finck 
1353c2c66affSColin Finck   if (SUCCEEDED(hres))
1354c2c66affSColin Finck   {
1355c2c66affSColin Finck     WriteClassStg(pStg, &objectClass);
1356c2c66affSColin Finck   }
1357c2c66affSColin Finck 
1358c2c66affSColin Finck   /*
1359c2c66affSColin Finck    * Then, we ask the object to save itself to the
1360c2c66affSColin Finck    * storage. If it is successful, we commit the storage.
1361c2c66affSColin Finck    */
1362c2c66affSColin Finck   hres = IPersistStorage_Save(pPS, pStg, fSameAsLoad);
1363c2c66affSColin Finck 
1364c2c66affSColin Finck   if (SUCCEEDED(hres))
1365c2c66affSColin Finck   {
1366c2c66affSColin Finck     IStorage_Commit(pStg,
1367c2c66affSColin Finck 		    STGC_DEFAULT);
1368c2c66affSColin Finck   }
1369c2c66affSColin Finck 
1370c2c66affSColin Finck   return hres;
1371c2c66affSColin Finck }
1372c2c66affSColin Finck 
1373c2c66affSColin Finck 
1374c2c66affSColin Finck /******************************************************************************
1375c2c66affSColin Finck  *              OleLockRunning        [OLE32.@]
1376c2c66affSColin Finck  */
OleLockRunning(LPUNKNOWN pUnknown,BOOL fLock,BOOL fLastUnlockCloses)1377c2c66affSColin Finck HRESULT WINAPI OleLockRunning(LPUNKNOWN pUnknown, BOOL fLock, BOOL fLastUnlockCloses)
1378c2c66affSColin Finck {
1379c2c66affSColin Finck   IRunnableObject* runnable = NULL;
1380c2c66affSColin Finck   HRESULT          hres;
1381c2c66affSColin Finck 
1382c2c66affSColin Finck   TRACE("(%p,%x,%x)\n", pUnknown, fLock, fLastUnlockCloses);
1383c2c66affSColin Finck 
1384c2c66affSColin Finck   hres = IUnknown_QueryInterface(pUnknown,
1385c2c66affSColin Finck 				 &IID_IRunnableObject,
1386c2c66affSColin Finck 				 (void**)&runnable);
1387c2c66affSColin Finck 
1388c2c66affSColin Finck   if (SUCCEEDED(hres))
1389c2c66affSColin Finck   {
1390c2c66affSColin Finck     hres = IRunnableObject_LockRunning(runnable, fLock, fLastUnlockCloses);
1391c2c66affSColin Finck 
1392c2c66affSColin Finck     IRunnableObject_Release(runnable);
1393c2c66affSColin Finck 
1394c2c66affSColin Finck     return hres;
1395c2c66affSColin Finck   }
1396c2c66affSColin Finck 
1397c2c66affSColin Finck   return S_OK;
1398c2c66affSColin Finck }
1399c2c66affSColin Finck 
1400c2c66affSColin Finck 
1401c2c66affSColin Finck /**************************************************************************
1402c2c66affSColin Finck  * Internal methods to manage the shared OLE menu in response to the
1403c2c66affSColin Finck  * OLE***MenuDescriptor API
1404c2c66affSColin Finck  */
1405c2c66affSColin Finck 
1406c2c66affSColin Finck /***
1407c2c66affSColin Finck  * OLEMenu_Initialize()
1408c2c66affSColin Finck  *
1409c2c66affSColin Finck  * Initializes the OLEMENU data structures.
1410c2c66affSColin Finck  */
OLEMenu_Initialize(void)1411c2c66affSColin Finck static void OLEMenu_Initialize(void)
1412c2c66affSColin Finck {
1413c2c66affSColin Finck }
1414c2c66affSColin Finck 
1415c2c66affSColin Finck /***
1416c2c66affSColin Finck  * OLEMenu_UnInitialize()
1417c2c66affSColin Finck  *
1418c2c66affSColin Finck  * Releases the OLEMENU data structures.
1419c2c66affSColin Finck  */
OLEMenu_UnInitialize(void)1420c2c66affSColin Finck static void OLEMenu_UnInitialize(void)
1421c2c66affSColin Finck {
1422c2c66affSColin Finck }
1423c2c66affSColin Finck 
1424c2c66affSColin Finck /*************************************************************************
1425c2c66affSColin Finck  * OLEMenu_InstallHooks
1426c2c66affSColin Finck  * Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
1427c2c66affSColin Finck  *
1428c2c66affSColin Finck  * RETURNS: TRUE if message hooks were successfully installed
1429c2c66affSColin Finck  *          FALSE on failure
1430c2c66affSColin Finck  */
OLEMenu_InstallHooks(DWORD tid)1431c2c66affSColin Finck static BOOL OLEMenu_InstallHooks( DWORD tid )
1432c2c66affSColin Finck {
1433c2c66affSColin Finck   OleMenuHookItem *pHookItem;
1434c2c66affSColin Finck 
1435c2c66affSColin Finck   /* Create an entry for the hook table */
1436c2c66affSColin Finck   if ( !(pHookItem = HeapAlloc(GetProcessHeap(), 0,
1437c2c66affSColin Finck                                sizeof(OleMenuHookItem)) ) )
1438c2c66affSColin Finck     return FALSE;
1439c2c66affSColin Finck 
1440c2c66affSColin Finck   pHookItem->tid = tid;
1441c2c66affSColin Finck   pHookItem->hHeap = GetProcessHeap();
1442c2c66affSColin Finck   pHookItem->CallWndProc_hHook = NULL;
1443c2c66affSColin Finck 
1444c2c66affSColin Finck   /* Install a thread scope message hook for WH_GETMESSAGE */
1445c2c66affSColin Finck   pHookItem->GetMsg_hHook = SetWindowsHookExW( WH_GETMESSAGE, OLEMenu_GetMsgProc,
1446c2c66affSColin Finck                                                0, GetCurrentThreadId() );
1447c2c66affSColin Finck   if ( !pHookItem->GetMsg_hHook )
1448c2c66affSColin Finck     goto CLEANUP;
1449c2c66affSColin Finck 
1450c2c66affSColin Finck   /* Install a thread scope message hook for WH_CALLWNDPROC */
1451c2c66affSColin Finck   pHookItem->CallWndProc_hHook = SetWindowsHookExW( WH_CALLWNDPROC, OLEMenu_CallWndProc,
1452c2c66affSColin Finck                                                     0, GetCurrentThreadId() );
1453c2c66affSColin Finck   if ( !pHookItem->CallWndProc_hHook )
1454c2c66affSColin Finck     goto CLEANUP;
1455c2c66affSColin Finck 
1456c2c66affSColin Finck   /* Insert the hook table entry */
1457c2c66affSColin Finck   pHookItem->next = hook_list;
1458c2c66affSColin Finck   hook_list = pHookItem;
1459c2c66affSColin Finck 
1460c2c66affSColin Finck   return TRUE;
1461c2c66affSColin Finck 
1462c2c66affSColin Finck CLEANUP:
1463c2c66affSColin Finck   /* Unhook any hooks */
1464c2c66affSColin Finck   if ( pHookItem->GetMsg_hHook )
1465c2c66affSColin Finck     UnhookWindowsHookEx( pHookItem->GetMsg_hHook );
1466c2c66affSColin Finck   if ( pHookItem->CallWndProc_hHook )
1467c2c66affSColin Finck     UnhookWindowsHookEx( pHookItem->CallWndProc_hHook );
1468c2c66affSColin Finck   /* Release the hook table entry */
1469c2c66affSColin Finck   HeapFree(pHookItem->hHeap, 0, pHookItem );
1470c2c66affSColin Finck 
1471c2c66affSColin Finck   return FALSE;
1472c2c66affSColin Finck }
1473c2c66affSColin Finck 
1474c2c66affSColin Finck /*************************************************************************
1475c2c66affSColin Finck  * OLEMenu_UnInstallHooks
1476c2c66affSColin Finck  * UnInstall thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
1477c2c66affSColin Finck  *
1478c2c66affSColin Finck  * RETURNS: TRUE if message hooks were successfully installed
1479c2c66affSColin Finck  *          FALSE on failure
1480c2c66affSColin Finck  */
OLEMenu_UnInstallHooks(DWORD tid)1481c2c66affSColin Finck static BOOL OLEMenu_UnInstallHooks( DWORD tid )
1482c2c66affSColin Finck {
1483c2c66affSColin Finck   OleMenuHookItem *pHookItem = NULL;
1484c2c66affSColin Finck   OleMenuHookItem **ppHook = &hook_list;
1485c2c66affSColin Finck 
1486c2c66affSColin Finck   while (*ppHook)
1487c2c66affSColin Finck   {
1488c2c66affSColin Finck       if ((*ppHook)->tid == tid)
1489c2c66affSColin Finck       {
1490c2c66affSColin Finck           pHookItem = *ppHook;
1491c2c66affSColin Finck           *ppHook = pHookItem->next;
1492c2c66affSColin Finck           break;
1493c2c66affSColin Finck       }
1494c2c66affSColin Finck       ppHook = &(*ppHook)->next;
1495c2c66affSColin Finck   }
1496c2c66affSColin Finck   if (!pHookItem) return FALSE;
1497c2c66affSColin Finck 
1498c2c66affSColin Finck   /* Uninstall the hooks installed for this thread */
1499c2c66affSColin Finck   if ( !UnhookWindowsHookEx( pHookItem->GetMsg_hHook ) )
1500c2c66affSColin Finck     goto CLEANUP;
1501c2c66affSColin Finck   if ( !UnhookWindowsHookEx( pHookItem->CallWndProc_hHook ) )
1502c2c66affSColin Finck     goto CLEANUP;
1503c2c66affSColin Finck 
1504c2c66affSColin Finck   /* Release the hook table entry */
1505c2c66affSColin Finck   HeapFree(pHookItem->hHeap, 0, pHookItem );
1506c2c66affSColin Finck 
1507c2c66affSColin Finck   return TRUE;
1508c2c66affSColin Finck 
1509c2c66affSColin Finck CLEANUP:
1510c2c66affSColin Finck   /* Release the hook table entry */
1511c2c66affSColin Finck   HeapFree(pHookItem->hHeap, 0, pHookItem );
1512c2c66affSColin Finck 
1513c2c66affSColin Finck   return FALSE;
1514c2c66affSColin Finck }
1515c2c66affSColin Finck 
1516c2c66affSColin Finck /*************************************************************************
1517c2c66affSColin Finck  * OLEMenu_IsHookInstalled
1518c2c66affSColin Finck  * Tests if OLEMenu hooks have been installed for a thread
1519c2c66affSColin Finck  *
1520c2c66affSColin Finck  * RETURNS: The pointer and index of the hook table entry for the tid
1521c2c66affSColin Finck  *          NULL and -1 for the index if no hooks were installed for this thread
1522c2c66affSColin Finck  */
OLEMenu_IsHookInstalled(DWORD tid)1523c2c66affSColin Finck static OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid )
1524c2c66affSColin Finck {
1525c2c66affSColin Finck   OleMenuHookItem *pHookItem;
1526c2c66affSColin Finck 
1527c2c66affSColin Finck   /* Do a simple linear search for an entry whose tid matches ours.
1528c2c66affSColin Finck    * We really need a map but efficiency is not a concern here. */
1529c2c66affSColin Finck   for (pHookItem = hook_list; pHookItem; pHookItem = pHookItem->next)
1530c2c66affSColin Finck   {
1531c2c66affSColin Finck     if ( tid == pHookItem->tid )
1532c2c66affSColin Finck       return pHookItem;
1533c2c66affSColin Finck   }
1534c2c66affSColin Finck 
1535c2c66affSColin Finck   return NULL;
1536c2c66affSColin Finck }
1537c2c66affSColin Finck 
1538c2c66affSColin Finck /***********************************************************************
1539c2c66affSColin Finck  *           OLEMenu_FindMainMenuIndex
1540c2c66affSColin Finck  *
1541c2c66affSColin Finck  * Used by OLEMenu API to find the top level group a menu item belongs to.
1542c2c66affSColin Finck  * On success pnPos contains the index of the item in the top level menu group
1543c2c66affSColin Finck  *
1544c2c66affSColin Finck  * RETURNS: TRUE if the ID was found, FALSE on failure
1545c2c66affSColin Finck  */
OLEMenu_FindMainMenuIndex(HMENU hMainMenu,HMENU hPopupMenu,UINT * pnPos)1546c2c66affSColin Finck static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos )
1547c2c66affSColin Finck {
1548c2c66affSColin Finck   INT i, nItems;
1549c2c66affSColin Finck 
1550c2c66affSColin Finck   nItems = GetMenuItemCount( hMainMenu );
1551c2c66affSColin Finck 
1552c2c66affSColin Finck   for (i = 0; i < nItems; i++)
1553c2c66affSColin Finck   {
1554c2c66affSColin Finck     HMENU hsubmenu;
1555c2c66affSColin Finck 
1556c2c66affSColin Finck     /*  Is the current item a submenu? */
1557c2c66affSColin Finck     if ( (hsubmenu = GetSubMenu(hMainMenu, i)) )
1558c2c66affSColin Finck     {
1559c2c66affSColin Finck       /* If the handle is the same we're done */
1560c2c66affSColin Finck       if ( hsubmenu == hPopupMenu )
1561c2c66affSColin Finck       {
1562c2c66affSColin Finck         if (pnPos)
1563c2c66affSColin Finck           *pnPos = i;
1564c2c66affSColin Finck         return TRUE;
1565c2c66affSColin Finck       }
1566c2c66affSColin Finck       /* Recursively search without updating pnPos */
1567c2c66affSColin Finck       else if ( OLEMenu_FindMainMenuIndex( hsubmenu, hPopupMenu, NULL ) )
1568c2c66affSColin Finck       {
1569c2c66affSColin Finck         if (pnPos)
1570c2c66affSColin Finck           *pnPos = i;
1571c2c66affSColin Finck         return TRUE;
1572c2c66affSColin Finck       }
1573c2c66affSColin Finck     }
1574c2c66affSColin Finck   }
1575c2c66affSColin Finck 
1576c2c66affSColin Finck   return FALSE;
1577c2c66affSColin Finck }
1578c2c66affSColin Finck 
1579c2c66affSColin Finck /***********************************************************************
1580c2c66affSColin Finck  *           OLEMenu_SetIsServerMenu
1581c2c66affSColin Finck  *
1582c2c66affSColin Finck  * Checks whether a popup menu belongs to a shared menu group which is
1583c2c66affSColin Finck  * owned by the server, and sets the menu descriptor state accordingly.
1584c2c66affSColin Finck  * All menu messages from these groups should be routed to the server.
1585c2c66affSColin Finck  *
1586c2c66affSColin Finck  * RETURNS: TRUE if the popup menu is part of a server owned group
1587c2c66affSColin Finck  *          FALSE if the popup menu is part of a container owned group
1588c2c66affSColin Finck  */
OLEMenu_SetIsServerMenu(HMENU hmenu,OleMenuDescriptor * pOleMenuDescriptor)1589c2c66affSColin Finck static BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor )
1590c2c66affSColin Finck {
1591c2c66affSColin Finck   UINT nPos = 0, nWidth, i;
1592c2c66affSColin Finck 
1593c2c66affSColin Finck   pOleMenuDescriptor->bIsServerItem = FALSE;
1594c2c66affSColin Finck 
1595c2c66affSColin Finck   /* Don't bother searching if the popup is the combined menu itself */
1596c2c66affSColin Finck   if ( hmenu == pOleMenuDescriptor->hmenuCombined )
1597c2c66affSColin Finck     return FALSE;
1598c2c66affSColin Finck 
1599c2c66affSColin Finck   /* Find the menu item index in the shared OLE menu that this item belongs to */
1600c2c66affSColin Finck   if ( !OLEMenu_FindMainMenuIndex( pOleMenuDescriptor->hmenuCombined, hmenu,  &nPos ) )
1601c2c66affSColin Finck     return FALSE;
1602c2c66affSColin Finck 
1603c2c66affSColin Finck   /* The group widths array has counts for the number of elements
1604c2c66affSColin Finck    * in the groups File, Edit, Container, Object, Window, Help.
1605c2c66affSColin Finck    * The Edit, Object & Help groups belong to the server object
1606c2c66affSColin Finck    * and the other three belong to the container.
1607c2c66affSColin Finck    * Loop through the group widths and locate the group we are a member of.
1608c2c66affSColin Finck    */
1609c2c66affSColin Finck   for ( i = 0, nWidth = 0; i < 6; i++ )
1610c2c66affSColin Finck   {
1611c2c66affSColin Finck     nWidth += pOleMenuDescriptor->mgw.width[i];
1612c2c66affSColin Finck     if ( nPos < nWidth )
1613c2c66affSColin Finck     {
1614c2c66affSColin Finck       /* Odd elements are server menu widths */
1615c2c66affSColin Finck       pOleMenuDescriptor->bIsServerItem = i%2;
1616c2c66affSColin Finck       break;
1617c2c66affSColin Finck     }
1618c2c66affSColin Finck   }
1619c2c66affSColin Finck 
1620c2c66affSColin Finck   return pOleMenuDescriptor->bIsServerItem;
1621c2c66affSColin Finck }
1622c2c66affSColin Finck 
1623c2c66affSColin Finck /*************************************************************************
1624c2c66affSColin Finck  * OLEMenu_CallWndProc
1625c2c66affSColin Finck  * Thread scope WH_CALLWNDPROC hook proc filter function (callback)
1626c2c66affSColin Finck  * This is invoked from a message hook installed in OleSetMenuDescriptor.
1627c2c66affSColin Finck  */
OLEMenu_CallWndProc(INT code,WPARAM wParam,LPARAM lParam)1628c2c66affSColin Finck static LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam)
1629c2c66affSColin Finck {
1630c2c66affSColin Finck   LPCWPSTRUCT pMsg;
1631c2c66affSColin Finck   HOLEMENU hOleMenu = 0;
1632c2c66affSColin Finck   OleMenuDescriptor *pOleMenuDescriptor = NULL;
1633c2c66affSColin Finck   OleMenuHookItem *pHookItem = NULL;
1634c2c66affSColin Finck   WORD fuFlags;
1635c2c66affSColin Finck 
1636c2c66affSColin Finck   TRACE("%i, %04lx, %08lx\n", code, wParam, lParam );
1637c2c66affSColin Finck 
1638c2c66affSColin Finck   /* Check if we're being asked to process the message */
1639c2c66affSColin Finck   if ( HC_ACTION != code )
1640c2c66affSColin Finck     goto NEXTHOOK;
1641c2c66affSColin Finck 
1642c2c66affSColin Finck   /* Retrieve the current message being dispatched from lParam */
1643c2c66affSColin Finck   pMsg = (LPCWPSTRUCT)lParam;
1644c2c66affSColin Finck 
1645c2c66affSColin Finck   /* Check if the message is destined for a window we are interested in:
1646c2c66affSColin Finck    * If the window has an OLEMenu property we may need to dispatch
1647c2c66affSColin Finck    * the menu message to its active objects window instead. */
1648c2c66affSColin Finck 
1649c2c66affSColin Finck   hOleMenu = GetPropW( pMsg->hwnd, prop_olemenuW );
1650c2c66affSColin Finck   if ( !hOleMenu )
1651c2c66affSColin Finck     goto NEXTHOOK;
1652c2c66affSColin Finck 
1653c2c66affSColin Finck   /* Get the menu descriptor */
1654c2c66affSColin Finck   pOleMenuDescriptor = GlobalLock( hOleMenu );
1655c2c66affSColin Finck   if ( !pOleMenuDescriptor ) /* Bad descriptor! */
1656c2c66affSColin Finck     goto NEXTHOOK;
1657c2c66affSColin Finck 
1658c2c66affSColin Finck   /* Process menu messages */
1659c2c66affSColin Finck   switch( pMsg->message )
1660c2c66affSColin Finck   {
1661c2c66affSColin Finck     case WM_INITMENU:
1662c2c66affSColin Finck     {
1663c2c66affSColin Finck       /* Reset the menu descriptor state */
1664c2c66affSColin Finck       pOleMenuDescriptor->bIsServerItem = FALSE;
1665c2c66affSColin Finck 
1666c2c66affSColin Finck       /* Send this message to the server as well */
1667c2c66affSColin Finck       SendMessageW( pOleMenuDescriptor->hwndActiveObject,
1668c2c66affSColin Finck                   pMsg->message, pMsg->wParam, pMsg->lParam );
1669c2c66affSColin Finck       goto NEXTHOOK;
1670c2c66affSColin Finck     }
1671c2c66affSColin Finck 
1672c2c66affSColin Finck     case WM_INITMENUPOPUP:
1673c2c66affSColin Finck     {
1674c2c66affSColin Finck       /* Save the state for whether this is a server owned menu */
1675c2c66affSColin Finck       OLEMenu_SetIsServerMenu( (HMENU)pMsg->wParam, pOleMenuDescriptor );
1676c2c66affSColin Finck       break;
1677c2c66affSColin Finck     }
1678c2c66affSColin Finck 
1679c2c66affSColin Finck     case WM_MENUSELECT:
1680c2c66affSColin Finck     {
1681c2c66affSColin Finck       fuFlags = HIWORD(pMsg->wParam);  /* Get flags */
1682c2c66affSColin Finck       if ( fuFlags & MF_SYSMENU )
1683c2c66affSColin Finck          goto NEXTHOOK;
1684c2c66affSColin Finck 
1685c2c66affSColin Finck       /* Save the state for whether this is a server owned popup menu */
1686c2c66affSColin Finck       else if ( fuFlags & MF_POPUP )
1687c2c66affSColin Finck         OLEMenu_SetIsServerMenu( (HMENU)pMsg->lParam, pOleMenuDescriptor );
1688c2c66affSColin Finck 
1689c2c66affSColin Finck       break;
1690c2c66affSColin Finck     }
1691c2c66affSColin Finck 
1692c2c66affSColin Finck     case WM_DRAWITEM:
1693c2c66affSColin Finck     {
1694c2c66affSColin Finck       LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) pMsg->lParam;
1695c2c66affSColin Finck       if ( pMsg->wParam != 0 || lpdis->CtlType != ODT_MENU )
1696c2c66affSColin Finck         goto NEXTHOOK;  /* Not a menu message */
1697c2c66affSColin Finck 
1698c2c66affSColin Finck       break;
1699c2c66affSColin Finck     }
1700c2c66affSColin Finck 
1701c2c66affSColin Finck     default:
1702c2c66affSColin Finck       goto NEXTHOOK;
1703c2c66affSColin Finck   }
1704c2c66affSColin Finck 
1705c2c66affSColin Finck   /* If the message was for the server dispatch it accordingly */
1706c2c66affSColin Finck   if ( pOleMenuDescriptor->bIsServerItem )
1707c2c66affSColin Finck   {
1708c2c66affSColin Finck     SendMessageW( pOleMenuDescriptor->hwndActiveObject,
1709c2c66affSColin Finck                   pMsg->message, pMsg->wParam, pMsg->lParam );
1710c2c66affSColin Finck   }
1711c2c66affSColin Finck 
1712c2c66affSColin Finck NEXTHOOK:
1713c2c66affSColin Finck   if ( pOleMenuDescriptor )
1714c2c66affSColin Finck     GlobalUnlock( hOleMenu );
1715c2c66affSColin Finck 
1716c2c66affSColin Finck   /* Lookup the hook item for the current thread */
1717c2c66affSColin Finck   if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) )
1718c2c66affSColin Finck   {
1719c2c66affSColin Finck     /* This should never fail!! */
1720c2c66affSColin Finck     WARN("could not retrieve hHook for current thread!\n" );
1721c2c66affSColin Finck     return 0;
1722c2c66affSColin Finck   }
1723c2c66affSColin Finck 
1724c2c66affSColin Finck   /* Pass on the message to the next hooker */
1725c2c66affSColin Finck   return CallNextHookEx( pHookItem->CallWndProc_hHook, code, wParam, lParam );
1726c2c66affSColin Finck }
1727c2c66affSColin Finck 
1728c2c66affSColin Finck /*************************************************************************
1729c2c66affSColin Finck  * OLEMenu_GetMsgProc
1730c2c66affSColin Finck  * Thread scope WH_GETMESSAGE hook proc filter function (callback)
1731c2c66affSColin Finck  * This is invoked from a message hook installed in OleSetMenuDescriptor.
1732c2c66affSColin Finck  */
OLEMenu_GetMsgProc(INT code,WPARAM wParam,LPARAM lParam)1733c2c66affSColin Finck static LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam)
1734c2c66affSColin Finck {
1735c2c66affSColin Finck   LPMSG pMsg;
1736c2c66affSColin Finck   HOLEMENU hOleMenu = 0;
1737c2c66affSColin Finck   OleMenuDescriptor *pOleMenuDescriptor = NULL;
1738c2c66affSColin Finck   OleMenuHookItem *pHookItem = NULL;
1739c2c66affSColin Finck   WORD wCode;
1740c2c66affSColin Finck 
1741c2c66affSColin Finck   TRACE("%i, %04lx, %08lx\n", code, wParam, lParam );
1742c2c66affSColin Finck 
1743c2c66affSColin Finck   /* Check if we're being asked to process a  messages */
1744c2c66affSColin Finck   if ( HC_ACTION != code )
1745c2c66affSColin Finck     goto NEXTHOOK;
1746c2c66affSColin Finck 
1747c2c66affSColin Finck   /* Retrieve the current message being dispatched from lParam */
1748c2c66affSColin Finck   pMsg = (LPMSG)lParam;
1749c2c66affSColin Finck 
1750c2c66affSColin Finck   /* Check if the message is destined for a window we are interested in:
1751c2c66affSColin Finck    * If the window has an OLEMenu property we may need to dispatch
1752c2c66affSColin Finck    * the menu message to its active objects window instead. */
1753c2c66affSColin Finck 
1754c2c66affSColin Finck   hOleMenu = GetPropW( pMsg->hwnd, prop_olemenuW );
1755c2c66affSColin Finck   if ( !hOleMenu )
1756c2c66affSColin Finck     goto NEXTHOOK;
1757c2c66affSColin Finck 
1758c2c66affSColin Finck   /* Process menu messages */
1759c2c66affSColin Finck   switch( pMsg->message )
1760c2c66affSColin Finck   {
1761c2c66affSColin Finck     case WM_COMMAND:
1762c2c66affSColin Finck     {
1763c2c66affSColin Finck       wCode = HIWORD(pMsg->wParam);  /* Get notification code */
1764c2c66affSColin Finck       if ( wCode )
1765c2c66affSColin Finck         goto NEXTHOOK;  /* Not a menu message */
1766c2c66affSColin Finck       break;
1767c2c66affSColin Finck     }
1768c2c66affSColin Finck     default:
1769c2c66affSColin Finck       goto NEXTHOOK;
1770c2c66affSColin Finck   }
1771c2c66affSColin Finck 
1772c2c66affSColin Finck   /* Get the menu descriptor */
1773c2c66affSColin Finck   pOleMenuDescriptor = GlobalLock( hOleMenu );
1774c2c66affSColin Finck   if ( !pOleMenuDescriptor ) /* Bad descriptor! */
1775c2c66affSColin Finck     goto NEXTHOOK;
1776c2c66affSColin Finck 
1777c2c66affSColin Finck   /* If the message was for the server dispatch it accordingly */
1778c2c66affSColin Finck   if ( pOleMenuDescriptor->bIsServerItem )
1779c2c66affSColin Finck   {
1780c2c66affSColin Finck     /* Change the hWnd in the message to the active objects hWnd.
1781c2c66affSColin Finck      * The message loop which reads this message will automatically
1782c2c66affSColin Finck      * dispatch it to the embedded objects window. */
1783c2c66affSColin Finck     pMsg->hwnd = pOleMenuDescriptor->hwndActiveObject;
1784c2c66affSColin Finck   }
1785c2c66affSColin Finck 
1786c2c66affSColin Finck NEXTHOOK:
1787c2c66affSColin Finck   if ( pOleMenuDescriptor )
1788c2c66affSColin Finck     GlobalUnlock( hOleMenu );
1789c2c66affSColin Finck 
1790c2c66affSColin Finck   /* Lookup the hook item for the current thread */
1791c2c66affSColin Finck   if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) )
1792c2c66affSColin Finck   {
1793c2c66affSColin Finck     /* This should never fail!! */
1794c2c66affSColin Finck     WARN("could not retrieve hHook for current thread!\n" );
1795c2c66affSColin Finck     return FALSE;
1796c2c66affSColin Finck   }
1797c2c66affSColin Finck 
1798c2c66affSColin Finck   /* Pass on the message to the next hooker */
1799c2c66affSColin Finck   return CallNextHookEx( pHookItem->GetMsg_hHook, code, wParam, lParam );
1800c2c66affSColin Finck }
1801c2c66affSColin Finck 
1802c2c66affSColin Finck /***********************************************************************
1803c2c66affSColin Finck  * OleCreateMenuDescriptor [OLE32.@]
1804c2c66affSColin Finck  * Creates an OLE menu descriptor for OLE to use when dispatching
1805c2c66affSColin Finck  * menu messages and commands.
1806c2c66affSColin Finck  *
1807c2c66affSColin Finck  * PARAMS:
1808c2c66affSColin Finck  *    hmenuCombined  -  Handle to the objects combined menu
1809c2c66affSColin Finck  *    lpMenuWidths   -  Pointer to array of 6 LONG's indicating menus per group
1810c2c66affSColin Finck  *
1811c2c66affSColin Finck  */
OleCreateMenuDescriptor(HMENU hmenuCombined,LPOLEMENUGROUPWIDTHS lpMenuWidths)1812c2c66affSColin Finck HOLEMENU WINAPI OleCreateMenuDescriptor(
1813c2c66affSColin Finck   HMENU                hmenuCombined,
1814c2c66affSColin Finck   LPOLEMENUGROUPWIDTHS lpMenuWidths)
1815c2c66affSColin Finck {
1816c2c66affSColin Finck   HOLEMENU hOleMenu;
1817c2c66affSColin Finck   OleMenuDescriptor *pOleMenuDescriptor;
1818c2c66affSColin Finck   int i;
1819c2c66affSColin Finck 
1820c2c66affSColin Finck   if ( !hmenuCombined || !lpMenuWidths )
1821c2c66affSColin Finck     return 0;
1822c2c66affSColin Finck 
1823c2c66affSColin Finck   /* Create an OLE menu descriptor */
1824c2c66affSColin Finck   if ( !(hOleMenu = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
1825c2c66affSColin Finck                                 sizeof(OleMenuDescriptor) ) ) )
1826c2c66affSColin Finck   return 0;
1827c2c66affSColin Finck 
1828c2c66affSColin Finck   pOleMenuDescriptor = GlobalLock( hOleMenu );
1829c2c66affSColin Finck   if ( !pOleMenuDescriptor )
1830c2c66affSColin Finck     return 0;
1831c2c66affSColin Finck 
1832c2c66affSColin Finck   /* Initialize menu group widths and hmenu */
1833c2c66affSColin Finck   for ( i = 0; i < 6; i++ )
1834c2c66affSColin Finck     pOleMenuDescriptor->mgw.width[i] = lpMenuWidths->width[i];
1835c2c66affSColin Finck 
1836c2c66affSColin Finck   pOleMenuDescriptor->hmenuCombined = hmenuCombined;
1837c2c66affSColin Finck   pOleMenuDescriptor->bIsServerItem = FALSE;
1838c2c66affSColin Finck   GlobalUnlock( hOleMenu );
1839c2c66affSColin Finck 
1840c2c66affSColin Finck   return hOleMenu;
1841c2c66affSColin Finck }
1842c2c66affSColin Finck 
1843c2c66affSColin Finck /***********************************************************************
1844c2c66affSColin Finck  * OleDestroyMenuDescriptor [OLE32.@]
1845c2c66affSColin Finck  * Destroy the shared menu descriptor
1846c2c66affSColin Finck  */
OleDestroyMenuDescriptor(HOLEMENU hmenuDescriptor)1847c2c66affSColin Finck HRESULT WINAPI OleDestroyMenuDescriptor(
1848c2c66affSColin Finck     HOLEMENU hmenuDescriptor)
1849c2c66affSColin Finck {
1850c2c66affSColin Finck     if ( hmenuDescriptor )
1851c2c66affSColin Finck         GlobalFree( hmenuDescriptor );
1852c2c66affSColin Finck     return S_OK;
1853c2c66affSColin Finck }
1854c2c66affSColin Finck 
1855c2c66affSColin Finck /***********************************************************************
1856c2c66affSColin Finck  * OleSetMenuDescriptor [OLE32.@]
1857c2c66affSColin Finck  * Installs or removes OLE dispatching code for the containers frame window.
1858c2c66affSColin Finck  *
1859c2c66affSColin Finck  * PARAMS
1860c2c66affSColin Finck  *     hOleMenu         Handle to composite menu descriptor
1861c2c66affSColin Finck  *     hwndFrame        Handle to containers frame window
1862c2c66affSColin Finck  *     hwndActiveObject Handle to objects in-place activation window
1863c2c66affSColin Finck  *     lpFrame          Pointer to IOleInPlaceFrame on containers window
1864c2c66affSColin Finck  *     lpActiveObject   Pointer to IOleInPlaceActiveObject on active in-place object
1865c2c66affSColin Finck  *
1866c2c66affSColin Finck  * RETURNS
1867c2c66affSColin Finck  *      S_OK                               - menu installed correctly
1868c2c66affSColin Finck  *      E_FAIL, E_INVALIDARG, E_UNEXPECTED - failure
1869c2c66affSColin Finck  *
1870c2c66affSColin Finck  * FIXME
1871c2c66affSColin Finck  *      The lpFrame and lpActiveObject parameters are currently ignored
1872c2c66affSColin Finck  *      OLE should install context sensitive help F1 filtering for the app when
1873c2c66affSColin Finck  *      these are non null.
1874c2c66affSColin Finck  */
OleSetMenuDescriptor(HOLEMENU hOleMenu,HWND hwndFrame,HWND hwndActiveObject,LPOLEINPLACEFRAME lpFrame,LPOLEINPLACEACTIVEOBJECT lpActiveObject)1875c2c66affSColin Finck HRESULT WINAPI OleSetMenuDescriptor(
1876c2c66affSColin Finck     HOLEMENU               hOleMenu,
1877c2c66affSColin Finck     HWND                   hwndFrame,
1878c2c66affSColin Finck     HWND                   hwndActiveObject,
1879c2c66affSColin Finck     LPOLEINPLACEFRAME        lpFrame,
1880c2c66affSColin Finck     LPOLEINPLACEACTIVEOBJECT lpActiveObject)
1881c2c66affSColin Finck {
1882c2c66affSColin Finck     OleMenuDescriptor *pOleMenuDescriptor = NULL;
1883c2c66affSColin Finck 
1884c2c66affSColin Finck     /* Check args */
1885c2c66affSColin Finck     if ( !hwndFrame || (hOleMenu && !hwndActiveObject) )
1886c2c66affSColin Finck         return E_INVALIDARG;
1887c2c66affSColin Finck 
1888c2c66affSColin Finck     if ( lpFrame || lpActiveObject )
1889c2c66affSColin Finck     {
1890c2c66affSColin Finck         FIXME("(%p, %p, %p, %p, %p), Context sensitive help filtering not implemented!\n",
1891c2c66affSColin Finck         hOleMenu,
1892c2c66affSColin Finck         hwndFrame,
1893c2c66affSColin Finck         hwndActiveObject,
1894c2c66affSColin Finck         lpFrame,
1895c2c66affSColin Finck         lpActiveObject);
1896c2c66affSColin Finck     }
1897c2c66affSColin Finck 
1898c2c66affSColin Finck     /* Set up a message hook to intercept the containers frame window messages.
1899c2c66affSColin Finck      * The message filter is responsible for dispatching menu messages from the
1900c2c66affSColin Finck      * shared menu which are intended for the object.
1901c2c66affSColin Finck      */
1902c2c66affSColin Finck 
1903c2c66affSColin Finck     if ( hOleMenu )  /* Want to install dispatching code */
1904c2c66affSColin Finck     {
1905c2c66affSColin Finck         /* If OLEMenu hooks are already installed for this thread, fail
1906c2c66affSColin Finck          * Note: This effectively means that OleSetMenuDescriptor cannot
1907c2c66affSColin Finck          * be called twice in succession on the same frame window
1908c2c66affSColin Finck          * without first calling it with a null hOleMenu to uninstall
1909c2c66affSColin Finck          */
1910c2c66affSColin Finck         if ( OLEMenu_IsHookInstalled( GetCurrentThreadId() ) )
1911c2c66affSColin Finck             return E_FAIL;
1912c2c66affSColin Finck 
1913c2c66affSColin Finck         /* Get the menu descriptor */
1914c2c66affSColin Finck         pOleMenuDescriptor = GlobalLock( hOleMenu );
1915c2c66affSColin Finck         if ( !pOleMenuDescriptor )
1916c2c66affSColin Finck             return E_UNEXPECTED;
1917c2c66affSColin Finck 
1918c2c66affSColin Finck         /* Update the menu descriptor */
1919c2c66affSColin Finck         pOleMenuDescriptor->hwndFrame = hwndFrame;
1920c2c66affSColin Finck         pOleMenuDescriptor->hwndActiveObject = hwndActiveObject;
1921c2c66affSColin Finck 
1922c2c66affSColin Finck         GlobalUnlock( hOleMenu );
1923c2c66affSColin Finck         pOleMenuDescriptor = NULL;
1924c2c66affSColin Finck 
1925c2c66affSColin Finck         /* Add a menu descriptor windows property to the frame window */
1926c2c66affSColin Finck         SetPropW( hwndFrame, prop_olemenuW, hOleMenu );
1927c2c66affSColin Finck 
1928c2c66affSColin Finck         /* Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC */
1929c2c66affSColin Finck         if ( !OLEMenu_InstallHooks( GetCurrentThreadId() ) )
1930c2c66affSColin Finck             return E_FAIL;
1931c2c66affSColin Finck     }
1932c2c66affSColin Finck     else  /* Want to uninstall dispatching code */
1933c2c66affSColin Finck     {
1934c2c66affSColin Finck         /* Uninstall the hooks */
1935c2c66affSColin Finck         if ( !OLEMenu_UnInstallHooks( GetCurrentThreadId() ) )
1936c2c66affSColin Finck             return E_FAIL;
1937c2c66affSColin Finck 
1938c2c66affSColin Finck         /* Remove the menu descriptor property from the frame window */
1939c2c66affSColin Finck         RemovePropW( hwndFrame, prop_olemenuW );
1940c2c66affSColin Finck     }
1941c2c66affSColin Finck 
1942c2c66affSColin Finck     return S_OK;
1943c2c66affSColin Finck }
1944c2c66affSColin Finck 
1945c2c66affSColin Finck /******************************************************************************
1946c2c66affSColin Finck  *              IsAccelerator        [OLE32.@]
1947c2c66affSColin Finck  * Mostly copied from controls/menu.c TranslateAccelerator implementation
1948c2c66affSColin Finck  */
IsAccelerator(HACCEL hAccel,int cAccelEntries,LPMSG lpMsg,WORD * lpwCmd)1949c2c66affSColin Finck BOOL WINAPI IsAccelerator(HACCEL hAccel, int cAccelEntries, LPMSG lpMsg, WORD* lpwCmd)
1950c2c66affSColin Finck {
1951c2c66affSColin Finck     LPACCEL lpAccelTbl;
1952c2c66affSColin Finck     int i;
1953c2c66affSColin Finck 
1954c2c66affSColin Finck     if(!lpMsg) return FALSE;
1955c2c66affSColin Finck     if (!hAccel)
1956c2c66affSColin Finck     {
1957c2c66affSColin Finck 	WARN_(accel)("NULL accel handle\n");
1958c2c66affSColin Finck 	return FALSE;
1959c2c66affSColin Finck     }
1960c2c66affSColin Finck     if((lpMsg->message != WM_KEYDOWN &&
1961c2c66affSColin Finck 	lpMsg->message != WM_SYSKEYDOWN &&
1962c2c66affSColin Finck 	lpMsg->message != WM_SYSCHAR &&
1963c2c66affSColin Finck 	lpMsg->message != WM_CHAR)) return FALSE;
1964c2c66affSColin Finck     lpAccelTbl = HeapAlloc(GetProcessHeap(), 0, cAccelEntries * sizeof(ACCEL));
1965c2c66affSColin Finck     if (NULL == lpAccelTbl)
1966c2c66affSColin Finck     {
1967c2c66affSColin Finck 	return FALSE;
1968c2c66affSColin Finck     }
1969c2c66affSColin Finck     if (CopyAcceleratorTableW(hAccel, lpAccelTbl, cAccelEntries) != cAccelEntries)
1970c2c66affSColin Finck     {
1971c2c66affSColin Finck 	WARN_(accel)("CopyAcceleratorTableW failed\n");
1972c2c66affSColin Finck 	HeapFree(GetProcessHeap(), 0, lpAccelTbl);
1973c2c66affSColin Finck 	return FALSE;
1974c2c66affSColin Finck     }
1975c2c66affSColin Finck 
1976c2c66affSColin Finck     TRACE_(accel)("hAccel=%p, cAccelEntries=%d,"
1977c2c66affSColin Finck 		"msg->hwnd=%p, msg->message=%04x, wParam=%08lx, lParam=%08lx\n",
1978c2c66affSColin Finck 		hAccel, cAccelEntries,
1979c2c66affSColin Finck 		lpMsg->hwnd, lpMsg->message, lpMsg->wParam, lpMsg->lParam);
1980c2c66affSColin Finck     for(i = 0; i < cAccelEntries; i++)
1981c2c66affSColin Finck     {
1982c2c66affSColin Finck 	if(lpAccelTbl[i].key != lpMsg->wParam)
1983c2c66affSColin Finck 	    continue;
1984c2c66affSColin Finck 
1985c2c66affSColin Finck 	if(lpMsg->message == WM_CHAR)
1986c2c66affSColin Finck 	{
1987c2c66affSColin Finck 	    if(!(lpAccelTbl[i].fVirt & FALT) && !(lpAccelTbl[i].fVirt & FVIRTKEY))
1988c2c66affSColin Finck 	    {
1989c2c66affSColin Finck 		TRACE_(accel)("found accel for WM_CHAR: ('%c')\n", LOWORD(lpMsg->wParam) & 0xff);
1990c2c66affSColin Finck 		goto found;
1991c2c66affSColin Finck 	    }
1992c2c66affSColin Finck 	}
1993c2c66affSColin Finck 	else
1994c2c66affSColin Finck 	{
1995c2c66affSColin Finck 	    if(lpAccelTbl[i].fVirt & FVIRTKEY)
1996c2c66affSColin Finck 	    {
1997c2c66affSColin Finck 		INT mask = 0;
1998c2c66affSColin Finck 		TRACE_(accel)("found accel for virt_key %04lx (scan %04x)\n",
1999c2c66affSColin Finck 				lpMsg->wParam, HIWORD(lpMsg->lParam) & 0xff);
2000c2c66affSColin Finck 		if(GetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT;
2001c2c66affSColin Finck 		if(GetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL;
2002c2c66affSColin Finck 		if(GetKeyState(VK_MENU) & 0x8000) mask |= FALT;
2003c2c66affSColin Finck 		if(mask == (lpAccelTbl[i].fVirt & (FSHIFT | FCONTROL | FALT))) goto found;
2004c2c66affSColin Finck 		TRACE_(accel)("incorrect SHIFT/CTRL/ALT-state\n");
2005c2c66affSColin Finck 	    }
2006c2c66affSColin Finck 	    else
2007c2c66affSColin Finck 	    {
2008c2c66affSColin Finck 		if(!(lpMsg->lParam & 0x01000000))  /* no special_key */
2009c2c66affSColin Finck 		{
2010c2c66affSColin Finck 		    if((lpAccelTbl[i].fVirt & FALT) && (lpMsg->lParam & 0x20000000))
2011c2c66affSColin Finck 		    {						       /* ^^ ALT pressed */
2012c2c66affSColin Finck 			TRACE_(accel)("found accel for Alt-%c\n", LOWORD(lpMsg->wParam) & 0xff);
2013c2c66affSColin Finck 			goto found;
2014c2c66affSColin Finck 		    }
2015c2c66affSColin Finck 		}
2016c2c66affSColin Finck 	    }
2017c2c66affSColin Finck 	}
2018c2c66affSColin Finck     }
2019c2c66affSColin Finck 
2020c2c66affSColin Finck     WARN_(accel)("couldn't translate accelerator key\n");
2021c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, lpAccelTbl);
2022c2c66affSColin Finck     return FALSE;
2023c2c66affSColin Finck 
2024c2c66affSColin Finck found:
2025c2c66affSColin Finck     if(lpwCmd) *lpwCmd = lpAccelTbl[i].cmd;
2026c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, lpAccelTbl);
2027c2c66affSColin Finck     return TRUE;
2028c2c66affSColin Finck }
2029c2c66affSColin Finck 
2030c2c66affSColin Finck /***********************************************************************
2031c2c66affSColin Finck  * ReleaseStgMedium [OLE32.@]
2032c2c66affSColin Finck  */
ReleaseStgMedium(STGMEDIUM * pmedium)2033c2c66affSColin Finck void WINAPI ReleaseStgMedium(
2034c2c66affSColin Finck   STGMEDIUM* pmedium)
2035c2c66affSColin Finck {
2036c2c66affSColin Finck   switch (pmedium->tymed)
2037c2c66affSColin Finck   {
2038c2c66affSColin Finck     case TYMED_HGLOBAL:
2039c2c66affSColin Finck     {
2040c2c66affSColin Finck       if ( (pmedium->pUnkForRelease==0) &&
2041c2c66affSColin Finck 	   (pmedium->u.hGlobal!=0) )
2042c2c66affSColin Finck 	GlobalFree(pmedium->u.hGlobal);
2043c2c66affSColin Finck       break;
2044c2c66affSColin Finck     }
2045c2c66affSColin Finck     case TYMED_FILE:
2046c2c66affSColin Finck     {
2047c2c66affSColin Finck       if (pmedium->u.lpszFileName!=0)
2048c2c66affSColin Finck       {
2049c2c66affSColin Finck 	if (pmedium->pUnkForRelease==0)
2050c2c66affSColin Finck 	{
2051c2c66affSColin Finck 	  DeleteFileW(pmedium->u.lpszFileName);
2052c2c66affSColin Finck 	}
2053c2c66affSColin Finck 
2054c2c66affSColin Finck 	CoTaskMemFree(pmedium->u.lpszFileName);
2055c2c66affSColin Finck       }
2056c2c66affSColin Finck       break;
2057c2c66affSColin Finck     }
2058c2c66affSColin Finck     case TYMED_ISTREAM:
2059c2c66affSColin Finck     {
2060c2c66affSColin Finck       if (pmedium->u.pstm!=0)
2061c2c66affSColin Finck       {
2062c2c66affSColin Finck 	IStream_Release(pmedium->u.pstm);
2063c2c66affSColin Finck       }
2064c2c66affSColin Finck       break;
2065c2c66affSColin Finck     }
2066c2c66affSColin Finck     case TYMED_ISTORAGE:
2067c2c66affSColin Finck     {
2068c2c66affSColin Finck       if (pmedium->u.pstg!=0)
2069c2c66affSColin Finck       {
2070c2c66affSColin Finck 	IStorage_Release(pmedium->u.pstg);
2071c2c66affSColin Finck       }
2072c2c66affSColin Finck       break;
2073c2c66affSColin Finck     }
2074c2c66affSColin Finck     case TYMED_GDI:
2075c2c66affSColin Finck     {
2076c2c66affSColin Finck       if ( (pmedium->pUnkForRelease==0) &&
2077c2c66affSColin Finck 	   (pmedium->u.hBitmap!=0) )
2078c2c66affSColin Finck 	DeleteObject(pmedium->u.hBitmap);
2079c2c66affSColin Finck       break;
2080c2c66affSColin Finck     }
2081c2c66affSColin Finck     case TYMED_MFPICT:
2082c2c66affSColin Finck     {
2083c2c66affSColin Finck       if ( (pmedium->pUnkForRelease==0) &&
2084c2c66affSColin Finck 	   (pmedium->u.hMetaFilePict!=0) )
2085c2c66affSColin Finck       {
2086c2c66affSColin Finck 	LPMETAFILEPICT pMP = GlobalLock(pmedium->u.hMetaFilePict);
2087c2c66affSColin Finck 	DeleteMetaFile(pMP->hMF);
2088c2c66affSColin Finck 	GlobalUnlock(pmedium->u.hMetaFilePict);
2089c2c66affSColin Finck 	GlobalFree(pmedium->u.hMetaFilePict);
2090c2c66affSColin Finck       }
2091c2c66affSColin Finck       break;
2092c2c66affSColin Finck     }
2093c2c66affSColin Finck     case TYMED_ENHMF:
2094c2c66affSColin Finck     {
2095c2c66affSColin Finck       if ( (pmedium->pUnkForRelease==0) &&
2096c2c66affSColin Finck 	   (pmedium->u.hEnhMetaFile!=0) )
2097c2c66affSColin Finck       {
2098c2c66affSColin Finck 	DeleteEnhMetaFile(pmedium->u.hEnhMetaFile);
2099c2c66affSColin Finck       }
2100c2c66affSColin Finck       break;
2101c2c66affSColin Finck     }
2102c2c66affSColin Finck     case TYMED_NULL:
2103c2c66affSColin Finck     default:
2104c2c66affSColin Finck       break;
2105c2c66affSColin Finck   }
2106c2c66affSColin Finck   pmedium->tymed=TYMED_NULL;
2107c2c66affSColin Finck 
2108c2c66affSColin Finck   /*
2109c2c66affSColin Finck    * After cleaning up, the unknown is released
2110c2c66affSColin Finck    */
2111c2c66affSColin Finck   if (pmedium->pUnkForRelease!=0)
2112c2c66affSColin Finck   {
2113c2c66affSColin Finck     IUnknown_Release(pmedium->pUnkForRelease);
2114c2c66affSColin Finck     pmedium->pUnkForRelease = 0;
2115c2c66affSColin Finck   }
2116c2c66affSColin Finck }
2117c2c66affSColin Finck 
2118c2c66affSColin Finck /***
2119c2c66affSColin Finck  * OLEDD_Initialize()
2120c2c66affSColin Finck  *
2121c2c66affSColin Finck  * Initializes the OLE drag and drop data structures.
2122c2c66affSColin Finck  */
OLEDD_Initialize(void)2123c2c66affSColin Finck static void OLEDD_Initialize(void)
2124c2c66affSColin Finck {
2125c2c66affSColin Finck     WNDCLASSW wndClass;
2126c2c66affSColin Finck 
2127c2c66affSColin Finck     ZeroMemory (&wndClass, sizeof(WNDCLASSW));
2128c2c66affSColin Finck     wndClass.style         = CS_GLOBALCLASS;
2129c2c66affSColin Finck     wndClass.lpfnWndProc   = OLEDD_DragTrackerWindowProc;
2130c2c66affSColin Finck     wndClass.cbClsExtra    = 0;
2131c2c66affSColin Finck     wndClass.cbWndExtra    = sizeof(TrackerWindowInfo*);
2132c2c66affSColin Finck     wndClass.hCursor       = 0;
2133c2c66affSColin Finck     wndClass.hbrBackground = 0;
2134c2c66affSColin Finck     wndClass.lpszClassName = OLEDD_DRAGTRACKERCLASS;
2135c2c66affSColin Finck 
2136c2c66affSColin Finck     RegisterClassW (&wndClass);
2137c2c66affSColin Finck }
2138c2c66affSColin Finck 
2139c2c66affSColin Finck /***
2140c2c66affSColin Finck  * OLEDD_DragTrackerWindowProc()
2141c2c66affSColin Finck  *
2142c2c66affSColin Finck  * This method is the WindowProcedure of the drag n drop tracking
2143c2c66affSColin Finck  * window. During a drag n Drop operation, an invisible window is created
2144c2c66affSColin Finck  * to receive the user input and act upon it. This procedure is in charge
2145c2c66affSColin Finck  * of this behavior.
2146c2c66affSColin Finck  */
2147c2c66affSColin Finck 
2148c2c66affSColin Finck #define DRAG_TIMER_ID 1
2149c2c66affSColin Finck 
OLEDD_DragTrackerWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)2150c2c66affSColin Finck static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
2151c2c66affSColin Finck 			 HWND   hwnd,
2152c2c66affSColin Finck 			 UINT   uMsg,
2153c2c66affSColin Finck 			 WPARAM wParam,
2154c2c66affSColin Finck 			 LPARAM   lParam)
2155c2c66affSColin Finck {
2156c2c66affSColin Finck   switch (uMsg)
2157c2c66affSColin Finck   {
2158c2c66affSColin Finck     case WM_CREATE:
2159c2c66affSColin Finck     {
2160c2c66affSColin Finck       LPCREATESTRUCTA createStruct = (LPCREATESTRUCTA)lParam;
2161c2c66affSColin Finck 
2162c2c66affSColin Finck       SetWindowLongPtrW(hwnd, 0, (LONG_PTR)createStruct->lpCreateParams);
2163c2c66affSColin Finck       SetTimer(hwnd, DRAG_TIMER_ID, 50, NULL);
2164c2c66affSColin Finck 
2165c2c66affSColin Finck       break;
2166c2c66affSColin Finck     }
2167c2c66affSColin Finck     case WM_TIMER:
2168c2c66affSColin Finck     case WM_MOUSEMOVE:
2169c2c66affSColin Finck     case WM_LBUTTONUP:
2170c2c66affSColin Finck     case WM_MBUTTONUP:
2171c2c66affSColin Finck     case WM_RBUTTONUP:
2172c2c66affSColin Finck     case WM_LBUTTONDOWN:
2173c2c66affSColin Finck     case WM_MBUTTONDOWN:
2174c2c66affSColin Finck     case WM_RBUTTONDOWN:
2175c2c66affSColin Finck     {
2176c2c66affSColin Finck       TrackerWindowInfo *trackerInfo = (TrackerWindowInfo*)GetWindowLongPtrA(hwnd, 0);
2177c2c66affSColin Finck       if (trackerInfo->trackingDone) break;
2178c2c66affSColin Finck       OLEDD_TrackStateChange(trackerInfo);
2179c2c66affSColin Finck       break;
2180c2c66affSColin Finck     }
2181c2c66affSColin Finck     case WM_DESTROY:
2182c2c66affSColin Finck     {
2183c2c66affSColin Finck       KillTimer(hwnd, DRAG_TIMER_ID);
2184c2c66affSColin Finck       break;
2185c2c66affSColin Finck     }
2186c2c66affSColin Finck   }
2187c2c66affSColin Finck 
2188c2c66affSColin Finck   /*
2189c2c66affSColin Finck    * This is a window proc after all. Let's call the default.
2190c2c66affSColin Finck    */
2191c2c66affSColin Finck   return DefWindowProcW (hwnd, uMsg, wParam, lParam);
2192c2c66affSColin Finck }
2193c2c66affSColin Finck 
2194332ca5f5SKatayama Hirofumi MZ #ifdef __REACTOS__
DefaultDragEnter(HWND hwndTarget,IDataObject * pDataObj,DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)2195332ca5f5SKatayama Hirofumi MZ static HRESULT WINAPI DefaultDragEnter(HWND hwndTarget,
2196332ca5f5SKatayama Hirofumi MZ                                        IDataObject* pDataObj,
2197332ca5f5SKatayama Hirofumi MZ                                        DWORD grfKeyState,
2198332ca5f5SKatayama Hirofumi MZ                                        POINTL pt,
2199332ca5f5SKatayama Hirofumi MZ                                        DWORD* pdwEffect)
2200332ca5f5SKatayama Hirofumi MZ {
2201332ca5f5SKatayama Hirofumi MZ     HRESULT hr;
2202332ca5f5SKatayama Hirofumi MZ     FORMATETC fme;
2203332ca5f5SKatayama Hirofumi MZ 
2204332ca5f5SKatayama Hirofumi MZ     ZeroMemory(&fme, sizeof(fme));
2205332ca5f5SKatayama Hirofumi MZ     fme.cfFormat = CF_HDROP;
2206332ca5f5SKatayama Hirofumi MZ     fme.ptd = NULL;
2207332ca5f5SKatayama Hirofumi MZ     fme.dwAspect = DVASPECT_CONTENT;
2208332ca5f5SKatayama Hirofumi MZ     fme.lindex = -1;
2209332ca5f5SKatayama Hirofumi MZ     fme.tymed = TYMED_HGLOBAL;
2210332ca5f5SKatayama Hirofumi MZ     hr = pDataObj->lpVtbl->QueryGetData(pDataObj, &fme);
2211332ca5f5SKatayama Hirofumi MZ 
2212332ca5f5SKatayama Hirofumi MZ     *pdwEffect = SUCCEEDED(hr) ? DROPEFFECT_COPY : DROPEFFECT_NONE;
2213332ca5f5SKatayama Hirofumi MZ 
2214332ca5f5SKatayama Hirofumi MZ     if (*pdwEffect == DROPEFFECT_NONE)
2215332ca5f5SKatayama Hirofumi MZ         return DRAGDROP_S_CANCEL;
2216332ca5f5SKatayama Hirofumi MZ 
2217332ca5f5SKatayama Hirofumi MZ     return S_OK;
2218332ca5f5SKatayama Hirofumi MZ }
2219332ca5f5SKatayama Hirofumi MZ 
DefaultDrop(HWND hwndAccepter,IDataObject * pDataObj,DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)2220332ca5f5SKatayama Hirofumi MZ static HRESULT WINAPI DefaultDrop(HWND hwndAccepter,
2221332ca5f5SKatayama Hirofumi MZ                                   IDataObject* pDataObj,
2222332ca5f5SKatayama Hirofumi MZ                                   DWORD grfKeyState,
2223332ca5f5SKatayama Hirofumi MZ                                   POINTL pt,
2224332ca5f5SKatayama Hirofumi MZ                                   DWORD* pdwEffect)
2225332ca5f5SKatayama Hirofumi MZ {
2226332ca5f5SKatayama Hirofumi MZ     FORMATETC fme;
2227332ca5f5SKatayama Hirofumi MZ     STGMEDIUM stgm;
2228332ca5f5SKatayama Hirofumi MZ     HRESULT hr;
2229332ca5f5SKatayama Hirofumi MZ     HGLOBAL hGlobal = NULL;
2230332ca5f5SKatayama Hirofumi MZ 
2231332ca5f5SKatayama Hirofumi MZ     ZeroMemory(&fme, sizeof(fme));
2232332ca5f5SKatayama Hirofumi MZ     fme.cfFormat = CF_HDROP;
2233332ca5f5SKatayama Hirofumi MZ     fme.ptd = NULL;
2234332ca5f5SKatayama Hirofumi MZ     fme.dwAspect = DVASPECT_CONTENT;
2235332ca5f5SKatayama Hirofumi MZ     fme.lindex = -1;
2236332ca5f5SKatayama Hirofumi MZ     fme.tymed = TYMED_HGLOBAL;
2237332ca5f5SKatayama Hirofumi MZ     hr = pDataObj->lpVtbl->QueryGetData(pDataObj, &fme);
2238332ca5f5SKatayama Hirofumi MZ     if (FAILED(hr))
2239332ca5f5SKatayama Hirofumi MZ         return hr;
2240332ca5f5SKatayama Hirofumi MZ 
2241332ca5f5SKatayama Hirofumi MZ     ZeroMemory(&stgm, sizeof(stgm));
2242332ca5f5SKatayama Hirofumi MZ     hr = pDataObj->lpVtbl->GetData(pDataObj, &fme, &stgm);
2243332ca5f5SKatayama Hirofumi MZ     if (SUCCEEDED(hr))
2244332ca5f5SKatayama Hirofumi MZ     {
2245332ca5f5SKatayama Hirofumi MZ         hGlobal = stgm.DUMMYUNIONNAME.hGlobal;
2246332ca5f5SKatayama Hirofumi MZ         if (hGlobal)
2247332ca5f5SKatayama Hirofumi MZ         {
2248332ca5f5SKatayama Hirofumi MZ             if (IsWindowUnicode(hwndAccepter))
2249332ca5f5SKatayama Hirofumi MZ                 PostMessageW(hwndAccepter, WM_DROPFILES, (WPARAM)hGlobal, 0);
2250332ca5f5SKatayama Hirofumi MZ             else
2251332ca5f5SKatayama Hirofumi MZ                 PostMessageA(hwndAccepter, WM_DROPFILES, (WPARAM)hGlobal, 0);
2252332ca5f5SKatayama Hirofumi MZ         }
2253332ca5f5SKatayama Hirofumi MZ         ReleaseStgMedium(&stgm);
2254332ca5f5SKatayama Hirofumi MZ     }
2255332ca5f5SKatayama Hirofumi MZ 
2256332ca5f5SKatayama Hirofumi MZ     return hr;
2257332ca5f5SKatayama Hirofumi MZ }
2258332ca5f5SKatayama Hirofumi MZ #endif
2259332ca5f5SKatayama Hirofumi MZ 
drag_enter(TrackerWindowInfo * info,HWND new_target)2260c2c66affSColin Finck static void drag_enter( TrackerWindowInfo *info, HWND new_target )
2261c2c66affSColin Finck {
2262c2c66affSColin Finck     HRESULT hr;
2263332ca5f5SKatayama Hirofumi MZ #ifdef __REACTOS__
2264332ca5f5SKatayama Hirofumi MZ     DWORD dwEffect = *info->pdwEffect;
2265332ca5f5SKatayama Hirofumi MZ #endif
2266c2c66affSColin Finck 
2267c2c66affSColin Finck     info->curTargetHWND = new_target;
2268c2c66affSColin Finck 
2269332ca5f5SKatayama Hirofumi MZ #ifdef __REACTOS__
2270332ca5f5SKatayama Hirofumi MZ     info->accepterHWND = NULL;
2271332ca5f5SKatayama Hirofumi MZ     while (new_target && !is_droptarget( new_target ))
2272332ca5f5SKatayama Hirofumi MZ     {
2273332ca5f5SKatayama Hirofumi MZ         if (is_acceptfiles(new_target))
2274332ca5f5SKatayama Hirofumi MZ         {
2275332ca5f5SKatayama Hirofumi MZ             dwEffect = info->dwOKEffect;
2276332ca5f5SKatayama Hirofumi MZ             hr = DefaultDragEnter(new_target, info->dataObject,
2277332ca5f5SKatayama Hirofumi MZ                                   info->dwKeyState, info->curMousePos,
2278332ca5f5SKatayama Hirofumi MZ                                   &dwEffect);
2279332ca5f5SKatayama Hirofumi MZ             dwEffect &= info->dwOKEffect;
2280332ca5f5SKatayama Hirofumi MZ 
2281332ca5f5SKatayama Hirofumi MZ             if (hr == S_OK)
2282332ca5f5SKatayama Hirofumi MZ             {
2283332ca5f5SKatayama Hirofumi MZ                 info->accepterHWND = new_target;
2284332ca5f5SKatayama Hirofumi MZ                 info->curDragTarget = NULL;
2285332ca5f5SKatayama Hirofumi MZ                 *info->pdwEffect = dwEffect;
2286332ca5f5SKatayama Hirofumi MZ                 return;
2287332ca5f5SKatayama Hirofumi MZ             }
2288332ca5f5SKatayama Hirofumi MZ         }
2289332ca5f5SKatayama Hirofumi MZ         new_target = GetParent( new_target );
2290332ca5f5SKatayama Hirofumi MZ     }
2291332ca5f5SKatayama Hirofumi MZ #else
2292c2c66affSColin Finck     while (new_target && !is_droptarget( new_target ))
2293c2c66affSColin Finck         new_target = GetParent( new_target );
2294332ca5f5SKatayama Hirofumi MZ #endif
2295c2c66affSColin Finck 
2296c2c66affSColin Finck     info->curDragTarget = get_droptarget_pointer( new_target );
2297c2c66affSColin Finck 
2298c2c66affSColin Finck     if (info->curDragTarget)
2299c2c66affSColin Finck     {
2300c2c66affSColin Finck         *info->pdwEffect = info->dwOKEffect;
2301c2c66affSColin Finck         hr = IDropTarget_DragEnter( info->curDragTarget, info->dataObject,
2302c2c66affSColin Finck                                     info->dwKeyState, info->curMousePos,
2303c2c66affSColin Finck                                     info->pdwEffect );
2304c2c66affSColin Finck         *info->pdwEffect &= info->dwOKEffect;
2305c2c66affSColin Finck 
2306c2c66affSColin Finck         /* failed DragEnter() means invalid target */
2307c2c66affSColin Finck         if (hr != S_OK)
2308c2c66affSColin Finck         {
2309c2c66affSColin Finck             IDropTarget_Release( info->curDragTarget );
2310c2c66affSColin Finck             info->curDragTarget = NULL;
2311c2c66affSColin Finck             info->curTargetHWND = NULL;
2312332ca5f5SKatayama Hirofumi MZ #ifdef __REACTOS__
2313332ca5f5SKatayama Hirofumi MZ             info->accepterHWND = NULL;
2314332ca5f5SKatayama Hirofumi MZ #endif
2315c2c66affSColin Finck         }
2316c2c66affSColin Finck     }
2317c2c66affSColin Finck }
2318c2c66affSColin Finck 
drag_end(TrackerWindowInfo * info)2319c2c66affSColin Finck static void drag_end( TrackerWindowInfo *info )
2320c2c66affSColin Finck {
2321c2c66affSColin Finck     HRESULT hr;
2322c2c66affSColin Finck 
2323c2c66affSColin Finck     info->trackingDone = TRUE;
2324c2c66affSColin Finck     ReleaseCapture();
2325c2c66affSColin Finck 
2326c2c66affSColin Finck     if (info->curDragTarget)
2327c2c66affSColin Finck     {
2328c2c66affSColin Finck         if (info->returnValue == DRAGDROP_S_DROP &&
2329c2c66affSColin Finck             *info->pdwEffect != DROPEFFECT_NONE)
2330c2c66affSColin Finck         {
2331c2c66affSColin Finck             *info->pdwEffect = info->dwOKEffect;
2332c2c66affSColin Finck             hr = IDropTarget_Drop( info->curDragTarget, info->dataObject, info->dwKeyState,
2333c2c66affSColin Finck                                    info->curMousePos, info->pdwEffect );
2334c2c66affSColin Finck             *info->pdwEffect &= info->dwOKEffect;
2335c2c66affSColin Finck 
2336c2c66affSColin Finck             if (FAILED( hr ))
2337c2c66affSColin Finck                 info->returnValue = hr;
2338c2c66affSColin Finck         }
2339c2c66affSColin Finck         else
2340c2c66affSColin Finck         {
2341c2c66affSColin Finck             IDropTarget_DragLeave( info->curDragTarget );
2342c2c66affSColin Finck             *info->pdwEffect = DROPEFFECT_NONE;
2343c2c66affSColin Finck         }
2344c2c66affSColin Finck         IDropTarget_Release( info->curDragTarget );
2345c2c66affSColin Finck         info->curDragTarget = NULL;
2346c2c66affSColin Finck     }
2347332ca5f5SKatayama Hirofumi MZ #ifdef __REACTOS__
2348332ca5f5SKatayama Hirofumi MZ     else if (info->accepterHWND)
2349332ca5f5SKatayama Hirofumi MZ     {
2350332ca5f5SKatayama Hirofumi MZ         if (info->returnValue == DRAGDROP_S_DROP &&
2351332ca5f5SKatayama Hirofumi MZ             *info->pdwEffect != DROPEFFECT_NONE)
2352332ca5f5SKatayama Hirofumi MZ         {
2353332ca5f5SKatayama Hirofumi MZ             *info->pdwEffect = info->dwOKEffect;
2354332ca5f5SKatayama Hirofumi MZ             hr = DefaultDrop(info->accepterHWND, info->dataObject, info->dwKeyState,
2355332ca5f5SKatayama Hirofumi MZ                              info->curMousePos, info->pdwEffect);
2356332ca5f5SKatayama Hirofumi MZ             *info->pdwEffect &= info->dwOKEffect;
2357332ca5f5SKatayama Hirofumi MZ 
2358332ca5f5SKatayama Hirofumi MZ             if (FAILED( hr ))
2359332ca5f5SKatayama Hirofumi MZ                 info->returnValue = hr;
2360332ca5f5SKatayama Hirofumi MZ         }
2361332ca5f5SKatayama Hirofumi MZ         else
2362332ca5f5SKatayama Hirofumi MZ         {
2363332ca5f5SKatayama Hirofumi MZ             *info->pdwEffect = DROPEFFECT_NONE;
2364332ca5f5SKatayama Hirofumi MZ         }
2365332ca5f5SKatayama Hirofumi MZ         info->accepterHWND = NULL;
2366332ca5f5SKatayama Hirofumi MZ     }
2367332ca5f5SKatayama Hirofumi MZ #endif
2368c2c66affSColin Finck     else
2369c2c66affSColin Finck         *info->pdwEffect = DROPEFFECT_NONE;
2370c2c66affSColin Finck }
2371c2c66affSColin Finck 
give_feedback(TrackerWindowInfo * info)2372c2c66affSColin Finck static HRESULT give_feedback( TrackerWindowInfo *info )
2373c2c66affSColin Finck {
2374c2c66affSColin Finck     HRESULT hr;
2375c2c66affSColin Finck     int res;
2376c2c66affSColin Finck     HCURSOR cur;
2377c2c66affSColin Finck 
2378332ca5f5SKatayama Hirofumi MZ #ifdef __REACTOS__
2379332ca5f5SKatayama Hirofumi MZ     if (info->curDragTarget == NULL && info->accepterHWND == NULL)
2380332ca5f5SKatayama Hirofumi MZ         *info->pdwEffect = DROPEFFECT_NONE;
2381332ca5f5SKatayama Hirofumi MZ #else
2382c2c66affSColin Finck     if (info->curDragTarget == NULL)
2383c2c66affSColin Finck         *info->pdwEffect = DROPEFFECT_NONE;
2384332ca5f5SKatayama Hirofumi MZ #endif
2385c2c66affSColin Finck 
2386c2c66affSColin Finck     hr = IDropSource_GiveFeedback( info->dropSource, *info->pdwEffect );
2387c2c66affSColin Finck 
2388c2c66affSColin Finck     if (hr == DRAGDROP_S_USEDEFAULTCURSORS)
2389c2c66affSColin Finck     {
2390c2c66affSColin Finck         if (*info->pdwEffect & DROPEFFECT_MOVE)
2391c2c66affSColin Finck             res = CURSOR_MOVE;
2392c2c66affSColin Finck         else if (*info->pdwEffect & DROPEFFECT_COPY)
2393c2c66affSColin Finck             res = CURSOR_COPY;
2394c2c66affSColin Finck         else if (*info->pdwEffect & DROPEFFECT_LINK)
2395c2c66affSColin Finck             res = CURSOR_LINK;
2396c2c66affSColin Finck         else
2397c2c66affSColin Finck             res = CURSOR_NODROP;
2398c2c66affSColin Finck 
2399c2c66affSColin Finck         cur = LoadCursorW( hProxyDll, MAKEINTRESOURCEW( res ) );
2400c2c66affSColin Finck         SetCursor( cur );
2401c2c66affSColin Finck     }
2402c2c66affSColin Finck 
2403c2c66affSColin Finck     return hr;
2404c2c66affSColin Finck }
2405c2c66affSColin Finck 
2406c2c66affSColin Finck /***
2407c2c66affSColin Finck  * OLEDD_TrackStateChange()
2408c2c66affSColin Finck  *
2409c2c66affSColin Finck  * This method is invoked while a drag and drop operation is in effect.
2410c2c66affSColin Finck  *
2411c2c66affSColin Finck  * params:
2412c2c66affSColin Finck  *    trackerInfo - Pointer to the structure identifying the
2413c2c66affSColin Finck  *                  drag & drop operation that is currently
2414c2c66affSColin Finck  *                  active.
2415c2c66affSColin Finck  */
OLEDD_TrackStateChange(TrackerWindowInfo * trackerInfo)2416c2c66affSColin Finck static void OLEDD_TrackStateChange(TrackerWindowInfo* trackerInfo)
2417c2c66affSColin Finck {
2418c2c66affSColin Finck   HWND   hwndNewTarget = 0;
2419c2c66affSColin Finck   POINT pt;
2420c2c66affSColin Finck 
2421c2c66affSColin Finck   /*
2422c2c66affSColin Finck    * Get the handle of the window under the mouse
2423c2c66affSColin Finck    */
2424c2c66affSColin Finck   pt.x = trackerInfo->curMousePos.x;
2425c2c66affSColin Finck   pt.y = trackerInfo->curMousePos.y;
2426c2c66affSColin Finck   hwndNewTarget = WindowFromPoint(pt);
2427c2c66affSColin Finck 
2428c2c66affSColin Finck   trackerInfo->returnValue = IDropSource_QueryContinueDrag(trackerInfo->dropSource,
2429c2c66affSColin Finck                                                            trackerInfo->escPressed,
2430c2c66affSColin Finck                                                            trackerInfo->dwKeyState);
2431c2c66affSColin Finck 
2432c2c66affSColin Finck   if (trackerInfo->curTargetHWND != hwndNewTarget &&
2433c2c66affSColin Finck       (trackerInfo->returnValue == S_OK ||
2434c2c66affSColin Finck        trackerInfo->returnValue == DRAGDROP_S_DROP))
2435c2c66affSColin Finck   {
2436c2c66affSColin Finck     if (trackerInfo->curDragTarget)
2437c2c66affSColin Finck     {
2438c2c66affSColin Finck       IDropTarget_DragLeave(trackerInfo->curDragTarget);
2439c2c66affSColin Finck       IDropTarget_Release(trackerInfo->curDragTarget);
2440c2c66affSColin Finck       trackerInfo->curDragTarget = NULL;
2441c2c66affSColin Finck       trackerInfo->curTargetHWND = NULL;
2442c2c66affSColin Finck     }
2443332ca5f5SKatayama Hirofumi MZ #ifdef __REACTOS__
2444332ca5f5SKatayama Hirofumi MZ     trackerInfo->accepterHWND = NULL;
2445332ca5f5SKatayama Hirofumi MZ #endif
2446c2c66affSColin Finck 
2447c2c66affSColin Finck     if (hwndNewTarget)
2448c2c66affSColin Finck       drag_enter( trackerInfo, hwndNewTarget );
2449c2c66affSColin Finck 
2450c2c66affSColin Finck     give_feedback( trackerInfo );
2451c2c66affSColin Finck 
2452c2c66affSColin Finck   }
2453c2c66affSColin Finck 
2454c2c66affSColin Finck   if (trackerInfo->returnValue == S_OK)
2455c2c66affSColin Finck   {
2456c2c66affSColin Finck     if (trackerInfo->curDragTarget)
2457c2c66affSColin Finck     {
2458c2c66affSColin Finck       *trackerInfo->pdwEffect = trackerInfo->dwOKEffect;
2459c2c66affSColin Finck       IDropTarget_DragOver(trackerInfo->curDragTarget,
2460c2c66affSColin Finck                            trackerInfo->dwKeyState,
2461c2c66affSColin Finck                            trackerInfo->curMousePos,
2462c2c66affSColin Finck                            trackerInfo->pdwEffect);
2463c2c66affSColin Finck       *trackerInfo->pdwEffect &= trackerInfo->dwOKEffect;
2464c2c66affSColin Finck     }
2465332ca5f5SKatayama Hirofumi MZ #ifdef __REACTOS__
2466332ca5f5SKatayama Hirofumi MZ     else if (trackerInfo->accepterHWND)
2467332ca5f5SKatayama Hirofumi MZ     {
2468332ca5f5SKatayama Hirofumi MZ       *trackerInfo->pdwEffect = trackerInfo->dwOKEffect;
2469332ca5f5SKatayama Hirofumi MZ     }
2470332ca5f5SKatayama Hirofumi MZ #endif
2471c2c66affSColin Finck     give_feedback( trackerInfo );
2472c2c66affSColin Finck   }
2473c2c66affSColin Finck   else
2474c2c66affSColin Finck     drag_end( trackerInfo );
2475c2c66affSColin Finck }
2476c2c66affSColin Finck 
2477c2c66affSColin Finck /***
2478c2c66affSColin Finck  * OLEDD_GetButtonState()
2479c2c66affSColin Finck  *
2480c2c66affSColin Finck  * This method will use the current state of the keyboard to build
2481c2c66affSColin Finck  * a button state mask equivalent to the one passed in the
2482c2c66affSColin Finck  * WM_MOUSEMOVE wParam.
2483c2c66affSColin Finck  */
OLEDD_GetButtonState(void)2484c2c66affSColin Finck static DWORD OLEDD_GetButtonState(void)
2485c2c66affSColin Finck {
2486c2c66affSColin Finck   BYTE  keyboardState[256];
2487c2c66affSColin Finck   DWORD keyMask = 0;
2488c2c66affSColin Finck 
2489c2c66affSColin Finck   GetKeyboardState(keyboardState);
2490c2c66affSColin Finck 
2491c2c66affSColin Finck   if ( (keyboardState[VK_SHIFT] & 0x80) !=0)
2492c2c66affSColin Finck     keyMask |= MK_SHIFT;
2493c2c66affSColin Finck 
2494c2c66affSColin Finck   if ( (keyboardState[VK_CONTROL] & 0x80) !=0)
2495c2c66affSColin Finck     keyMask |= MK_CONTROL;
2496c2c66affSColin Finck 
2497c2c66affSColin Finck   if ( (keyboardState[VK_MENU] & 0x80) !=0)
2498c2c66affSColin Finck     keyMask |= MK_ALT;
2499c2c66affSColin Finck 
2500c2c66affSColin Finck   if ( (keyboardState[VK_LBUTTON] & 0x80) !=0)
2501c2c66affSColin Finck     keyMask |= MK_LBUTTON;
2502c2c66affSColin Finck 
2503c2c66affSColin Finck   if ( (keyboardState[VK_RBUTTON] & 0x80) !=0)
2504c2c66affSColin Finck     keyMask |= MK_RBUTTON;
2505c2c66affSColin Finck 
2506c2c66affSColin Finck   if ( (keyboardState[VK_MBUTTON] & 0x80) !=0)
2507c2c66affSColin Finck     keyMask |= MK_MBUTTON;
2508c2c66affSColin Finck 
2509c2c66affSColin Finck   return keyMask;
2510c2c66affSColin Finck }
2511c2c66affSColin Finck 
2512c2c66affSColin Finck /***
2513c2c66affSColin Finck  * OLEDD_GetButtonState()
2514c2c66affSColin Finck  *
2515c2c66affSColin Finck  * This method will read the default value of the registry key in
2516c2c66affSColin Finck  * parameter and extract a DWORD value from it. The registry key value
2517c2c66affSColin Finck  * can be in a string key or a DWORD key.
2518c2c66affSColin Finck  *
2519c2c66affSColin Finck  * params:
2520c2c66affSColin Finck  *     regKey   - Key to read the default value from
2521c2c66affSColin Finck  *     pdwValue - Pointer to the location where the DWORD
2522c2c66affSColin Finck  *                value is returned. This value is not modified
2523c2c66affSColin Finck  *                if the value is not found.
2524c2c66affSColin Finck  */
2525c2c66affSColin Finck 
OLEUTL_ReadRegistryDWORDValue(HKEY regKey,DWORD * pdwValue)2526c2c66affSColin Finck static void OLEUTL_ReadRegistryDWORDValue(
2527c2c66affSColin Finck   HKEY   regKey,
2528c2c66affSColin Finck   DWORD* pdwValue)
2529c2c66affSColin Finck {
2530c2c66affSColin Finck   WCHAR buffer[20];
2531c2c66affSColin Finck   DWORD cbData = sizeof(buffer);
2532c2c66affSColin Finck   DWORD dwKeyType;
2533c2c66affSColin Finck   LONG  lres;
2534c2c66affSColin Finck 
2535c2c66affSColin Finck   lres = RegQueryValueExW(regKey,
2536c2c66affSColin Finck 			  emptyW,
2537c2c66affSColin Finck 			  NULL,
2538c2c66affSColin Finck 			  &dwKeyType,
2539c2c66affSColin Finck 			  (LPBYTE)buffer,
2540c2c66affSColin Finck 			  &cbData);
2541c2c66affSColin Finck 
2542c2c66affSColin Finck   if (lres==ERROR_SUCCESS)
2543c2c66affSColin Finck   {
2544c2c66affSColin Finck     switch (dwKeyType)
2545c2c66affSColin Finck     {
2546c2c66affSColin Finck       case REG_DWORD:
2547c2c66affSColin Finck 	*pdwValue = *(DWORD*)buffer;
2548c2c66affSColin Finck 	break;
2549c2c66affSColin Finck       case REG_EXPAND_SZ:
2550c2c66affSColin Finck       case REG_MULTI_SZ:
2551c2c66affSColin Finck       case REG_SZ:
2552*0f5d91b7SAmine Khaldi 	*pdwValue = wcstoul(buffer, NULL, 10);
2553c2c66affSColin Finck 	break;
2554c2c66affSColin Finck     }
2555c2c66affSColin Finck   }
2556c2c66affSColin Finck }
2557c2c66affSColin Finck 
2558c2c66affSColin Finck /******************************************************************************
2559c2c66affSColin Finck  * OleDraw (OLE32.@)
2560c2c66affSColin Finck  *
2561c2c66affSColin Finck  * The operation of this function is documented literally in the WinAPI
2562c2c66affSColin Finck  * documentation to involve a QueryInterface for the IViewObject interface,
2563c2c66affSColin Finck  * followed by a call to IViewObject::Draw.
2564c2c66affSColin Finck  */
OleDraw(IUnknown * pUnk,DWORD dwAspect,HDC hdcDraw,LPCRECT rect)2565c2c66affSColin Finck HRESULT WINAPI OleDraw(
2566c2c66affSColin Finck 	IUnknown *pUnk,
2567c2c66affSColin Finck 	DWORD dwAspect,
2568c2c66affSColin Finck 	HDC hdcDraw,
2569c2c66affSColin Finck 	LPCRECT rect)
2570c2c66affSColin Finck {
2571c2c66affSColin Finck   HRESULT hres;
2572c2c66affSColin Finck   IViewObject *viewobject;
2573c2c66affSColin Finck 
2574c2c66affSColin Finck   if (!pUnk) return E_INVALIDARG;
2575c2c66affSColin Finck 
2576c2c66affSColin Finck   hres = IUnknown_QueryInterface(pUnk,
2577c2c66affSColin Finck 				 &IID_IViewObject,
2578c2c66affSColin Finck 				 (void**)&viewobject);
2579c2c66affSColin Finck   if (SUCCEEDED(hres))
2580c2c66affSColin Finck   {
2581c2c66affSColin Finck     hres = IViewObject_Draw(viewobject, dwAspect, -1, 0, 0, 0, hdcDraw, (RECTL*)rect, 0, 0, 0);
2582c2c66affSColin Finck     IViewObject_Release(viewobject);
2583c2c66affSColin Finck     return hres;
2584c2c66affSColin Finck   }
2585c2c66affSColin Finck   else
2586c2c66affSColin Finck     return DV_E_NOIVIEWOBJECT;
2587c2c66affSColin Finck }
2588c2c66affSColin Finck 
2589c2c66affSColin Finck /***********************************************************************
2590c2c66affSColin Finck  *             OleTranslateAccelerator [OLE32.@]
2591c2c66affSColin Finck  */
OleTranslateAccelerator(LPOLEINPLACEFRAME lpFrame,LPOLEINPLACEFRAMEINFO lpFrameInfo,LPMSG lpmsg)2592c2c66affSColin Finck HRESULT WINAPI OleTranslateAccelerator (LPOLEINPLACEFRAME lpFrame,
2593c2c66affSColin Finck                    LPOLEINPLACEFRAMEINFO lpFrameInfo, LPMSG lpmsg)
2594c2c66affSColin Finck {
2595c2c66affSColin Finck     WORD wID;
2596c2c66affSColin Finck 
2597c2c66affSColin Finck     TRACE("(%p,%p,%p)\n", lpFrame, lpFrameInfo, lpmsg);
2598c2c66affSColin Finck 
2599c2c66affSColin Finck     if (IsAccelerator(lpFrameInfo->haccel,lpFrameInfo->cAccelEntries,lpmsg,&wID))
2600c2c66affSColin Finck         return IOleInPlaceFrame_TranslateAccelerator(lpFrame,lpmsg,wID);
2601c2c66affSColin Finck 
2602c2c66affSColin Finck     return S_FALSE;
2603c2c66affSColin Finck }
2604c2c66affSColin Finck 
2605c2c66affSColin Finck /******************************************************************************
2606c2c66affSColin Finck  *              OleCreate        [OLE32.@]
2607c2c66affSColin Finck  *
2608c2c66affSColin Finck  */
OleCreate(REFCLSID rclsid,REFIID riid,DWORD renderopt,LPFORMATETC pFormatEtc,LPOLECLIENTSITE pClientSite,LPSTORAGE pStg,LPVOID * ppvObj)2609c2c66affSColin Finck HRESULT WINAPI OleCreate(
2610c2c66affSColin Finck 	REFCLSID rclsid,
2611c2c66affSColin Finck 	REFIID riid,
2612c2c66affSColin Finck 	DWORD renderopt,
2613c2c66affSColin Finck 	LPFORMATETC pFormatEtc,
2614c2c66affSColin Finck 	LPOLECLIENTSITE pClientSite,
2615c2c66affSColin Finck 	LPSTORAGE pStg,
2616c2c66affSColin Finck 	LPVOID* ppvObj)
2617c2c66affSColin Finck {
2618c2c66affSColin Finck     HRESULT hres;
2619c2c66affSColin Finck     IUnknown * pUnk = NULL;
2620c2c66affSColin Finck     IOleObject *pOleObject = NULL;
2621c2c66affSColin Finck 
2622c2c66affSColin Finck     TRACE("(%s, %s, %d, %p, %p, %p, %p)\n", debugstr_guid(rclsid),
2623c2c66affSColin Finck         debugstr_guid(riid), renderopt, pFormatEtc, pClientSite, pStg, ppvObj);
2624c2c66affSColin Finck 
2625c2c66affSColin Finck     hres = CoCreateInstance(rclsid, 0, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, riid, (LPVOID*)&pUnk);
2626c2c66affSColin Finck 
2627c2c66affSColin Finck     if (SUCCEEDED(hres))
2628c2c66affSColin Finck         hres = IStorage_SetClass(pStg, rclsid);
2629c2c66affSColin Finck 
2630c2c66affSColin Finck     if (pClientSite && SUCCEEDED(hres))
2631c2c66affSColin Finck     {
2632c2c66affSColin Finck         hres = IUnknown_QueryInterface(pUnk, &IID_IOleObject, (LPVOID*)&pOleObject);
2633c2c66affSColin Finck         if (SUCCEEDED(hres))
2634c2c66affSColin Finck         {
2635c2c66affSColin Finck             DWORD dwStatus;
2636c2c66affSColin Finck             IOleObject_GetMiscStatus(pOleObject, DVASPECT_CONTENT, &dwStatus);
2637c2c66affSColin Finck         }
2638c2c66affSColin Finck     }
2639c2c66affSColin Finck 
2640c2c66affSColin Finck     if (SUCCEEDED(hres))
2641c2c66affSColin Finck     {
2642c2c66affSColin Finck         IPersistStorage * pPS;
2643c2c66affSColin Finck         if (SUCCEEDED((hres = IUnknown_QueryInterface(pUnk, &IID_IPersistStorage, (LPVOID*)&pPS))))
2644c2c66affSColin Finck         {
2645c2c66affSColin Finck             TRACE("trying to set stg %p\n", pStg);
2646c2c66affSColin Finck             hres = IPersistStorage_InitNew(pPS, pStg);
2647c2c66affSColin Finck             TRACE("-- result 0x%08x\n", hres);
2648c2c66affSColin Finck             IPersistStorage_Release(pPS);
2649c2c66affSColin Finck         }
2650c2c66affSColin Finck     }
2651c2c66affSColin Finck 
2652c2c66affSColin Finck     if (pClientSite && SUCCEEDED(hres))
2653c2c66affSColin Finck     {
2654c2c66affSColin Finck         TRACE("trying to set clientsite %p\n", pClientSite);
2655c2c66affSColin Finck         hres = IOleObject_SetClientSite(pOleObject, pClientSite);
2656c2c66affSColin Finck         TRACE("-- result 0x%08x\n", hres);
2657c2c66affSColin Finck     }
2658c2c66affSColin Finck 
2659c2c66affSColin Finck     if (pOleObject)
2660c2c66affSColin Finck         IOleObject_Release(pOleObject);
2661c2c66affSColin Finck 
2662c2c66affSColin Finck     if (((renderopt == OLERENDER_DRAW) || (renderopt == OLERENDER_FORMAT)) &&
2663c2c66affSColin Finck         SUCCEEDED(hres))
2664c2c66affSColin Finck     {
2665c2c66affSColin Finck         hres = OleRun(pUnk);
2666c2c66affSColin Finck         if (SUCCEEDED(hres))
2667c2c66affSColin Finck         {
2668c2c66affSColin Finck             IOleCache *pOleCache;
2669c2c66affSColin Finck 
2670c2c66affSColin Finck             if (SUCCEEDED(IUnknown_QueryInterface(pUnk, &IID_IOleCache, (void **)&pOleCache)))
2671c2c66affSColin Finck             {
2672c2c66affSColin Finck                 DWORD dwConnection;
2673c2c66affSColin Finck                 if (renderopt == OLERENDER_DRAW && !pFormatEtc) {
2674c2c66affSColin Finck                     FORMATETC pfe;
2675c2c66affSColin Finck                     pfe.cfFormat = 0;
2676c2c66affSColin Finck                     pfe.ptd = NULL;
2677c2c66affSColin Finck                     pfe.dwAspect = DVASPECT_CONTENT;
2678c2c66affSColin Finck                     pfe.lindex = -1;
2679c2c66affSColin Finck                     pfe.tymed = TYMED_NULL;
2680c2c66affSColin Finck                     hres = IOleCache_Cache(pOleCache, &pfe, ADVF_PRIMEFIRST, &dwConnection);
2681c2c66affSColin Finck                 }
2682c2c66affSColin Finck                 else
2683c2c66affSColin Finck                     hres = IOleCache_Cache(pOleCache, pFormatEtc, ADVF_PRIMEFIRST, &dwConnection);
2684c2c66affSColin Finck                 IOleCache_Release(pOleCache);
2685c2c66affSColin Finck             }
2686c2c66affSColin Finck         }
2687c2c66affSColin Finck     }
2688c2c66affSColin Finck 
2689c2c66affSColin Finck     if (FAILED(hres) && pUnk)
2690c2c66affSColin Finck     {
2691c2c66affSColin Finck         IUnknown_Release(pUnk);
2692c2c66affSColin Finck         pUnk = NULL;
2693c2c66affSColin Finck     }
2694c2c66affSColin Finck 
2695c2c66affSColin Finck     *ppvObj = pUnk;
2696c2c66affSColin Finck 
2697c2c66affSColin Finck     TRACE("-- %p\n", pUnk);
2698c2c66affSColin Finck     return hres;
2699c2c66affSColin Finck }
2700c2c66affSColin Finck 
2701c2c66affSColin Finck /******************************************************************************
2702c2c66affSColin Finck  *              OleGetAutoConvert        [OLE32.@]
2703c2c66affSColin Finck  */
OleGetAutoConvert(REFCLSID clsidOld,LPCLSID pClsidNew)2704c2c66affSColin Finck HRESULT WINAPI OleGetAutoConvert(REFCLSID clsidOld, LPCLSID pClsidNew)
2705c2c66affSColin Finck {
2706c2c66affSColin Finck     static const WCHAR wszAutoConvertTo[] = {'A','u','t','o','C','o','n','v','e','r','t','T','o',0};
2707c2c66affSColin Finck     HKEY hkey = NULL;
2708c2c66affSColin Finck     WCHAR buf[CHARS_IN_GUID];
2709c2c66affSColin Finck     LONG len;
2710c2c66affSColin Finck     HRESULT res = S_OK;
2711c2c66affSColin Finck 
2712c2c66affSColin Finck     res = COM_OpenKeyForCLSID(clsidOld, wszAutoConvertTo, KEY_READ, &hkey);
2713c2c66affSColin Finck     if (FAILED(res))
2714c2c66affSColin Finck         goto done;
2715c2c66affSColin Finck 
2716c2c66affSColin Finck     len = sizeof(buf);
2717c2c66affSColin Finck     if (RegQueryValueW(hkey, NULL, buf, &len))
2718c2c66affSColin Finck     {
2719c2c66affSColin Finck         res = REGDB_E_KEYMISSING;
2720c2c66affSColin Finck         goto done;
2721c2c66affSColin Finck     }
2722c2c66affSColin Finck     res = CLSIDFromString(buf, pClsidNew);
2723c2c66affSColin Finck done:
2724c2c66affSColin Finck     if (hkey) RegCloseKey(hkey);
2725c2c66affSColin Finck     return res;
2726c2c66affSColin Finck }
2727c2c66affSColin Finck 
2728c2c66affSColin Finck /******************************************************************************
2729c2c66affSColin Finck  *              OleSetAutoConvert        [OLE32.@]
2730c2c66affSColin Finck  */
OleSetAutoConvert(REFCLSID clsidOld,REFCLSID clsidNew)2731c2c66affSColin Finck HRESULT WINAPI OleSetAutoConvert(REFCLSID clsidOld, REFCLSID clsidNew)
2732c2c66affSColin Finck {
2733c2c66affSColin Finck     static const WCHAR wszAutoConvertTo[] = {'A','u','t','o','C','o','n','v','e','r','t','T','o',0};
2734c2c66affSColin Finck     HKEY hkey = NULL;
2735c2c66affSColin Finck     WCHAR szClsidNew[CHARS_IN_GUID];
2736c2c66affSColin Finck     HRESULT res = S_OK;
2737c2c66affSColin Finck 
2738c2c66affSColin Finck     TRACE("(%s,%s)\n", debugstr_guid(clsidOld), debugstr_guid(clsidNew));
2739c2c66affSColin Finck 
2740c2c66affSColin Finck     res = COM_OpenKeyForCLSID(clsidOld, NULL, KEY_READ | KEY_WRITE, &hkey);
2741c2c66affSColin Finck     if (FAILED(res))
2742c2c66affSColin Finck         goto done;
2743c2c66affSColin Finck     StringFromGUID2(clsidNew, szClsidNew, CHARS_IN_GUID);
2744*0f5d91b7SAmine Khaldi     if (RegSetValueW(hkey, wszAutoConvertTo, REG_SZ, szClsidNew, (lstrlenW(szClsidNew)+1) * sizeof(WCHAR)))
2745c2c66affSColin Finck     {
2746c2c66affSColin Finck         res = REGDB_E_WRITEREGDB;
2747c2c66affSColin Finck 	goto done;
2748c2c66affSColin Finck     }
2749c2c66affSColin Finck 
2750c2c66affSColin Finck done:
2751c2c66affSColin Finck     if (hkey) RegCloseKey(hkey);
2752c2c66affSColin Finck     return res;
2753c2c66affSColin Finck }
2754c2c66affSColin Finck 
2755c2c66affSColin Finck /******************************************************************************
2756c2c66affSColin Finck  *              OleDoAutoConvert        [OLE32.@]
2757c2c66affSColin Finck  */
OleDoAutoConvert(LPSTORAGE pStg,LPCLSID pClsidNew)2758c2c66affSColin Finck HRESULT WINAPI OleDoAutoConvert(LPSTORAGE pStg, LPCLSID pClsidNew)
2759c2c66affSColin Finck {
2760c2c66affSColin Finck     WCHAR *user_type_old, *user_type_new;
2761c2c66affSColin Finck     CLIPFORMAT cf;
2762c2c66affSColin Finck     STATSTG stat;
2763c2c66affSColin Finck     CLSID clsid;
2764c2c66affSColin Finck     HRESULT hr;
2765c2c66affSColin Finck 
2766c2c66affSColin Finck     TRACE("(%p, %p)\n", pStg, pClsidNew);
2767c2c66affSColin Finck 
2768c2c66affSColin Finck     *pClsidNew = CLSID_NULL;
2769c2c66affSColin Finck     if(!pStg)
2770c2c66affSColin Finck         return E_INVALIDARG;
2771c2c66affSColin Finck     hr = IStorage_Stat(pStg, &stat, STATFLAG_NONAME);
2772c2c66affSColin Finck     if(FAILED(hr))
2773c2c66affSColin Finck         return hr;
2774c2c66affSColin Finck 
2775c2c66affSColin Finck     *pClsidNew = stat.clsid;
2776c2c66affSColin Finck     hr = OleGetAutoConvert(&stat.clsid, &clsid);
2777c2c66affSColin Finck     if(FAILED(hr))
2778c2c66affSColin Finck         return hr;
2779c2c66affSColin Finck 
2780c2c66affSColin Finck     hr = IStorage_SetClass(pStg, &clsid);
2781c2c66affSColin Finck     if(FAILED(hr))
2782c2c66affSColin Finck         return hr;
2783c2c66affSColin Finck 
2784c2c66affSColin Finck     hr = ReadFmtUserTypeStg(pStg, &cf, &user_type_old);
2785c2c66affSColin Finck     if(FAILED(hr)) {
2786c2c66affSColin Finck         cf = 0;
2787c2c66affSColin Finck         user_type_new = NULL;
2788c2c66affSColin Finck     }
2789c2c66affSColin Finck 
2790c2c66affSColin Finck     hr = OleRegGetUserType(&clsid, USERCLASSTYPE_FULL, &user_type_new);
2791c2c66affSColin Finck     if(FAILED(hr))
2792c2c66affSColin Finck         user_type_new = NULL;
2793c2c66affSColin Finck 
2794c2c66affSColin Finck     hr = WriteFmtUserTypeStg(pStg, cf, user_type_new);
2795c2c66affSColin Finck     CoTaskMemFree(user_type_new);
2796c2c66affSColin Finck     if(FAILED(hr))
2797c2c66affSColin Finck     {
2798c2c66affSColin Finck         CoTaskMemFree(user_type_old);
2799c2c66affSColin Finck         IStorage_SetClass(pStg, &stat.clsid);
2800c2c66affSColin Finck         return hr;
2801c2c66affSColin Finck     }
2802c2c66affSColin Finck 
2803c2c66affSColin Finck     hr = SetConvertStg(pStg, TRUE);
2804c2c66affSColin Finck     if(FAILED(hr))
2805c2c66affSColin Finck     {
2806c2c66affSColin Finck         WriteFmtUserTypeStg(pStg, cf, user_type_old);
2807c2c66affSColin Finck         IStorage_SetClass(pStg, &stat.clsid);
2808c2c66affSColin Finck     }
2809c2c66affSColin Finck     else
2810c2c66affSColin Finck         *pClsidNew = clsid;
2811c2c66affSColin Finck     CoTaskMemFree(user_type_old);
2812c2c66affSColin Finck     return hr;
2813c2c66affSColin Finck }
2814c2c66affSColin Finck 
2815c2c66affSColin Finck /******************************************************************************
2816c2c66affSColin Finck  *              OleIsRunning        [OLE32.@]
2817c2c66affSColin Finck  */
OleIsRunning(LPOLEOBJECT object)2818c2c66affSColin Finck BOOL WINAPI OleIsRunning(LPOLEOBJECT object)
2819c2c66affSColin Finck {
2820c2c66affSColin Finck     IRunnableObject *pRunnable;
2821c2c66affSColin Finck     HRESULT hr;
2822c2c66affSColin Finck     BOOL running;
2823c2c66affSColin Finck 
2824c2c66affSColin Finck     TRACE("(%p)\n", object);
2825c2c66affSColin Finck 
2826c2c66affSColin Finck     if (!object) return FALSE;
2827c2c66affSColin Finck 
2828c2c66affSColin Finck     hr = IOleObject_QueryInterface(object, &IID_IRunnableObject, (void **)&pRunnable);
2829c2c66affSColin Finck     if (FAILED(hr))
2830c2c66affSColin Finck         return TRUE;
2831c2c66affSColin Finck     running = IRunnableObject_IsRunning(pRunnable);
2832c2c66affSColin Finck     IRunnableObject_Release(pRunnable);
2833c2c66affSColin Finck     return running;
2834c2c66affSColin Finck }
2835c2c66affSColin Finck 
2836c2c66affSColin Finck /***********************************************************************
2837c2c66affSColin Finck  *           OleNoteObjectVisible			    [OLE32.@]
2838c2c66affSColin Finck  */
OleNoteObjectVisible(LPUNKNOWN pUnknown,BOOL bVisible)2839c2c66affSColin Finck HRESULT WINAPI OleNoteObjectVisible(LPUNKNOWN pUnknown, BOOL bVisible)
2840c2c66affSColin Finck {
2841c2c66affSColin Finck     TRACE("(%p, %s)\n", pUnknown, bVisible ? "TRUE" : "FALSE");
2842c2c66affSColin Finck     return CoLockObjectExternal(pUnknown, bVisible, TRUE);
2843c2c66affSColin Finck }
2844c2c66affSColin Finck 
2845c2c66affSColin Finck 
2846c2c66affSColin Finck /***********************************************************************
2847c2c66affSColin Finck  *           OLE_FreeClipDataArray   [internal]
2848c2c66affSColin Finck  *
2849c2c66affSColin Finck  * NOTES:
2850c2c66affSColin Finck  *  frees the data associated with an array of CLIPDATAs
2851c2c66affSColin Finck  */
OLE_FreeClipDataArray(ULONG count,CLIPDATA * pClipDataArray)2852c2c66affSColin Finck static void OLE_FreeClipDataArray(ULONG count, CLIPDATA * pClipDataArray)
2853c2c66affSColin Finck {
2854c2c66affSColin Finck     ULONG i;
2855c2c66affSColin Finck     for (i = 0; i < count; i++)
2856c2c66affSColin Finck         CoTaskMemFree(pClipDataArray[i].pClipData);
2857c2c66affSColin Finck }
2858c2c66affSColin Finck 
2859c2c66affSColin Finck /***********************************************************************
2860c2c66affSColin Finck  *           PropSysAllocString			    [OLE32.@]
2861c2c66affSColin Finck  * NOTES
2862c2c66affSColin Finck  *  Forward to oleaut32.
2863c2c66affSColin Finck  */
PropSysAllocString(LPCOLESTR str)2864c2c66affSColin Finck BSTR WINAPI PropSysAllocString(LPCOLESTR str)
2865c2c66affSColin Finck {
2866c2c66affSColin Finck     return SysAllocString(str);
2867c2c66affSColin Finck }
2868c2c66affSColin Finck 
2869c2c66affSColin Finck /***********************************************************************
2870c2c66affSColin Finck  *           PropSysFreeString			    [OLE32.@]
2871c2c66affSColin Finck  * NOTES
2872c2c66affSColin Finck  *  Forward to oleaut32.
2873c2c66affSColin Finck  */
PropSysFreeString(LPOLESTR str)2874c2c66affSColin Finck void WINAPI PropSysFreeString(LPOLESTR str)
2875c2c66affSColin Finck {
2876c2c66affSColin Finck     SysFreeString(str);
2877c2c66affSColin Finck }
2878c2c66affSColin Finck 
2879c2c66affSColin Finck /******************************************************************************
2880c2c66affSColin Finck  * Check if a PROPVARIANT's type is valid.
2881c2c66affSColin Finck  */
PROPVARIANT_ValidateType(VARTYPE vt)2882c2c66affSColin Finck static inline HRESULT PROPVARIANT_ValidateType(VARTYPE vt)
2883c2c66affSColin Finck {
2884c2c66affSColin Finck     switch (vt)
2885c2c66affSColin Finck     {
2886c2c66affSColin Finck     case VT_EMPTY:
2887c2c66affSColin Finck     case VT_NULL:
2888c2c66affSColin Finck     case VT_I1:
2889c2c66affSColin Finck     case VT_I2:
2890c2c66affSColin Finck     case VT_I4:
2891c2c66affSColin Finck     case VT_I8:
2892c2c66affSColin Finck     case VT_R4:
2893c2c66affSColin Finck     case VT_R8:
2894c2c66affSColin Finck     case VT_CY:
2895c2c66affSColin Finck     case VT_DATE:
2896c2c66affSColin Finck     case VT_BSTR:
2897c2c66affSColin Finck     case VT_ERROR:
2898c2c66affSColin Finck     case VT_BOOL:
2899c2c66affSColin Finck     case VT_DECIMAL:
2900c2c66affSColin Finck     case VT_UI1:
2901c2c66affSColin Finck     case VT_UI2:
2902c2c66affSColin Finck     case VT_UI4:
2903c2c66affSColin Finck     case VT_UI8:
2904c2c66affSColin Finck     case VT_INT:
2905c2c66affSColin Finck     case VT_UINT:
2906c2c66affSColin Finck     case VT_LPSTR:
2907c2c66affSColin Finck     case VT_LPWSTR:
2908c2c66affSColin Finck     case VT_FILETIME:
2909c2c66affSColin Finck     case VT_BLOB:
2910c2c66affSColin Finck     case VT_DISPATCH:
2911c2c66affSColin Finck     case VT_UNKNOWN:
2912c2c66affSColin Finck     case VT_STREAM:
2913c2c66affSColin Finck     case VT_STORAGE:
2914c2c66affSColin Finck     case VT_STREAMED_OBJECT:
2915c2c66affSColin Finck     case VT_STORED_OBJECT:
2916c2c66affSColin Finck     case VT_BLOB_OBJECT:
2917c2c66affSColin Finck     case VT_CF:
2918c2c66affSColin Finck     case VT_CLSID:
2919c2c66affSColin Finck     case VT_I1|VT_VECTOR:
2920c2c66affSColin Finck     case VT_I2|VT_VECTOR:
2921c2c66affSColin Finck     case VT_I4|VT_VECTOR:
2922c2c66affSColin Finck     case VT_I8|VT_VECTOR:
2923c2c66affSColin Finck     case VT_R4|VT_VECTOR:
2924c2c66affSColin Finck     case VT_R8|VT_VECTOR:
2925c2c66affSColin Finck     case VT_CY|VT_VECTOR:
2926c2c66affSColin Finck     case VT_DATE|VT_VECTOR:
2927c2c66affSColin Finck     case VT_BSTR|VT_VECTOR:
2928c2c66affSColin Finck     case VT_ERROR|VT_VECTOR:
2929c2c66affSColin Finck     case VT_BOOL|VT_VECTOR:
2930c2c66affSColin Finck     case VT_VARIANT|VT_VECTOR:
2931c2c66affSColin Finck     case VT_UI1|VT_VECTOR:
2932c2c66affSColin Finck     case VT_UI2|VT_VECTOR:
2933c2c66affSColin Finck     case VT_UI4|VT_VECTOR:
2934c2c66affSColin Finck     case VT_UI8|VT_VECTOR:
2935c2c66affSColin Finck     case VT_LPSTR|VT_VECTOR:
2936c2c66affSColin Finck     case VT_LPWSTR|VT_VECTOR:
2937c2c66affSColin Finck     case VT_FILETIME|VT_VECTOR:
2938c2c66affSColin Finck     case VT_CF|VT_VECTOR:
2939c2c66affSColin Finck     case VT_CLSID|VT_VECTOR:
2940*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_I1:
2941*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_UI1:
2942*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_I2:
2943*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_UI2:
2944*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_I4:
2945*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_UI4:
2946*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_INT:
2947*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_UINT:
2948*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_R4:
2949*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_R8:
2950*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_CY:
2951*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_DATE:
2952*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_BSTR:
2953*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_BOOL:
2954*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_DECIMAL:
2955*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_DISPATCH:
2956*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_UNKNOWN:
2957*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_ERROR:
2958*0f5d91b7SAmine Khaldi     case VT_ARRAY|VT_VARIANT:
2959c2c66affSColin Finck         return S_OK;
2960c2c66affSColin Finck     }
2961c2c66affSColin Finck     WARN("Bad type %d\n", vt);
2962c2c66affSColin Finck     return STG_E_INVALIDPARAMETER;
2963c2c66affSColin Finck }
2964c2c66affSColin Finck 
2965c2c66affSColin Finck /***********************************************************************
2966c2c66affSColin Finck  *           PropVariantClear			    [OLE32.@]
2967c2c66affSColin Finck  */
PropVariantClear(PROPVARIANT * pvar)2968c2c66affSColin Finck HRESULT WINAPI PropVariantClear(PROPVARIANT * pvar) /* [in/out] */
2969c2c66affSColin Finck {
2970c2c66affSColin Finck     HRESULT hr;
2971c2c66affSColin Finck 
2972c2c66affSColin Finck     TRACE("(%p)\n", pvar);
2973c2c66affSColin Finck 
2974c2c66affSColin Finck     if (!pvar)
2975c2c66affSColin Finck         return S_OK;
2976c2c66affSColin Finck 
2977c2c66affSColin Finck     hr = PROPVARIANT_ValidateType(pvar->vt);
2978c2c66affSColin Finck     if (FAILED(hr))
2979c2c66affSColin Finck     {
2980c2c66affSColin Finck         memset(pvar, 0, sizeof(*pvar));
2981c2c66affSColin Finck         return hr;
2982c2c66affSColin Finck     }
2983c2c66affSColin Finck 
2984c2c66affSColin Finck     switch(pvar->vt)
2985c2c66affSColin Finck     {
2986c2c66affSColin Finck     case VT_EMPTY:
2987c2c66affSColin Finck     case VT_NULL:
2988c2c66affSColin Finck     case VT_I1:
2989c2c66affSColin Finck     case VT_I2:
2990c2c66affSColin Finck     case VT_I4:
2991c2c66affSColin Finck     case VT_I8:
2992c2c66affSColin Finck     case VT_R4:
2993c2c66affSColin Finck     case VT_R8:
2994c2c66affSColin Finck     case VT_CY:
2995c2c66affSColin Finck     case VT_DATE:
2996c2c66affSColin Finck     case VT_ERROR:
2997c2c66affSColin Finck     case VT_BOOL:
2998c2c66affSColin Finck     case VT_DECIMAL:
2999c2c66affSColin Finck     case VT_UI1:
3000c2c66affSColin Finck     case VT_UI2:
3001c2c66affSColin Finck     case VT_UI4:
3002c2c66affSColin Finck     case VT_UI8:
3003c2c66affSColin Finck     case VT_INT:
3004c2c66affSColin Finck     case VT_UINT:
3005c2c66affSColin Finck     case VT_FILETIME:
3006c2c66affSColin Finck         break;
3007c2c66affSColin Finck     case VT_DISPATCH:
3008c2c66affSColin Finck     case VT_UNKNOWN:
3009c2c66affSColin Finck     case VT_STREAM:
3010c2c66affSColin Finck     case VT_STREAMED_OBJECT:
3011c2c66affSColin Finck     case VT_STORAGE:
3012c2c66affSColin Finck     case VT_STORED_OBJECT:
3013c2c66affSColin Finck         if (pvar->u.pStream)
3014c2c66affSColin Finck             IStream_Release(pvar->u.pStream);
3015c2c66affSColin Finck         break;
3016c2c66affSColin Finck     case VT_CLSID:
3017c2c66affSColin Finck     case VT_LPSTR:
3018c2c66affSColin Finck     case VT_LPWSTR:
3019c2c66affSColin Finck         /* pick an arbitrary typed pointer - we don't care about the type
3020c2c66affSColin Finck          * as we are just freeing it */
3021c2c66affSColin Finck         CoTaskMemFree(pvar->u.puuid);
3022c2c66affSColin Finck         break;
3023c2c66affSColin Finck     case VT_BLOB:
3024c2c66affSColin Finck     case VT_BLOB_OBJECT:
3025c2c66affSColin Finck         CoTaskMemFree(pvar->u.blob.pBlobData);
3026c2c66affSColin Finck         break;
3027c2c66affSColin Finck     case VT_BSTR:
3028c2c66affSColin Finck         PropSysFreeString(pvar->u.bstrVal);
3029c2c66affSColin Finck         break;
3030c2c66affSColin Finck     case VT_CF:
3031c2c66affSColin Finck         if (pvar->u.pclipdata)
3032c2c66affSColin Finck         {
3033c2c66affSColin Finck             OLE_FreeClipDataArray(1, pvar->u.pclipdata);
3034c2c66affSColin Finck             CoTaskMemFree(pvar->u.pclipdata);
3035c2c66affSColin Finck         }
3036c2c66affSColin Finck         break;
3037c2c66affSColin Finck     default:
3038c2c66affSColin Finck         if (pvar->vt & VT_VECTOR)
3039c2c66affSColin Finck         {
3040c2c66affSColin Finck             ULONG i;
3041c2c66affSColin Finck 
3042c2c66affSColin Finck             switch (pvar->vt & ~VT_VECTOR)
3043c2c66affSColin Finck             {
3044c2c66affSColin Finck             case VT_VARIANT:
3045c2c66affSColin Finck                 FreePropVariantArray(pvar->u.capropvar.cElems, pvar->u.capropvar.pElems);
3046c2c66affSColin Finck                 break;
3047c2c66affSColin Finck             case VT_CF:
3048c2c66affSColin Finck                 OLE_FreeClipDataArray(pvar->u.caclipdata.cElems, pvar->u.caclipdata.pElems);
3049c2c66affSColin Finck                 break;
3050c2c66affSColin Finck             case VT_BSTR:
3051c2c66affSColin Finck                 for (i = 0; i < pvar->u.cabstr.cElems; i++)
3052c2c66affSColin Finck                     PropSysFreeString(pvar->u.cabstr.pElems[i]);
3053c2c66affSColin Finck                 break;
3054c2c66affSColin Finck             case VT_LPSTR:
3055c2c66affSColin Finck                 for (i = 0; i < pvar->u.calpstr.cElems; i++)
3056c2c66affSColin Finck                     CoTaskMemFree(pvar->u.calpstr.pElems[i]);
3057c2c66affSColin Finck                 break;
3058c2c66affSColin Finck             case VT_LPWSTR:
3059c2c66affSColin Finck                 for (i = 0; i < pvar->u.calpwstr.cElems; i++)
3060c2c66affSColin Finck                     CoTaskMemFree(pvar->u.calpwstr.pElems[i]);
3061c2c66affSColin Finck                 break;
3062c2c66affSColin Finck             }
3063c2c66affSColin Finck             if (pvar->vt & ~VT_VECTOR)
3064c2c66affSColin Finck             {
3065c2c66affSColin Finck                 /* pick an arbitrary VT_VECTOR structure - they all have the same
3066c2c66affSColin Finck                  * memory layout */
3067c2c66affSColin Finck                 CoTaskMemFree(pvar->u.capropvar.pElems);
3068c2c66affSColin Finck             }
3069c2c66affSColin Finck         }
3070*0f5d91b7SAmine Khaldi         else if (pvar->vt & VT_ARRAY)
3071*0f5d91b7SAmine Khaldi             hr = SafeArrayDestroy(pvar->u.parray);
3072c2c66affSColin Finck         else
3073c2c66affSColin Finck         {
3074c2c66affSColin Finck             WARN("Invalid/unsupported type %d\n", pvar->vt);
3075c2c66affSColin Finck             hr = STG_E_INVALIDPARAMETER;
3076c2c66affSColin Finck         }
3077c2c66affSColin Finck     }
3078c2c66affSColin Finck 
3079c2c66affSColin Finck     memset(pvar, 0, sizeof(*pvar));
3080c2c66affSColin Finck     return hr;
3081c2c66affSColin Finck }
3082c2c66affSColin Finck 
3083c2c66affSColin Finck /***********************************************************************
3084c2c66affSColin Finck  *           PropVariantCopy			    [OLE32.@]
3085c2c66affSColin Finck  */
PropVariantCopy(PROPVARIANT * pvarDest,const PROPVARIANT * pvarSrc)3086c2c66affSColin Finck HRESULT WINAPI PropVariantCopy(PROPVARIANT *pvarDest,      /* [out] */
3087c2c66affSColin Finck                                const PROPVARIANT *pvarSrc) /* [in] */
3088c2c66affSColin Finck {
3089c2c66affSColin Finck     ULONG len;
3090c2c66affSColin Finck     HRESULT hr;
3091c2c66affSColin Finck 
3092c2c66affSColin Finck     TRACE("(%p, %p vt %04x)\n", pvarDest, pvarSrc, pvarSrc->vt);
3093c2c66affSColin Finck 
3094c2c66affSColin Finck     hr = PROPVARIANT_ValidateType(pvarSrc->vt);
3095c2c66affSColin Finck     if (FAILED(hr))
3096c2c66affSColin Finck         return DISP_E_BADVARTYPE;
3097c2c66affSColin Finck 
3098c2c66affSColin Finck     /* this will deal with most cases */
3099c2c66affSColin Finck     *pvarDest = *pvarSrc;
3100c2c66affSColin Finck 
3101c2c66affSColin Finck     switch(pvarSrc->vt)
3102c2c66affSColin Finck     {
3103c2c66affSColin Finck     case VT_EMPTY:
3104c2c66affSColin Finck     case VT_NULL:
3105c2c66affSColin Finck     case VT_I1:
3106c2c66affSColin Finck     case VT_UI1:
3107c2c66affSColin Finck     case VT_I2:
3108c2c66affSColin Finck     case VT_UI2:
3109c2c66affSColin Finck     case VT_BOOL:
3110c2c66affSColin Finck     case VT_DECIMAL:
3111c2c66affSColin Finck     case VT_I4:
3112c2c66affSColin Finck     case VT_UI4:
3113c2c66affSColin Finck     case VT_R4:
3114c2c66affSColin Finck     case VT_ERROR:
3115c2c66affSColin Finck     case VT_I8:
3116c2c66affSColin Finck     case VT_UI8:
3117c2c66affSColin Finck     case VT_INT:
3118c2c66affSColin Finck     case VT_UINT:
3119c2c66affSColin Finck     case VT_R8:
3120c2c66affSColin Finck     case VT_CY:
3121c2c66affSColin Finck     case VT_DATE:
3122c2c66affSColin Finck     case VT_FILETIME:
3123c2c66affSColin Finck         break;
3124c2c66affSColin Finck     case VT_DISPATCH:
3125c2c66affSColin Finck     case VT_UNKNOWN:
3126c2c66affSColin Finck     case VT_STREAM:
3127c2c66affSColin Finck     case VT_STREAMED_OBJECT:
3128c2c66affSColin Finck     case VT_STORAGE:
3129c2c66affSColin Finck     case VT_STORED_OBJECT:
3130c2c66affSColin Finck         if (pvarDest->u.pStream)
3131c2c66affSColin Finck             IStream_AddRef(pvarDest->u.pStream);
3132c2c66affSColin Finck         break;
3133c2c66affSColin Finck     case VT_CLSID:
3134c2c66affSColin Finck         pvarDest->u.puuid = CoTaskMemAlloc(sizeof(CLSID));
3135c2c66affSColin Finck         *pvarDest->u.puuid = *pvarSrc->u.puuid;
3136c2c66affSColin Finck         break;
3137c2c66affSColin Finck     case VT_LPSTR:
3138c2c66affSColin Finck         if (pvarSrc->u.pszVal)
3139c2c66affSColin Finck         {
3140c2c66affSColin Finck             len = strlen(pvarSrc->u.pszVal);
3141c2c66affSColin Finck             pvarDest->u.pszVal = CoTaskMemAlloc((len+1)*sizeof(CHAR));
3142c2c66affSColin Finck             CopyMemory(pvarDest->u.pszVal, pvarSrc->u.pszVal, (len+1)*sizeof(CHAR));
3143c2c66affSColin Finck         }
3144c2c66affSColin Finck         break;
3145c2c66affSColin Finck     case VT_LPWSTR:
3146c2c66affSColin Finck         if (pvarSrc->u.pwszVal)
3147c2c66affSColin Finck         {
3148c2c66affSColin Finck             len = lstrlenW(pvarSrc->u.pwszVal);
3149c2c66affSColin Finck             pvarDest->u.pwszVal = CoTaskMemAlloc((len+1)*sizeof(WCHAR));
3150c2c66affSColin Finck             CopyMemory(pvarDest->u.pwszVal, pvarSrc->u.pwszVal, (len+1)*sizeof(WCHAR));
3151c2c66affSColin Finck         }
3152c2c66affSColin Finck         break;
3153c2c66affSColin Finck     case VT_BLOB:
3154c2c66affSColin Finck     case VT_BLOB_OBJECT:
3155c2c66affSColin Finck         if (pvarSrc->u.blob.pBlobData)
3156c2c66affSColin Finck         {
3157c2c66affSColin Finck             len = pvarSrc->u.blob.cbSize;
3158c2c66affSColin Finck             pvarDest->u.blob.pBlobData = CoTaskMemAlloc(len);
3159c2c66affSColin Finck             CopyMemory(pvarDest->u.blob.pBlobData, pvarSrc->u.blob.pBlobData, len);
3160c2c66affSColin Finck         }
3161c2c66affSColin Finck         break;
3162c2c66affSColin Finck     case VT_BSTR:
3163c2c66affSColin Finck         pvarDest->u.bstrVal = PropSysAllocString(pvarSrc->u.bstrVal);
3164c2c66affSColin Finck         break;
3165c2c66affSColin Finck     case VT_CF:
3166c2c66affSColin Finck         if (pvarSrc->u.pclipdata)
3167c2c66affSColin Finck         {
3168c2c66affSColin Finck             len = pvarSrc->u.pclipdata->cbSize - sizeof(pvarSrc->u.pclipdata->ulClipFmt);
3169c2c66affSColin Finck             pvarDest->u.pclipdata = CoTaskMemAlloc(sizeof (CLIPDATA));
3170c2c66affSColin Finck             pvarDest->u.pclipdata->cbSize = pvarSrc->u.pclipdata->cbSize;
3171c2c66affSColin Finck             pvarDest->u.pclipdata->ulClipFmt = pvarSrc->u.pclipdata->ulClipFmt;
3172c2c66affSColin Finck             pvarDest->u.pclipdata->pClipData = CoTaskMemAlloc(len);
3173c2c66affSColin Finck             CopyMemory(pvarDest->u.pclipdata->pClipData, pvarSrc->u.pclipdata->pClipData, len);
3174c2c66affSColin Finck         }
3175c2c66affSColin Finck         break;
3176c2c66affSColin Finck     default:
3177c2c66affSColin Finck         if (pvarSrc->vt & VT_VECTOR)
3178c2c66affSColin Finck         {
3179c2c66affSColin Finck             int elemSize;
3180c2c66affSColin Finck             ULONG i;
3181c2c66affSColin Finck 
3182c2c66affSColin Finck             switch(pvarSrc->vt & ~VT_VECTOR)
3183c2c66affSColin Finck             {
3184c2c66affSColin Finck             case VT_I1:       elemSize = sizeof(pvarSrc->u.cVal); break;
3185c2c66affSColin Finck             case VT_UI1:      elemSize = sizeof(pvarSrc->u.bVal); break;
3186c2c66affSColin Finck             case VT_I2:       elemSize = sizeof(pvarSrc->u.iVal); break;
3187c2c66affSColin Finck             case VT_UI2:      elemSize = sizeof(pvarSrc->u.uiVal); break;
3188c2c66affSColin Finck             case VT_BOOL:     elemSize = sizeof(pvarSrc->u.boolVal); break;
3189c2c66affSColin Finck             case VT_I4:       elemSize = sizeof(pvarSrc->u.lVal); break;
3190c2c66affSColin Finck             case VT_UI4:      elemSize = sizeof(pvarSrc->u.ulVal); break;
3191c2c66affSColin Finck             case VT_R4:       elemSize = sizeof(pvarSrc->u.fltVal); break;
3192c2c66affSColin Finck             case VT_R8:       elemSize = sizeof(pvarSrc->u.dblVal); break;
3193c2c66affSColin Finck             case VT_ERROR:    elemSize = sizeof(pvarSrc->u.scode); break;
3194c2c66affSColin Finck             case VT_I8:       elemSize = sizeof(pvarSrc->u.hVal); break;
3195c2c66affSColin Finck             case VT_UI8:      elemSize = sizeof(pvarSrc->u.uhVal); break;
3196c2c66affSColin Finck             case VT_CY:       elemSize = sizeof(pvarSrc->u.cyVal); break;
3197c2c66affSColin Finck             case VT_DATE:     elemSize = sizeof(pvarSrc->u.date); break;
3198c2c66affSColin Finck             case VT_FILETIME: elemSize = sizeof(pvarSrc->u.filetime); break;
3199c2c66affSColin Finck             case VT_CLSID:    elemSize = sizeof(*pvarSrc->u.puuid); break;
3200c2c66affSColin Finck             case VT_CF:       elemSize = sizeof(*pvarSrc->u.pclipdata); break;
3201c2c66affSColin Finck             case VT_BSTR:     elemSize = sizeof(pvarSrc->u.bstrVal); break;
3202c2c66affSColin Finck             case VT_LPSTR:    elemSize = sizeof(pvarSrc->u.pszVal); break;
3203c2c66affSColin Finck             case VT_LPWSTR:   elemSize = sizeof(pvarSrc->u.pwszVal); break;
3204c2c66affSColin Finck             case VT_VARIANT:  elemSize = sizeof(*pvarSrc->u.pvarVal); break;
3205c2c66affSColin Finck 
3206c2c66affSColin Finck             default:
3207c2c66affSColin Finck                 FIXME("Invalid element type: %ul\n", pvarSrc->vt & ~VT_VECTOR);
3208c2c66affSColin Finck                 return E_INVALIDARG;
3209c2c66affSColin Finck             }
3210c2c66affSColin Finck             len = pvarSrc->u.capropvar.cElems;
3211c2c66affSColin Finck             pvarDest->u.capropvar.pElems = len ? CoTaskMemAlloc(len * elemSize) : NULL;
3212c2c66affSColin Finck             if (pvarSrc->vt == (VT_VECTOR | VT_VARIANT))
3213c2c66affSColin Finck             {
3214c2c66affSColin Finck                 for (i = 0; i < len; i++)
3215c2c66affSColin Finck                     PropVariantCopy(&pvarDest->u.capropvar.pElems[i], &pvarSrc->u.capropvar.pElems[i]);
3216c2c66affSColin Finck             }
3217c2c66affSColin Finck             else if (pvarSrc->vt == (VT_VECTOR | VT_CF))
3218c2c66affSColin Finck             {
3219c2c66affSColin Finck                 FIXME("Copy clipformats\n");
3220c2c66affSColin Finck             }
3221c2c66affSColin Finck             else if (pvarSrc->vt == (VT_VECTOR | VT_BSTR))
3222c2c66affSColin Finck             {
3223c2c66affSColin Finck                 for (i = 0; i < len; i++)
3224c2c66affSColin Finck                     pvarDest->u.cabstr.pElems[i] = PropSysAllocString(pvarSrc->u.cabstr.pElems[i]);
3225c2c66affSColin Finck             }
3226c2c66affSColin Finck             else if (pvarSrc->vt == (VT_VECTOR | VT_LPSTR))
3227c2c66affSColin Finck             {
3228c2c66affSColin Finck                 size_t strLen;
3229c2c66affSColin Finck                 for (i = 0; i < len; i++)
3230c2c66affSColin Finck                 {
3231c2c66affSColin Finck                     strLen = lstrlenA(pvarSrc->u.calpstr.pElems[i]) + 1;
3232c2c66affSColin Finck                     pvarDest->u.calpstr.pElems[i] = CoTaskMemAlloc(strLen);
3233c2c66affSColin Finck                     memcpy(pvarDest->u.calpstr.pElems[i],
3234c2c66affSColin Finck                      pvarSrc->u.calpstr.pElems[i], strLen);
3235c2c66affSColin Finck                 }
3236c2c66affSColin Finck             }
3237c2c66affSColin Finck             else if (pvarSrc->vt == (VT_VECTOR | VT_LPWSTR))
3238c2c66affSColin Finck             {
3239c2c66affSColin Finck                 size_t strLen;
3240c2c66affSColin Finck                 for (i = 0; i < len; i++)
3241c2c66affSColin Finck                 {
3242c2c66affSColin Finck                     strLen = (lstrlenW(pvarSrc->u.calpwstr.pElems[i]) + 1) *
3243c2c66affSColin Finck                      sizeof(WCHAR);
3244c2c66affSColin Finck                     pvarDest->u.calpstr.pElems[i] = CoTaskMemAlloc(strLen);
3245c2c66affSColin Finck                     memcpy(pvarDest->u.calpstr.pElems[i],
3246c2c66affSColin Finck                      pvarSrc->u.calpstr.pElems[i], strLen);
3247c2c66affSColin Finck                 }
3248c2c66affSColin Finck             }
3249c2c66affSColin Finck             else
3250c2c66affSColin Finck                 CopyMemory(pvarDest->u.capropvar.pElems, pvarSrc->u.capropvar.pElems, len * elemSize);
3251c2c66affSColin Finck         }
3252*0f5d91b7SAmine Khaldi         else if (pvarSrc->vt & VT_ARRAY)
3253*0f5d91b7SAmine Khaldi         {
3254*0f5d91b7SAmine Khaldi             pvarDest->u.uhVal.QuadPart = 0;
3255*0f5d91b7SAmine Khaldi             return SafeArrayCopy(pvarSrc->u.parray, &pvarDest->u.parray);
3256*0f5d91b7SAmine Khaldi         }
3257c2c66affSColin Finck         else
3258c2c66affSColin Finck             WARN("Invalid/unsupported type %d\n", pvarSrc->vt);
3259c2c66affSColin Finck     }
3260c2c66affSColin Finck 
3261c2c66affSColin Finck     return S_OK;
3262c2c66affSColin Finck }
3263c2c66affSColin Finck 
3264c2c66affSColin Finck /***********************************************************************
3265c2c66affSColin Finck  *           FreePropVariantArray			    [OLE32.@]
3266c2c66affSColin Finck  */
FreePropVariantArray(ULONG cVariants,PROPVARIANT * rgvars)3267c2c66affSColin Finck HRESULT WINAPI FreePropVariantArray(ULONG cVariants, /* [in] */
3268c2c66affSColin Finck                                     PROPVARIANT *rgvars)    /* [in/out] */
3269c2c66affSColin Finck {
3270c2c66affSColin Finck     ULONG i;
3271c2c66affSColin Finck 
3272c2c66affSColin Finck     TRACE("(%u, %p)\n", cVariants, rgvars);
3273c2c66affSColin Finck 
3274c2c66affSColin Finck     if (!rgvars)
3275c2c66affSColin Finck         return E_INVALIDARG;
3276c2c66affSColin Finck 
3277c2c66affSColin Finck     for(i = 0; i < cVariants; i++)
3278c2c66affSColin Finck         PropVariantClear(&rgvars[i]);
3279c2c66affSColin Finck 
3280c2c66affSColin Finck     return S_OK;
3281c2c66affSColin Finck }
3282c2c66affSColin Finck 
3283c2c66affSColin Finck /******************************************************************************
3284c2c66affSColin Finck  * DllDebugObjectRPCHook (OLE32.@)
3285c2c66affSColin Finck  * turns on and off internal debugging,  pointer is only used on macintosh
3286c2c66affSColin Finck  */
3287c2c66affSColin Finck 
DllDebugObjectRPCHook(BOOL b,void * dummy)3288c2c66affSColin Finck BOOL WINAPI DllDebugObjectRPCHook(BOOL b, void *dummy)
3289c2c66affSColin Finck {
3290c2c66affSColin Finck   FIXME("stub\n");
3291c2c66affSColin Finck   return TRUE;
3292c2c66affSColin Finck }
3293