ddraw: Set dwMaxVertexCount to 2048.
[wine.git] / dlls / ole32 / ole2.c
blobf4672b704ee24448ad74b5fa6fabe9d20135a099
1 /*
2 * OLE2 library
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1999 Francis Beaudet
6 * Copyright 1999 Noel Borthwick
7 * Copyright 1999, 2000 Marcus Meissner
8 * Copyright 1999-2000 Abey George
9 * Copyright 2005 Juan Lang
10 * Copyright 2011 Adam Martinson for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include <assert.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
33 #define COBJMACROS
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winerror.h"
37 #include "wingdi.h"
38 #include "winuser.h"
39 #include "winnls.h"
40 #include "winreg.h"
41 #include "ole2.h"
42 #include "ole2ver.h"
44 #include "compobj_private.h"
45 #include "olestd.h"
46 #include "wine/list.h"
48 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(ole);
51 WINE_DECLARE_DEBUG_CHANNEL(accel);
53 /******************************************************************************
54 * These are static/global variables and internal data structures that the
55 * OLE module uses to maintain its state.
57 typedef struct tagTrackerWindowInfo
59 IDataObject* dataObject;
60 IDropSource* dropSource;
61 DWORD dwOKEffect;
62 DWORD* pdwEffect;
63 BOOL trackingDone;
64 BOOL inTrackCall;
65 HRESULT returnValue;
67 BOOL escPressed;
68 HWND curTargetHWND; /* window the mouse is hovering over */
69 IDropTarget* curDragTarget;
70 POINTL curMousePos; /* current position of the mouse in screen coordinates */
71 DWORD dwKeyState; /* current state of the shift and ctrl keys and the mouse buttons */
72 } TrackerWindowInfo;
74 typedef struct tagOleMenuDescriptor /* OleMenuDescriptor */
76 HWND hwndFrame; /* The containers frame window */
77 HWND hwndActiveObject; /* The active objects window */
78 OLEMENUGROUPWIDTHS mgw; /* OLE menu group widths for the shared menu */
79 HMENU hmenuCombined; /* The combined menu */
80 BOOL bIsServerItem; /* True if the currently open popup belongs to the server */
81 } OleMenuDescriptor;
83 typedef struct tagOleMenuHookItem /* OleMenu hook item in per thread hook list */
85 DWORD tid; /* Thread Id */
86 HANDLE hHeap; /* Heap this is allocated from */
87 HHOOK GetMsg_hHook; /* message hook for WH_GETMESSAGE */
88 HHOOK CallWndProc_hHook; /* message hook for WH_CALLWNDPROC */
89 struct tagOleMenuHookItem *next;
90 } OleMenuHookItem;
92 static OleMenuHookItem *hook_list;
95 * This is the lock count on the OLE library. It is controlled by the
96 * OLEInitialize/OLEUninitialize methods.
98 static LONG OLE_moduleLockCount = 0;
101 * Name of our registered window class.
103 static const WCHAR OLEDD_DRAGTRACKERCLASS[] = L"WineDragDropTracker32";
106 * Name of menu descriptor property.
108 static const WCHAR prop_olemenuW[] = L"PROP_OLEMenuDescriptor";
110 /* property to store IDropTarget pointer */
111 static const WCHAR prop_oledroptarget[] = L"OleDropTargetInterface";
113 /* property to store Marshalled IDropTarget pointer */
114 static const WCHAR prop_marshalleddroptarget[] = L"WineMarshalledDropTarget";
116 /******************************************************************************
117 * These are the prototypes of miscellaneous utility methods
119 static void OLEUTL_ReadRegistryDWORDValue(HKEY regKey, DWORD* pdwValue);
121 /******************************************************************************
122 * These are the prototypes of the utility methods used to manage a shared menu
124 static void OLEMenu_Initialize(void);
125 static void OLEMenu_UnInitialize(void);
126 static BOOL OLEMenu_InstallHooks( DWORD tid );
127 static BOOL OLEMenu_UnInstallHooks( DWORD tid );
128 static OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid );
129 static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos );
130 static BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor );
131 static LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam);
132 static LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam);
134 /******************************************************************************
135 * This is a prototype of the OLE Clipboard uninitialization method (in clipboard.c)
137 extern void clipbrd_uninitialize(void);
139 /******************************************************************************
140 * These are the prototypes of the utility methods used for OLE Drag n Drop
142 static void OLEDD_Initialize(void);
143 static LRESULT WINAPI OLEDD_DragTrackerWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
144 static void OLEDD_TrackStateChange(TrackerWindowInfo* trackerInfo);
145 static DWORD OLEDD_GetButtonState(void);
147 /******************************************************************************
148 * OleBuildVersion [OLE32.@]
150 DWORD WINAPI OleBuildVersion(void)
152 TRACE("Returning version %d, build %d.\n", rmm, rup);
153 return (rmm<<16)+rup;
156 /***********************************************************************
157 * OleInitialize (OLE32.@)
159 HRESULT WINAPI DECLSPEC_HOTPATCH OleInitialize(LPVOID reserved)
161 HRESULT hr;
163 TRACE("(%p)\n", reserved);
166 * The first duty of the OleInitialize is to initialize the COM libraries.
168 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
171 * If the CoInitializeEx call failed, the OLE libraries can't be
172 * initialized.
174 if (FAILED(hr))
175 return hr;
177 if (!COM_CurrentInfo()->ole_inits)
178 hr = S_OK;
179 else
180 hr = S_FALSE;
183 * Then, it has to initialize the OLE specific modules.
184 * This includes:
185 * Clipboard
186 * Drag and Drop
187 * Object linking and Embedding
188 * In-place activation
190 if (!COM_CurrentInfo()->ole_inits++ &&
191 InterlockedIncrement(&OLE_moduleLockCount) == 1)
194 * Initialize the libraries.
196 TRACE("() - Initializing the OLE libraries\n");
199 * Drag and Drop
201 OLEDD_Initialize();
204 * OLE shared menu
206 OLEMenu_Initialize();
209 return hr;
212 /******************************************************************************
213 * OleUninitialize [OLE32.@]
215 void WINAPI DECLSPEC_HOTPATCH OleUninitialize(void)
217 TRACE("()\n");
219 if (COM_CurrentInfo()->ole_inits == 0)
221 WARN("ole_inits is already 0\n");
222 return ;
225 * If we hit the bottom of the lock stack, free the libraries.
227 if (!--COM_CurrentInfo()->ole_inits && !InterlockedDecrement(&OLE_moduleLockCount))
230 * Actually free the libraries.
232 TRACE("() - Freeing the last reference count\n");
235 * OLE Clipboard
237 clipbrd_uninitialize();
240 * OLE shared menu
242 OLEMenu_UnInitialize();
246 * Then, uninitialize the COM libraries.
248 CoUninitialize();
251 /******************************************************************************
252 * OleInitializeWOW [OLE32.@]
254 HRESULT WINAPI OleInitializeWOW(DWORD x, DWORD y)
256 FIXME("%#lx, %#lx stub!\n", x, y);
257 return 0;
260 /*************************************************************
261 * get_droptarget_handle
263 * Retrieve a handle to the map containing the marshalled IDropTarget.
264 * This handle belongs to the process that called RegisterDragDrop.
265 * See get_droptarget_local_handle().
267 static inline HANDLE get_droptarget_handle(HWND hwnd)
269 return GetPropW(hwnd, prop_marshalleddroptarget);
272 /*************************************************************
273 * is_droptarget
275 * Is the window a droptarget.
277 static inline BOOL is_droptarget(HWND hwnd)
279 return get_droptarget_handle(hwnd) != 0;
282 /*************************************************************
283 * get_droptarget_local_handle
285 * Retrieve a handle to the map containing the marshalled IDropTarget.
286 * The handle should be closed when finished with.
288 static HANDLE get_droptarget_local_handle(HWND hwnd)
290 HANDLE handle, local_handle = 0;
292 handle = get_droptarget_handle(hwnd);
294 if(handle)
296 DWORD pid;
297 HANDLE process;
299 GetWindowThreadProcessId(hwnd, &pid);
300 process = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid);
301 if(process)
303 DuplicateHandle(process, handle, GetCurrentProcess(), &local_handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
304 CloseHandle(process);
307 return local_handle;
310 /***********************************************************************
311 * create_map_from_stream
313 * Helper for RegisterDragDrop. Creates a file mapping object
314 * with the contents of the provided stream. The stream must
315 * be a global memory backed stream.
317 static HRESULT create_map_from_stream(IStream *stream, HANDLE *map)
319 HGLOBAL hmem;
320 DWORD size;
321 HRESULT hr;
322 void *data;
324 hr = GetHGlobalFromStream(stream, &hmem);
325 if(FAILED(hr)) return hr;
327 size = GlobalSize(hmem);
328 *map = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, NULL);
329 if(!*map) return E_OUTOFMEMORY;
331 data = MapViewOfFile(*map, FILE_MAP_WRITE, 0, 0, size);
332 memcpy(data, GlobalLock(hmem), size);
333 GlobalUnlock(hmem);
334 UnmapViewOfFile(data);
335 return S_OK;
338 /***********************************************************************
339 * create_stream_from_map
341 * Creates a stream from the provided map.
343 static HRESULT create_stream_from_map(HANDLE map, IStream **stream)
345 HRESULT hr = E_OUTOFMEMORY;
346 HGLOBAL hmem;
347 void *data;
348 MEMORY_BASIC_INFORMATION info;
350 data = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
351 if(!data) return hr;
353 VirtualQuery(data, &info, sizeof(info));
354 TRACE("size %d\n", (int)info.RegionSize);
356 hmem = GlobalAlloc(GMEM_MOVEABLE, info.RegionSize);
357 if(hmem)
359 memcpy(GlobalLock(hmem), data, info.RegionSize);
360 GlobalUnlock(hmem);
361 hr = CreateStreamOnHGlobal(hmem, TRUE, stream);
363 UnmapViewOfFile(data);
364 return hr;
367 /* This is to work around apps which break COM rules by not implementing
368 * IDropTarget::QueryInterface(). Windows doesn't expose this because it
369 * doesn't call CoMarshallInterface() in RegisterDragDrop().
370 * The wrapper is only used internally, and only exists for the life of
371 * the marshal. We don't want to hold a ref on the app provided target
372 * as some apps destroy this prior to CoUninitialize without calling
373 * RevokeDragDrop. The only (long-term) ref is held by the window prop. */
374 typedef struct {
375 IDropTarget IDropTarget_iface;
376 HWND hwnd;
377 LONG refs;
378 } DropTargetWrapper;
380 static inline DropTargetWrapper* impl_from_IDropTarget(IDropTarget* iface)
382 return CONTAINING_RECORD(iface, DropTargetWrapper, IDropTarget_iface);
385 static HRESULT WINAPI DropTargetWrapper_QueryInterface(IDropTarget* iface,
386 REFIID riid,
387 void** ppvObject)
389 DropTargetWrapper* This = impl_from_IDropTarget(iface);
390 if (IsEqualIID(riid, &IID_IUnknown) ||
391 IsEqualIID(riid, &IID_IDropTarget))
393 IDropTarget_AddRef(&This->IDropTarget_iface);
394 *ppvObject = &This->IDropTarget_iface;
395 return S_OK;
397 *ppvObject = NULL;
398 return E_NOINTERFACE;
401 static ULONG WINAPI DropTargetWrapper_AddRef(IDropTarget* iface)
403 DropTargetWrapper* This = impl_from_IDropTarget(iface);
404 return InterlockedIncrement(&This->refs);
407 static ULONG WINAPI DropTargetWrapper_Release(IDropTarget* iface)
409 DropTargetWrapper* This = impl_from_IDropTarget(iface);
410 ULONG refs = InterlockedDecrement(&This->refs);
411 if (!refs) HeapFree(GetProcessHeap(), 0, This);
412 return refs;
415 static inline HRESULT get_target_from_wrapper( IDropTarget *wrapper, IDropTarget **target )
417 DropTargetWrapper* This = impl_from_IDropTarget( wrapper );
418 *target = GetPropW( This->hwnd, prop_oledroptarget );
419 if (!*target) return DRAGDROP_E_NOTREGISTERED;
420 IDropTarget_AddRef( *target );
421 return S_OK;
424 static HRESULT WINAPI DropTargetWrapper_DragEnter(IDropTarget* iface,
425 IDataObject* pDataObj,
426 DWORD grfKeyState,
427 POINTL pt,
428 DWORD* pdwEffect)
430 IDropTarget *target;
431 HRESULT r = get_target_from_wrapper( iface, &target );
433 if (SUCCEEDED( r ))
435 r = IDropTarget_DragEnter( target, pDataObj, grfKeyState, pt, pdwEffect );
436 IDropTarget_Release( target );
438 return r;
441 static HRESULT WINAPI DropTargetWrapper_DragOver(IDropTarget* iface,
442 DWORD grfKeyState,
443 POINTL pt,
444 DWORD* pdwEffect)
446 IDropTarget *target;
447 HRESULT r = get_target_from_wrapper( iface, &target );
449 if (SUCCEEDED( r ))
451 r = IDropTarget_DragOver( target, grfKeyState, pt, pdwEffect );
452 IDropTarget_Release( target );
454 return r;
457 static HRESULT WINAPI DropTargetWrapper_DragLeave(IDropTarget* iface)
459 IDropTarget *target;
460 HRESULT r = get_target_from_wrapper( iface, &target );
462 if (SUCCEEDED( r ))
464 r = IDropTarget_DragLeave( target );
465 IDropTarget_Release( target );
467 return r;
470 static HRESULT WINAPI DropTargetWrapper_Drop(IDropTarget* iface,
471 IDataObject* pDataObj,
472 DWORD grfKeyState,
473 POINTL pt,
474 DWORD* pdwEffect)
476 IDropTarget *target;
477 HRESULT r = get_target_from_wrapper( iface, &target );
479 if (SUCCEEDED( r ))
481 r = IDropTarget_Drop( target, pDataObj, grfKeyState, pt, pdwEffect );
482 IDropTarget_Release( target );
484 return r;
487 static const IDropTargetVtbl DropTargetWrapperVTbl =
489 DropTargetWrapper_QueryInterface,
490 DropTargetWrapper_AddRef,
491 DropTargetWrapper_Release,
492 DropTargetWrapper_DragEnter,
493 DropTargetWrapper_DragOver,
494 DropTargetWrapper_DragLeave,
495 DropTargetWrapper_Drop
498 static IDropTarget* WrapDropTarget( HWND hwnd )
500 DropTargetWrapper* This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
502 if (This)
504 This->IDropTarget_iface.lpVtbl = &DropTargetWrapperVTbl;
505 This->hwnd = hwnd;
506 This->refs = 1;
508 return &This->IDropTarget_iface;
511 /***********************************************************************
512 * get_droptarget_pointer
514 * Retrieves the marshalled IDropTarget from the window.
516 static IDropTarget* get_droptarget_pointer(HWND hwnd)
518 IDropTarget *droptarget = NULL;
519 HANDLE map;
520 IStream *stream;
522 map = get_droptarget_local_handle(hwnd);
523 if(!map) return NULL;
525 if(SUCCEEDED(create_stream_from_map(map, &stream)))
527 CoUnmarshalInterface(stream, &IID_IDropTarget, (void**)&droptarget);
528 IStream_Release(stream);
530 CloseHandle(map);
531 return droptarget;
534 /***********************************************************************
535 * RegisterDragDrop (OLE32.@)
537 HRESULT WINAPI RegisterDragDrop(HWND hwnd, LPDROPTARGET pDropTarget)
539 DWORD pid = 0;
540 HRESULT hr;
541 IStream *stream;
542 HANDLE map;
543 IDropTarget *wrapper;
545 TRACE("(%p,%p)\n", hwnd, pDropTarget);
547 if (!COM_CurrentApt())
549 ERR("COM not initialized\n");
550 return E_OUTOFMEMORY;
553 if (!pDropTarget)
554 return E_INVALIDARG;
556 if (!IsWindow(hwnd))
558 ERR("invalid hwnd %p\n", hwnd);
559 return DRAGDROP_E_INVALIDHWND;
562 /* block register for other processes windows */
563 GetWindowThreadProcessId(hwnd, &pid);
564 if (pid != GetCurrentProcessId())
566 FIXME("register for another process windows is disabled\n");
567 return DRAGDROP_E_INVALIDHWND;
570 /* check if the window is already registered */
571 if (is_droptarget(hwnd))
572 return DRAGDROP_E_ALREADYREGISTERED;
575 * Marshal the drop target pointer into a shared memory map and
576 * store the map's handle in a Wine specific window prop. We also
577 * store the drop target pointer itself in the
578 * "OleDropTargetInterface" prop for compatibility with Windows.
581 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
582 if(FAILED(hr)) return hr;
584 /* IDropTarget::QueryInterface() shouldn't be called, some (broken) apps depend on this. */
585 wrapper = WrapDropTarget( hwnd );
586 if(!wrapper)
588 IStream_Release(stream);
589 return E_OUTOFMEMORY;
591 hr = CoMarshalInterface(stream, &IID_IDropTarget, (IUnknown*)wrapper, MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
592 IDropTarget_Release(wrapper);
594 if(SUCCEEDED(hr))
596 hr = create_map_from_stream(stream, &map);
597 if(SUCCEEDED(hr))
599 IDropTarget_AddRef(pDropTarget);
600 SetPropW(hwnd, prop_oledroptarget, pDropTarget);
601 SetPropW(hwnd, prop_marshalleddroptarget, map);
603 else
605 LARGE_INTEGER zero;
606 zero.QuadPart = 0;
607 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
608 CoReleaseMarshalData(stream);
611 IStream_Release(stream);
613 return hr;
616 /***********************************************************************
617 * RevokeDragDrop (OLE32.@)
619 HRESULT WINAPI RevokeDragDrop(HWND hwnd)
621 HANDLE map;
622 IStream *stream;
623 IDropTarget *drop_target;
624 HRESULT hr;
626 TRACE("(%p)\n", hwnd);
628 if (!IsWindow(hwnd))
630 ERR("invalid hwnd %p\n", hwnd);
631 return DRAGDROP_E_INVALIDHWND;
634 /* no registration data */
635 if (!(map = get_droptarget_handle(hwnd)))
636 return DRAGDROP_E_NOTREGISTERED;
638 drop_target = GetPropW(hwnd, prop_oledroptarget);
639 if(drop_target) IDropTarget_Release(drop_target);
641 RemovePropW(hwnd, prop_oledroptarget);
642 RemovePropW(hwnd, prop_marshalleddroptarget);
644 hr = create_stream_from_map(map, &stream);
645 if(SUCCEEDED(hr))
647 CoReleaseMarshalData(stream);
648 IStream_Release(stream);
650 CloseHandle(map);
652 return hr;
655 /***********************************************************************
656 * OleRegGetUserType (OLE32.@)
658 HRESULT WINAPI OleRegGetUserType(REFCLSID clsid, DWORD form, LPOLESTR *usertype)
660 DWORD valuetype, valuelen;
661 WCHAR auxkeynameW[16];
662 HKEY usertypekey;
663 HRESULT hres;
664 LONG ret;
666 TRACE("%s, %lu, %p.\n", debugstr_guid(clsid), form, usertype);
668 if (!usertype)
669 return E_INVALIDARG;
671 *usertype = NULL;
673 /* Return immediately if it's not registered. */
674 hres = COM_OpenKeyForCLSID(clsid, NULL, KEY_READ, &usertypekey);
675 if (FAILED(hres))
676 return hres;
678 valuelen = 0;
680 /* Try additional types if requested. If they don't exist fall back to USERCLASSTYPE_FULL. */
681 if (form != USERCLASSTYPE_FULL)
683 HKEY auxkey;
685 swprintf(auxkeynameW, ARRAY_SIZE(auxkeynameW), L"AuxUserType\\%d", form);
686 if (COM_OpenKeyForCLSID(clsid, auxkeynameW, KEY_READ, &auxkey) == S_OK)
688 if (!RegQueryValueExW(auxkey, L"", NULL, &valuetype, NULL, &valuelen) && valuelen)
690 RegCloseKey(usertypekey);
691 usertypekey = auxkey;
693 else
694 RegCloseKey(auxkey);
698 valuelen = 0;
699 if (RegQueryValueExW(usertypekey, L"", NULL, &valuetype, NULL, &valuelen))
701 RegCloseKey(usertypekey);
702 return REGDB_E_READREGDB;
705 *usertype = CoTaskMemAlloc(valuelen);
706 if (!*usertype)
708 RegCloseKey(usertypekey);
709 return E_OUTOFMEMORY;
712 ret = RegQueryValueExW(usertypekey, L"", NULL, &valuetype, (BYTE *)*usertype, &valuelen);
713 RegCloseKey(usertypekey);
714 if (ret != ERROR_SUCCESS)
716 CoTaskMemFree(*usertype);
717 *usertype = NULL;
718 return REGDB_E_READREGDB;
721 return S_OK;
724 /***********************************************************************
725 * DoDragDrop [OLE32.@]
727 HRESULT WINAPI DoDragDrop (
728 IDataObject *pDataObject, /* [in] ptr to the data obj */
729 IDropSource* pDropSource, /* [in] ptr to the source obj */
730 DWORD dwOKEffect, /* [in] effects allowed by the source */
731 DWORD *pdwEffect) /* [out] ptr to effects of the source */
733 TrackerWindowInfo trackerInfo;
734 HWND hwndTrackWindow;
735 MSG msg;
737 TRACE("%p, %p, %#lx, %p.\n", pDataObject, pDropSource, dwOKEffect, pdwEffect);
739 if (!pDataObject || !pDropSource || !pdwEffect)
740 return E_INVALIDARG;
743 * Setup the drag n drop tracking window.
746 trackerInfo.dataObject = pDataObject;
747 trackerInfo.dropSource = pDropSource;
748 trackerInfo.dwOKEffect = dwOKEffect;
749 trackerInfo.pdwEffect = pdwEffect;
750 trackerInfo.trackingDone = FALSE;
751 trackerInfo.inTrackCall = FALSE;
752 trackerInfo.escPressed = FALSE;
753 trackerInfo.curTargetHWND = 0;
754 trackerInfo.curDragTarget = 0;
756 hwndTrackWindow = CreateWindowW(OLEDD_DRAGTRACKERCLASS, L"TrackerWindow",
757 WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT,
758 CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, 0,
759 &trackerInfo);
761 if (hwndTrackWindow)
764 * Capture the mouse input
766 SetCapture(hwndTrackWindow);
768 msg.message = 0;
771 * Pump messages. All mouse input should go to the capture window.
773 while (!trackerInfo.trackingDone && GetMessageW(&msg, 0, 0, 0) )
775 trackerInfo.curMousePos.x = msg.pt.x;
776 trackerInfo.curMousePos.y = msg.pt.y;
777 trackerInfo.dwKeyState = OLEDD_GetButtonState();
779 if ( (msg.message >= WM_KEYFIRST) &&
780 (msg.message <= WM_KEYLAST) )
783 * When keyboard messages are sent to windows on this thread, we
784 * want to ignore notify the drop source that the state changed.
785 * in the case of the Escape key, we also notify the drop source
786 * we give it a special meaning.
788 if ( (msg.message==WM_KEYDOWN) &&
789 (msg.wParam==VK_ESCAPE) )
791 trackerInfo.escPressed = TRUE;
795 * Notify the drop source.
797 OLEDD_TrackStateChange(&trackerInfo);
799 else
802 * Dispatch the messages only when it's not a keyboard message.
804 DispatchMessageW(&msg);
808 /* re-post the quit message to outer message loop */
809 if (msg.message == WM_QUIT)
810 PostQuitMessage(msg.wParam);
812 * Destroy the temporary window.
814 DestroyWindow(hwndTrackWindow);
816 return trackerInfo.returnValue;
819 return E_FAIL;
822 /***********************************************************************
823 * OleQueryLinkFromData [OLE32.@]
825 HRESULT WINAPI OleQueryLinkFromData(
826 IDataObject* pSrcDataObject)
828 FIXME("(%p),stub!\n", pSrcDataObject);
829 return S_FALSE;
832 /***********************************************************************
833 * OleRegGetMiscStatus [OLE32.@]
835 HRESULT WINAPI OleRegGetMiscStatus(
836 REFCLSID clsid,
837 DWORD dwAspect,
838 DWORD* pdwStatus)
840 WCHAR keyName[16];
841 HKEY miscStatusKey;
842 HKEY aspectKey;
843 LONG result;
844 HRESULT hr;
846 TRACE("%s, %ld, %p.\n", debugstr_guid(clsid), dwAspect, pdwStatus);
848 if (!pdwStatus) return E_INVALIDARG;
850 *pdwStatus = 0;
852 if (actctx_get_miscstatus(clsid, dwAspect, pdwStatus)) return S_OK;
854 hr = COM_OpenKeyForCLSID(clsid, L"MiscStatus", KEY_READ, &miscStatusKey);
855 if (FAILED(hr))
856 /* missing key is not a failure */
857 return hr == REGDB_E_KEYMISSING ? S_OK : hr;
859 OLEUTL_ReadRegistryDWORDValue(miscStatusKey, pdwStatus);
862 * Open the key specific to the requested aspect.
864 swprintf(keyName, ARRAY_SIZE(keyName), L"%d", dwAspect);
866 result = open_classes_key(miscStatusKey, keyName, KEY_READ, &aspectKey);
867 if (result == ERROR_SUCCESS)
869 OLEUTL_ReadRegistryDWORDValue(aspectKey, pdwStatus);
870 RegCloseKey(aspectKey);
873 RegCloseKey(miscStatusKey);
874 return S_OK;
877 static HRESULT EnumOLEVERB_Construct(HKEY hkeyVerb, ULONG index, IEnumOLEVERB **ppenum);
879 typedef struct
881 IEnumOLEVERB IEnumOLEVERB_iface;
882 LONG ref;
884 HKEY hkeyVerb;
885 ULONG index;
886 } EnumOLEVERB;
888 static inline EnumOLEVERB *impl_from_IEnumOLEVERB(IEnumOLEVERB *iface)
890 return CONTAINING_RECORD(iface, EnumOLEVERB, IEnumOLEVERB_iface);
893 static HRESULT WINAPI EnumOLEVERB_QueryInterface(
894 IEnumOLEVERB *iface, REFIID riid, void **ppv)
896 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
897 if (IsEqualIID(riid, &IID_IUnknown) ||
898 IsEqualIID(riid, &IID_IEnumOLEVERB))
900 IEnumOLEVERB_AddRef(iface);
901 *ppv = iface;
902 return S_OK;
904 return E_NOINTERFACE;
907 static ULONG WINAPI EnumOLEVERB_AddRef(
908 IEnumOLEVERB *iface)
910 EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);
911 TRACE("()\n");
912 return InterlockedIncrement(&This->ref);
915 static ULONG WINAPI EnumOLEVERB_Release(
916 IEnumOLEVERB *iface)
918 EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);
919 LONG refs = InterlockedDecrement(&This->ref);
920 TRACE("()\n");
921 if (!refs)
923 RegCloseKey(This->hkeyVerb);
924 HeapFree(GetProcessHeap(), 0, This);
926 return refs;
929 static HRESULT WINAPI EnumOLEVERB_Next(
930 IEnumOLEVERB *iface, ULONG celt, LPOLEVERB rgelt,
931 ULONG *pceltFetched)
933 EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);
934 HRESULT hr = S_OK;
936 TRACE("%p, %lu, %p, %p.\n", iface, celt, rgelt, pceltFetched);
938 if (pceltFetched)
939 *pceltFetched = 0;
941 for (; celt; celt--, rgelt++)
943 WCHAR wszSubKey[20];
944 LONG cbData;
945 LPWSTR pwszOLEVERB;
946 LPWSTR pwszMenuFlags;
947 LPWSTR pwszAttribs;
948 LONG res = RegEnumKeyW(This->hkeyVerb, This->index, wszSubKey, ARRAY_SIZE(wszSubKey));
949 if (res == ERROR_NO_MORE_ITEMS)
951 hr = S_FALSE;
952 break;
954 else if (res != ERROR_SUCCESS)
956 ERR("RegEnumKeyW failed with error %ld\n", res);
957 hr = REGDB_E_READREGDB;
958 break;
960 res = RegQueryValueW(This->hkeyVerb, wszSubKey, NULL, &cbData);
961 if (res != ERROR_SUCCESS)
963 ERR("RegQueryValueW failed with error %ld\n", res);
964 hr = REGDB_E_READREGDB;
965 break;
967 pwszOLEVERB = CoTaskMemAlloc(cbData);
968 if (!pwszOLEVERB)
970 hr = E_OUTOFMEMORY;
971 break;
973 res = RegQueryValueW(This->hkeyVerb, wszSubKey, pwszOLEVERB, &cbData);
974 if (res != ERROR_SUCCESS)
976 ERR("RegQueryValueW failed with error %ld\n", res);
977 hr = REGDB_E_READREGDB;
978 CoTaskMemFree(pwszOLEVERB);
979 break;
982 TRACE("verb string: %s\n", debugstr_w(pwszOLEVERB));
983 pwszMenuFlags = wcschr(pwszOLEVERB, ',');
984 if (!pwszMenuFlags)
986 hr = OLEOBJ_E_INVALIDVERB;
987 CoTaskMemFree(pwszOLEVERB);
988 break;
990 /* nul terminate the name string and advance to first character */
991 *pwszMenuFlags = '\0';
992 pwszMenuFlags++;
993 pwszAttribs = wcschr(pwszMenuFlags, ',');
994 if (!pwszAttribs)
996 hr = OLEOBJ_E_INVALIDVERB;
997 CoTaskMemFree(pwszOLEVERB);
998 break;
1000 /* nul terminate the menu string and advance to first character */
1001 *pwszAttribs = '\0';
1002 pwszAttribs++;
1004 /* fill out structure for this verb */
1005 rgelt->lVerb = wcstol(wszSubKey, NULL, 10);
1006 rgelt->lpszVerbName = pwszOLEVERB; /* user should free */
1007 rgelt->fuFlags = wcstol(pwszMenuFlags, NULL, 10);
1008 rgelt->grfAttribs = wcstol(pwszAttribs, NULL, 10);
1010 if (pceltFetched)
1011 (*pceltFetched)++;
1012 This->index++;
1014 return hr;
1017 static HRESULT WINAPI EnumOLEVERB_Skip(
1018 IEnumOLEVERB *iface, ULONG celt)
1020 EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);
1022 TRACE("%p, %lu.\n", iface, celt);
1024 This->index += celt;
1025 return S_OK;
1028 static HRESULT WINAPI EnumOLEVERB_Reset(
1029 IEnumOLEVERB *iface)
1031 EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);
1033 TRACE("()\n");
1035 This->index = 0;
1036 return S_OK;
1039 static HRESULT WINAPI EnumOLEVERB_Clone(
1040 IEnumOLEVERB *iface,
1041 IEnumOLEVERB **ppenum)
1043 EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);
1044 HKEY hkeyVerb;
1045 TRACE("(%p)\n", ppenum);
1046 if (!DuplicateHandle(GetCurrentProcess(), This->hkeyVerb, GetCurrentProcess(), (HANDLE *)&hkeyVerb, 0, FALSE, DUPLICATE_SAME_ACCESS))
1047 return HRESULT_FROM_WIN32(GetLastError());
1048 return EnumOLEVERB_Construct(hkeyVerb, This->index, ppenum);
1051 static const IEnumOLEVERBVtbl EnumOLEVERB_VTable =
1053 EnumOLEVERB_QueryInterface,
1054 EnumOLEVERB_AddRef,
1055 EnumOLEVERB_Release,
1056 EnumOLEVERB_Next,
1057 EnumOLEVERB_Skip,
1058 EnumOLEVERB_Reset,
1059 EnumOLEVERB_Clone
1062 static HRESULT EnumOLEVERB_Construct(HKEY hkeyVerb, ULONG index, IEnumOLEVERB **ppenum)
1064 EnumOLEVERB *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1065 if (!This)
1067 RegCloseKey(hkeyVerb);
1068 return E_OUTOFMEMORY;
1070 This->IEnumOLEVERB_iface.lpVtbl = &EnumOLEVERB_VTable;
1071 This->ref = 1;
1072 This->index = index;
1073 This->hkeyVerb = hkeyVerb;
1074 *ppenum = &This->IEnumOLEVERB_iface;
1075 return S_OK;
1078 /***********************************************************************
1079 * OleRegEnumVerbs [OLE32.@]
1081 * Enumerates verbs associated with a class stored in the registry.
1083 * PARAMS
1084 * clsid [I] Class ID to enumerate the verbs for.
1085 * ppenum [O] Enumerator.
1087 * RETURNS
1088 * S_OK: Success.
1089 * REGDB_E_CLASSNOTREG: The specified class does not have a key in the registry.
1090 * REGDB_E_READREGDB: The class key could not be opened for some other reason.
1091 * OLE_E_REGDB_KEY: The Verb subkey for the class is not present.
1092 * OLEOBJ_E_NOVERBS: The Verb subkey for the class is empty.
1094 HRESULT WINAPI OleRegEnumVerbs (REFCLSID clsid, LPENUMOLEVERB* ppenum)
1096 LONG res;
1097 HKEY hkeyVerb;
1098 DWORD dwSubKeys;
1100 TRACE("(%s, %p)\n", debugstr_guid(clsid), ppenum);
1102 res = COM_OpenKeyForCLSID(clsid, L"Verb", KEY_READ, &hkeyVerb);
1103 if (FAILED(res))
1105 if (res == REGDB_E_CLASSNOTREG)
1106 ERR("CLSID %s not registered\n", debugstr_guid(clsid));
1107 else if (res == REGDB_E_KEYMISSING)
1108 ERR("no Verbs key for class %s\n", debugstr_guid(clsid));
1109 else
1110 ERR("failed to open Verbs key for CLSID %s with error %ld\n",
1111 debugstr_guid(clsid), res);
1112 return res;
1115 res = RegQueryInfoKeyW(hkeyVerb, NULL, NULL, NULL, &dwSubKeys, NULL,
1116 NULL, NULL, NULL, NULL, NULL, NULL);
1117 if (res != ERROR_SUCCESS)
1119 ERR("failed to get subkey count with error %ld\n", GetLastError());
1120 return REGDB_E_READREGDB;
1123 if (!dwSubKeys)
1125 WARN("class %s has no verbs\n", debugstr_guid(clsid));
1126 RegCloseKey(hkeyVerb);
1127 return OLEOBJ_E_NOVERBS;
1130 return EnumOLEVERB_Construct(hkeyVerb, 0, ppenum);
1133 /******************************************************************************
1134 * OleSetContainedObject [OLE32.@]
1136 HRESULT WINAPI OleSetContainedObject(
1137 LPUNKNOWN pUnknown,
1138 BOOL fContained)
1140 IRunnableObject* runnable = NULL;
1141 HRESULT hres;
1143 TRACE("(%p,%x)\n", pUnknown, fContained);
1145 hres = IUnknown_QueryInterface(pUnknown,
1146 &IID_IRunnableObject,
1147 (void**)&runnable);
1149 if (SUCCEEDED(hres))
1151 hres = IRunnableObject_SetContainedObject(runnable, fContained);
1153 IRunnableObject_Release(runnable);
1155 return hres;
1158 return S_OK;
1161 /******************************************************************************
1162 * OleRun [OLE32.@]
1164 * Set the OLE object to the running state.
1166 * PARAMS
1167 * pUnknown [I] OLE object to run.
1169 * RETURNS
1170 * Success: S_OK.
1171 * Failure: Any HRESULT code.
1173 HRESULT WINAPI DECLSPEC_HOTPATCH OleRun(LPUNKNOWN pUnknown)
1175 IRunnableObject *runable;
1176 HRESULT hres;
1178 TRACE("(%p)\n", pUnknown);
1180 hres = IUnknown_QueryInterface(pUnknown, &IID_IRunnableObject, (void**)&runable);
1181 if (FAILED(hres))
1182 return S_OK; /* Appears to return no error. */
1184 hres = IRunnableObject_Run(runable, NULL);
1185 IRunnableObject_Release(runable);
1186 return hres;
1189 /******************************************************************************
1190 * OleLoad [OLE32.@]
1192 HRESULT WINAPI OleLoad(
1193 LPSTORAGE pStg,
1194 REFIID riid,
1195 LPOLECLIENTSITE pClientSite,
1196 LPVOID* ppvObj)
1198 IPersistStorage* persistStorage = NULL;
1199 IUnknown* pUnk;
1200 IOleObject* pOleObject = NULL;
1201 STATSTG storageInfo;
1202 HRESULT hres;
1204 TRACE("(%p, %s, %p, %p)\n", pStg, debugstr_guid(riid), pClientSite, ppvObj);
1206 *ppvObj = NULL;
1209 * TODO, Conversion ... OleDoAutoConvert
1213 * Get the class ID for the object.
1215 hres = IStorage_Stat(pStg, &storageInfo, STATFLAG_NONAME);
1216 if (FAILED(hres))
1217 return hres;
1220 * Now, try and create the handler for the object
1222 hres = CoCreateInstance(&storageInfo.clsid,
1223 NULL,
1224 CLSCTX_INPROC_HANDLER|CLSCTX_INPROC_SERVER,
1225 riid,
1226 (void**)&pUnk);
1229 * If that fails, as it will most times, load the default
1230 * OLE handler.
1232 if (FAILED(hres))
1234 hres = OleCreateDefaultHandler(&storageInfo.clsid,
1235 NULL,
1236 riid,
1237 (void**)&pUnk);
1241 * If we couldn't find a handler... this is bad. Abort the whole thing.
1243 if (FAILED(hres))
1244 return hres;
1246 if (pClientSite)
1248 hres = IUnknown_QueryInterface(pUnk, &IID_IOleObject, (void **)&pOleObject);
1249 if (SUCCEEDED(hres))
1251 DWORD dwStatus;
1252 hres = IOleObject_GetMiscStatus(pOleObject, DVASPECT_CONTENT, &dwStatus);
1257 * Initialize the object with its IPersistStorage interface.
1259 hres = IUnknown_QueryInterface(pUnk, &IID_IPersistStorage, (void**)&persistStorage);
1260 if (SUCCEEDED(hres))
1262 hres = IPersistStorage_Load(persistStorage, pStg);
1264 IPersistStorage_Release(persistStorage);
1265 persistStorage = NULL;
1268 if (SUCCEEDED(hres) && pClientSite)
1270 * Inform the new object of its client site.
1272 hres = IOleObject_SetClientSite(pOleObject, pClientSite);
1275 * Cleanup interfaces used internally
1277 if (pOleObject)
1278 IOleObject_Release(pOleObject);
1280 if (SUCCEEDED(hres))
1282 IOleLink *pOleLink;
1283 HRESULT hres1;
1284 hres1 = IUnknown_QueryInterface(pUnk, &IID_IOleLink, (void **)&pOleLink);
1285 if (SUCCEEDED(hres1))
1287 FIXME("handle OLE link\n");
1288 IOleLink_Release(pOleLink);
1292 if (FAILED(hres))
1294 IUnknown_Release(pUnk);
1295 pUnk = NULL;
1298 *ppvObj = pUnk;
1300 return hres;
1303 /***********************************************************************
1304 * OleSave [OLE32.@]
1306 HRESULT WINAPI OleSave(
1307 LPPERSISTSTORAGE pPS,
1308 LPSTORAGE pStg,
1309 BOOL fSameAsLoad)
1311 HRESULT hres;
1312 CLSID objectClass;
1314 TRACE("(%p,%p,%x)\n", pPS, pStg, fSameAsLoad);
1317 * First, we transfer the class ID (if available)
1319 hres = IPersistStorage_GetClassID(pPS, &objectClass);
1321 if (SUCCEEDED(hres))
1323 WriteClassStg(pStg, &objectClass);
1327 * Then, we ask the object to save itself to the
1328 * storage. If it is successful, we commit the storage.
1330 hres = IPersistStorage_Save(pPS, pStg, fSameAsLoad);
1332 if (SUCCEEDED(hres))
1334 IStorage_Commit(pStg,
1335 STGC_DEFAULT);
1338 return hres;
1342 /******************************************************************************
1343 * OleLockRunning [OLE32.@]
1345 HRESULT WINAPI OleLockRunning(LPUNKNOWN pUnknown, BOOL fLock, BOOL fLastUnlockCloses)
1347 IRunnableObject* runnable = NULL;
1348 HRESULT hres;
1350 TRACE("(%p,%x,%x)\n", pUnknown, fLock, fLastUnlockCloses);
1352 hres = IUnknown_QueryInterface(pUnknown,
1353 &IID_IRunnableObject,
1354 (void**)&runnable);
1356 if (SUCCEEDED(hres))
1358 hres = IRunnableObject_LockRunning(runnable, fLock, fLastUnlockCloses);
1360 IRunnableObject_Release(runnable);
1362 return hres;
1365 return S_OK;
1369 /**************************************************************************
1370 * Internal methods to manage the shared OLE menu in response to the
1371 * OLE***MenuDescriptor API
1374 /***
1375 * OLEMenu_Initialize()
1377 * Initializes the OLEMENU data structures.
1379 static void OLEMenu_Initialize(void)
1383 /***
1384 * OLEMenu_UnInitialize()
1386 * Releases the OLEMENU data structures.
1388 static void OLEMenu_UnInitialize(void)
1392 /*************************************************************************
1393 * OLEMenu_InstallHooks
1394 * Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
1396 * RETURNS: TRUE if message hooks were successfully installed
1397 * FALSE on failure
1399 static BOOL OLEMenu_InstallHooks( DWORD tid )
1401 OleMenuHookItem *pHookItem;
1403 /* Create an entry for the hook table */
1404 if ( !(pHookItem = HeapAlloc(GetProcessHeap(), 0,
1405 sizeof(OleMenuHookItem)) ) )
1406 return FALSE;
1408 pHookItem->tid = tid;
1409 pHookItem->hHeap = GetProcessHeap();
1410 pHookItem->CallWndProc_hHook = NULL;
1412 /* Install a thread scope message hook for WH_GETMESSAGE */
1413 pHookItem->GetMsg_hHook = SetWindowsHookExW( WH_GETMESSAGE, OLEMenu_GetMsgProc,
1414 0, GetCurrentThreadId() );
1415 if ( !pHookItem->GetMsg_hHook )
1416 goto CLEANUP;
1418 /* Install a thread scope message hook for WH_CALLWNDPROC */
1419 pHookItem->CallWndProc_hHook = SetWindowsHookExW( WH_CALLWNDPROC, OLEMenu_CallWndProc,
1420 0, GetCurrentThreadId() );
1421 if ( !pHookItem->CallWndProc_hHook )
1422 goto CLEANUP;
1424 /* Insert the hook table entry */
1425 pHookItem->next = hook_list;
1426 hook_list = pHookItem;
1428 return TRUE;
1430 CLEANUP:
1431 /* Unhook any hooks */
1432 if ( pHookItem->GetMsg_hHook )
1433 UnhookWindowsHookEx( pHookItem->GetMsg_hHook );
1434 if ( pHookItem->CallWndProc_hHook )
1435 UnhookWindowsHookEx( pHookItem->CallWndProc_hHook );
1436 /* Release the hook table entry */
1437 HeapFree(pHookItem->hHeap, 0, pHookItem );
1439 return FALSE;
1442 /*************************************************************************
1443 * OLEMenu_UnInstallHooks
1444 * UnInstall thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
1446 * RETURNS: TRUE if message hooks were successfully installed
1447 * FALSE on failure
1449 static BOOL OLEMenu_UnInstallHooks( DWORD tid )
1451 OleMenuHookItem *pHookItem = NULL;
1452 OleMenuHookItem **ppHook = &hook_list;
1454 while (*ppHook)
1456 if ((*ppHook)->tid == tid)
1458 pHookItem = *ppHook;
1459 *ppHook = pHookItem->next;
1460 break;
1462 ppHook = &(*ppHook)->next;
1464 if (!pHookItem) return FALSE;
1466 /* Uninstall the hooks installed for this thread */
1467 if ( !UnhookWindowsHookEx( pHookItem->GetMsg_hHook ) )
1468 goto CLEANUP;
1469 if ( !UnhookWindowsHookEx( pHookItem->CallWndProc_hHook ) )
1470 goto CLEANUP;
1472 /* Release the hook table entry */
1473 HeapFree(pHookItem->hHeap, 0, pHookItem );
1475 return TRUE;
1477 CLEANUP:
1478 /* Release the hook table entry */
1479 HeapFree(pHookItem->hHeap, 0, pHookItem );
1481 return FALSE;
1484 /*************************************************************************
1485 * OLEMenu_IsHookInstalled
1486 * Tests if OLEMenu hooks have been installed for a thread
1488 * RETURNS: The pointer and index of the hook table entry for the tid
1489 * NULL and -1 for the index if no hooks were installed for this thread
1491 static OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid )
1493 OleMenuHookItem *pHookItem;
1495 /* Do a simple linear search for an entry whose tid matches ours.
1496 * We really need a map but efficiency is not a concern here. */
1497 for (pHookItem = hook_list; pHookItem; pHookItem = pHookItem->next)
1499 if ( tid == pHookItem->tid )
1500 return pHookItem;
1503 return NULL;
1506 /***********************************************************************
1507 * OLEMenu_FindMainMenuIndex
1509 * Used by OLEMenu API to find the top level group a menu item belongs to.
1510 * On success pnPos contains the index of the item in the top level menu group
1512 * RETURNS: TRUE if the ID was found, FALSE on failure
1514 static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos )
1516 INT i, nItems;
1518 nItems = GetMenuItemCount( hMainMenu );
1520 for (i = 0; i < nItems; i++)
1522 HMENU hsubmenu;
1524 /* Is the current item a submenu? */
1525 if ( (hsubmenu = GetSubMenu(hMainMenu, i)) )
1527 /* If the handle is the same we're done */
1528 if ( hsubmenu == hPopupMenu )
1530 if (pnPos)
1531 *pnPos = i;
1532 return TRUE;
1534 /* Recursively search without updating pnPos */
1535 else if ( OLEMenu_FindMainMenuIndex( hsubmenu, hPopupMenu, NULL ) )
1537 if (pnPos)
1538 *pnPos = i;
1539 return TRUE;
1544 return FALSE;
1547 /***********************************************************************
1548 * OLEMenu_SetIsServerMenu
1550 * Checks whether a popup menu belongs to a shared menu group which is
1551 * owned by the server, and sets the menu descriptor state accordingly.
1552 * All menu messages from these groups should be routed to the server.
1554 * RETURNS: TRUE if the popup menu is part of a server owned group
1555 * FALSE if the popup menu is part of a container owned group
1557 static BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor )
1559 UINT nPos = 0, nWidth, i;
1561 pOleMenuDescriptor->bIsServerItem = FALSE;
1563 /* Don't bother searching if the popup is the combined menu itself */
1564 if ( hmenu == pOleMenuDescriptor->hmenuCombined )
1565 return FALSE;
1567 /* Find the menu item index in the shared OLE menu that this item belongs to */
1568 if ( !OLEMenu_FindMainMenuIndex( pOleMenuDescriptor->hmenuCombined, hmenu, &nPos ) )
1569 return FALSE;
1571 /* The group widths array has counts for the number of elements
1572 * in the groups File, Edit, Container, Object, Window, Help.
1573 * The Edit, Object & Help groups belong to the server object
1574 * and the other three belong to the container.
1575 * Loop through the group widths and locate the group we are a member of.
1577 for ( i = 0, nWidth = 0; i < 6; i++ )
1579 nWidth += pOleMenuDescriptor->mgw.width[i];
1580 if ( nPos < nWidth )
1582 /* Odd elements are server menu widths */
1583 pOleMenuDescriptor->bIsServerItem = i%2;
1584 break;
1588 return pOleMenuDescriptor->bIsServerItem;
1591 /*************************************************************************
1592 * OLEMenu_CallWndProc
1593 * Thread scope WH_CALLWNDPROC hook proc filter function (callback)
1594 * This is invoked from a message hook installed in OleSetMenuDescriptor.
1596 static LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam)
1598 LPCWPSTRUCT pMsg;
1599 HOLEMENU hOleMenu = 0;
1600 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1601 OleMenuHookItem *pHookItem = NULL;
1602 WORD fuFlags;
1604 TRACE("%i, %#Ix, %#Ix.\n", code, wParam, lParam );
1606 /* Check if we're being asked to process the message */
1607 if ( HC_ACTION != code )
1608 goto NEXTHOOK;
1610 /* Retrieve the current message being dispatched from lParam */
1611 pMsg = (LPCWPSTRUCT)lParam;
1613 /* Check if the message is destined for a window we are interested in:
1614 * If the window has an OLEMenu property we may need to dispatch
1615 * the menu message to its active objects window instead. */
1617 hOleMenu = GetPropW( pMsg->hwnd, prop_olemenuW );
1618 if ( !hOleMenu )
1619 goto NEXTHOOK;
1621 /* Get the menu descriptor */
1622 pOleMenuDescriptor = GlobalLock( hOleMenu );
1623 if ( !pOleMenuDescriptor ) /* Bad descriptor! */
1624 goto NEXTHOOK;
1626 /* Process menu messages */
1627 switch( pMsg->message )
1629 case WM_INITMENU:
1631 /* Reset the menu descriptor state */
1632 pOleMenuDescriptor->bIsServerItem = FALSE;
1634 /* Send this message to the server as well */
1635 SendMessageW( pOleMenuDescriptor->hwndActiveObject,
1636 pMsg->message, pMsg->wParam, pMsg->lParam );
1637 goto NEXTHOOK;
1640 case WM_INITMENUPOPUP:
1642 /* Save the state for whether this is a server owned menu */
1643 OLEMenu_SetIsServerMenu( (HMENU)pMsg->wParam, pOleMenuDescriptor );
1644 break;
1647 case WM_MENUSELECT:
1649 fuFlags = HIWORD(pMsg->wParam); /* Get flags */
1650 if ( fuFlags & MF_SYSMENU )
1651 goto NEXTHOOK;
1653 /* Save the state for whether this is a server owned popup menu */
1654 else if ( fuFlags & MF_POPUP )
1655 OLEMenu_SetIsServerMenu( (HMENU)pMsg->lParam, pOleMenuDescriptor );
1657 break;
1660 case WM_DRAWITEM:
1662 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) pMsg->lParam;
1663 if ( pMsg->wParam != 0 || lpdis->CtlType != ODT_MENU )
1664 goto NEXTHOOK; /* Not a menu message */
1666 break;
1669 default:
1670 goto NEXTHOOK;
1673 /* If the message was for the server dispatch it accordingly */
1674 if ( pOleMenuDescriptor->bIsServerItem )
1676 SendMessageW( pOleMenuDescriptor->hwndActiveObject,
1677 pMsg->message, pMsg->wParam, pMsg->lParam );
1680 NEXTHOOK:
1681 if ( pOleMenuDescriptor )
1682 GlobalUnlock( hOleMenu );
1684 /* Lookup the hook item for the current thread */
1685 if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) )
1687 /* This should never fail!! */
1688 WARN("could not retrieve hHook for current thread!\n" );
1689 return 0;
1692 /* Pass on the message to the next hooker */
1693 return CallNextHookEx( pHookItem->CallWndProc_hHook, code, wParam, lParam );
1696 /*************************************************************************
1697 * OLEMenu_GetMsgProc
1698 * Thread scope WH_GETMESSAGE hook proc filter function (callback)
1699 * This is invoked from a message hook installed in OleSetMenuDescriptor.
1701 static LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam)
1703 LPMSG pMsg;
1704 HOLEMENU hOleMenu = 0;
1705 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1706 OleMenuHookItem *pHookItem = NULL;
1707 WORD wCode;
1709 TRACE("%i, %#Ix, %#Ix.\n", code, wParam, lParam );
1711 /* Check if we're being asked to process a messages */
1712 if ( HC_ACTION != code )
1713 goto NEXTHOOK;
1715 /* Retrieve the current message being dispatched from lParam */
1716 pMsg = (LPMSG)lParam;
1718 /* Check if the message is destined for a window we are interested in:
1719 * If the window has an OLEMenu property we may need to dispatch
1720 * the menu message to its active objects window instead. */
1722 hOleMenu = GetPropW( pMsg->hwnd, prop_olemenuW );
1723 if ( !hOleMenu )
1724 goto NEXTHOOK;
1726 /* Process menu messages */
1727 switch( pMsg->message )
1729 case WM_COMMAND:
1731 wCode = HIWORD(pMsg->wParam); /* Get notification code */
1732 if ( wCode )
1733 goto NEXTHOOK; /* Not a menu message */
1734 break;
1736 default:
1737 goto NEXTHOOK;
1740 /* Get the menu descriptor */
1741 pOleMenuDescriptor = GlobalLock( hOleMenu );
1742 if ( !pOleMenuDescriptor ) /* Bad descriptor! */
1743 goto NEXTHOOK;
1745 /* If the message was for the server dispatch it accordingly */
1746 if ( pOleMenuDescriptor->bIsServerItem )
1748 /* Change the hWnd in the message to the active objects hWnd.
1749 * The message loop which reads this message will automatically
1750 * dispatch it to the embedded objects window. */
1751 pMsg->hwnd = pOleMenuDescriptor->hwndActiveObject;
1754 NEXTHOOK:
1755 if ( pOleMenuDescriptor )
1756 GlobalUnlock( hOleMenu );
1758 /* Lookup the hook item for the current thread */
1759 if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) )
1761 /* This should never fail!! */
1762 WARN("could not retrieve hHook for current thread!\n" );
1763 return FALSE;
1766 /* Pass on the message to the next hooker */
1767 return CallNextHookEx( pHookItem->GetMsg_hHook, code, wParam, lParam );
1770 /***********************************************************************
1771 * OleCreateMenuDescriptor [OLE32.@]
1772 * Creates an OLE menu descriptor for OLE to use when dispatching
1773 * menu messages and commands.
1775 * PARAMS:
1776 * hmenuCombined - Handle to the objects combined menu
1777 * lpMenuWidths - Pointer to array of 6 LONG's indicating menus per group
1780 HOLEMENU WINAPI OleCreateMenuDescriptor(
1781 HMENU hmenuCombined,
1782 LPOLEMENUGROUPWIDTHS lpMenuWidths)
1784 HOLEMENU hOleMenu;
1785 OleMenuDescriptor *pOleMenuDescriptor;
1786 int i;
1788 if ( !hmenuCombined || !lpMenuWidths )
1789 return 0;
1791 /* Create an OLE menu descriptor */
1792 if ( !(hOleMenu = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
1793 sizeof(OleMenuDescriptor) ) ) )
1794 return 0;
1796 pOleMenuDescriptor = GlobalLock( hOleMenu );
1797 if ( !pOleMenuDescriptor )
1798 return 0;
1800 /* Initialize menu group widths and hmenu */
1801 for ( i = 0; i < 6; i++ )
1802 pOleMenuDescriptor->mgw.width[i] = lpMenuWidths->width[i];
1804 pOleMenuDescriptor->hmenuCombined = hmenuCombined;
1805 pOleMenuDescriptor->bIsServerItem = FALSE;
1806 GlobalUnlock( hOleMenu );
1808 return hOleMenu;
1811 /***********************************************************************
1812 * OleDestroyMenuDescriptor [OLE32.@]
1813 * Destroy the shared menu descriptor
1815 HRESULT WINAPI OleDestroyMenuDescriptor(
1816 HOLEMENU hmenuDescriptor)
1818 if ( hmenuDescriptor )
1819 GlobalFree( hmenuDescriptor );
1820 return S_OK;
1823 /***********************************************************************
1824 * OleSetMenuDescriptor [OLE32.@]
1825 * Installs or removes OLE dispatching code for the containers frame window.
1827 * PARAMS
1828 * hOleMenu Handle to composite menu descriptor
1829 * hwndFrame Handle to containers frame window
1830 * hwndActiveObject Handle to objects in-place activation window
1831 * lpFrame Pointer to IOleInPlaceFrame on containers window
1832 * lpActiveObject Pointer to IOleInPlaceActiveObject on active in-place object
1834 * RETURNS
1835 * S_OK - menu installed correctly
1836 * E_FAIL, E_INVALIDARG, E_UNEXPECTED - failure
1838 * FIXME
1839 * The lpFrame and lpActiveObject parameters are currently ignored
1840 * OLE should install context sensitive help F1 filtering for the app when
1841 * these are non null.
1843 HRESULT WINAPI OleSetMenuDescriptor(
1844 HOLEMENU hOleMenu,
1845 HWND hwndFrame,
1846 HWND hwndActiveObject,
1847 LPOLEINPLACEFRAME lpFrame,
1848 LPOLEINPLACEACTIVEOBJECT lpActiveObject)
1850 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1852 /* Check args */
1853 if ( !hwndFrame || (hOleMenu && !hwndActiveObject) )
1854 return E_INVALIDARG;
1856 if ( lpFrame || lpActiveObject )
1858 FIXME("(%p, %p, %p, %p, %p), Context sensitive help filtering not implemented!\n",
1859 hOleMenu,
1860 hwndFrame,
1861 hwndActiveObject,
1862 lpFrame,
1863 lpActiveObject);
1866 /* Set up a message hook to intercept the containers frame window messages.
1867 * The message filter is responsible for dispatching menu messages from the
1868 * shared menu which are intended for the object.
1871 if ( hOleMenu ) /* Want to install dispatching code */
1873 /* If OLEMenu hooks are already installed for this thread, fail
1874 * Note: This effectively means that OleSetMenuDescriptor cannot
1875 * be called twice in succession on the same frame window
1876 * without first calling it with a null hOleMenu to uninstall
1878 if ( OLEMenu_IsHookInstalled( GetCurrentThreadId() ) )
1879 return E_FAIL;
1881 /* Get the menu descriptor */
1882 pOleMenuDescriptor = GlobalLock( hOleMenu );
1883 if ( !pOleMenuDescriptor )
1884 return E_UNEXPECTED;
1886 /* Update the menu descriptor */
1887 pOleMenuDescriptor->hwndFrame = hwndFrame;
1888 pOleMenuDescriptor->hwndActiveObject = hwndActiveObject;
1890 GlobalUnlock( hOleMenu );
1891 pOleMenuDescriptor = NULL;
1893 /* Add a menu descriptor windows property to the frame window */
1894 SetPropW( hwndFrame, prop_olemenuW, hOleMenu );
1896 /* Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC */
1897 if ( !OLEMenu_InstallHooks( GetCurrentThreadId() ) )
1898 return E_FAIL;
1900 else /* Want to uninstall dispatching code */
1902 /* Uninstall the hooks */
1903 if ( !OLEMenu_UnInstallHooks( GetCurrentThreadId() ) )
1904 return E_FAIL;
1906 /* Remove the menu descriptor property from the frame window */
1907 RemovePropW( hwndFrame, prop_olemenuW );
1910 return S_OK;
1913 /******************************************************************************
1914 * IsAccelerator [OLE32.@]
1915 * Mostly copied from controls/menu.c TranslateAccelerator implementation
1917 BOOL WINAPI IsAccelerator(HACCEL hAccel, int cAccelEntries, LPMSG lpMsg, WORD* lpwCmd)
1919 LPACCEL lpAccelTbl;
1920 int i;
1922 if(!lpMsg) return FALSE;
1923 if (!hAccel)
1925 WARN_(accel)("NULL accel handle\n");
1926 return FALSE;
1928 if((lpMsg->message != WM_KEYDOWN &&
1929 lpMsg->message != WM_SYSKEYDOWN &&
1930 lpMsg->message != WM_SYSCHAR &&
1931 lpMsg->message != WM_CHAR)) return FALSE;
1932 lpAccelTbl = HeapAlloc(GetProcessHeap(), 0, cAccelEntries * sizeof(ACCEL));
1933 if (NULL == lpAccelTbl)
1935 return FALSE;
1937 if (CopyAcceleratorTableW(hAccel, lpAccelTbl, cAccelEntries) != cAccelEntries)
1939 WARN_(accel)("CopyAcceleratorTableW failed\n");
1940 HeapFree(GetProcessHeap(), 0, lpAccelTbl);
1941 return FALSE;
1944 TRACE_(accel)("hAccel=%p, cAccelEntries=%d,"
1945 "msg->hwnd=%p, msg->message=%04x, wParam=%#Ix, lParam=%#Ix\n",
1946 hAccel, cAccelEntries,
1947 lpMsg->hwnd, lpMsg->message, lpMsg->wParam, lpMsg->lParam);
1948 for(i = 0; i < cAccelEntries; i++)
1950 if(lpAccelTbl[i].key != lpMsg->wParam)
1951 continue;
1953 if(lpMsg->message == WM_CHAR)
1955 if(!(lpAccelTbl[i].fVirt & FALT) && !(lpAccelTbl[i].fVirt & FVIRTKEY))
1957 TRACE_(accel)("found accel for WM_CHAR: ('%c')\n", LOWORD(lpMsg->wParam) & 0xff);
1958 goto found;
1961 else
1963 if(lpAccelTbl[i].fVirt & FVIRTKEY)
1965 INT mask = 0;
1966 TRACE_(accel)("found accel for virt_key %Ix (scan %04x)\n",
1967 lpMsg->wParam, HIWORD(lpMsg->lParam) & 0xff);
1968 if(GetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT;
1969 if(GetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL;
1970 if(GetKeyState(VK_MENU) & 0x8000) mask |= FALT;
1971 if(mask == (lpAccelTbl[i].fVirt & (FSHIFT | FCONTROL | FALT))) goto found;
1972 TRACE_(accel)("incorrect SHIFT/CTRL/ALT-state\n");
1974 else
1976 if(!(lpMsg->lParam & 0x01000000)) /* no special_key */
1978 if((lpAccelTbl[i].fVirt & FALT) && (lpMsg->lParam & 0x20000000))
1979 { /* ^^ ALT pressed */
1980 TRACE_(accel)("found accel for Alt-%c\n", LOWORD(lpMsg->wParam) & 0xff);
1981 goto found;
1988 WARN_(accel)("couldn't translate accelerator key\n");
1989 HeapFree(GetProcessHeap(), 0, lpAccelTbl);
1990 return FALSE;
1992 found:
1993 if(lpwCmd) *lpwCmd = lpAccelTbl[i].cmd;
1994 HeapFree(GetProcessHeap(), 0, lpAccelTbl);
1995 return TRUE;
1998 /***********************************************************************
1999 * ReleaseStgMedium [OLE32.@]
2001 void WINAPI ReleaseStgMedium(
2002 STGMEDIUM* pmedium)
2004 if (!pmedium) return;
2006 switch (pmedium->tymed)
2008 case TYMED_HGLOBAL:
2010 if ( (pmedium->pUnkForRelease==0) &&
2011 (pmedium->hGlobal!=0) )
2012 GlobalFree(pmedium->hGlobal);
2013 break;
2015 case TYMED_FILE:
2017 if (pmedium->lpszFileName!=0)
2019 if (pmedium->pUnkForRelease==0)
2021 DeleteFileW(pmedium->lpszFileName);
2024 CoTaskMemFree(pmedium->lpszFileName);
2026 break;
2028 case TYMED_ISTREAM:
2030 if (pmedium->pstm!=0)
2032 IStream_Release(pmedium->pstm);
2034 break;
2036 case TYMED_ISTORAGE:
2038 if (pmedium->pstg!=0)
2040 IStorage_Release(pmedium->pstg);
2042 break;
2044 case TYMED_GDI:
2046 if ( (pmedium->pUnkForRelease==0) &&
2047 (pmedium->hBitmap!=0) )
2048 DeleteObject(pmedium->hBitmap);
2049 break;
2051 case TYMED_MFPICT:
2053 if ( (pmedium->pUnkForRelease==0) &&
2054 (pmedium->hMetaFilePict!=0) )
2056 LPMETAFILEPICT pMP = GlobalLock(pmedium->hMetaFilePict);
2057 DeleteMetaFile(pMP->hMF);
2058 GlobalUnlock(pmedium->hMetaFilePict);
2059 GlobalFree(pmedium->hMetaFilePict);
2061 break;
2063 case TYMED_ENHMF:
2065 if ( (pmedium->pUnkForRelease==0) &&
2066 (pmedium->hEnhMetaFile!=0) )
2068 DeleteEnhMetaFile(pmedium->hEnhMetaFile);
2070 break;
2072 case TYMED_NULL:
2073 default:
2074 break;
2076 pmedium->tymed=TYMED_NULL;
2079 * After cleaning up, the unknown is released
2081 if (pmedium->pUnkForRelease!=0)
2083 IUnknown_Release(pmedium->pUnkForRelease);
2084 pmedium->pUnkForRelease = 0;
2088 /***
2089 * OLEDD_Initialize()
2091 * Initializes the OLE drag and drop data structures.
2093 static void OLEDD_Initialize(void)
2095 WNDCLASSW wndClass;
2097 ZeroMemory (&wndClass, sizeof(WNDCLASSW));
2098 wndClass.style = CS_GLOBALCLASS;
2099 wndClass.lpfnWndProc = OLEDD_DragTrackerWindowProc;
2100 wndClass.cbClsExtra = 0;
2101 wndClass.cbWndExtra = sizeof(TrackerWindowInfo*);
2102 wndClass.hCursor = 0;
2103 wndClass.hbrBackground = 0;
2104 wndClass.lpszClassName = OLEDD_DRAGTRACKERCLASS;
2106 RegisterClassW (&wndClass);
2109 /***
2110 * OLEDD_DragTrackerWindowProc()
2112 * This method is the WindowProcedure of the drag n drop tracking
2113 * window. During a drag n Drop operation, an invisible window is created
2114 * to receive the user input and act upon it. This procedure is in charge
2115 * of this behavior.
2118 #define DRAG_TIMER_ID 1
2120 static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
2121 HWND hwnd,
2122 UINT uMsg,
2123 WPARAM wParam,
2124 LPARAM lParam)
2126 switch (uMsg)
2128 case WM_CREATE:
2130 LPCREATESTRUCTA createStruct = (LPCREATESTRUCTA)lParam;
2132 SetWindowLongPtrW(hwnd, 0, (LONG_PTR)createStruct->lpCreateParams);
2133 SetTimer(hwnd, DRAG_TIMER_ID, 50, NULL);
2135 break;
2137 case WM_TIMER:
2138 case WM_MOUSEMOVE:
2139 case WM_LBUTTONUP:
2140 case WM_MBUTTONUP:
2141 case WM_RBUTTONUP:
2142 case WM_LBUTTONDOWN:
2143 case WM_MBUTTONDOWN:
2144 case WM_RBUTTONDOWN:
2146 TrackerWindowInfo *trackerInfo = (TrackerWindowInfo*)GetWindowLongPtrA(hwnd, 0);
2147 if (trackerInfo->trackingDone) break;
2148 OLEDD_TrackStateChange(trackerInfo);
2149 break;
2151 case WM_DESTROY:
2153 KillTimer(hwnd, DRAG_TIMER_ID);
2154 break;
2159 * This is a window proc after all. Let's call the default.
2161 return DefWindowProcW (hwnd, uMsg, wParam, lParam);
2164 static void drag_enter( TrackerWindowInfo *info, HWND new_target )
2166 HRESULT hr;
2168 info->curTargetHWND = new_target;
2170 while (new_target && !is_droptarget( new_target ))
2171 new_target = GetParent( new_target );
2173 info->curDragTarget = get_droptarget_pointer( new_target );
2175 if (info->curDragTarget)
2177 *info->pdwEffect = info->dwOKEffect;
2178 hr = IDropTarget_DragEnter( info->curDragTarget, info->dataObject,
2179 info->dwKeyState, info->curMousePos,
2180 info->pdwEffect );
2181 *info->pdwEffect &= info->dwOKEffect;
2183 /* failed DragEnter() means invalid target */
2184 if (hr != S_OK)
2186 IDropTarget_Release( info->curDragTarget );
2187 info->curDragTarget = NULL;
2188 info->curTargetHWND = NULL;
2193 static void drag_end( TrackerWindowInfo *info )
2195 HRESULT hr;
2197 info->trackingDone = TRUE;
2198 ReleaseCapture();
2200 if (info->curDragTarget)
2202 if (info->returnValue == DRAGDROP_S_DROP &&
2203 *info->pdwEffect != DROPEFFECT_NONE)
2205 *info->pdwEffect = info->dwOKEffect;
2206 hr = IDropTarget_Drop( info->curDragTarget, info->dataObject, info->dwKeyState,
2207 info->curMousePos, info->pdwEffect );
2208 *info->pdwEffect &= info->dwOKEffect;
2210 if (FAILED( hr ))
2211 info->returnValue = hr;
2213 else
2215 IDropTarget_DragLeave( info->curDragTarget );
2216 *info->pdwEffect = DROPEFFECT_NONE;
2218 IDropTarget_Release( info->curDragTarget );
2219 info->curDragTarget = NULL;
2221 else
2222 *info->pdwEffect = DROPEFFECT_NONE;
2225 static HRESULT give_feedback( TrackerWindowInfo *info )
2227 HRESULT hr;
2228 int res;
2229 HCURSOR cur;
2231 if (info->curDragTarget == NULL)
2232 *info->pdwEffect = DROPEFFECT_NONE;
2234 hr = IDropSource_GiveFeedback( info->dropSource, *info->pdwEffect );
2236 if (hr == DRAGDROP_S_USEDEFAULTCURSORS)
2238 if (*info->pdwEffect & DROPEFFECT_MOVE)
2239 res = CURSOR_MOVE;
2240 else if (*info->pdwEffect & DROPEFFECT_COPY)
2241 res = CURSOR_COPY;
2242 else if (*info->pdwEffect & DROPEFFECT_LINK)
2243 res = CURSOR_LINK;
2244 else
2245 res = CURSOR_NODROP;
2247 cur = LoadCursorW( hProxyDll, MAKEINTRESOURCEW( res ) );
2248 SetCursor( cur );
2251 return hr;
2254 /***
2255 * OLEDD_TrackStateChange()
2257 * This method is invoked while a drag and drop operation is in effect.
2259 * params:
2260 * trackerInfo - Pointer to the structure identifying the
2261 * drag & drop operation that is currently
2262 * active.
2264 static void OLEDD_TrackStateChange(TrackerWindowInfo* trackerInfo)
2266 HWND hwndNewTarget = 0;
2267 POINT pt;
2270 * This method may be called from QueryContinueDrag again,
2271 * (i.e. by running message loop) so avoid recursive call chain.
2273 if (trackerInfo->inTrackCall) return;
2274 trackerInfo->inTrackCall = TRUE;
2277 * Get the handle of the window under the mouse
2279 pt.x = trackerInfo->curMousePos.x;
2280 pt.y = trackerInfo->curMousePos.y;
2281 hwndNewTarget = WindowFromPoint(pt);
2283 trackerInfo->returnValue = IDropSource_QueryContinueDrag(trackerInfo->dropSource,
2284 trackerInfo->escPressed,
2285 trackerInfo->dwKeyState);
2287 if (trackerInfo->curTargetHWND != hwndNewTarget &&
2288 (trackerInfo->returnValue == S_OK ||
2289 trackerInfo->returnValue == DRAGDROP_S_DROP))
2291 if (trackerInfo->curDragTarget)
2293 IDropTarget_DragLeave(trackerInfo->curDragTarget);
2294 IDropTarget_Release(trackerInfo->curDragTarget);
2295 trackerInfo->curDragTarget = NULL;
2296 trackerInfo->curTargetHWND = NULL;
2299 if (hwndNewTarget)
2300 drag_enter( trackerInfo, hwndNewTarget );
2302 give_feedback( trackerInfo );
2306 if (trackerInfo->returnValue == S_OK)
2308 if (trackerInfo->curDragTarget)
2310 *trackerInfo->pdwEffect = trackerInfo->dwOKEffect;
2311 IDropTarget_DragOver(trackerInfo->curDragTarget,
2312 trackerInfo->dwKeyState,
2313 trackerInfo->curMousePos,
2314 trackerInfo->pdwEffect);
2315 *trackerInfo->pdwEffect &= trackerInfo->dwOKEffect;
2317 give_feedback( trackerInfo );
2319 else
2320 drag_end( trackerInfo );
2322 trackerInfo->inTrackCall = FALSE;
2325 /***
2326 * OLEDD_GetButtonState()
2328 * This method will use the current state of the keyboard to build
2329 * a button state mask equivalent to the one passed in the
2330 * WM_MOUSEMOVE wParam.
2332 static DWORD OLEDD_GetButtonState(void)
2334 BYTE keyboardState[256];
2335 DWORD keyMask = 0;
2337 GetKeyboardState(keyboardState);
2339 if ( (keyboardState[VK_SHIFT] & 0x80) !=0)
2340 keyMask |= MK_SHIFT;
2342 if ( (keyboardState[VK_CONTROL] & 0x80) !=0)
2343 keyMask |= MK_CONTROL;
2345 if ( (keyboardState[VK_MENU] & 0x80) !=0)
2346 keyMask |= MK_ALT;
2348 if ( (keyboardState[VK_LBUTTON] & 0x80) !=0)
2349 keyMask |= MK_LBUTTON;
2351 if ( (keyboardState[VK_RBUTTON] & 0x80) !=0)
2352 keyMask |= MK_RBUTTON;
2354 if ( (keyboardState[VK_MBUTTON] & 0x80) !=0)
2355 keyMask |= MK_MBUTTON;
2357 return keyMask;
2360 /***
2361 * OLEDD_GetButtonState()
2363 * This method will read the default value of the registry key in
2364 * parameter and extract a DWORD value from it. The registry key value
2365 * can be in a string key or a DWORD key.
2367 * params:
2368 * regKey - Key to read the default value from
2369 * pdwValue - Pointer to the location where the DWORD
2370 * value is returned. This value is not modified
2371 * if the value is not found.
2374 static void OLEUTL_ReadRegistryDWORDValue(
2375 HKEY regKey,
2376 DWORD* pdwValue)
2378 WCHAR buffer[20];
2379 DWORD cbData = sizeof(buffer);
2380 DWORD dwKeyType;
2381 LONG lres;
2383 lres = RegQueryValueExW(regKey, L"", NULL, &dwKeyType, (BYTE *)buffer, &cbData);
2385 if (lres==ERROR_SUCCESS)
2387 switch (dwKeyType)
2389 case REG_DWORD:
2390 *pdwValue = *(DWORD*)buffer;
2391 break;
2392 case REG_EXPAND_SZ:
2393 case REG_MULTI_SZ:
2394 case REG_SZ:
2395 *pdwValue = wcstoul(buffer, NULL, 10);
2396 break;
2401 /******************************************************************************
2402 * OleDraw (OLE32.@)
2404 * The operation of this function is documented literally in the WinAPI
2405 * documentation to involve a QueryInterface for the IViewObject interface,
2406 * followed by a call to IViewObject::Draw.
2408 HRESULT WINAPI OleDraw(
2409 IUnknown *pUnk,
2410 DWORD dwAspect,
2411 HDC hdcDraw,
2412 LPCRECT rect)
2414 HRESULT hres;
2415 IViewObject *viewobject;
2417 if (!pUnk) return E_INVALIDARG;
2419 hres = IUnknown_QueryInterface(pUnk,
2420 &IID_IViewObject,
2421 (void**)&viewobject);
2422 if (SUCCEEDED(hres))
2424 hres = IViewObject_Draw(viewobject, dwAspect, -1, 0, 0, 0, hdcDraw, (RECTL*)rect, 0, 0, 0);
2425 IViewObject_Release(viewobject);
2426 return hres;
2428 else
2429 return DV_E_NOIVIEWOBJECT;
2432 /***********************************************************************
2433 * OleTranslateAccelerator [OLE32.@]
2435 HRESULT WINAPI OleTranslateAccelerator (LPOLEINPLACEFRAME lpFrame,
2436 LPOLEINPLACEFRAMEINFO lpFrameInfo, LPMSG lpmsg)
2438 WORD wID;
2440 TRACE("(%p,%p,%p)\n", lpFrame, lpFrameInfo, lpmsg);
2442 if (IsAccelerator(lpFrameInfo->haccel,lpFrameInfo->cAccelEntries,lpmsg,&wID))
2443 return IOleInPlaceFrame_TranslateAccelerator(lpFrame,lpmsg,wID);
2445 return S_FALSE;
2448 /******************************************************************************
2449 * OleCreate [OLE32.@]
2452 HRESULT WINAPI OleCreate(
2453 REFCLSID rclsid,
2454 REFIID riid,
2455 DWORD renderopt,
2456 LPFORMATETC pFormatEtc,
2457 LPOLECLIENTSITE pClientSite,
2458 LPSTORAGE pStg,
2459 LPVOID* ppvObj)
2461 HRESULT hres;
2462 IUnknown * pUnk = NULL;
2463 IOleObject *pOleObject = NULL;
2465 TRACE("%s, %s, %ld, %p, %p, %p, %p.\n", debugstr_guid(rclsid),
2466 debugstr_guid(riid), renderopt, pFormatEtc, pClientSite, pStg, ppvObj);
2468 hres = CoCreateInstance(rclsid, 0, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, riid, (LPVOID*)&pUnk);
2470 if (SUCCEEDED(hres))
2471 hres = IStorage_SetClass(pStg, rclsid);
2473 if (pClientSite && SUCCEEDED(hres))
2475 hres = IUnknown_QueryInterface(pUnk, &IID_IOleObject, (LPVOID*)&pOleObject);
2476 if (SUCCEEDED(hres))
2478 DWORD dwStatus;
2479 IOleObject_GetMiscStatus(pOleObject, DVASPECT_CONTENT, &dwStatus);
2483 if (SUCCEEDED(hres))
2485 IPersistStorage * pPS;
2486 if (SUCCEEDED((hres = IUnknown_QueryInterface(pUnk, &IID_IPersistStorage, (LPVOID*)&pPS))))
2488 TRACE("trying to set stg %p\n", pStg);
2489 hres = IPersistStorage_InitNew(pPS, pStg);
2490 TRACE("-- result %#lx\n", hres);
2491 IPersistStorage_Release(pPS);
2495 if (pClientSite && SUCCEEDED(hres))
2497 TRACE("trying to set clientsite %p\n", pClientSite);
2498 hres = IOleObject_SetClientSite(pOleObject, pClientSite);
2499 TRACE("-- result %#lx\n", hres);
2502 if (pOleObject)
2503 IOleObject_Release(pOleObject);
2505 if (((renderopt == OLERENDER_DRAW) || (renderopt == OLERENDER_FORMAT)) &&
2506 SUCCEEDED(hres))
2508 hres = OleRun(pUnk);
2509 if (SUCCEEDED(hres))
2511 IOleCache *pOleCache;
2513 if (SUCCEEDED(IUnknown_QueryInterface(pUnk, &IID_IOleCache, (void **)&pOleCache)))
2515 DWORD dwConnection;
2516 if (renderopt == OLERENDER_DRAW && !pFormatEtc) {
2517 FORMATETC pfe;
2518 pfe.cfFormat = 0;
2519 pfe.ptd = NULL;
2520 pfe.dwAspect = DVASPECT_CONTENT;
2521 pfe.lindex = -1;
2522 pfe.tymed = TYMED_NULL;
2523 hres = IOleCache_Cache(pOleCache, &pfe, ADVF_PRIMEFIRST, &dwConnection);
2525 else
2526 hres = IOleCache_Cache(pOleCache, pFormatEtc, ADVF_PRIMEFIRST, &dwConnection);
2527 IOleCache_Release(pOleCache);
2532 if (FAILED(hres) && pUnk)
2534 IUnknown_Release(pUnk);
2535 pUnk = NULL;
2538 *ppvObj = pUnk;
2540 TRACE("-- %p\n", pUnk);
2541 return hres;
2544 /******************************************************************************
2545 * OleGetAutoConvert [OLE32.@]
2547 HRESULT WINAPI OleGetAutoConvert(REFCLSID clsidOld, LPCLSID pClsidNew)
2549 HKEY hkey = NULL;
2550 WCHAR buf[CHARS_IN_GUID];
2551 LONG len;
2552 HRESULT res = S_OK;
2554 res = COM_OpenKeyForCLSID(clsidOld, L"AutoConvertTo", KEY_READ, &hkey);
2555 if (FAILED(res))
2556 goto done;
2558 len = sizeof(buf);
2559 if (RegQueryValueW(hkey, NULL, buf, &len))
2561 res = REGDB_E_KEYMISSING;
2562 goto done;
2564 res = CLSIDFromString(buf, pClsidNew);
2565 done:
2566 if (hkey) RegCloseKey(hkey);
2567 return res;
2570 /******************************************************************************
2571 * OleSetAutoConvert [OLE32.@]
2573 HRESULT WINAPI OleSetAutoConvert(REFCLSID clsidOld, REFCLSID clsidNew)
2575 HKEY hkey = NULL;
2576 WCHAR szClsidNew[CHARS_IN_GUID];
2577 HRESULT res = S_OK;
2579 TRACE("(%s,%s)\n", debugstr_guid(clsidOld), debugstr_guid(clsidNew));
2581 res = COM_OpenKeyForCLSID(clsidOld, NULL, KEY_READ | KEY_WRITE, &hkey);
2582 if (FAILED(res))
2583 goto done;
2584 StringFromGUID2(clsidNew, szClsidNew, CHARS_IN_GUID);
2585 if (RegSetValueW(hkey, L"AutoConvertTo", REG_SZ, szClsidNew, (lstrlenW(szClsidNew)+1) * sizeof(WCHAR)))
2587 res = REGDB_E_WRITEREGDB;
2588 goto done;
2591 done:
2592 if (hkey) RegCloseKey(hkey);
2593 return res;
2596 /******************************************************************************
2597 * OleDoAutoConvert [OLE32.@]
2599 HRESULT WINAPI OleDoAutoConvert(LPSTORAGE pStg, LPCLSID pClsidNew)
2601 WCHAR *user_type_old, *user_type_new;
2602 CLIPFORMAT cf;
2603 STATSTG stat;
2604 CLSID clsid;
2605 HRESULT hr;
2607 TRACE("(%p, %p)\n", pStg, pClsidNew);
2609 *pClsidNew = CLSID_NULL;
2610 if(!pStg)
2611 return E_INVALIDARG;
2612 hr = IStorage_Stat(pStg, &stat, STATFLAG_NONAME);
2613 if(FAILED(hr))
2614 return hr;
2616 *pClsidNew = stat.clsid;
2617 hr = OleGetAutoConvert(&stat.clsid, &clsid);
2618 if(FAILED(hr))
2619 return hr;
2621 hr = IStorage_SetClass(pStg, &clsid);
2622 if(FAILED(hr))
2623 return hr;
2625 hr = ReadFmtUserTypeStg(pStg, &cf, &user_type_old);
2626 if(FAILED(hr)) {
2627 cf = 0;
2628 user_type_new = NULL;
2631 hr = OleRegGetUserType(&clsid, USERCLASSTYPE_FULL, &user_type_new);
2632 if(FAILED(hr))
2633 user_type_new = NULL;
2635 hr = WriteFmtUserTypeStg(pStg, cf, user_type_new);
2636 CoTaskMemFree(user_type_new);
2637 if(FAILED(hr))
2639 CoTaskMemFree(user_type_old);
2640 IStorage_SetClass(pStg, &stat.clsid);
2641 return hr;
2644 hr = SetConvertStg(pStg, TRUE);
2645 if(FAILED(hr))
2647 WriteFmtUserTypeStg(pStg, cf, user_type_old);
2648 IStorage_SetClass(pStg, &stat.clsid);
2650 else
2651 *pClsidNew = clsid;
2652 CoTaskMemFree(user_type_old);
2653 return hr;
2656 /******************************************************************************
2657 * OleIsRunning [OLE32.@]
2659 BOOL WINAPI OleIsRunning(LPOLEOBJECT object)
2661 IRunnableObject *pRunnable;
2662 HRESULT hr;
2663 BOOL running;
2665 TRACE("(%p)\n", object);
2667 if (!object) return FALSE;
2669 hr = IOleObject_QueryInterface(object, &IID_IRunnableObject, (void **)&pRunnable);
2670 if (FAILED(hr))
2671 return TRUE;
2672 running = IRunnableObject_IsRunning(pRunnable);
2673 IRunnableObject_Release(pRunnable);
2674 return running;
2677 /***********************************************************************
2678 * OleNoteObjectVisible [OLE32.@]
2680 HRESULT WINAPI OleNoteObjectVisible(LPUNKNOWN pUnknown, BOOL bVisible)
2682 TRACE("(%p, %s)\n", pUnknown, bVisible ? "TRUE" : "FALSE");
2683 return CoLockObjectExternal(pUnknown, bVisible, TRUE);
2686 /***********************************************************************
2687 * PropSysAllocString [OLE32.@]
2688 * NOTES
2689 * Forward to oleaut32.
2691 BSTR WINAPI PropSysAllocString(LPCOLESTR str)
2693 return SysAllocString(str);
2696 /***********************************************************************
2697 * PropSysFreeString [OLE32.@]
2698 * NOTES
2699 * Forward to oleaut32.
2701 void WINAPI PropSysFreeString(LPOLESTR str)
2703 SysFreeString(str);
2706 /******************************************************************************
2707 * OleQueryCreateFromData [OLE32.@]
2709 * Checks whether an object can become an embedded object.
2710 * the clipboard or OLE drag and drop.
2711 * Returns : S_OK - Format that supports Embedded object creation are present.
2712 * OLE_E_STATIC - Format that supports static object creation are present.
2713 * S_FALSE - No acceptable format is available.
2716 HRESULT WINAPI OleQueryCreateFromData(IDataObject *data)
2718 IEnumFORMATETC *enum_fmt;
2719 FORMATETC fmt;
2720 BOOL found_static = FALSE;
2721 HRESULT hr;
2723 hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
2725 if(FAILED(hr)) return hr;
2729 hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
2730 if(hr == S_OK)
2732 if(fmt.cfFormat == embedded_object_clipboard_format ||
2733 fmt.cfFormat == embed_source_clipboard_format ||
2734 fmt.cfFormat == filename_clipboard_format)
2736 IEnumFORMATETC_Release(enum_fmt);
2737 return S_OK;
2740 if(fmt.cfFormat == CF_METAFILEPICT ||
2741 fmt.cfFormat == CF_BITMAP ||
2742 fmt.cfFormat == CF_DIB)
2743 found_static = TRUE;
2745 } while (hr == S_OK);
2747 IEnumFORMATETC_Release(enum_fmt);
2749 return found_static ? OLE_S_STATIC : S_FALSE;
2752 static inline void init_fmtetc(FORMATETC *fmt, CLIPFORMAT cf, TYMED tymed)
2754 fmt->cfFormat = cf;
2755 fmt->ptd = NULL;
2756 fmt->dwAspect = DVASPECT_CONTENT;
2757 fmt->lindex = -1;
2758 fmt->tymed = tymed;
2761 /***************************************************************************
2762 * get_storage
2764 * Retrieve an object's storage from a variety of sources.
2766 * FIXME: CF_FILENAME.
2768 static HRESULT get_storage(IDataObject *data, IStorage *stg, UINT *src_cf, BOOL other_fmts)
2770 static const UINT fmt_id[] = { CF_METAFILEPICT, CF_BITMAP, CF_DIB };
2771 UINT i;
2772 HRESULT hr;
2773 FORMATETC fmt;
2774 STGMEDIUM med;
2775 IPersistStorage *persist;
2776 CLSID clsid;
2778 if (src_cf) *src_cf = 0;
2780 /* CF_EMBEDEDOBJECT */
2781 init_fmtetc(&fmt, embedded_object_clipboard_format, TYMED_ISTORAGE);
2782 med.tymed = TYMED_ISTORAGE;
2783 med.pstg = stg;
2784 med.pUnkForRelease = NULL;
2785 hr = IDataObject_GetDataHere(data, &fmt, &med);
2786 if(SUCCEEDED(hr))
2788 if (src_cf) *src_cf = embedded_object_clipboard_format;
2789 return hr;
2792 /* CF_EMBEDSOURCE */
2793 init_fmtetc(&fmt, embed_source_clipboard_format, TYMED_ISTORAGE);
2794 med.tymed = TYMED_ISTORAGE;
2795 med.pstg = stg;
2796 med.pUnkForRelease = NULL;
2797 hr = IDataObject_GetDataHere(data, &fmt, &med);
2798 if(SUCCEEDED(hr))
2800 if (src_cf) *src_cf = embed_source_clipboard_format;
2801 return hr;
2804 if (other_fmts)
2806 for (i = 0; i < ARRAY_SIZE(fmt_id); i++)
2808 init_fmtetc(&fmt, fmt_id[i], TYMED_ISTORAGE);
2809 hr = IDataObject_QueryGetData(data, &fmt);
2810 if (SUCCEEDED(hr))
2812 if (src_cf) *src_cf = fmt_id[i];
2813 return hr;
2818 /* IPersistStorage */
2819 hr = IDataObject_QueryInterface(data, &IID_IPersistStorage, (void**)&persist);
2820 if(FAILED(hr)) return hr;
2822 hr = IPersistStorage_GetClassID(persist, &clsid);
2823 if(FAILED(hr)) goto end;
2825 hr = IStorage_SetClass(stg, &clsid);
2826 if(FAILED(hr)) goto end;
2828 hr = IPersistStorage_Save(persist, stg, FALSE);
2829 if(FAILED(hr)) goto end;
2831 hr = IPersistStorage_SaveCompleted(persist, NULL);
2833 end:
2834 IPersistStorage_Release(persist);
2836 return hr;
2839 /******************************************************************************
2840 * OleCreateFromDataEx [OLE32.@]
2842 * Creates an embedded object from data transfer object retrieved from
2843 * the clipboard or OLE drag and drop.
2845 HRESULT WINAPI OleCreateFromDataEx(IDataObject *data, REFIID iid, DWORD flags,
2846 DWORD renderopt, ULONG num_cache_fmts, DWORD *adv_flags, FORMATETC *cache_fmts,
2847 IAdviseSink *sink, DWORD *conns,
2848 IOleClientSite *client_site, IStorage *stg, void **obj)
2850 HRESULT hr;
2851 UINT src_cf;
2853 FIXME("%p, %s, %#lx, %#lx, %ld, %p, %p, %p, %p, %p, %p, %p: stub\n",
2854 data, debugstr_guid(iid), flags, renderopt, num_cache_fmts, adv_flags, cache_fmts,
2855 sink, conns, client_site, stg, obj);
2857 hr = get_storage(data, stg, &src_cf, TRUE);
2858 if(FAILED(hr)) return hr;
2860 hr = OleLoad(stg, iid, client_site, obj);
2861 if(FAILED(hr)) return hr;
2863 /* FIXME: Init cache */
2865 return hr;
2868 /******************************************************************************
2869 * OleCreateFromData [OLE32.@]
2871 HRESULT WINAPI OleCreateFromData(IDataObject *data, REFIID iid, DWORD renderopt, FORMATETC *fmt,
2872 IOleClientSite *client_site, IStorage *stg, void **obj)
2874 DWORD advf = ADVF_PRIMEFIRST;
2876 return OleCreateFromDataEx(data, iid, 0, renderopt, fmt ? 1 : 0, fmt ? &advf : NULL,
2877 fmt, NULL, NULL, client_site, stg, obj);
2880 /******************************************************************************
2881 * OleCreateLinkFromData [OLE32.@]
2883 HRESULT WINAPI OleCreateLinkFromData(IDataObject *data, REFIID iid, DWORD renderopt, FORMATETC *fmt,
2884 IOleClientSite *client_site, IStorage *stg, void **obj)
2886 FIXME("%p, %s, %#lx, %p, %p, %p, %p: semi-stub\n",
2887 data, debugstr_guid(iid), renderopt, fmt, client_site, stg, obj);
2888 return OleCreateFromData(data, iid, renderopt, fmt, client_site, stg, obj);
2891 /******************************************************************************
2892 * OleCreateStaticFromData [OLE32.@]
2894 HRESULT WINAPI OleCreateStaticFromData(IDataObject *data, REFIID iid, DWORD renderopt, FORMATETC *fmt,
2895 IOleClientSite *client_site, IStorage *stg, void **obj)
2897 HRESULT hr;
2898 CLSID clsid;
2899 IOleObject * ole_object = NULL;
2900 IOleCache2 *ole_cache = NULL;
2901 IPersistStorage *persist = NULL;
2902 DWORD connection;
2903 STGMEDIUM stgmedium;
2904 LPOLESTR ole_typename;
2906 TRACE("%p, %s, %#lx, %p, %p, %p, %p.\n", data, debugstr_guid(iid), renderopt, fmt, client_site, stg, obj);
2908 if (!obj || !stg)
2909 return E_INVALIDARG;
2911 if (renderopt != OLERENDER_FORMAT)
2913 FIXME("semi-stub\n");
2914 return OleCreateFromData(data, iid, renderopt, fmt, client_site, stg, obj);
2917 if (!fmt)
2918 return E_INVALIDARG;
2920 hr = IDataObject_GetData(data, fmt, &stgmedium);
2921 if (FAILED(hr)) return hr;
2923 switch (fmt->cfFormat)
2925 case CF_BITMAP:
2926 case CF_DIB:
2927 clsid = CLSID_Picture_Dib;
2928 break;
2929 case CF_ENHMETAFILE:
2930 clsid = CLSID_Picture_EnhMetafile;
2931 break;
2932 case CF_METAFILEPICT:
2933 clsid = CLSID_Picture_Metafile;
2934 break;
2935 default:
2936 ReleaseStgMedium(&stgmedium);
2937 return DV_E_CLIPFORMAT;
2939 hr = OleCreateDefaultHandler(&clsid, NULL, &IID_IOleObject, (void **)&ole_object);
2940 if (FAILED(hr)) goto end;
2942 if (client_site)
2944 hr = IOleObject_SetClientSite(ole_object, client_site);
2945 if (FAILED(hr)) goto end;
2948 hr = IOleObject_QueryInterface(ole_object, &IID_IOleCache2, (void **)&ole_cache);
2949 if (FAILED(hr)) goto end;
2951 hr = IOleObject_QueryInterface(ole_object, &IID_IPersistStorage, (void **)&persist);
2952 if (FAILED(hr)) goto end;
2954 hr = WriteClassStg(stg, &clsid);
2955 if (FAILED(hr)) goto end;
2957 hr = IPersistStorage_InitNew(persist, stg);
2958 if (FAILED(hr)) goto end;
2960 hr = IOleCache2_Cache(ole_cache, fmt, ADVF_PRIMEFIRST, &connection);
2961 if (FAILED(hr)) goto end;
2963 hr = IOleCache2_SetData(ole_cache, fmt, &stgmedium, TRUE);
2964 if (FAILED(hr)) goto end;
2965 stgmedium.tymed = TYMED_NULL;
2967 hr = IOleObject_GetUserType(ole_object, USERCLASSTYPE_FULL, &ole_typename);
2968 if(FAILED(hr))
2969 ole_typename = NULL;
2970 hr = WriteFmtUserTypeStg(stg, fmt->cfFormat, ole_typename);
2971 CoTaskMemFree(ole_typename);
2972 if (FAILED(hr)) goto end;
2974 hr = IPersistStorage_Save(persist, stg, TRUE);
2975 if (FAILED(hr)) goto end;
2977 hr = IPersistStorage_SaveCompleted(persist, NULL);
2978 if (FAILED(hr)) goto end;
2980 hr = IOleObject_QueryInterface(ole_object, iid, obj);
2982 end:
2983 if (stgmedium.tymed == TYMED_NULL)
2984 ReleaseStgMedium(&stgmedium);
2985 if (persist)
2986 IPersistStorage_Release(persist);
2987 if (ole_cache)
2988 IOleCache2_Release(ole_cache);
2989 if (ole_object)
2990 IOleObject_Release(ole_object);
2991 return hr;
2994 /******************************************************************************
2995 * OleCreateFromFileEx [OLE32.@]
2997 HRESULT WINAPI OleCreateFromFileEx(REFCLSID clsid, const OLECHAR *filename, REFIID iid, DWORD flags,
2998 DWORD renderopt, ULONG num_fmts, DWORD *adv_flags, FORMATETC *fmts, IAdviseSink *sink,
2999 DWORD *conns, IOleClientSite *client_site, IStorage *stg, void **obj)
3001 HRESULT hr;
3002 IMoniker *mon;
3003 IDataObject *data;
3004 IUnknown *unk = NULL;
3005 IOleCache *cache = NULL;
3006 ULONG i;
3008 TRACE("cls %s, %s, iid %s, flags %ld, render opts %ld, num fmts %ld, adv flags %p, fmts %p\n", debugstr_guid(clsid),
3009 debugstr_w(filename), debugstr_guid(iid), flags, renderopt, num_fmts, adv_flags, fmts);
3010 TRACE("sink %p, conns %p, client site %p, storage %p, obj %p\n", sink, conns, client_site, stg, obj);
3011 for (i = 0; i < num_fmts; i++)
3012 TRACE("\t%ld: fmt %s adv flags %ld\n", i, debugstr_formatetc(fmts + i), adv_flags[i]);
3014 hr = CreateFileMoniker( filename, &mon );
3015 if (FAILED(hr)) return hr;
3017 hr = BindMoniker( mon, 0, &IID_IDataObject, (void**)&data );
3018 IMoniker_Release( mon );
3019 if (FAILED(hr)) return hr;
3021 hr = get_storage( data, stg, NULL, FALSE );
3022 if (FAILED(hr)) goto end;
3024 hr = OleLoad( stg, &IID_IUnknown, client_site, (void**)&unk );
3025 if (FAILED(hr)) goto end;
3027 if (renderopt == OLERENDER_FORMAT)
3029 hr = IUnknown_QueryInterface( unk, &IID_IOleCache, (void**)&cache );
3030 if (FAILED(hr)) goto end;
3032 for (i = 0; i < num_fmts; i++)
3034 STGMEDIUM med;
3035 DWORD dummy_conn;
3037 memset( &med, 0, sizeof(med) );
3038 hr = IDataObject_GetData( data, fmts + i, &med );
3039 if (FAILED(hr)) goto end;
3040 hr = IOleCache_Cache( cache, fmts + i, adv_flags[i], &dummy_conn );
3041 if (SUCCEEDED(hr))
3042 hr = IOleCache_SetData( cache, fmts + i, &med, TRUE );
3043 if (FAILED(hr))
3045 ReleaseStgMedium( &med );
3046 goto end;
3051 hr = IUnknown_QueryInterface( unk, iid, obj );
3053 end:
3054 if (cache) IOleCache_Release( cache );
3055 if (unk) IUnknown_Release( unk );
3056 IDataObject_Release( data );
3057 return hr;
3060 /******************************************************************************
3061 * OleCreateFromFile [OLE32.@]
3063 HRESULT WINAPI OleCreateFromFile(REFCLSID clsid, const OLECHAR *filename, REFIID iid, DWORD renderopt,
3064 FORMATETC *fmt, IOleClientSite *client_site, IStorage *storage, void **obj)
3066 DWORD advf = ADVF_PRIMEFIRST;
3068 return OleCreateFromFileEx(clsid, filename, iid, 0, renderopt, fmt ? 1 : 0, fmt ? &advf : NULL, fmt,
3069 NULL, NULL, client_site, storage, obj);
3072 /******************************************************************************
3073 * OleDuplicateData [OLE32.@]
3075 HANDLE WINAPI OleDuplicateData(HANDLE hSrc, CLIPFORMAT cfFormat, UINT uiFlags)
3077 HANDLE hDst = NULL;
3079 TRACE("(%p,%x,%x)\n", hSrc, cfFormat, uiFlags);
3081 if (!uiFlags) uiFlags = GMEM_MOVEABLE;
3083 switch (cfFormat)
3085 case CF_ENHMETAFILE:
3086 hDst = CopyEnhMetaFileW(hSrc, NULL);
3087 break;
3088 case CF_METAFILEPICT:
3089 hDst = CopyMetaFileW(hSrc, NULL);
3090 break;
3091 case CF_PALETTE:
3093 LOGPALETTE * logpalette;
3094 UINT nEntries = GetPaletteEntries(hSrc, 0, 0, NULL);
3095 if (!nEntries) return NULL;
3096 logpalette = HeapAlloc(GetProcessHeap(), 0,
3097 FIELD_OFFSET(LOGPALETTE, palPalEntry[nEntries]));
3098 if (!logpalette) return NULL;
3099 if (!GetPaletteEntries(hSrc, 0, nEntries, logpalette->palPalEntry))
3101 HeapFree(GetProcessHeap(), 0, logpalette);
3102 return NULL;
3104 logpalette->palVersion = 0x300;
3105 logpalette->palNumEntries = (WORD)nEntries;
3107 hDst = CreatePalette(logpalette);
3109 HeapFree(GetProcessHeap(), 0, logpalette);
3110 break;
3112 case CF_BITMAP:
3114 LONG size;
3115 BITMAP bm;
3116 if (!GetObjectW(hSrc, sizeof(bm), &bm))
3117 return NULL;
3118 size = GetBitmapBits(hSrc, 0, NULL);
3119 if (!size) return NULL;
3120 bm.bmBits = HeapAlloc(GetProcessHeap(), 0, size);
3121 if (!bm.bmBits) return NULL;
3122 if (GetBitmapBits(hSrc, size, bm.bmBits))
3123 hDst = CreateBitmapIndirect(&bm);
3124 HeapFree(GetProcessHeap(), 0, bm.bmBits);
3125 break;
3127 default:
3129 SIZE_T size = GlobalSize(hSrc);
3130 LPVOID pvSrc = NULL;
3131 LPVOID pvDst = NULL;
3133 /* allocate space for object */
3134 if (!size) return NULL;
3135 hDst = GlobalAlloc(uiFlags, size);
3136 if (!hDst) return NULL;
3138 /* lock pointers */
3139 pvSrc = GlobalLock(hSrc);
3140 if (!pvSrc)
3142 GlobalFree(hDst);
3143 return NULL;
3145 pvDst = GlobalLock(hDst);
3146 if (!pvDst)
3148 GlobalUnlock(hSrc);
3149 GlobalFree(hDst);
3150 return NULL;
3152 /* copy data */
3153 memcpy(pvDst, pvSrc, size);
3155 /* cleanup */
3156 GlobalUnlock(hDst);
3157 GlobalUnlock(hSrc);
3161 TRACE("returning %p\n", hDst);
3162 return hDst;