source: trunk/src/ole32/ole2.c@ 21554

Last change on this file since 21554 was 21554, checked in by dmik, 15 years ago

Fixed broken indentation.

File size: 99.8 KB
Line 
1
2/*
3 * OLE2 library
4 *
5 * Copyright 1995 Martin von Loewis
6 * Copyright 1999 Francis Beaudet
7 * Copyright 1999 Noel Borthwick
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include "config.h"
25
26#include <assert.h>
27#include <stdlib.h>
28#include <stdio.h>
29#include <string.h>
30
31#include "commctrl.h"
32#include "ole2.h"
33#include "ole2ver.h"
34#include "windef.h"
35#include "winbase.h"
36#include "winerror.h"
37#include "winuser.h"
38#include "winreg.h"
39
40#include "wine/obj_clientserver.h"
41#ifdef __WIN32OS2__ /* we've got older headers! */
42#include "wine/obj_propertystorage.h"
43#include "wine/obj_oleaut.h"
44#endif
45#include "wine/winbase16.h"
46#include "wine/wingdi16.h"
47#include "wine/winuser16.h"
48#include "ole32_main.h"
49
50#include "wine/debug.h"
51
52WINE_DEFAULT_DEBUG_CHANNEL(ole);
53WINE_DECLARE_DEBUG_CHANNEL(accel);
54
55/******************************************************************************
56 * These are static/global variables and internal data structures that the
57 * OLE module uses to maintain it's state.
58 */
59typedef struct tagDropTargetNode
60{
61 HWND hwndTarget;
62 IDropTarget* dropTarget;
63#ifdef __WIN32OS2__
64 BOOL fDragEnter;
65 DWORD dwEffect;
66 IDataObject * pDataObject;
67#endif
68 struct tagDropTargetNode* prevDropTarget;
69 struct tagDropTargetNode* nextDropTarget;
70} DropTargetNode;
71
72typedef struct tagTrackerWindowInfo
73{
74 IDataObject* dataObject;
75 IDropSource* dropSource;
76 DWORD dwOKEffect;
77 DWORD* pdwEffect;
78 BOOL trackingDone;
79 HRESULT returnValue;
80
81 BOOL escPressed;
82 HWND curTargetHWND; /* window the mouse is hovering over */
83 HWND curDragTargetHWND; /* might be a ancestor of curTargetHWND */
84 IDropTarget* curDragTarget;
85} TrackerWindowInfo;
86
87typedef struct tagOleMenuDescriptor /* OleMenuDescriptor */
88{
89 HWND hwndFrame; /* The containers frame window */
90 HWND hwndActiveObject; /* The active objects window */
91 OLEMENUGROUPWIDTHS mgw; /* OLE menu group widths for the shared menu */
92 HMENU hmenuCombined; /* The combined menu */
93 BOOL bIsServerItem; /* True if the currently open popup belongs to the server */
94} OleMenuDescriptor;
95
96typedef struct tagOleMenuHookItem /* OleMenu hook item in per thread hook list */
97{
98 DWORD tid; /* Thread Id */
99 HANDLE hHeap; /* Heap this is allocated from */
100 HHOOK GetMsg_hHook; /* message hook for WH_GETMESSAGE */
101 HHOOK CallWndProc_hHook; /* message hook for WH_CALLWNDPROC */
102 struct tagOleMenuHookItem *next;
103} OleMenuHookItem;
104
105static OleMenuHookItem *hook_list;
106
107/*
108 * This is the lock count on the OLE library. It is controlled by the
109 * OLEInitialize/OLEUninitialize methods.
110 */
111static ULONG OLE_moduleLockCount = 0;
112
113/*
114 * Name of our registered window class.
115 */
116static const char OLEDD_DRAGTRACKERCLASS[] = "WineDragDropTracker32";
117
118/*
119 * This is the head of the Drop target container.
120 */
121static DropTargetNode* targetListHead = NULL;
122
123/******************************************************************************
124 * These are the prototypes of miscelaneous utility methods
125 */
126static void OLEUTL_ReadRegistryDWORDValue(HKEY regKey, DWORD* pdwValue);
127
128/******************************************************************************
129 * These are the prototypes of the utility methods used to manage a shared menu
130 */
131#ifdef __WIN32OS2__
132/* Changed () -> (void) as () isn't a prototype good enought for VAC. */
133#endif
134static void OLEMenu_Initialize(void);
135static void OLEMenu_UnInitialize(void);
136BOOL OLEMenu_InstallHooks( DWORD tid );
137BOOL OLEMenu_UnInstallHooks( DWORD tid );
138OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid );
139static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos );
140BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor );
141LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam);
142LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam);
143
144/******************************************************************************
145 * These are the prototypes of the OLE Clipboard initialization methods (in clipboard.c)
146 */
147void OLEClipbrd_UnInitialize(void);
148void OLEClipbrd_Initialize(void);
149
150/******************************************************************************
151 * These are the prototypes of the utility methods used for OLE Drag n Drop
152 */
153static void OLEDD_Initialize(void);
154static void OLEDD_UnInitialize(void);
155static void OLEDD_InsertDropTarget(
156 DropTargetNode* nodeToAdd);
157static DropTargetNode* OLEDD_ExtractDropTarget(
158 HWND hwndOfTarget);
159static DropTargetNode* OLEDD_FindDropTarget(
160 HWND hwndOfTarget);
161static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
162 HWND hwnd,
163 UINT uMsg,
164 WPARAM wParam,
165 LPARAM lParam);
166static void OLEDD_TrackMouseMove(
167 TrackerWindowInfo* trackerInfo,
168 POINT mousePos,
169 DWORD keyState);
170static void OLEDD_TrackStateChange(
171 TrackerWindowInfo* trackerInfo,
172 POINT mousePos,
173 DWORD keyState);
174static DWORD OLEDD_GetButtonState(void);
175
176#ifdef __WIN32OS2__
177static IDropTarget *IDropTarget_Constructor(void);
178
179HWND hwndTracker = 0;
180#endif
181
182/******************************************************************************
183 * OleBuildVersion [OLE2.1]
184 * OleBuildVersion [OLE32.@]
185 */
186DWORD WINAPI OleBuildVersion(void)
187{
188 TRACE("Returning version %d, build %d.\n", rmm, rup);
189 return (rmm<<16)+rup;
190}
191
192/***********************************************************************
193 * OleInitialize (OLE2.2)
194 * OleInitialize (OLE32.@)
195 */
196HRESULT WINAPI OleInitialize(LPVOID reserved)
197{
198 HRESULT hr;
199
200 TRACE("(%p)\n", reserved);
201
202 /*
203 * The first duty of the OleInitialize is to initialize the COM libraries.
204 */
205 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
206
207 /*
208 * If the CoInitializeEx call failed, the OLE libraries can't be
209 * initialized.
210 */
211 if (FAILED(hr))
212 return hr;
213
214 /*
215 * Then, it has to initialize the OLE specific modules.
216 * This includes:
217 * Clipboard
218 * Drag and Drop
219 * Object linking and Embedding
220 * In-place activation
221 */
222 if (OLE_moduleLockCount==0)
223 {
224 /*
225 * Initialize the libraries.
226 */
227 TRACE("() - Initializing the OLE libraries\n");
228
229 /*
230 * OLE Clipboard
231 */
232 OLEClipbrd_Initialize();
233
234 /*
235 * Drag and Drop
236 */
237 OLEDD_Initialize();
238
239 /*
240 * OLE shared menu
241 */
242 OLEMenu_Initialize();
243 }
244
245 /*
246 * Then, we increase the lock count on the OLE module.
247 */
248 OLE_moduleLockCount++;
249
250 return hr;
251}
252
253/******************************************************************************
254 * CoGetCurrentProcess [COMPOBJ.34]
255 * CoGetCurrentProcess [OLE32.@]
256 *
257 * NOTES
258 * Is DWORD really the correct return type for this function?
259 */
260DWORD WINAPI CoGetCurrentProcess(void)
261{
262 return GetCurrentProcessId();
263}
264
265/******************************************************************************
266 * OleUninitialize [OLE2.3]
267 * OleUninitialize [OLE32.@]
268 */
269void WINAPI OleUninitialize(void)
270{
271 TRACE("()\n");
272
273 /*
274 * Decrease the lock count on the OLE module.
275 */
276 OLE_moduleLockCount--;
277
278 /*
279 * If we hit the bottom of the lock stack, free the libraries.
280 */
281 if (OLE_moduleLockCount==0)
282 {
283 /*
284 * Actually free the libraries.
285 */
286 TRACE("() - Freeing the last reference count\n");
287
288 /*
289 * OLE Clipboard
290 */
291 OLEClipbrd_UnInitialize();
292
293 /*
294 * Drag and Drop
295 */
296 OLEDD_UnInitialize();
297
298 /*
299 * OLE shared menu
300 */
301 OLEMenu_UnInitialize();
302 }
303
304 /*
305 * Then, uninitialize the COM libraries.
306 */
307 CoUninitialize();
308}
309
310/******************************************************************************
311 * CoRegisterMessageFilter [OLE32.@]
312 */
313HRESULT WINAPI CoRegisterMessageFilter(
314 LPMESSAGEFILTER lpMessageFilter, /* [in] Pointer to interface */
315 LPMESSAGEFILTER *lplpMessageFilter /* [out] Indirect pointer to prior instance if non-NULL */
316) {
317 FIXME("stub\n");
318 if (lplpMessageFilter) {
319 *lplpMessageFilter = NULL;
320 }
321 return S_OK;
322}
323
324/******************************************************************************
325 * OleInitializeWOW [OLE32.@]
326 */
327HRESULT WINAPI OleInitializeWOW(DWORD x) {
328 FIXME("(0x%08lx),stub!\n",x);
329 return 0;
330}
331
332/***********************************************************************
333 * RegisterDragDrop (OLE32.@)
334 */
335HRESULT WINAPI RegisterDragDrop(
336 HWND hwnd,
337 LPDROPTARGET pDropTarget)
338{
339 DropTargetNode* dropTargetInfo;
340
341 TRACE("(%p,%p)\n", hwnd, pDropTarget);
342
343 /*
344 * First, check if the window is already registered.
345 */
346 dropTargetInfo = OLEDD_FindDropTarget(hwnd);
347
348 if (dropTargetInfo!=NULL)
349 return DRAGDROP_E_ALREADYREGISTERED;
350
351 /*
352 * If it's not there, we can add it. We first create a node for it.
353 */
354 dropTargetInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(DropTargetNode));
355
356 if (dropTargetInfo==NULL)
357 return E_OUTOFMEMORY;
358
359 dropTargetInfo->hwndTarget = hwnd;
360 dropTargetInfo->prevDropTarget = NULL;
361 dropTargetInfo->nextDropTarget = NULL;
362
363#ifdef __WIN32OS2__
364 dropTargetInfo->pDataObject = NULL;
365 dropTargetInfo->fDragEnter = FALSE;
366 dropTargetInfo->dwEffect = 0;
367#endif
368 /*
369 * Don't forget that this is an interface pointer, need to nail it down since
370 * we keep a copy of it.
371 */
372 dropTargetInfo->dropTarget = pDropTarget;
373 IDropTarget_AddRef(dropTargetInfo->dropTarget);
374
375 OLEDD_InsertDropTarget(dropTargetInfo);
376
377 return S_OK;
378}
379
380/***********************************************************************
381 * RevokeDragDrop (OLE32.@)
382 */
383HRESULT WINAPI RevokeDragDrop(
384 HWND hwnd)
385{
386 DropTargetNode* dropTargetInfo;
387
388 TRACE("(%p)\n", hwnd);
389
390 /*
391 * First, check if the window is already registered.
392 */
393 dropTargetInfo = OLEDD_ExtractDropTarget(hwnd);
394
395 /*
396 * If it ain't in there, it's an error.
397 */
398 if (dropTargetInfo==NULL)
399 return DRAGDROP_E_NOTREGISTERED;
400
401#ifdef __WIN32OS2__
402 if(dropTargetInfo->pDataObject) {
403 IDataObject_Release(dropTargetInfo->pDataObject);
404 }
405#endif
406
407 /*
408 * If it's in there, clean-up it's used memory and
409 * references
410 */
411 IDropTarget_Release(dropTargetInfo->dropTarget);
412 HeapFree(GetProcessHeap(), 0, dropTargetInfo);
413
414 return S_OK;
415}
416
417/***********************************************************************
418 * OleRegGetUserType (OLE32.@)
419 *
420 * This implementation of OleRegGetUserType ignores the dwFormOfType
421 * parameter and always returns the full name of the object. This is
422 * not too bad since this is the case for many objects because of the
423 * way they are registered.
424 */
425HRESULT WINAPI OleRegGetUserType(
426 REFCLSID clsid,
427 DWORD dwFormOfType,
428 LPOLESTR* pszUserType)
429{
430 char keyName[60];
431 DWORD dwKeyType;
432 DWORD cbData;
433 HKEY clsidKey;
434 LONG hres;
435 LPBYTE buffer;
436 HRESULT retVal;
437 /*
438 * Initialize the out parameter.
439 */
440 *pszUserType = NULL;
441
442 /*
443 * Build the key name we're looking for
444 */
445 sprintf( keyName, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\",
446 clsid->Data1, clsid->Data2, clsid->Data3,
447 clsid->Data4[0], clsid->Data4[1], clsid->Data4[2], clsid->Data4[3],
448 clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7] );
449
450 TRACE("(%s, %ld, %p)\n", keyName, dwFormOfType, pszUserType);
451
452 /*
453 * Open the class id Key
454 */
455 hres = RegOpenKeyA(HKEY_CLASSES_ROOT,
456 keyName,
457 &clsidKey);
458
459 if (hres != ERROR_SUCCESS)
460 return REGDB_E_CLASSNOTREG;
461
462 /*
463 * Retrieve the size of the name string.
464 */
465 cbData = 0;
466
467 hres = RegQueryValueExA(clsidKey,
468 "",
469 NULL,
470 &dwKeyType,
471 NULL,
472 &cbData);
473
474 if (hres!=ERROR_SUCCESS)
475 {
476 RegCloseKey(clsidKey);
477 return REGDB_E_READREGDB;
478 }
479
480 /*
481 * Allocate a buffer for the registry value.
482 */
483 *pszUserType = CoTaskMemAlloc(cbData*2);
484
485 if (*pszUserType==NULL)
486 {
487 RegCloseKey(clsidKey);
488 return E_OUTOFMEMORY;
489 }
490
491 buffer = HeapAlloc(GetProcessHeap(), 0, cbData);
492
493 if (buffer == NULL)
494 {
495 RegCloseKey(clsidKey);
496 CoTaskMemFree(*pszUserType);
497 *pszUserType=NULL;
498 return E_OUTOFMEMORY;
499 }
500
501 hres = RegQueryValueExA(clsidKey,
502 "",
503 NULL,
504 &dwKeyType,
505 buffer,
506 &cbData);
507
508 RegCloseKey(clsidKey);
509
510
511 if (hres!=ERROR_SUCCESS)
512 {
513 CoTaskMemFree(*pszUserType);
514 *pszUserType=NULL;
515
516 retVal = REGDB_E_READREGDB;
517 }
518 else
519 {
520 MultiByteToWideChar( CP_ACP, 0, buffer, -1, *pszUserType, cbData /*FIXME*/ );
521 retVal = S_OK;
522 }
523 HeapFree(GetProcessHeap(), 0, buffer);
524
525 return retVal;
526}
527
528/***********************************************************************
529 * DoDragDrop [OLE32.@]
530 */
531HRESULT WINAPI DoDragDrop (
532 IDataObject *pDataObject, /* [in] ptr to the data obj */
533 IDropSource* pDropSource, /* [in] ptr to the source obj */
534 DWORD dwOKEffect, /* [in] effects allowed by the source */
535 DWORD *pdwEffect) /* [out] ptr to effects of the source */
536{
537 TrackerWindowInfo trackerInfo;
538 HWND hwndTrackWindow;
539 MSG msg;
540
541 TRACE("(DataObject %p, DropSource %p)\n", pDataObject, pDropSource);
542
543 /*
544 * Setup the drag n drop tracking window.
545 */
546 if (!IsValidInterface((LPUNKNOWN)pDropSource))
547 return E_INVALIDARG;
548
549 trackerInfo.dataObject = pDataObject;
550 trackerInfo.dropSource = pDropSource;
551 trackerInfo.dwOKEffect = dwOKEffect;
552 trackerInfo.pdwEffect = pdwEffect;
553 trackerInfo.trackingDone = FALSE;
554 trackerInfo.escPressed = FALSE;
555 trackerInfo.curDragTargetHWND = 0;
556 trackerInfo.curTargetHWND = 0;
557 trackerInfo.curDragTarget = 0;
558
559#ifdef __WIN32OS2__
560 IDataObject_AddRef(trackerInfo.dataObject);
561#endif
562
563 hwndTrackWindow = CreateWindowA(OLEDD_DRAGTRACKERCLASS,
564 "TrackerWindow",
565 WS_POPUP,
566 CW_USEDEFAULT, CW_USEDEFAULT,
567 CW_USEDEFAULT, CW_USEDEFAULT,
568 0,
569 0,
570 0,
571 (LPVOID)&trackerInfo);
572
573 if (hwndTrackWindow!=0)
574 {
575#ifdef __WIN32OS2__
576 hwndTracker = hwndTrackWindow;
577#endif
578
579 /*
580 * Capture the mouse input
581 */
582 SetCapture(hwndTrackWindow);
583
584 /*
585 * Pump messages. All mouse input should go the the capture window.
586 */
587 while (!trackerInfo.trackingDone && GetMessageA(&msg, 0, 0, 0) )
588 {
589 if ( (msg.message >= WM_KEYFIRST) &&
590 (msg.message <= WM_KEYLAST) )
591 {
592#ifdef __WIN32OS2__
593 dprintf(("dragloop: key msg %x\n", msg.message));
594#endif
595 /*
596 * When keyboard messages are sent to windows on this thread, we
597 * want to ignore notify the drop source that the state changed.
598 * in the case of the Escape key, we also notify the drop source
599 * we give it a special meaning.
600 */
601 if ( (msg.message==WM_KEYDOWN) &&
602 (msg.wParam==VK_ESCAPE) )
603 {
604 trackerInfo.escPressed = TRUE;
605 }
606
607 /*
608 * Notify the drop source.
609 */
610 OLEDD_TrackStateChange(&trackerInfo,
611 msg.pt,
612 OLEDD_GetButtonState());
613 }
614 else
615 {
616#ifdef __WIN32OS2__
617 dprintf(("dragloop: dispmsg %x\n", msg.message));
618#endif
619 /*
620 * Dispatch the messages only when it's not a keyboard message.
621 */
622 DispatchMessageA(&msg);
623 }
624 }
625
626 /*
627 * Destroy the temporary window.
628 */
629 DestroyWindow(hwndTrackWindow);
630
631#ifdef __WIN32OS2__
632 IDataObject_Release(trackerInfo.dataObject);
633#endif
634
635 return trackerInfo.returnValue;
636 }
637
638#ifdef __WIN32OS2__
639 IDataObject_Release(trackerInfo.dataObject);
640#endif
641
642 return E_FAIL;
643}
644
645/***********************************************************************
646 * OleQueryLinkFromData [OLE32.@]
647 */
648HRESULT WINAPI OleQueryLinkFromData(
649 IDataObject* pSrcDataObject)
650{
651 FIXME("(%p),stub!\n", pSrcDataObject);
652 return S_OK;
653}
654
655/***********************************************************************
656 * OleRegGetMiscStatus [OLE32.@]
657 */
658HRESULT WINAPI OleRegGetMiscStatus(
659 REFCLSID clsid,
660 DWORD dwAspect,
661 DWORD* pdwStatus)
662{
663 char keyName[60];
664 HKEY clsidKey;
665 HKEY miscStatusKey;
666 HKEY aspectKey;
667 LONG result;
668
669 /*
670 * Initialize the out parameter.
671 */
672 *pdwStatus = 0;
673
674 /*
675 * Build the key name we're looking for
676 */
677 sprintf( keyName, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\",
678 clsid->Data1, clsid->Data2, clsid->Data3,
679 clsid->Data4[0], clsid->Data4[1], clsid->Data4[2], clsid->Data4[3],
680 clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7] );
681
682 TRACE("(%s, %ld, %p)\n", keyName, dwAspect, pdwStatus);
683
684 /*
685 * Open the class id Key
686 */
687 result = RegOpenKeyA(HKEY_CLASSES_ROOT,
688 keyName,
689 &clsidKey);
690
691 if (result != ERROR_SUCCESS)
692 return REGDB_E_CLASSNOTREG;
693
694 /*
695 * Get the MiscStatus
696 */
697 result = RegOpenKeyA(clsidKey,
698 "MiscStatus",
699 &miscStatusKey);
700
701
702 if (result != ERROR_SUCCESS)
703 {
704 RegCloseKey(clsidKey);
705 return REGDB_E_READREGDB;
706 }
707
708 /*
709 * Read the default value
710 */
711 OLEUTL_ReadRegistryDWORDValue(miscStatusKey, pdwStatus);
712
713 /*
714 * Open the key specific to the requested aspect.
715 */
716 sprintf(keyName, "%ld", dwAspect);
717
718 result = RegOpenKeyA(miscStatusKey,
719 keyName,
720 &aspectKey);
721
722 if (result == ERROR_SUCCESS)
723 {
724 OLEUTL_ReadRegistryDWORDValue(aspectKey, pdwStatus);
725 RegCloseKey(aspectKey);
726 }
727
728 /*
729 * Cleanup
730 */
731 RegCloseKey(miscStatusKey);
732 RegCloseKey(clsidKey);
733
734 return S_OK;
735}
736
737/******************************************************************************
738 * OleSetContainedObject [OLE32.@]
739 */
740HRESULT WINAPI OleSetContainedObject(
741 LPUNKNOWN pUnknown,
742 BOOL fContained)
743{
744 IRunnableObject* runnable = NULL;
745 HRESULT hres;
746
747 TRACE("(%p,%x), stub!\n", pUnknown, fContained);
748
749 hres = IUnknown_QueryInterface(pUnknown,
750 &IID_IRunnableObject,
751 (void**)&runnable);
752
753 if (SUCCEEDED(hres))
754 {
755 hres = IRunnableObject_SetContainedObject(runnable, fContained);
756
757 IRunnableObject_Release(runnable);
758
759 return hres;
760 }
761
762 return S_OK;
763}
764
765/******************************************************************************
766 * OleLoad [OLE32.@]
767 */
768HRESULT WINAPI OleLoad(
769 LPSTORAGE pStg,
770 REFIID riid,
771 LPOLECLIENTSITE pClientSite,
772 LPVOID* ppvObj)
773{
774 IPersistStorage* persistStorage = NULL;
775 IOleObject* oleObject = NULL;
776 STATSTG storageInfo;
777 HRESULT hres;
778
779 TRACE("(%p,%p,%p,%p)\n", pStg, riid, pClientSite, ppvObj);
780
781 /*
782 * TODO, Conversion ... OleDoAutoConvert
783 */
784
785 /*
786 * Get the class ID for the object.
787 */
788 hres = IStorage_Stat(pStg, &storageInfo, STATFLAG_NONAME);
789
790 /*
791 * Now, try and create the handler for the object
792 */
793 hres = CoCreateInstance(&storageInfo.clsid,
794 NULL,
795 CLSCTX_INPROC_HANDLER,
796 &IID_IOleObject,
797 (void**)&oleObject);
798
799 /*
800 * If that fails, as it will most times, load the default
801 * OLE handler.
802 */
803 if (FAILED(hres))
804 {
805 hres = OleCreateDefaultHandler(&storageInfo.clsid,
806 NULL,
807 &IID_IOleObject,
808 (void**)&oleObject);
809 }
810
811 /*
812 * If we couldn't find a handler... this is bad. Abort the whole thing.
813 */
814 if (FAILED(hres))
815 return hres;
816
817 /*
818 * Inform the new object of it's client site.
819 */
820 hres = IOleObject_SetClientSite(oleObject, pClientSite);
821
822 /*
823 * Initialize the object with it's IPersistStorage interface.
824 */
825 hres = IOleObject_QueryInterface(oleObject,
826 &IID_IPersistStorage,
827 (void**)&persistStorage);
828
829 if (SUCCEEDED(hres))
830 {
831 IPersistStorage_Load(persistStorage, pStg);
832
833 IPersistStorage_Release(persistStorage);
834 persistStorage = NULL;
835 }
836
837 /*
838 * Return the requested interface to the caller.
839 */
840 hres = IOleObject_QueryInterface(oleObject, riid, ppvObj);
841
842 /*
843 * Cleanup interfaces used internally
844 */
845 IOleObject_Release(oleObject);
846
847 return hres;
848}
849
850/***********************************************************************
851 * OleSave [OLE32.@]
852 */
853HRESULT WINAPI OleSave(
854 LPPERSISTSTORAGE pPS,
855 LPSTORAGE pStg,
856 BOOL fSameAsLoad)
857{
858 HRESULT hres;
859 CLSID objectClass;
860
861 TRACE("(%p,%p,%x)\n", pPS, pStg, fSameAsLoad);
862
863 /*
864 * First, we transfer the class ID (if available)
865 */
866 hres = IPersistStorage_GetClassID(pPS, &objectClass);
867
868 if (SUCCEEDED(hres))
869 {
870 WriteClassStg(pStg, &objectClass);
871 }
872
873 /*
874 * Then, we ask the object to save itself to the
875 * storage. If it is successful, we commit the storage.
876 */
877 hres = IPersistStorage_Save(pPS, pStg, fSameAsLoad);
878
879 if (SUCCEEDED(hres))
880 {
881 IStorage_Commit(pStg,
882 STGC_DEFAULT);
883 }
884
885 return hres;
886}
887
888
889/******************************************************************************
890 * OleLockRunning [OLE32.@]
891 */
892HRESULT WINAPI OleLockRunning(LPUNKNOWN pUnknown, BOOL fLock, BOOL fLastUnlockCloses)
893{
894 IRunnableObject* runnable = NULL;
895 HRESULT hres;
896
897 TRACE("(%p,%x,%x)\n", pUnknown, fLock, fLastUnlockCloses);
898
899 hres = IUnknown_QueryInterface(pUnknown,
900 &IID_IRunnableObject,
901 (void**)&runnable);
902
903 if (SUCCEEDED(hres))
904 {
905 hres = IRunnableObject_LockRunning(runnable, fLock, fLastUnlockCloses);
906
907 IRunnableObject_Release(runnable);
908
909 return hres;
910 }
911 else
912 return E_INVALIDARG;
913}
914
915
916/**************************************************************************
917 * Internal methods to manage the shared OLE menu in response to the
918 * OLE***MenuDescriptor API
919 */
920
921/***
922 * OLEMenu_Initialize()
923 *
924 * Initializes the OLEMENU data structures.
925 */
926static void OLEMenu_Initialize()
927{
928}
929
930/***
931 * OLEMenu_UnInitialize()
932 *
933 * Releases the OLEMENU data structures.
934 */
935static void OLEMenu_UnInitialize()
936{
937}
938
939/*************************************************************************
940 * OLEMenu_InstallHooks
941 * Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
942 *
943 * RETURNS: TRUE if message hooks were successfully installed
944 * FALSE on failure
945 */
946BOOL OLEMenu_InstallHooks( DWORD tid )
947{
948 OleMenuHookItem *pHookItem = NULL;
949
950 /* Create an entry for the hook table */
951 if ( !(pHookItem = HeapAlloc(GetProcessHeap(), 0,
952 sizeof(OleMenuHookItem)) ) )
953 return FALSE;
954
955 pHookItem->tid = tid;
956 pHookItem->hHeap = GetProcessHeap();
957
958 /* Install a thread scope message hook for WH_GETMESSAGE */
959 pHookItem->GetMsg_hHook = SetWindowsHookExA( WH_GETMESSAGE, OLEMenu_GetMsgProc,
960 0, GetCurrentThreadId() );
961 if ( !pHookItem->GetMsg_hHook )
962 goto CLEANUP;
963
964 /* Install a thread scope message hook for WH_CALLWNDPROC */
965 pHookItem->CallWndProc_hHook = SetWindowsHookExA( WH_CALLWNDPROC, OLEMenu_CallWndProc,
966 0, GetCurrentThreadId() );
967 if ( !pHookItem->CallWndProc_hHook )
968 goto CLEANUP;
969
970 /* Insert the hook table entry */
971 pHookItem->next = hook_list;
972 hook_list = pHookItem;
973
974 return TRUE;
975
976CLEANUP:
977 /* Unhook any hooks */
978 if ( pHookItem->GetMsg_hHook )
979 UnhookWindowsHookEx( pHookItem->GetMsg_hHook );
980 if ( pHookItem->CallWndProc_hHook )
981 UnhookWindowsHookEx( pHookItem->CallWndProc_hHook );
982 /* Release the hook table entry */
983 HeapFree(pHookItem->hHeap, 0, pHookItem );
984
985 return FALSE;
986}
987
988/*************************************************************************
989 * OLEMenu_UnInstallHooks
990 * UnInstall thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
991 *
992 * RETURNS: TRUE if message hooks were successfully installed
993 * FALSE on failure
994 */
995BOOL OLEMenu_UnInstallHooks( DWORD tid )
996{
997 OleMenuHookItem *pHookItem = NULL;
998 OleMenuHookItem **ppHook = &hook_list;
999
1000 while (*ppHook)
1001 {
1002 if ((*ppHook)->tid == tid)
1003 {
1004 pHookItem = *ppHook;
1005 *ppHook = pHookItem->next;
1006 break;
1007 }
1008 ppHook = &(*ppHook)->next;
1009 }
1010 if (!pHookItem) return FALSE;
1011
1012 /* Uninstall the hooks installed for this thread */
1013 if ( !UnhookWindowsHookEx( pHookItem->GetMsg_hHook ) )
1014 goto CLEANUP;
1015 if ( !UnhookWindowsHookEx( pHookItem->CallWndProc_hHook ) )
1016 goto CLEANUP;
1017
1018 /* Release the hook table entry */
1019 HeapFree(pHookItem->hHeap, 0, pHookItem );
1020
1021 return TRUE;
1022
1023CLEANUP:
1024 /* Release the hook table entry */
1025 if (pHookItem)
1026 HeapFree(pHookItem->hHeap, 0, pHookItem );
1027
1028 return FALSE;
1029}
1030
1031/*************************************************************************
1032 * OLEMenu_IsHookInstalled
1033 * Tests if OLEMenu hooks have been installed for a thread
1034 *
1035 * RETURNS: The pointer and index of the hook table entry for the tid
1036 * NULL and -1 for the index if no hooks were installed for this thread
1037 */
1038OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid )
1039{
1040 OleMenuHookItem *pHookItem = NULL;
1041
1042 /* Do a simple linear search for an entry whose tid matches ours.
1043 * We really need a map but efficiency is not a concern here. */
1044 for (pHookItem = hook_list; pHookItem; pHookItem = pHookItem->next)
1045 {
1046 if ( tid == pHookItem->tid )
1047 return pHookItem;
1048 }
1049
1050 return NULL;
1051}
1052
1053/***********************************************************************
1054 * OLEMenu_FindMainMenuIndex
1055 *
1056 * Used by OLEMenu API to find the top level group a menu item belongs to.
1057 * On success pnPos contains the index of the item in the top level menu group
1058 *
1059 * RETURNS: TRUE if the ID was found, FALSE on failure
1060 */
1061static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos )
1062{
1063 UINT i, nItems;
1064
1065 nItems = GetMenuItemCount( hMainMenu );
1066
1067 for (i = 0; i < nItems; i++)
1068 {
1069 HMENU hsubmenu;
1070
1071 /* Is the current item a submenu? */
1072 if ( (hsubmenu = GetSubMenu(hMainMenu, i)) )
1073 {
1074 /* If the handle is the same we're done */
1075 if ( hsubmenu == hPopupMenu )
1076 {
1077 if (pnPos)
1078 *pnPos = i;
1079 return TRUE;
1080 }
1081 /* Recursively search without updating pnPos */
1082 else if ( OLEMenu_FindMainMenuIndex( hsubmenu, hPopupMenu, NULL ) )
1083 {
1084 if (pnPos)
1085 *pnPos = i;
1086 return TRUE;
1087 }
1088 }
1089 }
1090
1091 return FALSE;
1092}
1093
1094/***********************************************************************
1095 * OLEMenu_SetIsServerMenu
1096 *
1097 * Checks whether a popup menu belongs to a shared menu group which is
1098 * owned by the server, and sets the menu descriptor state accordingly.
1099 * All menu messages from these groups should be routed to the server.
1100 *
1101 * RETURNS: TRUE if the popup menu is part of a server owned group
1102 * FASE if the popup menu is part of a container owned group
1103 */
1104BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor )
1105{
1106 UINT nPos = 0, nWidth, i;
1107
1108 pOleMenuDescriptor->bIsServerItem = FALSE;
1109
1110 /* Don't bother searching if the popup is the combined menu itself */
1111 if ( hmenu == pOleMenuDescriptor->hmenuCombined )
1112 return FALSE;
1113
1114 /* Find the menu item index in the shared OLE menu that this item belongs to */
1115 if ( !OLEMenu_FindMainMenuIndex( pOleMenuDescriptor->hmenuCombined, hmenu, &nPos ) )
1116 return FALSE;
1117
1118 /* The group widths array has counts for the number of elements
1119 * in the groups File, Edit, Container, Object, Window, Help.
1120 * The Edit, Object & Help groups belong to the server object
1121 * and the other three belong to the container.
1122 * Loop through the group widths and locate the group we are a member of.
1123 */
1124 for ( i = 0, nWidth = 0; i < 6; i++ )
1125 {
1126 nWidth += pOleMenuDescriptor->mgw.width[i];
1127 if ( nPos < nWidth )
1128 {
1129 /* Odd elements are server menu widths */
1130 pOleMenuDescriptor->bIsServerItem = (i%2) ? TRUE : FALSE;
1131 break;
1132 }
1133 }
1134
1135 return pOleMenuDescriptor->bIsServerItem;
1136}
1137
1138/*************************************************************************
1139 * OLEMenu_CallWndProc
1140 * Thread scope WH_CALLWNDPROC hook proc filter function (callback)
1141 * This is invoked from a message hook installed in OleSetMenuDescriptor.
1142 */
1143LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam)
1144{
1145 LPCWPSTRUCT pMsg = NULL;
1146 HOLEMENU hOleMenu = 0;
1147 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1148 OleMenuHookItem *pHookItem = NULL;
1149 WORD fuFlags;
1150
1151 TRACE("%i, %04x, %08x\n", code, wParam, (unsigned)lParam );
1152
1153 /* Check if we're being asked to process the message */
1154 if ( HC_ACTION != code )
1155 goto NEXTHOOK;
1156
1157 /* Retrieve the current message being dispatched from lParam */
1158 pMsg = (LPCWPSTRUCT)lParam;
1159
1160 /* Check if the message is destined for a window we are interested in:
1161 * If the window has an OLEMenu property we may need to dispatch
1162 * the menu message to its active objects window instead. */
1163
1164 hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" );
1165 if ( !hOleMenu )
1166 goto NEXTHOOK;
1167
1168 /* Get the menu descriptor */
1169 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1170 if ( !pOleMenuDescriptor ) /* Bad descriptor! */
1171 goto NEXTHOOK;
1172
1173 /* Process menu messages */
1174 switch( pMsg->message )
1175 {
1176 case WM_INITMENU:
1177 {
1178 /* Reset the menu descriptor state */
1179 pOleMenuDescriptor->bIsServerItem = FALSE;
1180
1181 /* Send this message to the server as well */
1182 SendMessageA( pOleMenuDescriptor->hwndActiveObject,
1183 pMsg->message, pMsg->wParam, pMsg->lParam );
1184 goto NEXTHOOK;
1185 }
1186
1187 case WM_INITMENUPOPUP:
1188 {
1189 /* Save the state for whether this is a server owned menu */
1190 OLEMenu_SetIsServerMenu( (HMENU)pMsg->wParam, pOleMenuDescriptor );
1191 break;
1192 }
1193
1194 case WM_MENUSELECT:
1195 {
1196 fuFlags = HIWORD(pMsg->wParam); /* Get flags */
1197 if ( fuFlags & MF_SYSMENU )
1198 goto NEXTHOOK;
1199
1200 /* Save the state for whether this is a server owned popup menu */
1201 else if ( fuFlags & MF_POPUP )
1202 OLEMenu_SetIsServerMenu( (HMENU)pMsg->lParam, pOleMenuDescriptor );
1203
1204 break;
1205 }
1206
1207 case WM_DRAWITEM:
1208 {
1209 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) pMsg->lParam;
1210 if ( pMsg->wParam != 0 || lpdis->CtlType != ODT_MENU )
1211 goto NEXTHOOK; /* Not a menu message */
1212
1213 break;
1214 }
1215
1216 default:
1217 goto NEXTHOOK;
1218 }
1219
1220 /* If the message was for the server dispatch it accordingly */
1221 if ( pOleMenuDescriptor->bIsServerItem )
1222 {
1223 SendMessageA( pOleMenuDescriptor->hwndActiveObject,
1224 pMsg->message, pMsg->wParam, pMsg->lParam );
1225 }
1226
1227NEXTHOOK:
1228 if ( pOleMenuDescriptor )
1229 GlobalUnlock( hOleMenu );
1230
1231 /* Lookup the hook item for the current thread */
1232 if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) )
1233 {
1234 /* This should never fail!! */
1235 WARN("could not retrieve hHook for current thread!\n" );
1236 return 0;
1237 }
1238
1239 /* Pass on the message to the next hooker */
1240 return CallNextHookEx( pHookItem->CallWndProc_hHook, code, wParam, lParam );
1241}
1242
1243/*************************************************************************
1244 * OLEMenu_GetMsgProc
1245 * Thread scope WH_GETMESSAGE hook proc filter function (callback)
1246 * This is invoked from a message hook installed in OleSetMenuDescriptor.
1247 */
1248LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam)
1249{
1250 LPMSG pMsg = NULL;
1251 HOLEMENU hOleMenu = 0;
1252 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1253 OleMenuHookItem *pHookItem = NULL;
1254 WORD wCode;
1255
1256 TRACE("%i, %04x, %08x\n", code, wParam, (unsigned)lParam );
1257
1258 /* Check if we're being asked to process a messages */
1259 if ( HC_ACTION != code )
1260 goto NEXTHOOK;
1261
1262 /* Retrieve the current message being dispatched from lParam */
1263 pMsg = (LPMSG)lParam;
1264
1265 /* Check if the message is destined for a window we are interested in:
1266 * If the window has an OLEMenu property we may need to dispatch
1267 * the menu message to its active objects window instead. */
1268
1269 hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" );
1270 if ( !hOleMenu )
1271 goto NEXTHOOK;
1272
1273 /* Process menu messages */
1274 switch( pMsg->message )
1275 {
1276 case WM_COMMAND:
1277 {
1278 wCode = HIWORD(pMsg->wParam); /* Get notification code */
1279 if ( wCode )
1280 goto NEXTHOOK; /* Not a menu message */
1281 break;
1282 }
1283 default:
1284 goto NEXTHOOK;
1285 }
1286
1287 /* Get the menu descriptor */
1288 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1289 if ( !pOleMenuDescriptor ) /* Bad descriptor! */
1290 goto NEXTHOOK;
1291
1292 /* If the message was for the server dispatch it accordingly */
1293 if ( pOleMenuDescriptor->bIsServerItem )
1294 {
1295 /* Change the hWnd in the message to the active objects hWnd.
1296 * The message loop which reads this message will automatically
1297 * dispatch it to the embedded objects window. */
1298 pMsg->hwnd = pOleMenuDescriptor->hwndActiveObject;
1299 }
1300
1301NEXTHOOK:
1302 if ( pOleMenuDescriptor )
1303 GlobalUnlock( hOleMenu );
1304
1305 /* Lookup the hook item for the current thread */
1306 if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) )
1307 {
1308 /* This should never fail!! */
1309 WARN("could not retrieve hHook for current thread!\n" );
1310 return FALSE;
1311 }
1312
1313 /* Pass on the message to the next hooker */
1314 return CallNextHookEx( pHookItem->GetMsg_hHook, code, wParam, lParam );
1315}
1316
1317/***********************************************************************
1318 * OleCreateMenuDescriptor [OLE32.@]
1319 * Creates an OLE menu descriptor for OLE to use when dispatching
1320 * menu messages and commands.
1321 *
1322 * PARAMS:
1323 * hmenuCombined - Handle to the objects combined menu
1324 * lpMenuWidths - Pointer to array of 6 LONG's indicating menus per group
1325 *
1326 */
1327HOLEMENU WINAPI OleCreateMenuDescriptor(
1328 HMENU hmenuCombined,
1329 LPOLEMENUGROUPWIDTHS lpMenuWidths)
1330{
1331 HOLEMENU hOleMenu;
1332 OleMenuDescriptor *pOleMenuDescriptor;
1333 int i;
1334
1335 if ( !hmenuCombined || !lpMenuWidths )
1336 return 0;
1337
1338 /* Create an OLE menu descriptor */
1339 if ( !(hOleMenu = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
1340 sizeof(OleMenuDescriptor) ) ) )
1341 return 0;
1342
1343 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1344 if ( !pOleMenuDescriptor )
1345 return 0;
1346
1347 /* Initialize menu group widths and hmenu */
1348 for ( i = 0; i < 6; i++ )
1349 pOleMenuDescriptor->mgw.width[i] = lpMenuWidths->width[i];
1350
1351 pOleMenuDescriptor->hmenuCombined = hmenuCombined;
1352 pOleMenuDescriptor->bIsServerItem = FALSE;
1353 GlobalUnlock( hOleMenu );
1354
1355 return hOleMenu;
1356}
1357
1358/***********************************************************************
1359 * OleDestroyMenuDescriptor [OLE32.@]
1360 * Destroy the shared menu descriptor
1361 */
1362HRESULT WINAPI OleDestroyMenuDescriptor(
1363 HOLEMENU hmenuDescriptor)
1364{
1365 if ( hmenuDescriptor )
1366 GlobalFree( hmenuDescriptor );
1367 return S_OK;
1368}
1369
1370/***********************************************************************
1371 * OleSetMenuDescriptor [OLE32.@]
1372 * Installs or removes OLE dispatching code for the containers frame window
1373 * FIXME: The lpFrame and lpActiveObject parameters are currently ignored
1374 * OLE should install context sensitive help F1 filtering for the app when
1375 * these are non null.
1376 *
1377 * PARAMS:
1378 * hOleMenu Handle to composite menu descriptor
1379 * hwndFrame Handle to containers frame window
1380 * hwndActiveObject Handle to objects in-place activation window
1381 * lpFrame Pointer to IOleInPlaceFrame on containers window
1382 * lpActiveObject Pointer to IOleInPlaceActiveObject on active in-place object
1383 *
1384 * RETURNS:
1385 * S_OK - menu installed correctly
1386 * E_FAIL, E_INVALIDARG, E_UNEXPECTED - failure
1387 */
1388HRESULT WINAPI OleSetMenuDescriptor(
1389 HOLEMENU hOleMenu,
1390 HWND hwndFrame,
1391 HWND hwndActiveObject,
1392 LPOLEINPLACEFRAME lpFrame,
1393 LPOLEINPLACEACTIVEOBJECT lpActiveObject)
1394{
1395 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1396
1397 /* Check args */
1398 if ( !hwndFrame || (hOleMenu && !hwndActiveObject) )
1399 return E_INVALIDARG;
1400
1401 if ( lpFrame || lpActiveObject )
1402 {
1403 FIXME("(%x, %p, %p, %p, %p), Context sensitive help filtering not implemented!\n",
1404 (unsigned int)hOleMenu,
1405 hwndFrame,
1406 hwndActiveObject,
1407 lpFrame,
1408 lpActiveObject);
1409 }
1410
1411 /* Set up a message hook to intercept the containers frame window messages.
1412 * The message filter is responsible for dispatching menu messages from the
1413 * shared menu which are intended for the object.
1414 */
1415
1416 if ( hOleMenu ) /* Want to install dispatching code */
1417 {
1418 /* If OLEMenu hooks are already installed for this thread, fail
1419 * Note: This effectively means that OleSetMenuDescriptor cannot
1420 * be called twice in succession on the same frame window
1421 * without first calling it with a null hOleMenu to uninstall */
1422 if ( OLEMenu_IsHookInstalled( GetCurrentThreadId() ) )
1423 return E_FAIL;
1424
1425 /* Get the menu descriptor */
1426 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1427 if ( !pOleMenuDescriptor )
1428 return E_UNEXPECTED;
1429
1430 /* Update the menu descriptor */
1431 pOleMenuDescriptor->hwndFrame = hwndFrame;
1432 pOleMenuDescriptor->hwndActiveObject = hwndActiveObject;
1433
1434 GlobalUnlock( hOleMenu );
1435 pOleMenuDescriptor = NULL;
1436
1437 /* Add a menu descriptor windows property to the frame window */
1438 SetPropA( hwndFrame, "PROP_OLEMenuDescriptor", hOleMenu );
1439
1440 /* Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC */
1441 if ( !OLEMenu_InstallHooks( GetCurrentThreadId() ) )
1442 return E_FAIL;
1443 }
1444 else /* Want to uninstall dispatching code */
1445 {
1446 /* Uninstall the hooks */
1447 if ( !OLEMenu_UnInstallHooks( GetCurrentThreadId() ) )
1448 return E_FAIL;
1449
1450 /* Remove the menu descriptor property from the frame window */
1451 RemovePropA( hwndFrame, "PROP_OLEMenuDescriptor" );
1452 }
1453
1454 return S_OK;
1455}
1456
1457/******************************************************************************
1458 * IsAccelerator [OLE32.@]
1459 * Mostly copied from controls/menu.c TranslateAccelerator implementation
1460 */
1461BOOL WINAPI IsAccelerator(HACCEL hAccel, int cAccelEntries, LPMSG lpMsg, WORD* lpwCmd)
1462{
1463 /* YES, Accel16! */
1464 LPACCEL16 lpAccelTbl;
1465 int i;
1466
1467 if(!lpMsg) return FALSE;
1468
1469#ifdef __WIN32OS2__
1470 if (!hAccel || !(lpAccelTbl = (LPACCEL16)LockResource(hAccel)))
1471#else
1472 if (!hAccel || !(lpAccelTbl = (LPACCEL16)LockResource16(hAccel)))
1473#endif
1474 {
1475 WARN_(accel)("invalid accel handle=%p\n", hAccel);
1476 return FALSE;
1477 }
1478 if((lpMsg->message != WM_KEYDOWN &&
1479 lpMsg->message != WM_KEYUP &&
1480 lpMsg->message != WM_SYSKEYDOWN &&
1481 lpMsg->message != WM_SYSKEYUP &&
1482 lpMsg->message != WM_CHAR)) return FALSE;
1483
1484 TRACE_(accel)("hAccel=%p, cAccelEntries=%d,"
1485 "msg->hwnd=%p, msg->message=%04x, wParam=%08x, lParam=%08lx\n",
1486 hAccel, cAccelEntries,
1487 lpMsg->hwnd, lpMsg->message, lpMsg->wParam, lpMsg->lParam);
1488 for(i = 0; i < cAccelEntries; i++)
1489 {
1490 if(lpAccelTbl[i].key != lpMsg->wParam)
1491 continue;
1492
1493 if(lpMsg->message == WM_CHAR)
1494 {
1495 if(!(lpAccelTbl[i].fVirt & FALT) && !(lpAccelTbl[i].fVirt & FVIRTKEY))
1496 {
1497 TRACE_(accel)("found accel for WM_CHAR: ('%c')\n", lpMsg->wParam & 0xff);
1498 goto found;
1499 }
1500 }
1501 else
1502 {
1503 if(lpAccelTbl[i].fVirt & FVIRTKEY)
1504 {
1505 INT mask = 0;
1506 TRACE_(accel)("found accel for virt_key %04x (scan %04x)\n",
1507 lpMsg->wParam, HIWORD(lpMsg->lParam) & 0xff);
1508 if(GetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT;
1509 if(GetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL;
1510 if(GetKeyState(VK_MENU) & 0x8000) mask |= FALT;
1511 if(mask == (lpAccelTbl[i].fVirt & (FSHIFT | FCONTROL | FALT))) goto found;
1512 TRACE_(accel)("incorrect SHIFT/CTRL/ALT-state\n");
1513 }
1514 else
1515 {
1516 if(!(lpMsg->lParam & 0x01000000)) /* no special_key */
1517 {
1518 if((lpAccelTbl[i].fVirt & FALT) && (lpMsg->lParam & 0x20000000))
1519 { /* ^^ ALT pressed */
1520 TRACE_(accel)("found accel for Alt-%c\n", lpMsg->wParam & 0xff);
1521 goto found;
1522 }
1523 }
1524 }
1525 }
1526 }
1527
1528 WARN_(accel)("couldn't translate accelerator key\n");
1529 return FALSE;
1530
1531found:
1532 if(lpwCmd) *lpwCmd = lpAccelTbl[i].cmd;
1533 return TRUE;
1534}
1535
1536/***********************************************************************
1537 * ReleaseStgMedium [OLE32.@]
1538 */
1539void WINAPI ReleaseStgMedium(
1540 STGMEDIUM* pmedium)
1541{
1542 switch (pmedium->tymed)
1543 {
1544 case TYMED_HGLOBAL:
1545 {
1546 if ( (pmedium->pUnkForRelease==0) &&
1547 (pmedium->u.hGlobal!=0) )
1548 GlobalFree(pmedium->u.hGlobal);
1549
1550 pmedium->u.hGlobal = 0;
1551 break;
1552 }
1553 case TYMED_FILE:
1554 {
1555 if (pmedium->u.lpszFileName!=0)
1556 {
1557 if (pmedium->pUnkForRelease==0)
1558 {
1559 DeleteFileW(pmedium->u.lpszFileName);
1560 }
1561
1562 CoTaskMemFree(pmedium->u.lpszFileName);
1563 }
1564
1565 pmedium->u.lpszFileName = 0;
1566 break;
1567 }
1568 case TYMED_ISTREAM:
1569 {
1570 if (pmedium->u.pstm!=0)
1571 {
1572 IStream_Release(pmedium->u.pstm);
1573 }
1574
1575 pmedium->u.pstm = 0;
1576 break;
1577 }
1578 case TYMED_ISTORAGE:
1579 {
1580 if (pmedium->u.pstg!=0)
1581 {
1582 IStorage_Release(pmedium->u.pstg);
1583 }
1584
1585 pmedium->u.pstg = 0;
1586 break;
1587 }
1588 case TYMED_GDI:
1589 {
1590 if ( (pmedium->pUnkForRelease==0) &&
1591 (pmedium->u.hGlobal!=0) )
1592 DeleteObject(pmedium->u.hGlobal);
1593
1594 pmedium->u.hGlobal = 0;
1595 break;
1596 }
1597 case TYMED_MFPICT:
1598 {
1599 if ( (pmedium->pUnkForRelease==0) &&
1600 (pmedium->u.hMetaFilePict!=0) )
1601 {
1602 LPMETAFILEPICT pMP = GlobalLock(pmedium->u.hGlobal);
1603 DeleteMetaFile(pMP->hMF);
1604 GlobalUnlock(pmedium->u.hGlobal);
1605 GlobalFree(pmedium->u.hGlobal);
1606 }
1607
1608 pmedium->u.hMetaFilePict = 0;
1609 break;
1610 }
1611 case TYMED_ENHMF:
1612 {
1613 if ( (pmedium->pUnkForRelease==0) &&
1614 (pmedium->u.hEnhMetaFile!=0) )
1615 {
1616 DeleteEnhMetaFile(pmedium->u.hEnhMetaFile);
1617 }
1618
1619 pmedium->u.hEnhMetaFile = 0;
1620 break;
1621 }
1622 case TYMED_NULL:
1623 default:
1624 break;
1625 }
1626 pmedium->tymed=TYMED_NULL;
1627
1628 /*
1629 * After cleaning up, the unknown is released
1630 */
1631 if (pmedium->pUnkForRelease!=0)
1632 {
1633 IUnknown_Release(pmedium->pUnkForRelease);
1634 pmedium->pUnkForRelease = 0;
1635 }
1636}
1637
1638/***
1639 * OLEDD_Initialize()
1640 *
1641 * Initializes the OLE drag and drop data structures.
1642 */
1643static void OLEDD_Initialize()
1644{
1645 WNDCLASSA wndClass;
1646
1647 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1648 wndClass.style = CS_GLOBALCLASS;
1649 wndClass.lpfnWndProc = (WNDPROC)OLEDD_DragTrackerWindowProc;
1650 wndClass.cbClsExtra = 0;
1651 wndClass.cbWndExtra = sizeof(TrackerWindowInfo*);
1652 wndClass.hCursor = 0;
1653 wndClass.hbrBackground = 0;
1654 wndClass.lpszClassName = OLEDD_DRAGTRACKERCLASS;
1655
1656 RegisterClassA (&wndClass);
1657
1658#ifdef __WIN32OS2__
1659 {
1660 IDropTarget *desktopdnd;
1661
1662 desktopdnd = IDropTarget_Constructor();
1663 RegisterDragDrop(GetDesktopWindow(), desktopdnd);
1664 }
1665#endif
1666}
1667
1668/***
1669 * OLEDD_UnInitialize()
1670 *
1671 * Releases the OLE drag and drop data structures.
1672 */
1673static void OLEDD_UnInitialize()
1674{
1675 /*
1676 * Simply empty the list.
1677 */
1678 while (targetListHead!=NULL)
1679 {
1680 RevokeDragDrop(targetListHead->hwndTarget);
1681 }
1682}
1683
1684/***
1685 * OLEDD_InsertDropTarget()
1686 *
1687 * Insert the target node in the tree.
1688 */
1689static void OLEDD_InsertDropTarget(DropTargetNode* nodeToAdd)
1690{
1691 DropTargetNode* curNode;
1692 DropTargetNode** parentNodeLink;
1693
1694 /*
1695 * Iterate the tree to find the insertion point.
1696 */
1697 curNode = targetListHead;
1698 parentNodeLink = &targetListHead;
1699
1700 while (curNode!=NULL)
1701 {
1702 if (nodeToAdd->hwndTarget<curNode->hwndTarget)
1703 {
1704 /*
1705 * If the node we want to add has a smaller HWND, go left
1706 */
1707 parentNodeLink = &curNode->prevDropTarget;
1708 curNode = curNode->prevDropTarget;
1709 }
1710 else if (nodeToAdd->hwndTarget>curNode->hwndTarget)
1711 {
1712 /*
1713 * If the node we want to add has a larger HWND, go right
1714 */
1715 parentNodeLink = &curNode->nextDropTarget;
1716 curNode = curNode->nextDropTarget;
1717 }
1718 else
1719 {
1720 /*
1721 * The item was found in the list. It shouldn't have been there
1722 */
1723 assert(FALSE);
1724 return;
1725 }
1726 }
1727
1728 /*
1729 * If we get here, we have found a spot for our item. The parentNodeLink
1730 * pointer points to the pointer that we have to modify.
1731 * The curNode should be NULL. We just have to establish the link and Voila!
1732 */
1733 assert(curNode==NULL);
1734 assert(parentNodeLink!=NULL);
1735 assert(*parentNodeLink==NULL);
1736
1737 *parentNodeLink=nodeToAdd;
1738}
1739
1740/***
1741 * OLEDD_ExtractDropTarget()
1742 *
1743 * Removes the target node from the tree.
1744 */
1745static DropTargetNode* OLEDD_ExtractDropTarget(HWND hwndOfTarget)
1746{
1747 DropTargetNode* curNode;
1748 DropTargetNode** parentNodeLink;
1749
1750 /*
1751 * Iterate the tree to find the insertion point.
1752 */
1753 curNode = targetListHead;
1754 parentNodeLink = &targetListHead;
1755
1756 while (curNode!=NULL)
1757 {
1758 if (hwndOfTarget<curNode->hwndTarget)
1759 {
1760 /*
1761 * If the node we want to add has a smaller HWND, go left
1762 */
1763 parentNodeLink = &curNode->prevDropTarget;
1764 curNode = curNode->prevDropTarget;
1765 }
1766 else if (hwndOfTarget>curNode->hwndTarget)
1767 {
1768 /*
1769 * If the node we want to add has a larger HWND, go right
1770 */
1771 parentNodeLink = &curNode->nextDropTarget;
1772 curNode = curNode->nextDropTarget;
1773 }
1774 else
1775 {
1776 /*
1777 * The item was found in the list. Detach it from it's parent and
1778 * re-insert it's kids in the tree.
1779 */
1780 assert(parentNodeLink!=NULL);
1781 assert(*parentNodeLink==curNode);
1782
1783 /*
1784 * We arbitrately re-attach the left sub-tree to the parent.
1785 */
1786 *parentNodeLink = curNode->prevDropTarget;
1787
1788 /*
1789 * And we re-insert the right subtree
1790 */
1791 if (curNode->nextDropTarget!=NULL)
1792 {
1793 OLEDD_InsertDropTarget(curNode->nextDropTarget);
1794 }
1795
1796 /*
1797 * The node we found is still a valid node once we complete
1798 * the unlinking of the kids.
1799 */
1800 curNode->nextDropTarget=NULL;
1801 curNode->prevDropTarget=NULL;
1802
1803 return curNode;
1804 }
1805 }
1806
1807 /*
1808 * If we get here, the node is not in the tree
1809 */
1810 return NULL;
1811}
1812
1813/***
1814 * OLEDD_FindDropTarget()
1815 *
1816 * Finds information about the drop target.
1817 */
1818static DropTargetNode* OLEDD_FindDropTarget(HWND hwndOfTarget)
1819{
1820 DropTargetNode* curNode;
1821
1822 /*
1823 * Iterate the tree to find the HWND value.
1824 */
1825 curNode = targetListHead;
1826
1827 while (curNode!=NULL)
1828 {
1829 if (hwndOfTarget<curNode->hwndTarget)
1830 {
1831 /*
1832 * If the node we want to add has a smaller HWND, go left
1833 */
1834 curNode = curNode->prevDropTarget;
1835 }
1836 else if (hwndOfTarget>curNode->hwndTarget)
1837 {
1838 /*
1839 * If the node we want to add has a larger HWND, go right
1840 */
1841 curNode = curNode->nextDropTarget;
1842 }
1843 else
1844 {
1845 /*
1846 * The item was found in the list.
1847 */
1848 return curNode;
1849 }
1850 }
1851
1852 /*
1853 * If we get here, the item is not in the list
1854 */
1855 return NULL;
1856}
1857
1858/***
1859 * OLEDD_DragTrackerWindowProc()
1860 *
1861 * This method is the WindowProcedure of the drag n drop tracking
1862 * window. During a drag n Drop operation, an invisible window is created
1863 * to receive the user input and act upon it. This procedure is in charge
1864 * of this behavior.
1865 */
1866static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
1867 HWND hwnd,
1868 UINT uMsg,
1869 WPARAM wParam,
1870 LPARAM lParam)
1871{
1872 dprintf(("OLEDD_DragTrackerWindowProc(%x, %x, %x, %x)\n", hwnd, uMsg, wParam, lParam));
1873 switch (uMsg)
1874 {
1875 case WM_CREATE:
1876 {
1877 LPCREATESTRUCTA createStruct = (LPCREATESTRUCTA)lParam;
1878
1879 SetWindowLongA(hwnd, 0, (LONG)createStruct->lpCreateParams);
1880
1881 break;
1882 }
1883 case WM_MOUSEMOVE:
1884 {
1885 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
1886 POINT mousePos;
1887
1888 /*
1889 * Get the current mouse position in screen coordinates.
1890 */
1891 mousePos.x = LOWORD(lParam);
1892 mousePos.y = HIWORD(lParam);
1893 ClientToScreen(hwnd, &mousePos);
1894
1895 /*
1896 * Track the movement of the mouse.
1897 */
1898#ifdef __WIN32OS2__
1899 wParam = OLEDD_GetButtonState();
1900#endif
1901 OLEDD_TrackMouseMove(trackerInfo, mousePos, wParam);
1902
1903 break;
1904 }
1905 case WM_LBUTTONUP:
1906 case WM_MBUTTONUP:
1907 case WM_RBUTTONUP:
1908 case WM_LBUTTONDOWN:
1909 case WM_MBUTTONDOWN:
1910 case WM_RBUTTONDOWN:
1911 {
1912 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
1913 POINT mousePos;
1914
1915 /*
1916 * Get the current mouse position in screen coordinates.
1917 */
1918 mousePos.x = LOWORD(lParam);
1919 mousePos.y = HIWORD(lParam);
1920 ClientToScreen(hwnd, &mousePos);
1921
1922 /*
1923 * Notify everyone that the button state changed
1924 * TODO: Check if the "escape" key was pressed.
1925 */
1926 OLEDD_TrackStateChange(trackerInfo, mousePos, wParam);
1927
1928 break;
1929 }
1930 }
1931
1932 /*
1933 * This is a window proc after all. Let's call the default.
1934 */
1935 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1936}
1937
1938/***
1939 * OLEDD_TrackMouseMove()
1940 *
1941 * This method is invoked while a drag and drop operation is in effect.
1942 * it will generate the appropriate callbacks in the drop source
1943 * and drop target. It will also provide the expected feedback to
1944 * the user.
1945 *
1946 * params:
1947 * trackerInfo - Pointer to the structure identifying the
1948 * drag & drop operation that is currently
1949 * active.
1950 * mousePos - Current position of the mouse in screen
1951 * coordinates.
1952 * keyState - Contains the state of the shift keys and the
1953 * mouse buttons (MK_LBUTTON and the like)
1954 */
1955static void OLEDD_TrackMouseMove(
1956 TrackerWindowInfo* trackerInfo,
1957 POINT mousePos,
1958 DWORD keyState)
1959{
1960 HWND hwndNewTarget;
1961 HRESULT hr;
1962
1963#ifdef __WIN32OS2__
1964 TRACE("OLEDD_TrackMouseMove: %p, (%d,%d), %x\n", trackerInfo, mousePos.x, mousePos.y, keyState);
1965#endif
1966
1967 /*
1968 * Get the handle of the window under the mouse
1969 */
1970 hwndNewTarget = WindowFromPoint(mousePos);
1971
1972#ifdef __WIN32OS2__
1973 dprintf(("OLEDD_TrackMouseMove: hwndNewTarget %x current %x", hwndNewTarget, trackerInfo->curDragTargetHWND));
1974#endif
1975
1976 /*
1977 * Every time, we re-initialize the effects passed to the
1978 * IDropTarget to the effects allowed by the source.
1979 */
1980 *trackerInfo->pdwEffect = trackerInfo->dwOKEffect;
1981
1982 /*
1983 * If we are hovering over the same target as before, send the
1984 * DragOver notification
1985 */
1986 if ( (trackerInfo->curDragTarget != 0) &&
1987 (trackerInfo->curTargetHWND == hwndNewTarget) )
1988 {
1989 POINTL mousePosParam;
1990
1991 /*
1992 * The documentation tells me that the coordinate should be in the target
1993 * window's coordinate space. However, the tests I made tell me the
1994 * coordinates should be in screen coordinates.
1995 */
1996 mousePosParam.x = mousePos.x;
1997 mousePosParam.y = mousePos.y;
1998
1999#ifdef __WIN32OS2__
2000 hr =
2001#endif
2002 IDropTarget_DragOver(trackerInfo->curDragTarget,
2003 keyState,
2004 mousePosParam,
2005 trackerInfo->pdwEffect);
2006#ifdef __WIN32OS2__
2007 TRACE("OLEDD_TrackMouseMove: IDropTarget_DragOver -> %x, *pdwEffect=%x\n", hr, *trackerInfo->pdwEffect);
2008#endif
2009 }
2010 else
2011 {
2012 DropTargetNode* newDropTargetNode = 0;
2013
2014 /*
2015 * If we changed window, we have to notify our old target and check for
2016 * the new one.
2017 */
2018 if (trackerInfo->curDragTarget!=0)
2019 {
2020#ifdef __WIN32OS2__
2021 hr =
2022#endif
2023 IDropTarget_DragLeave(trackerInfo->curDragTarget);
2024#ifdef __WIN32OS2__
2025 TRACE("OLEDD_TrackMouseMove: IDropTarget_DragLeave -> %x\n", hr);
2026#endif
2027 }
2028
2029 /*
2030 * Make sure we're hovering over a window.
2031 */
2032 if (hwndNewTarget!=0)
2033 {
2034 /*
2035 * Find-out if there is a drag target under the mouse
2036 */
2037 HWND nexttar = hwndNewTarget;
2038 trackerInfo->curTargetHWND = hwndNewTarget;
2039
2040 do {
2041 newDropTargetNode = OLEDD_FindDropTarget(nexttar);
2042 }
2043 while (!newDropTargetNode && (nexttar = GetParent(nexttar)) != 0);
2044
2045 if (nexttar)
2046 hwndNewTarget = nexttar;
2047
2048 trackerInfo->curDragTargetHWND = hwndNewTarget;
2049 trackerInfo->curDragTarget = newDropTargetNode ? newDropTargetNode->dropTarget : 0;
2050
2051 /*
2052 * If there is, notify it that we just dragged-in
2053 */
2054 if (trackerInfo->curDragTarget!=0)
2055 {
2056 POINTL mousePosParam;
2057
2058 /*
2059 * The documentation tells me that the coordinate should be in the target
2060 * window's coordinate space. However, the tests I made tell me the
2061 * coordinates should be in screen coordinates.
2062 */
2063 mousePosParam.x = mousePos.x;
2064 mousePosParam.y = mousePos.y;
2065
2066#ifdef __WIN32OS2__
2067 hr =
2068#endif
2069 IDropTarget_DragEnter(trackerInfo->curDragTarget,
2070 trackerInfo->dataObject,
2071 keyState,
2072 mousePosParam,
2073 trackerInfo->pdwEffect);
2074#ifdef __WIN32OS2__
2075 TRACE("OLEDD_TrackMouseMove: IDropTarget_DragEnter -> %x, *pdwEffect=%x\n", hr, *trackerInfo->pdwEffect);
2076#endif
2077 }
2078 }
2079 else
2080 {
2081 /*
2082 * The mouse is not over a window so we don't track anything.
2083 */
2084 trackerInfo->curDragTargetHWND = 0;
2085 trackerInfo->curTargetHWND = 0;
2086 trackerInfo->curDragTarget = 0;
2087 }
2088 }
2089
2090 /*
2091 * Now that we have done that, we have to tell the source to give
2092 * us feedback on the work being done by the target. If we don't
2093 * have a target, simulate no effect.
2094 */
2095 if (trackerInfo->curDragTarget==0)
2096 {
2097 *trackerInfo->pdwEffect = DROPEFFECT_NONE;
2098 }
2099
2100 hr = IDropSource_GiveFeedback(trackerInfo->dropSource,
2101 *trackerInfo->pdwEffect);
2102#ifdef __WIN32OS2__
2103 TRACE("OLEDD_TrackMouseMove: IDropSource_GiveFeedback *pdwEffect=%x -> %x\n", *trackerInfo->pdwEffect, hr);
2104#endif
2105
2106 /*
2107 * When we ask for feedback from the drop source, sometimes it will
2108 * do all the necessary work and sometimes it will not handle it
2109 * when that's the case, we must display the standard drag and drop
2110 * cursors.
2111 */
2112 if (hr==DRAGDROP_S_USEDEFAULTCURSORS)
2113 {
2114 if (*trackerInfo->pdwEffect & DROPEFFECT_MOVE)
2115 {
2116 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(1)));
2117 }
2118 else if (*trackerInfo->pdwEffect & DROPEFFECT_COPY)
2119 {
2120 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(2)));
2121 }
2122 else if (*trackerInfo->pdwEffect & DROPEFFECT_LINK)
2123 {
2124 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(3)));
2125 }
2126 else
2127 {
2128 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(0)));
2129 }
2130 }
2131}
2132
2133/***
2134 * OLEDD_TrackStateChange()
2135 *
2136 * This method is invoked while a drag and drop operation is in effect.
2137 * It is used to notify the drop target/drop source callbacks when
2138 * the state of the keyboard or mouse button change.
2139 *
2140 * params:
2141 * trackerInfo - Pointer to the structure identifying the
2142 * drag & drop operation that is currently
2143 * active.
2144 * mousePos - Current position of the mouse in screen
2145 * coordinates.
2146 * keyState - Contains the state of the shift keys and the
2147 * mouse buttons (MK_LBUTTON and the like)
2148 */
2149static void OLEDD_TrackStateChange(
2150 TrackerWindowInfo* trackerInfo,
2151 POINT mousePos,
2152 DWORD keyState)
2153{
2154#ifdef __WIN32OS2__
2155 TRACE("OLEDD_TrackStateChange: %p (%d,%d) %x\n", trackerInfo, mousePos.x, mousePos.y, keyState);
2156#endif
2157
2158 /*
2159 * Ask the drop source what to do with the operation.
2160 */
2161 trackerInfo->returnValue = IDropSource_QueryContinueDrag(
2162 trackerInfo->dropSource,
2163 trackerInfo->escPressed,
2164 keyState);
2165#ifdef __WIN32OS2__
2166 TRACE("OLEDD_TrackStateChange: IDropSource_QueryContinueDrag -> %x\n", trackerInfo->returnValue);
2167#endif
2168
2169 /*
2170 * All the return valued will stop the operation except the S_OK
2171 * return value.
2172 */
2173 if (trackerInfo->returnValue!=S_OK)
2174 {
2175 /*
2176 * Make sure the message loop in DoDragDrop stops
2177 */
2178 trackerInfo->trackingDone = TRUE;
2179
2180 /*
2181 * Release the mouse in case the drop target decides to show a popup
2182 * or a menu or something.
2183 */
2184 ReleaseCapture();
2185
2186 /*
2187 * If we end-up over a target, drop the object in the target or
2188 * inform the target that the operation was cancelled.
2189 */
2190 if (trackerInfo->curDragTarget!=0)
2191 {
2192 switch (trackerInfo->returnValue)
2193 {
2194 /*
2195 * If the source wants us to complete the operation, we tell
2196 * the drop target that we just dropped the object in it.
2197 */
2198 case DRAGDROP_S_DROP:
2199 {
2200 POINTL mousePosParam;
2201
2202 /*
2203 * The documentation tells me that the coordinate should be
2204 * in the target window's coordinate space. However, the tests
2205 * I made tell me the coordinates should be in screen coordinates.
2206 */
2207 mousePosParam.x = mousePos.x;
2208 mousePosParam.y = mousePos.y;
2209
2210 IDropTarget_Drop(trackerInfo->curDragTarget,
2211 trackerInfo->dataObject,
2212 keyState,
2213 mousePosParam,
2214 trackerInfo->pdwEffect);
2215 break;
2216 }
2217 /*
2218 * If the source told us that we should cancel, fool the drop
2219 * target by telling it that the mouse left it's window.
2220 * Also set the drop effect to "NONE" in case the application
2221 * ignores the result of DoDragDrop.
2222 */
2223 case DRAGDROP_S_CANCEL:
2224 IDropTarget_DragLeave(trackerInfo->curDragTarget);
2225 *trackerInfo->pdwEffect = DROPEFFECT_NONE;
2226 break;
2227
2228#ifdef __WIN32OS2__
2229#ifdef DEBUG
2230 default:
2231 TRACE("OLEDD_TrackStateChange: unknown return value %x\n", trackerInfo->returnValue);
2232 assert(FALSE);
2233 break;
2234#endif
2235#endif
2236 }
2237 }
2238 }
2239#ifdef __WIN32OS2__
2240 else /* Read DoDragDrop() docs. This is point 5 in the remark section. */
2241 OLEDD_TrackMouseMove(trackerInfo, mousePos, keyState);
2242 TRACE("OLEDD_TrackStateChange: IDropSource_QueryContinueDrag -> %x\n", trackerInfo->returnValue);
2243#endif
2244}
2245
2246/***
2247 * OLEDD_GetButtonState()
2248 *
2249 * This method will use the current state of the keyboard to build
2250 * a button state mask equivalent to the one passed in the
2251 * WM_MOUSEMOVE wParam.
2252 */
2253static DWORD OLEDD_GetButtonState(void)
2254{
2255 BYTE keyboardState[256];
2256 DWORD keyMask = 0;
2257
2258 GetKeyboardState(keyboardState);
2259
2260 if ( (keyboardState[VK_SHIFT] & 0x80) !=0)
2261 keyMask |= MK_SHIFT;
2262
2263 if ( (keyboardState[VK_CONTROL] & 0x80) !=0)
2264 keyMask |= MK_CONTROL;
2265
2266#ifdef __WIN32OS2__
2267 if ( (keyboardState[VK_MENU] & 0x80) != 0)
2268 keyMask |= MK_ALT;
2269#endif
2270
2271 if ( (keyboardState[VK_LBUTTON] & 0x80) !=0)
2272 keyMask |= MK_LBUTTON;
2273
2274 if ( (keyboardState[VK_RBUTTON] & 0x80) !=0)
2275 keyMask |= MK_RBUTTON;
2276
2277 if ( (keyboardState[VK_MBUTTON] & 0x80) !=0)
2278 keyMask |= MK_MBUTTON;
2279
2280
2281 return keyMask;
2282}
2283
2284/***
2285 * OLEDD_GetButtonState()
2286 *
2287 * This method will read the default value of the registry key in
2288 * parameter and extract a DWORD value from it. The registry key value
2289 * can be in a string key or a DWORD key.
2290 *
2291 * params:
2292 * regKey - Key to read the default value from
2293 * pdwValue - Pointer to the location where the DWORD
2294 * value is returned. This value is not modified
2295 * if the value is not found.
2296 */
2297
2298static void OLEUTL_ReadRegistryDWORDValue(
2299 HKEY regKey,
2300 DWORD* pdwValue)
2301{
2302 char buffer[20];
2303 DWORD dwKeyType;
2304 DWORD cbData = 20;
2305 LONG lres;
2306
2307 lres = RegQueryValueExA(regKey,
2308 "",
2309 NULL,
2310 &dwKeyType,
2311 (LPBYTE)buffer,
2312 &cbData);
2313
2314 if (lres==ERROR_SUCCESS)
2315 {
2316 switch (dwKeyType)
2317 {
2318 case REG_DWORD:
2319 *pdwValue = *(DWORD*)buffer;
2320 break;
2321 case REG_EXPAND_SZ:
2322 case REG_MULTI_SZ:
2323 case REG_SZ:
2324 *pdwValue = (DWORD)strtoul(buffer, NULL, 10);
2325 break;
2326 }
2327 }
2328}
2329
2330
2331/******************************************************************************
2332 * OleDraw (OLE32.@)
2333 *
2334 * The operation of this function is documented literally in the WinAPI
2335 * documentation to involve a QueryInterface for the IViewObject interface,
2336 * followed by a call to IViewObject::Draw.
2337 */
2338HRESULT WINAPI OleDraw(
2339 IUnknown *pUnk,
2340 DWORD dwAspect,
2341 HDC hdcDraw,
2342 LPCRECT lprcBounds)
2343{
2344 HRESULT hres;
2345 IViewObject *viewobject;
2346
2347 hres = IUnknown_QueryInterface(pUnk,
2348 &IID_IViewObject,
2349 (void**)&viewobject);
2350
2351 if (SUCCEEDED(hres))
2352 {
2353 RECTL rectl;
2354
2355 rectl.left = lprcBounds->left;
2356 rectl.right = lprcBounds->right;
2357 rectl.top = lprcBounds->top;
2358 rectl.bottom = lprcBounds->bottom;
2359 hres = IViewObject_Draw(viewobject, dwAspect, -1, 0, 0, 0, hdcDraw, &rectl, 0, 0, 0);
2360
2361 IViewObject_Release(viewobject);
2362 return hres;
2363 }
2364 else
2365 {
2366 return DV_E_NOIVIEWOBJECT;
2367 }
2368}
2369
2370/***********************************************************************
2371 * OleTranslateAccelerator [OLE32.@]
2372 */
2373HRESULT WINAPI OleTranslateAccelerator (LPOLEINPLACEFRAME lpFrame,
2374 LPOLEINPLACEFRAMEINFO lpFrameInfo, LPMSG lpmsg)
2375{
2376 WORD wID;
2377
2378 TRACE("(%p,%p,%p)\n", lpFrame, lpFrameInfo, lpmsg);
2379
2380 if (IsAccelerator(lpFrameInfo->haccel,lpFrameInfo->cAccelEntries,lpmsg,&wID))
2381 return IOleInPlaceFrame_TranslateAccelerator(lpFrame,lpmsg,wID);
2382
2383 return S_FALSE;
2384}
2385
2386/******************************************************************************
2387 * OleCreate [OLE32.@]
2388 *
2389 */
2390HRESULT WINAPI OleCreate(
2391 REFCLSID rclsid,
2392 REFIID riid,
2393 DWORD renderopt,
2394 LPFORMATETC pFormatEtc,
2395 LPOLECLIENTSITE pClientSite,
2396 LPSTORAGE pStg,
2397 LPVOID* ppvObj)
2398{
2399 HRESULT hres, hres1;
2400 IUnknown * pUnk = NULL;
2401
2402 FIXME("\n\t%s\n\t%s semi-stub!\n", debugstr_guid(rclsid), debugstr_guid(riid));
2403
2404 if (SUCCEEDED((hres = CoCreateInstance(rclsid, 0, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER|CLSCTX_LOCAL_SERVER , riid, (LPVOID*)&pUnk))))
2405 {
2406 if (pClientSite)
2407 {
2408 IOleObject * pOE;
2409 IPersistStorage * pPS;
2410 if (SUCCEEDED((hres = IUnknown_QueryInterface( pUnk, &IID_IOleObject, (LPVOID*)&pOE))))
2411 {
2412 TRACE("trying to set clientsite %p\n", pClientSite);
2413 hres1 = IOleObject_SetClientSite(pOE, pClientSite);
2414 TRACE("-- result 0x%08lx\n", hres1);
2415 IOleObject_Release(pOE);
2416 }
2417 if (SUCCEEDED((hres = IUnknown_QueryInterface( pUnk, &IID_IPersistStorage, (LPVOID*)&pPS))))
2418 {
2419 TRACE("trying to set stg %p\n", pStg);
2420 hres1 = IPersistStorage_InitNew(pPS, pStg);
2421 TRACE("-- result 0x%08lx\n", hres1);
2422 IPersistStorage_Release(pPS);
2423 }
2424 }
2425 }
2426
2427 *ppvObj = pUnk;
2428
2429 TRACE("-- %p \n", pUnk);
2430 return hres;
2431}
2432
2433/***********************************************************************
2434 * OLE_FreeClipDataArray [internal]
2435 *
2436 * NOTES:
2437 * frees the data associated with an array of CLIPDATAs
2438 */
2439static void OLE_FreeClipDataArray(ULONG count, CLIPDATA * pClipDataArray)
2440{
2441 ULONG i;
2442 for (i = 0; i < count; i++)
2443 if (pClipDataArray[i].pClipData)
2444 CoTaskMemFree(pClipDataArray[i].pClipData);
2445}
2446
2447HRESULT WINAPI FreePropVariantArray(ULONG,PROPVARIANT*);
2448
2449/***********************************************************************
2450 * PropVariantClear [OLE32.@]
2451 */
2452HRESULT WINAPI PropVariantClear(PROPVARIANT * pvar) /* [in/out] */
2453{
2454 TRACE("(%p)\n", pvar);
2455
2456 if (!pvar)
2457 return S_OK;
2458
2459 switch(pvar->vt)
2460 {
2461 case VT_STREAM:
2462 case VT_STREAMED_OBJECT:
2463 case VT_STORAGE:
2464 case VT_STORED_OBJECT:
2465 IUnknown_Release((LPUNKNOWN)pvar->u.pStream);
2466 break;
2467 case VT_CLSID:
2468 case VT_LPSTR:
2469 case VT_LPWSTR:
2470 /* pick an arbitary typed pointer - we don't care about the type
2471 * as we are just freeing it */
2472 CoTaskMemFree(pvar->u.puuid);
2473 break;
2474 case VT_BLOB:
2475 case VT_BLOB_OBJECT:
2476 CoTaskMemFree(pvar->u.blob.pBlobData);
2477 break;
2478 case VT_BSTR:
2479 FIXME("Need to load OLEAUT32 for SysFreeString\n");
2480 /* SysFreeString(pvar->u.bstrVal); */
2481 break;
2482 case VT_CF:
2483 if (pvar->u.pclipdata)
2484 {
2485 OLE_FreeClipDataArray(1, pvar->u.pclipdata);
2486 CoTaskMemFree(pvar->u.pclipdata);
2487 }
2488 break;
2489 default:
2490 if (pvar->vt & VT_ARRAY)
2491 {
2492 FIXME("Need to call SafeArrayDestroy\n");
2493 /* SafeArrayDestroy(pvar->u.caub); */
2494 }
2495 switch (pvar->vt & VT_VECTOR)
2496 {
2497 case VT_VARIANT:
2498 FreePropVariantArray(pvar->u.capropvar.cElems, pvar->u.capropvar.pElems);
2499 break;
2500 case VT_CF:
2501 OLE_FreeClipDataArray(pvar->u.caclipdata.cElems, pvar->u.caclipdata.pElems);
2502 break;
2503 case VT_BSTR:
2504 case VT_LPSTR:
2505 case VT_LPWSTR:
2506 FIXME("Freeing of vector sub-type not supported yet\n");
2507 }
2508 if (pvar->vt & VT_VECTOR)
2509 {
2510 /* pick an arbitary VT_VECTOR structure - they all have the same
2511 * memory layout */
2512 CoTaskMemFree(pvar->u.capropvar.pElems);
2513 }
2514 }
2515
2516 ZeroMemory(pvar, sizeof(*pvar));
2517
2518 return S_OK;
2519}
2520
2521/***********************************************************************
2522 * PropVariantCopy [OLE32.@]
2523 */
2524HRESULT WINAPI PropVariantCopy(PROPVARIANT *pvarDest, /* [out] */
2525 const PROPVARIANT *pvarSrc) /* [in] */
2526{
2527 ULONG len;
2528 TRACE("(%p, %p): stub:\n", pvarDest, pvarSrc);
2529
2530 /* this will deal with most cases */
2531 CopyMemory(pvarDest, pvarSrc, sizeof(*pvarDest));
2532
2533 switch(pvarSrc->vt)
2534 {
2535 case VT_STREAM:
2536 case VT_STREAMED_OBJECT:
2537 case VT_STORAGE:
2538 case VT_STORED_OBJECT:
2539 IUnknown_AddRef((LPUNKNOWN)pvarDest->u.pStream);
2540 break;
2541 case VT_CLSID:
2542 pvarDest->u.puuid = CoTaskMemAlloc(sizeof(CLSID));
2543 CopyMemory(pvarDest->u.puuid, pvarSrc->u.puuid, sizeof(CLSID));
2544 break;
2545 case VT_LPSTR:
2546 len = strlen(pvarSrc->u.pszVal);
2547 pvarDest->u.pszVal = CoTaskMemAlloc(len);
2548 CopyMemory(pvarDest->u.pszVal, pvarSrc->u.pszVal, len);
2549 break;
2550 case VT_LPWSTR:
2551 len = lstrlenW(pvarSrc->u.pwszVal);
2552 pvarDest->u.pwszVal = CoTaskMemAlloc(len);
2553 CopyMemory(pvarDest->u.pwszVal, pvarSrc->u.pwszVal, len);
2554 break;
2555 case VT_BLOB:
2556 case VT_BLOB_OBJECT:
2557 if (pvarSrc->u.blob.pBlobData)
2558 {
2559 len = pvarSrc->u.blob.cbSize;
2560 pvarDest->u.blob.pBlobData = CoTaskMemAlloc(len);
2561 CopyMemory(pvarDest->u.blob.pBlobData, pvarSrc->u.blob.pBlobData, len);
2562 }
2563 break;
2564 case VT_BSTR:
2565 FIXME("Need to copy BSTR\n");
2566 break;
2567 case VT_CF:
2568 if (pvarSrc->u.pclipdata)
2569 {
2570 len = pvarSrc->u.pclipdata->cbSize - sizeof(pvarSrc->u.pclipdata->ulClipFmt);
2571 CoTaskMemAlloc(len);
2572 CopyMemory(pvarDest->u.pclipdata->pClipData, pvarSrc->u.pclipdata->pClipData, len);
2573 }
2574 break;
2575 default:
2576 if (pvarSrc->vt & VT_ARRAY)
2577 {
2578 FIXME("Need to call SafeArrayCopy\n");
2579 /* SafeArrayCopy(...); */
2580 }
2581 if (pvarSrc->vt & VT_VECTOR)
2582 {
2583 int elemSize;
2584 switch(pvarSrc->vt & VT_VECTOR)
2585 {
2586 case VT_I1: elemSize = sizeof(pvarSrc->u.cVal); break;
2587 case VT_UI1: elemSize = sizeof(pvarSrc->u.bVal); break;
2588 case VT_I2: elemSize = sizeof(pvarSrc->u.iVal); break;
2589 case VT_UI2: elemSize = sizeof(pvarSrc->u.uiVal); break;
2590 case VT_BOOL: elemSize = sizeof(pvarSrc->u.boolVal); break;
2591 case VT_I4: elemSize = sizeof(pvarSrc->u.lVal); break;
2592 case VT_UI4: elemSize = sizeof(pvarSrc->u.ulVal); break;
2593 case VT_R4: elemSize = sizeof(pvarSrc->u.fltVal); break;
2594 case VT_R8: elemSize = sizeof(pvarSrc->u.dblVal); break;
2595 case VT_ERROR: elemSize = sizeof(pvarSrc->u.scode); break;
2596 case VT_I8: elemSize = sizeof(pvarSrc->u.hVal); break;
2597 case VT_UI8: elemSize = sizeof(pvarSrc->u.uhVal); break;
2598 case VT_CY: elemSize = sizeof(pvarSrc->u.cyVal); break;
2599 case VT_DATE: elemSize = sizeof(pvarSrc->u.date); break;
2600 case VT_FILETIME: elemSize = sizeof(pvarSrc->u.filetime); break;
2601 case VT_CLSID: elemSize = sizeof(*pvarSrc->u.puuid); break;
2602 case VT_CF: elemSize = sizeof(*pvarSrc->u.pclipdata); break;
2603
2604 case VT_BSTR:
2605 case VT_LPSTR:
2606 case VT_LPWSTR:
2607 case VT_VARIANT:
2608 default:
2609 FIXME("Invalid element type: %ul\n", pvarSrc->vt & VT_VECTOR);
2610 return E_INVALIDARG;
2611 }
2612 len = pvarSrc->u.capropvar.cElems;
2613 pvarDest->u.capropvar.pElems = CoTaskMemAlloc(len * elemSize);
2614 if (pvarSrc->vt == (VT_VECTOR | VT_VARIANT))
2615 {
2616 ULONG i;
2617 for (i = 0; i < len; i++)
2618 PropVariantCopy(&pvarDest->u.capropvar.pElems[i], &pvarSrc->u.capropvar.pElems[i]);
2619 }
2620 else if (pvarSrc->vt == (VT_VECTOR | VT_CF))
2621 {
2622 FIXME("Copy clipformats\n");
2623 }
2624 else if (pvarSrc->vt == (VT_VECTOR | VT_BSTR))
2625 {
2626 FIXME("Copy BSTRs\n");
2627 }
2628 else if (pvarSrc->vt == (VT_VECTOR | VT_LPSTR))
2629 {
2630 FIXME("Copy LPSTRs\n");
2631 }
2632 else if (pvarSrc->vt == (VT_VECTOR | VT_LPSTR))
2633 {
2634 FIXME("Copy LPWSTRs\n");
2635 }
2636 else
2637 CopyMemory(pvarDest->u.capropvar.pElems, pvarSrc->u.capropvar.pElems, len * elemSize);
2638 }
2639 }
2640
2641 return S_OK;
2642}
2643
2644/***********************************************************************
2645 * FreePropVariantArray [OLE32.@]
2646 */
2647HRESULT WINAPI FreePropVariantArray(ULONG cVariants, /* [in] */
2648 PROPVARIANT *rgvars) /* [in/out] */
2649{
2650 ULONG i;
2651
2652 TRACE("(%lu, %p)\n", cVariants, rgvars);
2653
2654 for(i = 0; i < cVariants; i++)
2655 PropVariantClear(&rgvars[i]);
2656
2657 return S_OK;
2658}
2659
2660
2661
2662#ifdef __WIN32OS2__
2663#include <dbglog.h>
2664
2665/***********************************************************************
2666* IEnumFORMATETC implementation
2667*/
2668
2669typedef struct
2670{
2671 /* IUnknown fields */
2672 ICOM_VFIELD(IEnumFORMATETC);
2673 DWORD ref;
2674 /* IEnumFORMATETC fields */
2675 UINT posFmt;
2676 UINT countFmt;
2677 LPFORMATETC pFmt;
2678} IEnumFORMATETCImpl;
2679
2680static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj);
2681static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface);
2682static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface);
2683static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC* rgelt, ULONG* pceltFethed);
2684static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt);
2685static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface);
2686static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
2687
2688static struct ICOM_VTABLE(IEnumFORMATETC) efvt =
2689{
2690 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2691 IEnumFORMATETC_fnQueryInterface,
2692 IEnumFORMATETC_fnAddRef,
2693 IEnumFORMATETC_fnRelease,
2694 IEnumFORMATETC_fnNext,
2695 IEnumFORMATETC_fnSkip,
2696 IEnumFORMATETC_fnReset,
2697 IEnumFORMATETC_fnClone
2698};
2699
2700static LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[])
2701{
2702 IEnumFORMATETCImpl* ef;
2703 DWORD size=cfmt * sizeof(FORMATETC);
2704
2705 ef=(IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl));
2706
2707 if(ef)
2708 {
2709 ef->ref=1;
2710 ICOM_VTBL(ef)=&efvt;
2711
2712 ef->countFmt = cfmt;
2713 ef->pFmt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2714
2715 if (ef->pFmt)
2716 {
2717 memcpy(ef->pFmt, afmt, size);
2718 }
2719 }
2720
2721 TRACE("(%p)->(%u,%p)\n",ef, cfmt, afmt);
2722 return (LPENUMFORMATETC)ef;
2723}
2724
2725static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
2726{
2727 ICOM_THIS(IEnumFORMATETCImpl,iface);
2728 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2729
2730 *ppvObj = NULL;
2731
2732 if(IsEqualIID(riid, &IID_IUnknown))
2733 {
2734 *ppvObj = This;
2735 }
2736 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
2737 {
2738 *ppvObj = (IEnumFORMATETC*)This;
2739 }
2740
2741 if(*ppvObj)
2742 {
2743 IUnknown_AddRef((IUnknown*)(*ppvObj));
2744 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
2745 return S_OK;
2746 }
2747 TRACE("-- Interface: E_NOINTERFACE\n");
2748 return E_NOINTERFACE;
2749
2750}
2751
2752static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface)
2753{
2754 ICOM_THIS(IEnumFORMATETCImpl,iface);
2755 TRACE("(%p)->(count=%lu)\n",This, This->ref);
2756 return ++(This->ref);
2757}
2758
2759static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface)
2760{
2761 ICOM_THIS(IEnumFORMATETCImpl,iface);
2762 TRACE("(%p)->()\n",This);
2763
2764 if (!--(This->ref))
2765 {
2766 TRACE(" destroying IEnumFORMATETC(%p)\n",This);
2767 if (This->pFmt)
2768 {
2769 HeapFree(GetProcessHeap(),0, This->pFmt);
2770 }
2771 HeapFree(GetProcessHeap(),0,This);
2772 return 0;
2773 }
2774 return This->ref;
2775}
2776
2777static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
2778{
2779 ICOM_THIS(IEnumFORMATETCImpl,iface);
2780 int i;
2781
2782 TRACE("(%p)->(%lu,%p)\n", This, celt, rgelt);
2783
2784 if(!This->pFmt)return S_FALSE;
2785 if(!rgelt) return E_INVALIDARG;
2786 if (pceltFethed) *pceltFethed = 0;
2787
2788 for(i = 0; This->posFmt < This->countFmt && celt > i; i++)
2789 {
2790 *rgelt++ = This->pFmt[This->posFmt++];
2791 }
2792
2793 if (pceltFethed) *pceltFethed = i;
2794
2795 return ((i == celt) ? S_OK : S_FALSE);
2796}
2797
2798static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt)
2799{
2800 ICOM_THIS(IEnumFORMATETCImpl,iface);
2801 TRACE("(%p)->(num=%lu)\n", This, celt);
2802
2803 if((This->posFmt + celt) >= This->countFmt) return S_FALSE;
2804 This->posFmt += celt;
2805 return S_OK;
2806}
2807
2808static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface)
2809{
2810 ICOM_THIS(IEnumFORMATETCImpl,iface);
2811 TRACE("(%p)->()\n", This);
2812
2813 This->posFmt = 0;
2814 return S_OK;
2815}
2816
2817static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
2818{
2819 ICOM_THIS(IEnumFORMATETCImpl,iface);
2820 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
2821
2822 if (!ppenum) return E_INVALIDARG;
2823 *ppenum = IEnumFORMATETC_Constructor(This->countFmt, This->pFmt);
2824 return S_OK;
2825}
2826
2827/***********************************************************************
2828* IDataObject implementation
2829*/
2830
2831
2832typedef struct
2833{
2834 /* IUnknown fields */
2835 ICOM_VFIELD(IDataObject);
2836 DWORD ref;
2837
2838 /* IDataObject fields */
2839 LPFORMATETC pFormatEtc;
2840 LPSTGMEDIUM pStgMedium;
2841 DWORD cDataCount;
2842} IDataObjectImpl;
2843
2844static struct ICOM_VTABLE(IDataObject) dtovt;
2845
2846/**************************************************************************
2847* IDataObject_Constructor
2848*/
2849static LPDATAOBJECT IDataObject_Constructor(void)
2850{
2851 IDataObjectImpl* dto;
2852
2853 dto = (IDataObjectImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDataObjectImpl));
2854
2855 if (dto)
2856 {
2857 dto->ref = 1;
2858 ICOM_VTBL(dto) = &dtovt;
2859 }
2860
2861 return (LPDATAOBJECT)dto;
2862}
2863
2864/***************************************************************************
2865* IDataObject_QueryInterface
2866*/
2867static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID * ppvObj)
2868{
2869 ICOM_THIS(IDataObjectImpl,iface);
2870 dprintf(("IDataObject_fnQueryInterface (%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj));
2871
2872 *ppvObj = NULL;
2873
2874 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
2875 {
2876 *ppvObj = This;
2877 }
2878 else if(IsEqualIID(riid, &IID_IDataObject)) /*IDataObject*/
2879 {
2880 *ppvObj = (IDataObject*)This;
2881 }
2882
2883 if(*ppvObj)
2884 {
2885 IUnknown_AddRef((IUnknown*)*ppvObj);
2886 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
2887 return S_OK;
2888 }
2889 TRACE("-- Interface: E_NOINTERFACE\n");
2890 return E_NOINTERFACE;
2891}
2892
2893/**************************************************************************
2894* IDataObject_AddRef
2895*/
2896static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface)
2897{
2898 ICOM_THIS(IDataObjectImpl,iface);
2899
2900 dprintf(("IDataObject_fnAddRef (%p)->(count=%lu)\n",This, This->ref));
2901
2902 return ++(This->ref);
2903}
2904
2905/**************************************************************************
2906* IDataObject_Release
2907*/
2908static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface)
2909{
2910 ICOM_THIS(IDataObjectImpl,iface);
2911 dprintf(("IDataObject_fnRelease (%p)->()\n",This));
2912
2913 if (!--(This->ref))
2914 {
2915 TRACE(" destroying IDataObject(%p)\n",This);
2916 HeapFree(GetProcessHeap(),0,This);
2917 return 0;
2918 }
2919 return This->ref;
2920}
2921
2922/**************************************************************************
2923* IDataObject_fnGetData
2924*/
2925static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
2926{
2927 int i;
2928
2929 ICOM_THIS(IDataObjectImpl,iface);
2930
2931 if(pformatetcIn == NULL || pmedium == NULL)
2932 return E_INVALIDARG;
2933
2934 dprintf(("IDataObject_fnGetData %x %x", pformatetcIn, pmedium));
2935
2936 if(pformatetcIn->cfFormat != CF_HDROP && pformatetcIn->cfFormat != CF_TEXT && pformatetcIn->cfFormat != CF_UNICODETEXT)
2937 {
2938 FIXME("-- expected clipformat not implemented\n");
2939 return (E_INVALIDARG);
2940 }
2941
2942 /* check our formats table what we have */
2943 for (i=0; i<This->cDataCount; i++)
2944 {
2945 if ((This->pFormatEtc[i].cfFormat == pformatetcIn->cfFormat)
2946 && (This->pFormatEtc[i].tymed == pformatetcIn->tymed))
2947 {
2948 pmedium->u.hGlobal = This->pStgMedium[i].u.hGlobal;
2949 break;
2950 }
2951 }
2952 if (pmedium->u.hGlobal)
2953 {
2954 pmedium->tymed = TYMED_HGLOBAL;
2955 pmedium->pUnkForRelease = NULL;
2956 return S_OK;
2957 }
2958 return E_OUTOFMEMORY;
2959}
2960
2961static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium)
2962{
2963 ICOM_THIS(IDataObjectImpl,iface);
2964
2965 dprintf(("IDataObject_fnGetDataHere %x %x STUB", pformatetc, pmedium));
2966 return E_NOTIMPL;
2967}
2968
2969static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc)
2970{
2971 ICOM_THIS(IDataObjectImpl,iface);
2972 UINT i;
2973
2974 dprintf(("IDataObject_fnQueryGetData (%p)->(fmt=0x%08x tym=0x%08lx)\n", This, pformatetc->cfFormat, pformatetc->tymed));
2975
2976 if(!(DVASPECT_CONTENT & pformatetc->dwAspect))
2977 return DV_E_DVASPECT;
2978
2979 if(This->pFormatEtc == NULL) {
2980 return DV_E_TYMED;
2981 }
2982 /* check our formats table what we have */
2983 for (i=0; i<This->cDataCount; i++)
2984 {
2985 if ((This->pFormatEtc[i].cfFormat == pformatetc->cfFormat)
2986 && (This->pFormatEtc[i].tymed == pformatetc->tymed))
2987 {
2988 return S_OK;
2989 }
2990 }
2991
2992 return DV_E_TYMED;
2993}
2994
2995static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
2996{
2997 ICOM_THIS(IDataObjectImpl,iface);
2998
2999 dprintf(("IDataObject_fnGetCanonicalFormatEtc STUB"));
3000 return DATA_S_SAMEFORMATETC;
3001}
3002
3003static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
3004{
3005 LPFORMATETC pfeNew, pfeTemp;
3006 LPSTGMEDIUM psmNew, psmTemp;
3007 ICOM_THIS(IDataObjectImpl,iface);
3008
3009 //no need for more than one item
3010 if(This->cDataCount != 0) {
3011 DebugInt3();
3012 return E_OUTOFMEMORY;
3013 }
3014 This->cDataCount++;
3015
3016 pfeNew = malloc(sizeof(FORMATETC) * This->cDataCount);
3017 psmNew = malloc(sizeof(STGMEDIUM) * This->cDataCount);
3018
3019 if(pfeNew && psmNew)
3020 {
3021 memset(pfeNew, 0, sizeof(FORMATETC) * This->cDataCount);
3022 memset(psmNew, 0, sizeof(STGMEDIUM) * This->cDataCount);
3023
3024 /* copy the existing data */
3025 if(This->pFormatEtc)
3026 {
3027 memcpy(pfeNew, This->pFormatEtc, sizeof(FORMATETC) * (This->cDataCount - 1));
3028 }
3029 if(This->pStgMedium)
3030 {
3031 memcpy(psmNew, This->pStgMedium, sizeof(STGMEDIUM) * (This->cDataCount - 1));
3032 }
3033
3034 /* add the new data */
3035 pfeNew[This->cDataCount - 1] = *pformatetc;
3036 if(fRelease)
3037 {
3038 psmNew[This->cDataCount - 1] = *pmedium;
3039 }
3040 else
3041 {
3042 DebugInt3();
3043// CopyStgMedium(pmedium, &psmNew[This->cDataCount - 1]);
3044 }
3045
3046 pfeTemp = This->pFormatEtc;
3047 This->pFormatEtc = pfeNew;
3048 pfeNew = pfeTemp;
3049
3050 psmTemp = This->pStgMedium;
3051 This->pStgMedium = psmNew;
3052 psmNew = psmTemp;
3053 }
3054
3055 if(pfeNew)
3056 free(pfeNew);
3057
3058 if(psmNew)
3059 free(psmNew);
3060
3061 if(This->pFormatEtc && This->pStgMedium)
3062 return S_OK;
3063
3064 return E_OUTOFMEMORY;
3065}
3066
3067static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
3068{
3069 ICOM_THIS(IDataObjectImpl,iface);
3070
3071 TRACE("(%p)->()\n", This);
3072 *ppenumFormatEtc=NULL;
3073
3074 /* only get data */
3075 if (DATADIR_GET == dwDirection)
3076 {
3077 *ppenumFormatEtc = IEnumFORMATETC_Constructor(This->cDataCount, This->pFormatEtc);
3078 return (*ppenumFormatEtc) ? S_OK : E_FAIL;
3079 }
3080
3081 return E_NOTIMPL;
3082}
3083
3084static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
3085{
3086 ICOM_THIS(IDataObjectImpl,iface);
3087
3088 dprintf(("IDataObject_fnDAdvise STUB"));
3089 return E_NOTIMPL;
3090}
3091static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection)
3092{
3093 ICOM_THIS(IDataObjectImpl,iface);
3094
3095 dprintf(("IDataObject_fnDUnadvise STUB"));
3096 return E_NOTIMPL;
3097}
3098static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise)
3099{
3100 ICOM_THIS(IDataObjectImpl,iface);
3101
3102 dprintf(("IDataObject_fnEnumDAdvise STUB"));
3103 return OLE_E_ADVISENOTSUPPORTED;
3104}
3105
3106static struct ICOM_VTABLE(IDataObject) dtovt =
3107{
3108 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3109 IDataObject_fnQueryInterface,
3110 IDataObject_fnAddRef,
3111 IDataObject_fnRelease,
3112 IDataObject_fnGetData,
3113 IDataObject_fnGetDataHere,
3114 IDataObject_fnQueryGetData,
3115 IDataObject_fnGetCanonicalFormatEtc,
3116 IDataObject_fnSetData,
3117 IDataObject_fnEnumFormatEtc,
3118 IDataObject_fnDAdvise,
3119 IDataObject_fnDUnadvise,
3120 IDataObject_fnEnumDAdvise
3121};
3122
3123//******************************************************************************
3124//******************************************************************************
3125BOOL WINAPI OLEDD_AcceptsDragDrop(HWND hwnd)
3126{
3127 DropTargetNode *pTarget;
3128
3129 /*
3130 * Find-out if there is a drag target under the mouse
3131 */
3132 HWND nexttar = hwnd;
3133 do {
3134 pTarget = OLEDD_FindDropTarget(nexttar);
3135 }
3136 while(!pTarget && (nexttar = GetParent(nexttar)) != 0);
3137
3138 if(pTarget != NULL) {
3139 dprintf(("OLEDD_AcceptsDragDrop %x accepted", hwnd));
3140 return TRUE;
3141 }
3142 dprintf(("OLEDD_AcceptsDragDrop %x refused", hwnd));
3143 return FALSE;
3144}
3145//******************************************************************************
3146//******************************************************************************
3147BOOL WINAPI OLEDD_DropFiles(HWND hwnd)
3148{
3149 DropTargetNode *pTarget;
3150 DWORD keyState = 0;
3151 POINTL mousePosParam;
3152 POINT mousePos;
3153 HWND nexttar = hwnd;
3154
3155 dprintf(("OLEDD_DropFiles %x", hwnd));
3156
3157 do {
3158 pTarget = OLEDD_FindDropTarget(nexttar);
3159 }
3160 while(!pTarget && (nexttar = GetParent(nexttar)) != 0);
3161 if(pTarget == NULL) {
3162 return FALSE;
3163 }
3164
3165 /*
3166 * The documentation tells me that the coordinate should be in the target
3167 * window's coordinate space. However, the tests I made tell me the
3168 * coordinates should be in screen coordinates.
3169 */
3170 GetCursorPos(&mousePos);
3171 mousePosParam.x = mousePos.x;
3172 mousePosParam.y = mousePos.y;
3173
3174 if(GetKeyState(VK_SHIFT) & 0x8000) keyState |= MK_SHIFT;
3175 if(GetKeyState(VK_CONTROL) & 0x8000) keyState |= MK_CONTROL;
3176 if(GetKeyState(VK_MENU) & 0x8000) keyState |= MK_ALT;
3177 if(GetKeyState(VK_LBUTTON) & 0x8000) keyState |= MK_LBUTTON;
3178 if(GetKeyState(VK_RBUTTON) & 0x8000) keyState |= MK_RBUTTON;
3179 if(GetKeyState(VK_MBUTTON) & 0x8000) keyState |= MK_MBUTTON;
3180
3181 return IDropTarget_Drop(pTarget->dropTarget, pTarget->pDataObject,
3182 keyState, mousePosParam, &pTarget->dwEffect) == S_OK;
3183}
3184//******************************************************************************
3185//******************************************************************************
3186BOOL WIN32API OLEDD_DragOver(HWND hwnd, DWORD dwEffect)
3187{
3188 DropTargetNode *pTarget;
3189 DWORD keyState = 0;
3190 POINTL mousePosParam;
3191 POINT mousePos;
3192 HWND nexttar = hwnd;
3193
3194 dprintf(("OLEDD_DragOver %x %d", hwnd, dwEffect));
3195
3196 do {
3197 pTarget = OLEDD_FindDropTarget(nexttar);
3198 }
3199 while(!pTarget && (nexttar = GetParent(nexttar)) != 0);
3200 if(pTarget == NULL) {
3201 return FALSE;
3202 }
3203
3204 /*
3205 * The documentation tells me that the coordinate should be in the target
3206 * window's coordinate space. However, the tests I made tell me the
3207 * coordinates should be in screen coordinates.
3208 */
3209 GetCursorPos(&mousePos);
3210 mousePosParam.x = mousePos.x;
3211 mousePosParam.y = mousePos.y;
3212
3213 if(GetKeyState(VK_SHIFT) & 0x8000) keyState |= MK_SHIFT;
3214 if(GetKeyState(VK_CONTROL) & 0x8000) keyState |= MK_CONTROL;
3215 if(GetKeyState(VK_MENU) & 0x8000) keyState |= MK_ALT;
3216 if(GetKeyState(VK_LBUTTON) & 0x8000) keyState |= MK_LBUTTON;
3217 if(GetKeyState(VK_RBUTTON) & 0x8000) keyState |= MK_RBUTTON;
3218 if(GetKeyState(VK_MBUTTON) & 0x8000) keyState |= MK_MBUTTON;
3219 return IDropTarget_DragOver(pTarget->dropTarget, keyState, mousePosParam, &dwEffect) == S_OK;
3220}
3221//******************************************************************************
3222//******************************************************************************
3223BOOL WIN32API OLEDD_DragEnter(HWND hwnd, HDROP hDrop, DWORD dwEffect)
3224{
3225 FORMATETC fe;
3226 STGMEDIUM medium;
3227 DropTargetNode *pTarget;
3228 DWORD keyState = 0;
3229 POINTL mousePosParam;
3230 POINT mousePos;
3231 HWND nexttar = hwnd;
3232
3233 dprintf(("OLEDD_DragEnter %x %x %d", hwnd, hDrop, dwEffect));
3234
3235 do {
3236 pTarget = OLEDD_FindDropTarget(nexttar);
3237 }
3238 while(!pTarget && (nexttar = GetParent(nexttar)) != 0);
3239 if(pTarget == NULL) {
3240 return FALSE;
3241 }
3242
3243 /*
3244 * The documentation tells me that the coordinate should be in the target
3245 * window's coordinate space. However, the tests I made tell me the
3246 * coordinates should be in screen coordinates.
3247 */
3248 GetCursorPos(&mousePos);
3249 mousePosParam.x = mousePos.x;
3250 mousePosParam.y = mousePos.y;
3251
3252 if(GetKeyState(VK_SHIFT) & 0x8000) keyState |= MK_SHIFT;
3253 if(GetKeyState(VK_CONTROL) & 0x8000) keyState |= MK_CONTROL;
3254 if(GetKeyState(VK_MENU) & 0x8000) keyState |= MK_ALT;
3255 if(GetKeyState(VK_LBUTTON) & 0x8000) keyState |= MK_LBUTTON;
3256 if(GetKeyState(VK_RBUTTON) & 0x8000) keyState |= MK_RBUTTON;
3257 if(GetKeyState(VK_MBUTTON) & 0x8000) keyState |= MK_MBUTTON;
3258
3259 /* Note: It's the application's responsibility to free hDrop */
3260 /* TODO: Possible memory leak if app never calls GetData */
3261 fe.cfFormat = CF_HDROP;
3262 fe.ptd = NULL;
3263 fe.dwAspect = DVASPECT_CONTENT;
3264 fe.lindex = -1;
3265 fe.tymed = TYMED_HGLOBAL;
3266
3267 medium.u.hGlobal = hDrop;
3268 medium.tymed = TYMED_HGLOBAL;
3269 medium.pUnkForRelease = NULL;
3270
3271 pTarget->fDragEnter = TRUE;
3272 pTarget->dwEffect = dwEffect;
3273
3274 if(pTarget->pDataObject) {
3275 IDataObject_Release(pTarget->pDataObject);
3276 }
3277
3278 pTarget->pDataObject = IDataObject_Constructor();
3279 IDataObject_SetData(pTarget->pDataObject, &fe, &medium, TRUE);
3280 return IDropTarget_DragEnter(pTarget->dropTarget, pTarget->pDataObject, keyState, mousePosParam, &dwEffect) == S_OK;
3281}
3282//******************************************************************************
3283//******************************************************************************
3284BOOL WIN32API OLEDD_DragLeave(HWND hwnd)
3285{
3286 DropTargetNode *pTarget;
3287 HWND nexttar = hwnd;
3288
3289 dprintf(("OLEDD_DragLeave %x", hwnd));
3290
3291 do {
3292 pTarget = OLEDD_FindDropTarget(nexttar);
3293 }
3294 while(!pTarget && (nexttar = GetParent(nexttar)) != 0);
3295 if(pTarget == NULL) {
3296 return FALSE;
3297 }
3298 pTarget->fDragEnter = FALSE;
3299 if(pTarget->pDataObject) {
3300 IDataObject_Release(pTarget->pDataObject);
3301 pTarget->pDataObject = NULL;
3302 }
3303 return IDropTarget_DragLeave(pTarget->dropTarget) == S_OK;
3304}
3305//******************************************************************************
3306//******************************************************************************
3307
3308#include <oslibdnd.h>
3309
3310typedef struct
3311{
3312 /* IUnknown fields */
3313 ICOM_VFIELD(IDropTarget);
3314 DWORD ref;
3315
3316 LPVOID lpDnDData;
3317 LPSTR lpOS2StringData;
3318 LPVOID lpDragStruct;
3319 POINTL pt;
3320 HGLOBAL hDndData;
3321 FORMATETC format;
3322 STGMEDIUM medium;
3323 LPDATAOBJECT pDataObject;
3324} IDropTargetImpl;
3325
3326
3327/***************************************************************************
3328* IDropTarget_QueryInterface
3329*/
3330static HRESULT WINAPI IDropTarget_fnQueryInterface(IDropTarget *iface, REFIID riid, LPVOID * ppvObj)
3331{
3332 ICOM_THIS(IDropTargetImpl,iface);
3333
3334 dprintf(("IDropTarget_fnQueryInterface (%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj));
3335
3336 *ppvObj = NULL;
3337
3338 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
3339 {
3340 *ppvObj = This;
3341 }
3342 else if(IsEqualIID(riid, &IID_IDropTarget)) /*IDropTarget*/
3343 {
3344 *ppvObj = (IDropTarget*)This;
3345 }
3346
3347 if(*ppvObj)
3348 {
3349 IUnknown_AddRef((IUnknown*)*ppvObj);
3350 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
3351 return S_OK;
3352 }
3353 TRACE("-- Interface: E_NOINTERFACE\n");
3354 return E_NOINTERFACE;
3355}
3356
3357/**************************************************************************
3358* IDropTarget_AddRef
3359*/
3360static ULONG WINAPI IDropTarget_fnAddRef(IDropTarget *iface)
3361{
3362 ICOM_THIS(IDropTargetImpl,iface);
3363
3364 dprintf(("IDropTarget_fnAddRef (%p)->(count=%lu)\n",This, This->ref));
3365
3366 return ++(This->ref);
3367}
3368
3369/**************************************************************************
3370* IDropTarget_fnCleanup
3371*/
3372static ULONG WINAPI IDropTarget_fnCleanup(IDropTarget *iface)
3373{
3374 ICOM_THIS(IDropTargetImpl,iface);
3375
3376 if(This->pDataObject) {
3377 IDataObject_Release(This->pDataObject);
3378 This->pDataObject = 0;
3379 if(This->lpDnDData) {
3380 HeapFree(GetProcessHeap(), 0, This->lpDnDData);
3381 This->lpDnDData = NULL;
3382 }
3383 if(This->lpOS2StringData) {
3384 HeapFree(GetProcessHeap(), 0, This->lpOS2StringData);
3385 This->lpOS2StringData = NULL;
3386 }
3387 if(This->lpDragStruct) {
3388 OSLibFreeDragStruct(This->lpDragStruct);
3389 This->lpDragStruct = NULL;
3390 }
3391 }
3392 return S_OK;
3393}
3394/**************************************************************************
3395* IDropTarget_Release
3396*/
3397static ULONG WINAPI IDropTarget_fnRelease(IDropTarget *iface)
3398{
3399 ICOM_THIS(IDropTargetImpl,iface);
3400
3401 dprintf(("IDropTarget_fnRelease (%p)->(count=%lu)\n",This, This->ref));
3402
3403 IDropTarget_fnCleanup(iface);
3404 if(This->ref == 1) {
3405 if(This->hDndData) {
3406 GlobalFree(This->hDndData);
3407 This->hDndData = 0;
3408 }
3409 }
3410 return --(This->ref);
3411}
3412//******************************************************************************
3413//******************************************************************************
3414static HRESULT WINAPI IDropTarget_fnDragEnter(IDropTarget *iface, IDataObject* pDataObject,
3415 DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
3416{
3417 HRESULT ret;
3418 DWORD size, dwEffect;
3419 LPVOID lpData;
3420 DROPFILES *lpDrop;
3421 LPSTR *lpStringData;
3422 ICOM_THIS(IDropTargetImpl,iface);
3423 DWORD supportedformats[] = {CF_HDROP, CF_TEXT};
3424 int i;
3425
3426 dprintf(("IDropTarget_fnDragEnter %x (%d,%d)", grfKeyState, pt.x, pt.y));
3427 IDropTarget_fnCleanup(iface);
3428
3429 IDataObject_AddRef(pDataObject);
3430 This->pDataObject = pDataObject;
3431
3432#ifdef DEBUG
3433 {
3434 IEnumFORMATETC *enumfmt = NULL;
3435
3436 if(IDataObject_EnumFormatEtc(pDataObject, DATADIR_GET, &enumfmt) == S_OK) {
3437 for (;;) {
3438
3439 FORMATETC tmp;
3440 ULONG actual = 1, res;
3441
3442 res = IEnumFORMATETC_Next(enumfmt, 1, &tmp, &actual);
3443
3444 if(res != S_OK) break;
3445
3446 dprintf(("format %x typed %x", tmp.cfFormat, tmp.tymed));
3447 }
3448 IEnumFORMATETC_Release(enumfmt);
3449 }
3450 }
3451#endif
3452
3453 for(i=0;i<sizeof(supportedformats)/sizeof(supportedformats[0]);i++)
3454 {
3455 This->format.cfFormat = supportedformats[i];
3456 This->format.ptd = NULL;
3457 This->format.dwAspect = DVASPECT_CONTENT;
3458 This->format.lindex = -1;
3459 This->format.tymed = TYMED_HGLOBAL;
3460 ret = IDataObject_GetData(pDataObject, &This->format, &This->medium);
3461 if(ret != S_OK) {
3462 dprintf(("IDataObject_GetData failed with %x", ret));
3463 continue;
3464 }
3465 size = GlobalSize(This->medium.u.hGlobal);
3466 if(size == 0) {
3467 dprintf(("GlobalSize failed for %x", This->medium.u.hGlobal));
3468 ReleaseStgMedium(&This->medium);
3469 return E_OUTOFMEMORY;
3470 }
3471 dprintf(("handle %x size %d, format %x tymed %x", This->medium.u.hGlobal, size, This->format.cfFormat, This->format.tymed));
3472
3473 if(size == 1) {//empty string; use previous data
3474 if(This->hDndData == 0) {
3475 DebugInt3();
3476 ReleaseStgMedium(&This->medium);
3477 return E_OUTOFMEMORY;
3478 }
3479 This->medium.u.hGlobal = This->hDndData;
3480
3481 dprintf(("Reuse old global handle %x", This->hDndData));
3482 size = GlobalSize(This->medium.u.hGlobal);
3483 if(size == 0) {
3484 dprintf(("GlobalSize failed for %x", This->medium.u.hGlobal));
3485 ReleaseStgMedium(&This->medium);
3486 return E_OUTOFMEMORY;
3487 }
3488 dprintf(("handle %x size %d, format %x tymed %x", This->medium.u.hGlobal, size, This->format.cfFormat, This->format.tymed));
3489 }
3490 else This->hDndData = This->medium.u.hGlobal;
3491
3492 This->lpDnDData = (LPVOID)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3493 if(This->lpDnDData == NULL) {
3494 dprintf(("HeapAlloc failed for %d bytes", size));
3495 return E_OUTOFMEMORY;
3496 }
3497 This->lpOS2StringData = (LPVOID)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size*2);
3498 if(This->lpOS2StringData == NULL) {
3499 dprintf(("HeapAlloc failed for %d bytes", size));
3500 return E_OUTOFMEMORY;
3501 }
3502 lpData = GlobalLock(This->medium.u.hGlobal);
3503
3504 if(This->format.cfFormat == CF_HDROP) {
3505 memcpy(This->lpDnDData, lpData, size);
3506 lpDrop = (DROPFILES *)This->lpDnDData;
3507 lpStringData = (LPSTR)(lpDrop) + lpDrop->pFiles;
3508 if(lpDrop->fWide == FALSE) {
3509 OemToCharA((LPSTR)lpStringData, (LPSTR)This->lpOS2StringData);
3510 }
3511 else {
3512 int len;
3513 len = lstrlenW((LPWSTR)lpStringData);
3514 WideCharToMultiByte( CP_OEMCP, 0, (LPWSTR)lpStringData, len, (LPSTR)This->lpOS2StringData, len, NULL, NULL );
3515 }
3516 }
3517 else
3518 if(This->format.cfFormat == CF_TEXT) {
3519 strcpy(This->lpDnDData, lpData);
3520 OemToCharA( This->lpDnDData, This->lpOS2StringData );
3521 }
3522 dprintf(("Drop string %s", This->lpOS2StringData));
3523 GlobalUnlock(This->medium.u.hGlobal);
3524
3525 This->pt = pt;
3526
3527 This->lpDragStruct = OSLibCreateDragStruct(hwndTracker, This->pt.x, This->pt.y, This->lpOS2StringData);
3528 if(This->lpDragStruct == NULL) {
3529 dprintf(("OSLibCreateDragStruct"));
3530 ReleaseStgMedium(&This->medium);
3531 return E_OUTOFMEMORY;
3532 }
3533
3534 dwEffect = OSLibDragOver(This->lpDragStruct, pt.x, pt.y);
3535 break;
3536 }
3537 if(ret != S_OK) {
3538 dprintf(("IDataObject_GetData failed (fatal) with %x", ret));
3539 return ret;
3540 }
3541 if(pdwEffect) {
3542 *pdwEffect = dwEffect;
3543 }
3544
3545 return S_OK;
3546}
3547//******************************************************************************
3548//******************************************************************************
3549static HRESULT WINAPI IDropTarget_fnDragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
3550 DWORD* pdwEffect)
3551{
3552 DWORD dwEffect;
3553 ICOM_THIS(IDropTargetImpl,iface);
3554
3555 dprintf(("IDropTarget_fnDragOver %x (%d,%d)", grfKeyState, pt.x, pt.y));
3556
3557 dwEffect = OSLibDragOver(This->lpDragStruct, pt.x, pt.y);
3558 if(pdwEffect) {
3559 *pdwEffect = dwEffect;
3560 }
3561 return S_OK;
3562}
3563//******************************************************************************
3564//******************************************************************************
3565static HRESULT WINAPI IDropTarget_fnDragLeave(IDropTarget *iface)
3566{
3567 ICOM_THIS(IDropTargetImpl,iface);
3568
3569 dprintf(("IDropTarget_fnDragLeave"));
3570
3571 OSLibDragLeave(This->lpDragStruct);
3572
3573 IDropTarget_fnCleanup(iface);
3574 return S_OK;
3575}
3576//******************************************************************************
3577//******************************************************************************
3578static HRESULT WINAPI IDropTarget_fnDrop(IDropTarget *iface, IDataObject* pDataObject, DWORD grfKeyState,
3579 POINTL pt, DWORD* pdwEffect)
3580{
3581 DWORD dwEffect;
3582 ICOM_THIS(IDropTargetImpl,iface);
3583
3584 dprintf(("IDropTarget_fnDrop %x (%d,%d) %s", grfKeyState, pt.x, pt.y, This->lpOS2StringData));
3585
3586 dwEffect = OSLibDragDrop(This->lpDragStruct, pt.x, pt.y, This->lpOS2StringData);
3587 if(pdwEffect) {
3588 *pdwEffect = dwEffect;
3589 }
3590 return S_OK;
3591}
3592//******************************************************************************
3593//******************************************************************************
3594
3595static struct ICOM_VTABLE(IDropTarget) droptarget =
3596{
3597 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3598 IDropTarget_fnQueryInterface,
3599 IDropTarget_fnAddRef,
3600 IDropTarget_fnRelease,
3601 IDropTarget_fnDragEnter,
3602 IDropTarget_fnDragOver,
3603 IDropTarget_fnDragLeave,
3604 IDropTarget_fnDrop,
3605};
3606
3607
3608/**************************************************************************
3609* IDropTarget_Constructor
3610*/
3611static IDropTarget *IDropTarget_Constructor()
3612{
3613 IDropTargetImpl* dto;
3614
3615 dto = (IDropTargetImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDropTargetImpl));
3616
3617 if (dto)
3618 {
3619 dto->ref = 1;
3620 dto->pDataObject = NULL;
3621 dto->lpDnDData = NULL;
3622 dto->lpOS2StringData = NULL;
3623 dto->hDndData = 0;
3624 ICOM_VTBL(dto) = &droptarget;
3625 }
3626
3627 return (IDropTarget *)dto;
3628}
3629
3630#endif
3631
3632#ifndef __WIN32OS2__
3633/******************************************************************************
3634 * OleMetaFilePictFromIconAndLabel (OLE2.56)
3635 *
3636 * Returns a global memory handle to a metafile which contains the icon and
3637 * label given.
3638 * I guess the result of that should look somehow like desktop icons.
3639 * If no hIcon is given, we load the icon via lpszSourceFile and iIconIndex.
3640 * This code might be wrong at some places.
3641 */
3642HGLOBAL16 WINAPI OleMetaFilePictFromIconAndLabel16(
3643 HICON16 hIcon,
3644 LPCOLESTR16 lpszLabel,
3645 LPCOLESTR16 lpszSourceFile,
3646 UINT16 iIconIndex
3647) {
3648 METAFILEPICT16 *mf;
3649 HGLOBAL16 hmf;
3650 HDC16 hdc;
3651
3652 FIXME("(%04x, '%s', '%s', %d): incorrect metrics, please try to correct them !\n\n\n", hIcon, lpszLabel, lpszSourceFile, iIconIndex);
3653
3654 if (!hIcon) {
3655 if (lpszSourceFile) {
3656 HINSTANCE16 hInstance = LoadLibrary16(lpszSourceFile);
3657
3658 /* load the icon at index from lpszSourceFile */
3659 hIcon = (HICON16)LoadIconA(hInstance, (LPCSTR)(DWORD)iIconIndex);
3660 FreeLibrary16(hInstance);
3661 } else
3662 return (HGLOBAL)NULL;
3663 }
3664
3665 hdc = CreateMetaFile16(NULL);
3666 DrawIcon(hdc, 0, 0, hIcon); /* FIXME */
3667 TextOutA(hdc, 0, 0, lpszLabel, 1); /* FIXME */
3668 hmf = GlobalAlloc16(0, sizeof(METAFILEPICT16));
3669 mf = (METAFILEPICT16 *)GlobalLock16(hmf);
3670 mf->mm = MM_ANISOTROPIC;
3671 mf->xExt = 20; /* FIXME: bogus */
3672 mf->yExt = 20; /* dito */
3673 mf->hMF = CloseMetaFile16(hdc);
3674 return hmf;
3675}
3676#endif
3677
3678/******************************************************************************
3679 * DllDebugObjectRPCHook (OLE32.@)
3680 * turns on and off internal debugging, pointer is only used on macintosh
3681 */
3682
3683BOOL WINAPI DllDebugObjectRPCHook(BOOL b, void *dummy)
3684{
3685 FIXME("stub\n");
3686 return TRUE;
3687}
Note: See TracBrowser for help on using the repository browser.