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

Last change on this file since 8563 was 8563, checked in by sandervl, 23 years ago

fix for drag 'n drop

File size: 76.4 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#include "wine/winbase16.h"
42#include "wine/wingdi16.h"
43#include "wine/winuser16.h"
44#include "ole32_main.h"
45
46#include "wine/debug.h"
47
48WINE_DEFAULT_DEBUG_CHANNEL(ole);
49WINE_DECLARE_DEBUG_CHANNEL(accel);
50
51/******************************************************************************
52 * These are static/global variables and internal data structures that the
53 * OLE module uses to maintain it's state.
54 */
55typedef struct tagDropTargetNode
56{
57 HWND hwndTarget;
58 IDropTarget* dropTarget;
59#ifdef __WIN32OS2__
60 BOOL fDragEnter;
61 DWORD dwEffect;
62 IDataObject * pDataObject;
63 HDROP hDrop;
64#endif
65 struct tagDropTargetNode* prevDropTarget;
66 struct tagDropTargetNode* nextDropTarget;
67} DropTargetNode;
68
69typedef struct tagTrackerWindowInfo
70{
71 IDataObject* dataObject;
72 IDropSource* dropSource;
73 DWORD dwOKEffect;
74 DWORD* pdwEffect;
75 BOOL trackingDone;
76 HRESULT returnValue;
77
78 BOOL escPressed;
79 HWND curDragTargetHWND;
80 IDropTarget* curDragTarget;
81} TrackerWindowInfo;
82
83typedef struct tagOleMenuDescriptor /* OleMenuDescriptor */
84{
85 HWND hwndFrame; /* The containers frame window */
86 HWND hwndActiveObject; /* The active objects window */
87 OLEMENUGROUPWIDTHS mgw; /* OLE menu group widths for the shared menu */
88 HMENU hmenuCombined; /* The combined menu */
89 BOOL bIsServerItem; /* True if the currently open popup belongs to the server */
90} OleMenuDescriptor;
91
92typedef struct tagOleMenuHookItem /* OleMenu hook item in per thread hook list */
93{
94 DWORD tid; /* Thread Id */
95 HANDLE hHeap; /* Heap this is allocated from */
96 HHOOK GetMsg_hHook; /* message hook for WH_GETMESSAGE */
97 HHOOK CallWndProc_hHook; /* message hook for WH_CALLWNDPROC */
98 struct tagOleMenuHookItem *next;
99} OleMenuHookItem;
100
101static OleMenuHookItem *hook_list;
102
103/*
104 * This is the lock count on the OLE library. It is controlled by the
105 * OLEInitialize/OLEUninitialize methods.
106 */
107static ULONG OLE_moduleLockCount = 0;
108
109/*
110 * Name of our registered window class.
111 */
112static const char OLEDD_DRAGTRACKERCLASS[] = "WineDragDropTracker32";
113
114/*
115 * This is the head of the Drop target container.
116 */
117static DropTargetNode* targetListHead = NULL;
118
119/******************************************************************************
120 * These are the prototypes of miscelaneous utility methods
121 */
122static void OLEUTL_ReadRegistryDWORDValue(HKEY regKey, DWORD* pdwValue);
123
124/******************************************************************************
125 * These are the prototypes of the utility methods used to manage a shared menu
126 */
127static void OLEMenu_Initialize();
128static void OLEMenu_UnInitialize();
129BOOL OLEMenu_InstallHooks( DWORD tid );
130BOOL OLEMenu_UnInstallHooks( DWORD tid );
131OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid );
132static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos );
133BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor );
134LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam);
135LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam);
136
137/******************************************************************************
138 * These are the prototypes of the OLE Clipboard initialization methods (in clipboard.c)
139 */
140void OLEClipbrd_UnInitialize();
141void OLEClipbrd_Initialize();
142
143/******************************************************************************
144 * These are the prototypes of the utility methods used for OLE Drag n Drop
145 */
146static void OLEDD_Initialize();
147static void OLEDD_UnInitialize();
148static void OLEDD_InsertDropTarget(
149 DropTargetNode* nodeToAdd);
150static DropTargetNode* OLEDD_ExtractDropTarget(
151 HWND hwndOfTarget);
152static DropTargetNode* OLEDD_FindDropTarget(
153 HWND hwndOfTarget);
154static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
155 HWND hwnd,
156 UINT uMsg,
157 WPARAM wParam,
158 LPARAM lParam);
159static void OLEDD_TrackMouseMove(
160 TrackerWindowInfo* trackerInfo,
161 POINT mousePos,
162 DWORD keyState);
163static void OLEDD_TrackStateChange(
164 TrackerWindowInfo* trackerInfo,
165 POINT mousePos,
166 DWORD keyState);
167static DWORD OLEDD_GetButtonState();
168
169
170/******************************************************************************
171 * OleBuildVersion [OLE2.1]
172 * OleBuildVersion [OLE32.84]
173 */
174DWORD WINAPI OleBuildVersion(void)
175{
176 TRACE("Returning version %d, build %d.\n", rmm, rup);
177 return (rmm<<16)+rup;
178}
179
180/***********************************************************************
181 * OleInitialize (OLE2.2)
182 * OleInitialize (OLE32.108)
183 */
184HRESULT WINAPI OleInitialize(LPVOID reserved)
185{
186 HRESULT hr;
187
188 TRACE("(%p)\n", reserved);
189
190 /*
191 * The first duty of the OleInitialize is to initialize the COM libraries.
192 */
193 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
194
195 /*
196 * If the CoInitializeEx call failed, the OLE libraries can't be
197 * initialized.
198 */
199 if (FAILED(hr))
200 return hr;
201
202 /*
203 * Then, it has to initialize the OLE specific modules.
204 * This includes:
205 * Clipboard
206 * Drag and Drop
207 * Object linking and Embedding
208 * In-place activation
209 */
210 if (OLE_moduleLockCount==0)
211 {
212 /*
213 * Initialize the libraries.
214 */
215 TRACE("() - Initializing the OLE libraries\n");
216
217 /*
218 * OLE Clipboard
219 */
220 OLEClipbrd_Initialize();
221
222 /*
223 * Drag and Drop
224 */
225 OLEDD_Initialize();
226
227 /*
228 * OLE shared menu
229 */
230 OLEMenu_Initialize();
231 }
232
233 /*
234 * Then, we increase the lock count on the OLE module.
235 */
236 OLE_moduleLockCount++;
237
238 return hr;
239}
240
241/******************************************************************************
242 * CoGetCurrentProcess [COMPOBJ.34]
243 * CoGetCurrentProcess [OLE32.18]
244 *
245 * NOTES
246 * Is DWORD really the correct return type for this function?
247 */
248DWORD WINAPI CoGetCurrentProcess(void)
249{
250 return GetCurrentProcessId();
251}
252
253/******************************************************************************
254 * OleUninitialize [OLE2.3]
255 * OleUninitialize [OLE32.131]
256 */
257void WINAPI OleUninitialize(void)
258{
259 TRACE("()\n");
260
261 /*
262 * Decrease the lock count on the OLE module.
263 */
264 OLE_moduleLockCount--;
265
266 /*
267 * If we hit the bottom of the lock stack, free the libraries.
268 */
269 if (OLE_moduleLockCount==0)
270 {
271 /*
272 * Actually free the libraries.
273 */
274 TRACE("() - Freeing the last reference count\n");
275
276 /*
277 * OLE Clipboard
278 */
279 OLEClipbrd_UnInitialize();
280
281 /*
282 * Drag and Drop
283 */
284 OLEDD_UnInitialize();
285
286 /*
287 * OLE shared menu
288 */
289 OLEMenu_UnInitialize();
290 }
291
292 /*
293 * Then, uninitialize the COM libraries.
294 */
295 CoUninitialize();
296}
297
298/******************************************************************************
299 * CoRegisterMessageFilter [OLE32.38]
300 */
301HRESULT WINAPI CoRegisterMessageFilter(
302 LPMESSAGEFILTER lpMessageFilter, /* [in] Pointer to interface */
303 LPMESSAGEFILTER *lplpMessageFilter /* [out] Indirect pointer to prior instance if non-NULL */
304) {
305 FIXME("stub\n");
306 if (lplpMessageFilter) {
307 *lplpMessageFilter = NULL;
308 }
309 return S_OK;
310}
311
312/******************************************************************************
313 * OleInitializeWOW [OLE32.109]
314 */
315HRESULT WINAPI OleInitializeWOW(DWORD x) {
316 FIXME("(0x%08lx),stub!\n",x);
317 return 0;
318}
319
320/***********************************************************************
321 * RegisterDragDrop (OLE2.35)
322 */
323HRESULT WINAPI RegisterDragDrop16(
324 HWND16 hwnd,
325 LPDROPTARGET pDropTarget
326) {
327 FIXME("(0x%04x,%p),stub!\n",hwnd,pDropTarget);
328 return S_OK;
329}
330
331/***********************************************************************
332 * RegisterDragDrop (OLE32.139)
333 */
334HRESULT WINAPI RegisterDragDrop(
335 HWND hwnd,
336 LPDROPTARGET pDropTarget)
337{
338 DropTargetNode* dropTargetInfo;
339
340 TRACE("(0x%x,%p)\n", hwnd, pDropTarget);
341
342 /*
343 * First, check if the window is already registered.
344 */
345 dropTargetInfo = OLEDD_FindDropTarget(hwnd);
346
347 if (dropTargetInfo!=NULL)
348 return DRAGDROP_E_ALREADYREGISTERED;
349
350 /*
351 * If it's not there, we can add it. We first create a node for it.
352 */
353 dropTargetInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(DropTargetNode));
354
355 if (dropTargetInfo==NULL)
356 return E_OUTOFMEMORY;
357
358 dropTargetInfo->hwndTarget = hwnd;
359 dropTargetInfo->prevDropTarget = NULL;
360 dropTargetInfo->nextDropTarget = NULL;
361
362#ifdef __WIN32OS2__
363 dropTargetInfo->hDrop = 0;
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 (OLE2.36)
382 */
383HRESULT WINAPI RevokeDragDrop16(
384 HWND16 hwnd
385) {
386 FIXME("(0x%04x),stub!\n",hwnd);
387 return S_OK;
388}
389
390/***********************************************************************
391 * RevokeDragDrop (OLE32.141)
392 */
393HRESULT WINAPI RevokeDragDrop(
394 HWND hwnd)
395{
396 DropTargetNode* dropTargetInfo;
397
398 TRACE("(0x%x)\n", hwnd);
399
400 /*
401 * First, check if the window is already registered.
402 */
403 dropTargetInfo = OLEDD_ExtractDropTarget(hwnd);
404
405 /*
406 * If it ain't in there, it's an error.
407 */
408 if (dropTargetInfo==NULL)
409 return DRAGDROP_E_NOTREGISTERED;
410
411#ifdef __WIN32OS2__
412 //just in case dragleave wasn't called...
413 if(dropTargetInfo->hDrop) {
414 GlobalFree(dropTargetInfo->hDrop);
415 }
416 if(dropTargetInfo->pDataObject) {
417 IDataObject_Release(dropTargetInfo->pDataObject);
418 }
419#endif
420
421 /*
422 * If it's in there, clean-up it's used memory and
423 * references
424 */
425 IDropTarget_Release(dropTargetInfo->dropTarget);
426 HeapFree(GetProcessHeap(), 0, dropTargetInfo);
427
428 return S_OK;
429}
430
431/***********************************************************************
432 * OleRegGetUserType (OLE32.122)
433 *
434 * This implementation of OleRegGetUserType ignores the dwFormOfType
435 * parameter and always returns the full name of the object. This is
436 * not too bad since this is the case for many objects because of the
437 * way they are registered.
438 */
439HRESULT WINAPI OleRegGetUserType(
440 REFCLSID clsid,
441 DWORD dwFormOfType,
442 LPOLESTR* pszUserType)
443{
444 char keyName[60];
445 DWORD dwKeyType;
446 DWORD cbData;
447 HKEY clsidKey;
448 LONG hres;
449 LPBYTE buffer;
450 HRESULT retVal;
451 /*
452 * Initialize the out parameter.
453 */
454 *pszUserType = NULL;
455
456 /*
457 * Build the key name we're looking for
458 */
459 sprintf( keyName, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\",
460 clsid->Data1, clsid->Data2, clsid->Data3,
461 clsid->Data4[0], clsid->Data4[1], clsid->Data4[2], clsid->Data4[3],
462 clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7] );
463
464 TRACE("(%s, %ld, %p)\n", keyName, dwFormOfType, pszUserType);
465
466 /*
467 * Open the class id Key
468 */
469 hres = RegOpenKeyA(HKEY_CLASSES_ROOT,
470 keyName,
471 &clsidKey);
472
473 if (hres != ERROR_SUCCESS)
474 return REGDB_E_CLASSNOTREG;
475
476 /*
477 * Retrieve the size of the name string.
478 */
479 cbData = 0;
480
481 hres = RegQueryValueExA(clsidKey,
482 "",
483 NULL,
484 &dwKeyType,
485 NULL,
486 &cbData);
487
488 if (hres!=ERROR_SUCCESS)
489 {
490 RegCloseKey(clsidKey);
491 return REGDB_E_READREGDB;
492 }
493
494 /*
495 * Allocate a buffer for the registry value.
496 */
497 *pszUserType = CoTaskMemAlloc(cbData*2);
498
499 if (*pszUserType==NULL)
500 {
501 RegCloseKey(clsidKey);
502 return E_OUTOFMEMORY;
503 }
504
505 buffer = HeapAlloc(GetProcessHeap(), 0, cbData);
506
507 if (buffer == NULL)
508 {
509 RegCloseKey(clsidKey);
510 CoTaskMemFree(*pszUserType);
511 *pszUserType=NULL;
512 return E_OUTOFMEMORY;
513 }
514
515 hres = RegQueryValueExA(clsidKey,
516 "",
517 NULL,
518 &dwKeyType,
519 buffer,
520 &cbData);
521
522 RegCloseKey(clsidKey);
523
524
525 if (hres!=ERROR_SUCCESS)
526 {
527 CoTaskMemFree(*pszUserType);
528 *pszUserType=NULL;
529
530 retVal = REGDB_E_READREGDB;
531 }
532 else
533 {
534 MultiByteToWideChar( CP_ACP, 0, buffer, -1, *pszUserType, cbData /*FIXME*/ );
535 retVal = S_OK;
536 }
537 HeapFree(GetProcessHeap(), 0, buffer);
538
539 return retVal;
540}
541
542/***********************************************************************
543 * DoDragDrop [OLE32.65]
544 */
545HRESULT WINAPI DoDragDrop (
546 IDataObject *pDataObject, /* [in] ptr to the data obj */
547 IDropSource* pDropSource, /* [in] ptr to the source obj */
548 DWORD dwOKEffect, /* [in] effects allowed by the source */
549 DWORD *pdwEffect) /* [out] ptr to effects of the source */
550{
551 TrackerWindowInfo trackerInfo;
552 HWND hwndTrackWindow;
553 MSG msg;
554
555 TRACE("(DataObject %p, DropSource %p)\n", pDataObject, pDropSource);
556
557 /*
558 * Setup the drag n drop tracking window.
559 */
560 trackerInfo.dataObject = pDataObject;
561 trackerInfo.dropSource = pDropSource;
562 trackerInfo.dwOKEffect = dwOKEffect;
563 trackerInfo.pdwEffect = pdwEffect;
564 trackerInfo.trackingDone = FALSE;
565 trackerInfo.escPressed = FALSE;
566 trackerInfo.curDragTargetHWND = 0;
567 trackerInfo.curDragTarget = 0;
568
569 hwndTrackWindow = CreateWindowA(OLEDD_DRAGTRACKERCLASS,
570 "TrackerWindow",
571 WS_POPUP,
572 CW_USEDEFAULT, CW_USEDEFAULT,
573 CW_USEDEFAULT, CW_USEDEFAULT,
574 0,
575 0,
576 0,
577 (LPVOID)&trackerInfo);
578
579 if (hwndTrackWindow!=0)
580 {
581 /*
582 * Capture the mouse input
583 */
584 SetCapture(hwndTrackWindow);
585
586 /*
587 * Pump messages. All mouse input should go the the capture window.
588 */
589 while (!trackerInfo.trackingDone && GetMessageA(&msg, 0, 0, 0) )
590 {
591 if ( (msg.message >= WM_KEYFIRST) &&
592 (msg.message <= WM_KEYLAST) )
593 {
594 /*
595 * When keyboard messages are sent to windows on this thread, we
596 * want to ignore notify the drop source that the state changed.
597 * in the case of the Escape key, we also notify the drop source
598 * we give it a special meaning.
599 */
600 if ( (msg.message==WM_KEYDOWN) &&
601 (msg.wParam==VK_ESCAPE) )
602 {
603 trackerInfo.escPressed = TRUE;
604 }
605
606 /*
607 * Notify the drop source.
608 */
609 OLEDD_TrackStateChange(&trackerInfo,
610 msg.pt,
611 OLEDD_GetButtonState());
612 }
613 else
614 {
615 /*
616 * Dispatch the messages only when it's not a keyboard message.
617 */
618 DispatchMessageA(&msg);
619 }
620 }
621
622 /*
623 * Destroy the temporary window.
624 */
625 DestroyWindow(hwndTrackWindow);
626
627 return trackerInfo.returnValue;
628 }
629
630 return E_FAIL;
631}
632
633/***********************************************************************
634 * OleQueryLinkFromData [OLE32.118]
635 */
636HRESULT WINAPI OleQueryLinkFromData(
637 IDataObject* pSrcDataObject)
638{
639 FIXME("(%p),stub!\n", pSrcDataObject);
640 return S_OK;
641}
642
643/***********************************************************************
644 * OleRegGetMiscStatus [OLE32.121]
645 */
646HRESULT WINAPI OleRegGetMiscStatus(
647 REFCLSID clsid,
648 DWORD dwAspect,
649 DWORD* pdwStatus)
650{
651 char keyName[60];
652 HKEY clsidKey;
653 HKEY miscStatusKey;
654 HKEY aspectKey;
655 LONG result;
656
657 /*
658 * Initialize the out parameter.
659 */
660 *pdwStatus = 0;
661
662 /*
663 * Build the key name we're looking for
664 */
665 sprintf( keyName, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\",
666 clsid->Data1, clsid->Data2, clsid->Data3,
667 clsid->Data4[0], clsid->Data4[1], clsid->Data4[2], clsid->Data4[3],
668 clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7] );
669
670 TRACE("(%s, %ld, %p)\n", keyName, dwAspect, pdwStatus);
671
672 /*
673 * Open the class id Key
674 */
675 result = RegOpenKeyA(HKEY_CLASSES_ROOT,
676 keyName,
677 &clsidKey);
678
679 if (result != ERROR_SUCCESS)
680 return REGDB_E_CLASSNOTREG;
681
682 /*
683 * Get the MiscStatus
684 */
685 result = RegOpenKeyA(clsidKey,
686 "MiscStatus",
687 &miscStatusKey);
688
689
690 if (result != ERROR_SUCCESS)
691 {
692 RegCloseKey(clsidKey);
693 return REGDB_E_READREGDB;
694 }
695
696 /*
697 * Read the default value
698 */
699 OLEUTL_ReadRegistryDWORDValue(miscStatusKey, pdwStatus);
700
701 /*
702 * Open the key specific to the requested aspect.
703 */
704 sprintf(keyName, "%ld", dwAspect);
705
706 result = RegOpenKeyA(miscStatusKey,
707 keyName,
708 &aspectKey);
709
710 if (result == ERROR_SUCCESS)
711 {
712 OLEUTL_ReadRegistryDWORDValue(aspectKey, pdwStatus);
713 RegCloseKey(aspectKey);
714 }
715
716 /*
717 * Cleanup
718 */
719 RegCloseKey(miscStatusKey);
720 RegCloseKey(clsidKey);
721
722 return S_OK;
723}
724
725/******************************************************************************
726 * OleSetContainedObject [OLE32.128]
727 */
728HRESULT WINAPI OleSetContainedObject(
729 LPUNKNOWN pUnknown,
730 BOOL fContained)
731{
732 IRunnableObject* runnable = NULL;
733 HRESULT hres;
734
735 TRACE("(%p,%x), stub!\n", pUnknown, fContained);
736
737 hres = IUnknown_QueryInterface(pUnknown,
738 &IID_IRunnableObject,
739 (void**)&runnable);
740
741 if (SUCCEEDED(hres))
742 {
743 hres = IRunnableObject_SetContainedObject(runnable, fContained);
744
745 IRunnableObject_Release(runnable);
746
747 return hres;
748 }
749
750 return S_OK;
751}
752
753/******************************************************************************
754 * OleLoad [OLE32.112]
755 */
756HRESULT WINAPI OleLoad(
757 LPSTORAGE pStg,
758 REFIID riid,
759 LPOLECLIENTSITE pClientSite,
760 LPVOID* ppvObj)
761{
762 IPersistStorage* persistStorage = NULL;
763 IOleObject* oleObject = NULL;
764 STATSTG storageInfo;
765 HRESULT hres;
766
767 TRACE("(%p,%p,%p,%p)\n", pStg, riid, pClientSite, ppvObj);
768
769 /*
770 * TODO, Conversion ... OleDoAutoConvert
771 */
772
773 /*
774 * Get the class ID for the object.
775 */
776 hres = IStorage_Stat(pStg, &storageInfo, STATFLAG_NONAME);
777
778 /*
779 * Now, try and create the handler for the object
780 */
781 hres = CoCreateInstance(&storageInfo.clsid,
782 NULL,
783 CLSCTX_INPROC_HANDLER,
784 &IID_IOleObject,
785 (void**)&oleObject);
786
787 /*
788 * If that fails, as it will most times, load the default
789 * OLE handler.
790 */
791 if (FAILED(hres))
792 {
793 hres = OleCreateDefaultHandler(&storageInfo.clsid,
794 NULL,
795 &IID_IOleObject,
796 (void**)&oleObject);
797 }
798
799 /*
800 * If we couldn't find a handler... this is bad. Abort the whole thing.
801 */
802 if (FAILED(hres))
803 return hres;
804
805 /*
806 * Inform the new object of it's client site.
807 */
808 hres = IOleObject_SetClientSite(oleObject, pClientSite);
809
810 /*
811 * Initialize the object with it's IPersistStorage interface.
812 */
813 hres = IOleObject_QueryInterface(oleObject,
814 &IID_IPersistStorage,
815 (void**)&persistStorage);
816
817 if (SUCCEEDED(hres))
818 {
819 IPersistStorage_Load(persistStorage, pStg);
820
821 IPersistStorage_Release(persistStorage);
822 persistStorage = NULL;
823 }
824
825 /*
826 * Return the requested interface to the caller.
827 */
828 hres = IOleObject_QueryInterface(oleObject, riid, ppvObj);
829
830 /*
831 * Cleanup interfaces used internally
832 */
833 IOleObject_Release(oleObject);
834
835 return hres;
836}
837
838/***********************************************************************
839 * OleSave [OLE32.124]
840 */
841HRESULT WINAPI OleSave(
842 LPPERSISTSTORAGE pPS,
843 LPSTORAGE pStg,
844 BOOL fSameAsLoad)
845{
846 HRESULT hres;
847 CLSID objectClass;
848
849 TRACE("(%p,%p,%x)\n", pPS, pStg, fSameAsLoad);
850
851 /*
852 * First, we transfer the class ID (if available)
853 */
854 hres = IPersistStorage_GetClassID(pPS, &objectClass);
855
856 if (SUCCEEDED(hres))
857 {
858 WriteClassStg(pStg, &objectClass);
859 }
860
861 /*
862 * Then, we ask the object to save itself to the
863 * storage. If it is successful, we commit the storage.
864 */
865 hres = IPersistStorage_Save(pPS, pStg, fSameAsLoad);
866
867 if (SUCCEEDED(hres))
868 {
869 IStorage_Commit(pStg,
870 STGC_DEFAULT);
871 }
872
873 return hres;
874}
875
876
877/******************************************************************************
878 * OleLockRunning [OLE32.114]
879 */
880HRESULT WINAPI OleLockRunning(LPUNKNOWN pUnknown, BOOL fLock, BOOL fLastUnlockCloses)
881{
882 IRunnableObject* runnable = NULL;
883 HRESULT hres;
884
885 TRACE("(%p,%x,%x)\n", pUnknown, fLock, fLastUnlockCloses);
886
887 hres = IUnknown_QueryInterface(pUnknown,
888 &IID_IRunnableObject,
889 (void**)&runnable);
890
891 if (SUCCEEDED(hres))
892 {
893 hres = IRunnableObject_LockRunning(runnable, fLock, fLastUnlockCloses);
894
895 IRunnableObject_Release(runnable);
896
897 return hres;
898 }
899 else
900 return E_INVALIDARG;
901}
902
903
904/**************************************************************************
905 * Internal methods to manage the shared OLE menu in response to the
906 * OLE***MenuDescriptor API
907 */
908
909/***
910 * OLEMenu_Initialize()
911 *
912 * Initializes the OLEMENU data structures.
913 */
914static void OLEMenu_Initialize()
915{
916}
917
918/***
919 * OLEMenu_UnInitialize()
920 *
921 * Releases the OLEMENU data structures.
922 */
923static void OLEMenu_UnInitialize()
924{
925}
926
927/*************************************************************************
928 * OLEMenu_InstallHooks
929 * Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
930 *
931 * RETURNS: TRUE if message hooks were succesfully installed
932 * FALSE on failure
933 */
934BOOL OLEMenu_InstallHooks( DWORD tid )
935{
936 OleMenuHookItem *pHookItem = NULL;
937
938 /* Create an entry for the hook table */
939 if ( !(pHookItem = HeapAlloc(GetProcessHeap(), 0,
940 sizeof(OleMenuHookItem)) ) )
941 return FALSE;
942
943 pHookItem->tid = tid;
944 pHookItem->hHeap = GetProcessHeap();
945
946 /* Install a thread scope message hook for WH_GETMESSAGE */
947 pHookItem->GetMsg_hHook = SetWindowsHookExA( WH_GETMESSAGE, OLEMenu_GetMsgProc,
948 0, GetCurrentThreadId() );
949 if ( !pHookItem->GetMsg_hHook )
950 goto CLEANUP;
951
952 /* Install a thread scope message hook for WH_CALLWNDPROC */
953 pHookItem->CallWndProc_hHook = SetWindowsHookExA( WH_CALLWNDPROC, OLEMenu_CallWndProc,
954 0, GetCurrentThreadId() );
955 if ( !pHookItem->CallWndProc_hHook )
956 goto CLEANUP;
957
958 /* Insert the hook table entry */
959 pHookItem->next = hook_list;
960 hook_list = pHookItem;
961
962 return TRUE;
963
964CLEANUP:
965 /* Unhook any hooks */
966 if ( pHookItem->GetMsg_hHook )
967 UnhookWindowsHookEx( pHookItem->GetMsg_hHook );
968 if ( pHookItem->CallWndProc_hHook )
969 UnhookWindowsHookEx( pHookItem->CallWndProc_hHook );
970 /* Release the hook table entry */
971 HeapFree(pHookItem->hHeap, 0, pHookItem );
972
973 return FALSE;
974}
975
976/*************************************************************************
977 * OLEMenu_UnInstallHooks
978 * UnInstall thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
979 *
980 * RETURNS: TRUE if message hooks were succesfully installed
981 * FALSE on failure
982 */
983BOOL OLEMenu_UnInstallHooks( DWORD tid )
984{
985 OleMenuHookItem *pHookItem = NULL;
986 OleMenuHookItem **ppHook = &hook_list;
987
988 while (*ppHook)
989 {
990 if ((*ppHook)->tid == tid)
991 {
992 pHookItem = *ppHook;
993 *ppHook = pHookItem->next;
994 break;
995 }
996 ppHook = &(*ppHook)->next;
997 }
998 if (!pHookItem) return FALSE;
999
1000 /* Uninstall the hooks installed for this thread */
1001 if ( !UnhookWindowsHookEx( pHookItem->GetMsg_hHook ) )
1002 goto CLEANUP;
1003 if ( !UnhookWindowsHookEx( pHookItem->CallWndProc_hHook ) )
1004 goto CLEANUP;
1005
1006 /* Release the hook table entry */
1007 HeapFree(pHookItem->hHeap, 0, pHookItem );
1008
1009 return TRUE;
1010
1011CLEANUP:
1012 /* Release the hook table entry */
1013 if (pHookItem)
1014 HeapFree(pHookItem->hHeap, 0, pHookItem );
1015
1016 return FALSE;
1017}
1018
1019/*************************************************************************
1020 * OLEMenu_IsHookInstalled
1021 * Tests if OLEMenu hooks have been installed for a thread
1022 *
1023 * RETURNS: The pointer and index of the hook table entry for the tid
1024 * NULL and -1 for the index if no hooks were installed for this thread
1025 */
1026OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid )
1027{
1028 OleMenuHookItem *pHookItem = NULL;
1029
1030 /* Do a simple linear search for an entry whose tid matches ours.
1031 * We really need a map but efficiency is not a concern here. */
1032 for (pHookItem = hook_list; pHookItem; pHookItem = pHookItem->next)
1033 {
1034 if ( tid == pHookItem->tid )
1035 return pHookItem;
1036 }
1037
1038 return NULL;
1039}
1040
1041/***********************************************************************
1042 * OLEMenu_FindMainMenuIndex
1043 *
1044 * Used by OLEMenu API to find the top level group a menu item belongs to.
1045 * On success pnPos contains the index of the item in the top level menu group
1046 *
1047 * RETURNS: TRUE if the ID was found, FALSE on failure
1048 */
1049static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos )
1050{
1051 UINT i, nItems;
1052
1053 nItems = GetMenuItemCount( hMainMenu );
1054
1055 for (i = 0; i < nItems; i++)
1056 {
1057 HMENU hsubmenu;
1058
1059 /* Is the current item a submenu? */
1060 if ( (hsubmenu = GetSubMenu(hMainMenu, i)) )
1061 {
1062 /* If the handle is the same we're done */
1063 if ( hsubmenu == hPopupMenu )
1064 {
1065 if (pnPos)
1066 *pnPos = i;
1067 return TRUE;
1068 }
1069 /* Recursively search without updating pnPos */
1070 else if ( OLEMenu_FindMainMenuIndex( hsubmenu, hPopupMenu, NULL ) )
1071 {
1072 if (pnPos)
1073 *pnPos = i;
1074 return TRUE;
1075 }
1076 }
1077 }
1078
1079 return FALSE;
1080}
1081
1082/***********************************************************************
1083 * OLEMenu_SetIsServerMenu
1084 *
1085 * Checks whether a popup menu belongs to a shared menu group which is
1086 * owned by the server, and sets the menu descriptor state accordingly.
1087 * All menu messages from these groups should be routed to the server.
1088 *
1089 * RETURNS: TRUE if the popup menu is part of a server owned group
1090 * FASE if the popup menu is part of a container owned group
1091 */
1092BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor )
1093{
1094 UINT nPos = 0, nWidth, i;
1095
1096 pOleMenuDescriptor->bIsServerItem = FALSE;
1097
1098 /* Don't bother searching if the popup is the combined menu itself */
1099 if ( hmenu == pOleMenuDescriptor->hmenuCombined )
1100 return FALSE;
1101
1102 /* Find the menu item index in the shared OLE menu that this item belongs to */
1103 if ( !OLEMenu_FindMainMenuIndex( pOleMenuDescriptor->hmenuCombined, hmenu, &nPos ) )
1104 return FALSE;
1105
1106 /* The group widths array has counts for the number of elements
1107 * in the groups File, Edit, Container, Object, Window, Help.
1108 * The Edit, Object & Help groups belong to the server object
1109 * and the other three belong to the container.
1110 * Loop through the group widths and locate the group we are a member of.
1111 */
1112 for ( i = 0, nWidth = 0; i < 6; i++ )
1113 {
1114 nWidth += pOleMenuDescriptor->mgw.width[i];
1115 if ( nPos < nWidth )
1116 {
1117 /* Odd elements are server menu widths */
1118 pOleMenuDescriptor->bIsServerItem = (i%2) ? TRUE : FALSE;
1119 break;
1120 }
1121 }
1122
1123 return pOleMenuDescriptor->bIsServerItem;
1124}
1125
1126/*************************************************************************
1127 * OLEMenu_CallWndProc
1128 * Thread scope WH_CALLWNDPROC hook proc filter function (callback)
1129 * This is invoked from a message hook installed in OleSetMenuDescriptor.
1130 */
1131LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam)
1132{
1133 LPCWPSTRUCT pMsg = NULL;
1134 HOLEMENU hOleMenu = 0;
1135 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1136 OleMenuHookItem *pHookItem = NULL;
1137 WORD fuFlags;
1138
1139 TRACE("%i, %04x, %08x\n", code, wParam, (unsigned)lParam );
1140
1141 /* Check if we're being asked to process the message */
1142 if ( HC_ACTION != code )
1143 goto NEXTHOOK;
1144
1145 /* Retrieve the current message being dispatched from lParam */
1146 pMsg = (LPCWPSTRUCT)lParam;
1147
1148 /* Check if the message is destined for a window we are interested in:
1149 * If the window has an OLEMenu property we may need to dispatch
1150 * the menu message to its active objects window instead. */
1151
1152 hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" );
1153 if ( !hOleMenu )
1154 goto NEXTHOOK;
1155
1156 /* Get the menu descriptor */
1157 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1158 if ( !pOleMenuDescriptor ) /* Bad descriptor! */
1159 goto NEXTHOOK;
1160
1161 /* Process menu messages */
1162 switch( pMsg->message )
1163 {
1164 case WM_INITMENU:
1165 {
1166 /* Reset the menu descriptor state */
1167 pOleMenuDescriptor->bIsServerItem = FALSE;
1168
1169 /* Send this message to the server as well */
1170 SendMessageA( pOleMenuDescriptor->hwndActiveObject,
1171 pMsg->message, pMsg->wParam, pMsg->lParam );
1172 goto NEXTHOOK;
1173 }
1174
1175 case WM_INITMENUPOPUP:
1176 {
1177 /* Save the state for whether this is a server owned menu */
1178 OLEMenu_SetIsServerMenu( (HMENU)pMsg->wParam, pOleMenuDescriptor );
1179 break;
1180 }
1181
1182 case WM_MENUSELECT:
1183 {
1184 fuFlags = HIWORD(pMsg->wParam); /* Get flags */
1185 if ( fuFlags & MF_SYSMENU )
1186 goto NEXTHOOK;
1187
1188 /* Save the state for whether this is a server owned popup menu */
1189 else if ( fuFlags & MF_POPUP )
1190 OLEMenu_SetIsServerMenu( (HMENU)pMsg->lParam, pOleMenuDescriptor );
1191
1192 break;
1193 }
1194
1195 case WM_DRAWITEM:
1196 {
1197 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) pMsg->lParam;
1198 if ( pMsg->wParam != 0 || lpdis->CtlType != ODT_MENU )
1199 goto NEXTHOOK; /* Not a menu message */
1200
1201 break;
1202 }
1203
1204 default:
1205 goto NEXTHOOK;
1206 }
1207
1208 /* If the message was for the server dispatch it accordingly */
1209 if ( pOleMenuDescriptor->bIsServerItem )
1210 {
1211 SendMessageA( pOleMenuDescriptor->hwndActiveObject,
1212 pMsg->message, pMsg->wParam, pMsg->lParam );
1213 }
1214
1215NEXTHOOK:
1216 if ( pOleMenuDescriptor )
1217 GlobalUnlock( hOleMenu );
1218
1219 /* Lookup the hook item for the current thread */
1220 if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) )
1221 {
1222 /* This should never fail!! */
1223 WARN("could not retrieve hHook for current thread!\n" );
1224 return 0;
1225 }
1226
1227 /* Pass on the message to the next hooker */
1228 return CallNextHookEx( pHookItem->CallWndProc_hHook, code, wParam, lParam );
1229}
1230
1231/*************************************************************************
1232 * OLEMenu_GetMsgProc
1233 * Thread scope WH_GETMESSAGE hook proc filter function (callback)
1234 * This is invoked from a message hook installed in OleSetMenuDescriptor.
1235 */
1236LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam)
1237{
1238 LPMSG pMsg = NULL;
1239 HOLEMENU hOleMenu = 0;
1240 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1241 OleMenuHookItem *pHookItem = NULL;
1242 WORD wCode;
1243
1244 TRACE("%i, %04x, %08x\n", code, wParam, (unsigned)lParam );
1245
1246 /* Check if we're being asked to process a messages */
1247 if ( HC_ACTION != code )
1248 goto NEXTHOOK;
1249
1250 /* Retrieve the current message being dispatched from lParam */
1251 pMsg = (LPMSG)lParam;
1252
1253 /* Check if the message is destined for a window we are interested in:
1254 * If the window has an OLEMenu property we may need to dispatch
1255 * the menu message to its active objects window instead. */
1256
1257 hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" );
1258 if ( !hOleMenu )
1259 goto NEXTHOOK;
1260
1261 /* Process menu messages */
1262 switch( pMsg->message )
1263 {
1264 case WM_COMMAND:
1265 {
1266 wCode = HIWORD(pMsg->wParam); /* Get notification code */
1267 if ( wCode )
1268 goto NEXTHOOK; /* Not a menu message */
1269 break;
1270 }
1271 default:
1272 goto NEXTHOOK;
1273 }
1274
1275 /* Get the menu descriptor */
1276 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1277 if ( !pOleMenuDescriptor ) /* Bad descriptor! */
1278 goto NEXTHOOK;
1279
1280 /* If the message was for the server dispatch it accordingly */
1281 if ( pOleMenuDescriptor->bIsServerItem )
1282 {
1283 /* Change the hWnd in the message to the active objects hWnd.
1284 * The message loop which reads this message will automatically
1285 * dispatch it to the embedded objects window. */
1286 pMsg->hwnd = pOleMenuDescriptor->hwndActiveObject;
1287 }
1288
1289NEXTHOOK:
1290 if ( pOleMenuDescriptor )
1291 GlobalUnlock( hOleMenu );
1292
1293 /* Lookup the hook item for the current thread */
1294 if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) )
1295 {
1296 /* This should never fail!! */
1297 WARN("could not retrieve hHook for current thread!\n" );
1298 return FALSE;
1299 }
1300
1301 /* Pass on the message to the next hooker */
1302 return CallNextHookEx( pHookItem->GetMsg_hHook, code, wParam, lParam );
1303}
1304
1305/***********************************************************************
1306 * OleCreateMenuDescriptor [OLE32.97]
1307 * Creates an OLE menu descriptor for OLE to use when dispatching
1308 * menu messages and commands.
1309 *
1310 * PARAMS:
1311 * hmenuCombined - Handle to the objects combined menu
1312 * lpMenuWidths - Pointer to array of 6 LONG's indicating menus per group
1313 *
1314 */
1315HOLEMENU WINAPI OleCreateMenuDescriptor(
1316 HMENU hmenuCombined,
1317 LPOLEMENUGROUPWIDTHS lpMenuWidths)
1318{
1319 HOLEMENU hOleMenu;
1320 OleMenuDescriptor *pOleMenuDescriptor;
1321 int i;
1322
1323 if ( !hmenuCombined || !lpMenuWidths )
1324 return 0;
1325
1326 /* Create an OLE menu descriptor */
1327 if ( !(hOleMenu = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
1328 sizeof(OleMenuDescriptor) ) ) )
1329 return 0;
1330
1331 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1332 if ( !pOleMenuDescriptor )
1333 return 0;
1334
1335 /* Initialize menu group widths and hmenu */
1336 for ( i = 0; i < 6; i++ )
1337 pOleMenuDescriptor->mgw.width[i] = lpMenuWidths->width[i];
1338
1339 pOleMenuDescriptor->hmenuCombined = hmenuCombined;
1340 pOleMenuDescriptor->bIsServerItem = FALSE;
1341 GlobalUnlock( hOleMenu );
1342
1343 return hOleMenu;
1344}
1345
1346/***********************************************************************
1347 * OleDestroyMenuDescriptor [OLE32.99]
1348 * Destroy the shared menu descriptor
1349 */
1350HRESULT WINAPI OleDestroyMenuDescriptor(
1351 HOLEMENU hmenuDescriptor)
1352{
1353 if ( hmenuDescriptor )
1354 GlobalFree( hmenuDescriptor );
1355 return S_OK;
1356}
1357
1358/***********************************************************************
1359 * OleSetMenuDescriptor [OLE32.129]
1360 * Installs or removes OLE dispatching code for the containers frame window
1361 * FIXME: The lpFrame and lpActiveObject parameters are currently ignored
1362 * OLE should install context sensitive help F1 filtering for the app when
1363 * these are non null.
1364 *
1365 * PARAMS:
1366 * hOleMenu Handle to composite menu descriptor
1367 * hwndFrame Handle to containers frame window
1368 * hwndActiveObject Handle to objects in-place activation window
1369 * lpFrame Pointer to IOleInPlaceFrame on containers window
1370 * lpActiveObject Pointer to IOleInPlaceActiveObject on active in-place object
1371 *
1372 * RETURNS:
1373 * S_OK - menu installed correctly
1374 * E_FAIL, E_INVALIDARG, E_UNEXPECTED - failure
1375 */
1376HRESULT WINAPI OleSetMenuDescriptor(
1377 HOLEMENU hOleMenu,
1378 HWND hwndFrame,
1379 HWND hwndActiveObject,
1380 LPOLEINPLACEFRAME lpFrame,
1381 LPOLEINPLACEACTIVEOBJECT lpActiveObject)
1382{
1383 OleMenuDescriptor *pOleMenuDescriptor = NULL;
1384
1385 /* Check args */
1386 if ( !hwndFrame || (hOleMenu && !hwndActiveObject) )
1387 return E_INVALIDARG;
1388
1389 if ( lpFrame || lpActiveObject )
1390 {
1391 FIXME("(%x, %x, %x, %p, %p), Context sensitive help filtering not implemented!\n",
1392 (unsigned int)hOleMenu,
1393 hwndFrame,
1394 hwndActiveObject,
1395 lpFrame,
1396 lpActiveObject);
1397 }
1398
1399 /* Set up a message hook to intercept the containers frame window messages.
1400 * The message filter is responsible for dispatching menu messages from the
1401 * shared menu which are intended for the object.
1402 */
1403
1404 if ( hOleMenu ) /* Want to install dispatching code */
1405 {
1406 /* If OLEMenu hooks are already installed for this thread, fail
1407 * Note: This effectively means that OleSetMenuDescriptor cannot
1408 * be called twice in succession on the same frame window
1409 * without first calling it with a null hOleMenu to uninstall */
1410 if ( OLEMenu_IsHookInstalled( GetCurrentThreadId() ) )
1411 return E_FAIL;
1412
1413 /* Get the menu descriptor */
1414 pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
1415 if ( !pOleMenuDescriptor )
1416 return E_UNEXPECTED;
1417
1418 /* Update the menu descriptor */
1419 pOleMenuDescriptor->hwndFrame = hwndFrame;
1420 pOleMenuDescriptor->hwndActiveObject = hwndActiveObject;
1421
1422 GlobalUnlock( hOleMenu );
1423 pOleMenuDescriptor = NULL;
1424
1425 /* Add a menu descriptor windows property to the frame window */
1426 SetPropA( hwndFrame, "PROP_OLEMenuDescriptor", hOleMenu );
1427
1428 /* Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC */
1429 if ( !OLEMenu_InstallHooks( GetCurrentThreadId() ) )
1430 return E_FAIL;
1431 }
1432 else /* Want to uninstall dispatching code */
1433 {
1434 /* Uninstall the hooks */
1435 if ( !OLEMenu_UnInstallHooks( GetCurrentThreadId() ) )
1436 return E_FAIL;
1437
1438 /* Remove the menu descriptor property from the frame window */
1439 RemovePropA( hwndFrame, "PROP_OLEMenuDescriptor" );
1440 }
1441
1442 return S_OK;
1443}
1444
1445/******************************************************************************
1446 * IsAccelerator [OLE32.75]
1447 * Mostly copied from controls/menu.c TranslateAccelerator implementation
1448 */
1449BOOL WINAPI IsAccelerator(HACCEL hAccel, int cAccelEntries, LPMSG lpMsg, WORD* lpwCmd)
1450{
1451 /* YES, Accel16! */
1452 LPACCEL16 lpAccelTbl;
1453 int i;
1454
1455 if(!lpMsg) return FALSE;
1456
1457#ifdef __WIN32OS2__
1458 if (!hAccel || !(lpAccelTbl = (LPACCEL16)LockResource(hAccel)))
1459#else
1460 if (!hAccel || !(lpAccelTbl = (LPACCEL16)LockResource16(hAccel)))
1461#endif
1462 {
1463 WARN_(accel)("invalid accel handle=%04x\n", hAccel);
1464 return FALSE;
1465 }
1466 if((lpMsg->message != WM_KEYDOWN &&
1467 lpMsg->message != WM_KEYUP &&
1468 lpMsg->message != WM_SYSKEYDOWN &&
1469 lpMsg->message != WM_SYSKEYUP &&
1470 lpMsg->message != WM_CHAR)) return FALSE;
1471
1472 TRACE_(accel)("hAccel=%04x, cAccelEntries=%d,"
1473 "msg->hwnd=%04x, msg->message=%04x, wParam=%08x, lParam=%08lx\n",
1474 hAccel, cAccelEntries,
1475 lpMsg->hwnd, lpMsg->message, lpMsg->wParam, lpMsg->lParam);
1476 for(i = 0; i < cAccelEntries; i++)
1477 {
1478 if(lpAccelTbl[i].key != lpMsg->wParam)
1479 continue;
1480
1481 if(lpMsg->message == WM_CHAR)
1482 {
1483 if(!(lpAccelTbl[i].fVirt & FALT) && !(lpAccelTbl[i].fVirt & FVIRTKEY))
1484 {
1485 TRACE_(accel)("found accel for WM_CHAR: ('%c')\n", lpMsg->wParam & 0xff);
1486 goto found;
1487 }
1488 }
1489 else
1490 {
1491 if(lpAccelTbl[i].fVirt & FVIRTKEY)
1492 {
1493 INT mask = 0;
1494 TRACE_(accel)("found accel for virt_key %04x (scan %04x)\n",
1495 lpMsg->wParam, HIWORD(lpMsg->lParam) & 0xff);
1496 if(GetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT;
1497 if(GetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL;
1498 if(GetKeyState(VK_MENU) & 0x8000) mask |= FALT;
1499 if(mask == (lpAccelTbl[i].fVirt & (FSHIFT | FCONTROL | FALT))) goto found;
1500 TRACE_(accel)("incorrect SHIFT/CTRL/ALT-state\n");
1501 }
1502 else
1503 {
1504 if(!(lpMsg->lParam & 0x01000000)) /* no special_key */
1505 {
1506 if((lpAccelTbl[i].fVirt & FALT) && (lpMsg->lParam & 0x20000000))
1507 { /* ^^ ALT pressed */
1508 TRACE_(accel)("found accel for Alt-%c\n", lpMsg->wParam & 0xff);
1509 goto found;
1510 }
1511 }
1512 }
1513 }
1514 }
1515
1516 WARN_(accel)("couldn't translate accelerator key\n");
1517 return FALSE;
1518
1519found:
1520 if(lpwCmd) *lpwCmd = lpAccelTbl[i].cmd;
1521 return TRUE;
1522}
1523
1524/***********************************************************************
1525 * ReleaseStgMedium [OLE32.140]
1526 */
1527void WINAPI ReleaseStgMedium(
1528 STGMEDIUM* pmedium)
1529{
1530 switch (pmedium->tymed)
1531 {
1532 case TYMED_HGLOBAL:
1533 {
1534 if ( (pmedium->pUnkForRelease==0) &&
1535 (pmedium->u.hGlobal!=0) )
1536 GlobalFree(pmedium->u.hGlobal);
1537
1538 pmedium->u.hGlobal = 0;
1539 break;
1540 }
1541 case TYMED_FILE:
1542 {
1543 if (pmedium->u.lpszFileName!=0)
1544 {
1545 if (pmedium->pUnkForRelease==0)
1546 {
1547 DeleteFileW(pmedium->u.lpszFileName);
1548 }
1549
1550 CoTaskMemFree(pmedium->u.lpszFileName);
1551 }
1552
1553 pmedium->u.lpszFileName = 0;
1554 break;
1555 }
1556 case TYMED_ISTREAM:
1557 {
1558 if (pmedium->u.pstm!=0)
1559 {
1560 IStream_Release(pmedium->u.pstm);
1561 }
1562
1563 pmedium->u.pstm = 0;
1564 break;
1565 }
1566 case TYMED_ISTORAGE:
1567 {
1568 if (pmedium->u.pstg!=0)
1569 {
1570 IStorage_Release(pmedium->u.pstg);
1571 }
1572
1573 pmedium->u.pstg = 0;
1574 break;
1575 }
1576 case TYMED_GDI:
1577 {
1578 if ( (pmedium->pUnkForRelease==0) &&
1579 (pmedium->u.hGlobal!=0) )
1580 DeleteObject(pmedium->u.hGlobal);
1581
1582 pmedium->u.hGlobal = 0;
1583 break;
1584 }
1585 case TYMED_MFPICT:
1586 {
1587 if ( (pmedium->pUnkForRelease==0) &&
1588 (pmedium->u.hMetaFilePict!=0) )
1589 {
1590 LPMETAFILEPICT pMP = GlobalLock(pmedium->u.hGlobal);
1591 DeleteMetaFile(pMP->hMF);
1592 GlobalUnlock(pmedium->u.hGlobal);
1593 GlobalFree(pmedium->u.hGlobal);
1594 }
1595
1596 pmedium->u.hMetaFilePict = 0;
1597 break;
1598 }
1599 case TYMED_ENHMF:
1600 {
1601 if ( (pmedium->pUnkForRelease==0) &&
1602 (pmedium->u.hEnhMetaFile!=0) )
1603 {
1604 DeleteEnhMetaFile(pmedium->u.hEnhMetaFile);
1605 }
1606
1607 pmedium->u.hEnhMetaFile = 0;
1608 break;
1609 }
1610 case TYMED_NULL:
1611 default:
1612 break;
1613 }
1614
1615 /*
1616 * After cleaning up, the unknown is released
1617 */
1618 if (pmedium->pUnkForRelease!=0)
1619 {
1620 IUnknown_Release(pmedium->pUnkForRelease);
1621 pmedium->pUnkForRelease = 0;
1622 }
1623}
1624
1625/***
1626 * OLEDD_Initialize()
1627 *
1628 * Initializes the OLE drag and drop data structures.
1629 */
1630static void OLEDD_Initialize()
1631{
1632 WNDCLASSA wndClass;
1633
1634 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1635 wndClass.style = CS_GLOBALCLASS;
1636 wndClass.lpfnWndProc = (WNDPROC)OLEDD_DragTrackerWindowProc;
1637 wndClass.cbClsExtra = 0;
1638 wndClass.cbWndExtra = sizeof(TrackerWindowInfo*);
1639 wndClass.hCursor = 0;
1640 wndClass.hbrBackground = 0;
1641 wndClass.lpszClassName = OLEDD_DRAGTRACKERCLASS;
1642
1643 RegisterClassA (&wndClass);
1644}
1645
1646/***
1647 * OLEDD_UnInitialize()
1648 *
1649 * Releases the OLE drag and drop data structures.
1650 */
1651static void OLEDD_UnInitialize()
1652{
1653 /*
1654 * Simply empty the list.
1655 */
1656 while (targetListHead!=NULL)
1657 {
1658 RevokeDragDrop(targetListHead->hwndTarget);
1659 }
1660}
1661
1662/***
1663 * OLEDD_InsertDropTarget()
1664 *
1665 * Insert the target node in the tree.
1666 */
1667static void OLEDD_InsertDropTarget(DropTargetNode* nodeToAdd)
1668{
1669 DropTargetNode* curNode;
1670 DropTargetNode** parentNodeLink;
1671
1672 /*
1673 * Iterate the tree to find the insertion point.
1674 */
1675 curNode = targetListHead;
1676 parentNodeLink = &targetListHead;
1677
1678 while (curNode!=NULL)
1679 {
1680 if (nodeToAdd->hwndTarget<curNode->hwndTarget)
1681 {
1682 /*
1683 * If the node we want to add has a smaller HWND, go left
1684 */
1685 parentNodeLink = &curNode->prevDropTarget;
1686 curNode = curNode->prevDropTarget;
1687 }
1688 else if (nodeToAdd->hwndTarget>curNode->hwndTarget)
1689 {
1690 /*
1691 * If the node we want to add has a larger HWND, go right
1692 */
1693 parentNodeLink = &curNode->nextDropTarget;
1694 curNode = curNode->nextDropTarget;
1695 }
1696 else
1697 {
1698 /*
1699 * The item was found in the list. It shouldn't have been there
1700 */
1701 assert(FALSE);
1702 return;
1703 }
1704 }
1705
1706 /*
1707 * If we get here, we have found a spot for our item. The parentNodeLink
1708 * pointer points to the pointer that we have to modify.
1709 * The curNode should be NULL. We just have to establish the link and Voila!
1710 */
1711 assert(curNode==NULL);
1712 assert(parentNodeLink!=NULL);
1713 assert(*parentNodeLink==NULL);
1714
1715 *parentNodeLink=nodeToAdd;
1716}
1717
1718/***
1719 * OLEDD_ExtractDropTarget()
1720 *
1721 * Removes the target node from the tree.
1722 */
1723static DropTargetNode* OLEDD_ExtractDropTarget(HWND hwndOfTarget)
1724{
1725 DropTargetNode* curNode;
1726 DropTargetNode** parentNodeLink;
1727
1728 /*
1729 * Iterate the tree to find the insertion point.
1730 */
1731 curNode = targetListHead;
1732 parentNodeLink = &targetListHead;
1733
1734 while (curNode!=NULL)
1735 {
1736 if (hwndOfTarget<curNode->hwndTarget)
1737 {
1738 /*
1739 * If the node we want to add has a smaller HWND, go left
1740 */
1741 parentNodeLink = &curNode->prevDropTarget;
1742 curNode = curNode->prevDropTarget;
1743 }
1744 else if (hwndOfTarget>curNode->hwndTarget)
1745 {
1746 /*
1747 * If the node we want to add has a larger HWND, go right
1748 */
1749 parentNodeLink = &curNode->nextDropTarget;
1750 curNode = curNode->nextDropTarget;
1751 }
1752 else
1753 {
1754 /*
1755 * The item was found in the list. Detach it from it's parent and
1756 * re-insert it's kids in the tree.
1757 */
1758 assert(parentNodeLink!=NULL);
1759 assert(*parentNodeLink==curNode);
1760
1761 /*
1762 * We arbitrately re-attach the left sub-tree to the parent.
1763 */
1764 *parentNodeLink = curNode->prevDropTarget;
1765
1766 /*
1767 * And we re-insert the right subtree
1768 */
1769 if (curNode->nextDropTarget!=NULL)
1770 {
1771 OLEDD_InsertDropTarget(curNode->nextDropTarget);
1772 }
1773
1774 /*
1775 * The node we found is still a valid node once we complete
1776 * the unlinking of the kids.
1777 */
1778 curNode->nextDropTarget=NULL;
1779 curNode->prevDropTarget=NULL;
1780
1781 return curNode;
1782 }
1783 }
1784
1785 /*
1786 * If we get here, the node is not in the tree
1787 */
1788 return NULL;
1789}
1790
1791/***
1792 * OLEDD_FindDropTarget()
1793 *
1794 * Finds information about the drop target.
1795 */
1796static DropTargetNode* OLEDD_FindDropTarget(HWND hwndOfTarget)
1797{
1798 DropTargetNode* curNode;
1799
1800 /*
1801 * Iterate the tree to find the HWND value.
1802 */
1803 curNode = targetListHead;
1804
1805 while (curNode!=NULL)
1806 {
1807 if (hwndOfTarget<curNode->hwndTarget)
1808 {
1809 /*
1810 * If the node we want to add has a smaller HWND, go left
1811 */
1812 curNode = curNode->prevDropTarget;
1813 }
1814 else if (hwndOfTarget>curNode->hwndTarget)
1815 {
1816 /*
1817 * If the node we want to add has a larger HWND, go right
1818 */
1819 curNode = curNode->nextDropTarget;
1820 }
1821 else
1822 {
1823 /*
1824 * The item was found in the list.
1825 */
1826 return curNode;
1827 }
1828 }
1829
1830 /*
1831 * If we get here, the item is not in the list
1832 */
1833 return NULL;
1834}
1835
1836/***
1837 * OLEDD_DragTrackerWindowProc()
1838 *
1839 * This method is the WindowProcedure of the drag n drop tracking
1840 * window. During a drag n Drop operation, an invisible window is created
1841 * to receive the user input and act upon it. This procedure is in charge
1842 * of this behavior.
1843 */
1844static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
1845 HWND hwnd,
1846 UINT uMsg,
1847 WPARAM wParam,
1848 LPARAM lParam)
1849{
1850 switch (uMsg)
1851 {
1852 case WM_CREATE:
1853 {
1854 LPCREATESTRUCTA createStruct = (LPCREATESTRUCTA)lParam;
1855
1856 SetWindowLongA(hwnd, 0, (LONG)createStruct->lpCreateParams);
1857
1858
1859 break;
1860 }
1861 case WM_MOUSEMOVE:
1862 {
1863 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
1864 POINT mousePos;
1865
1866 /*
1867 * Get the current mouse position in screen coordinates.
1868 */
1869 mousePos.x = LOWORD(lParam);
1870 mousePos.y = HIWORD(lParam);
1871 ClientToScreen(hwnd, &mousePos);
1872
1873 /*
1874 * Track the movement of the mouse.
1875 */
1876 OLEDD_TrackMouseMove(trackerInfo, mousePos, wParam);
1877
1878 break;
1879 }
1880 case WM_LBUTTONUP:
1881 case WM_MBUTTONUP:
1882 case WM_RBUTTONUP:
1883 case WM_LBUTTONDOWN:
1884 case WM_MBUTTONDOWN:
1885 case WM_RBUTTONDOWN:
1886 {
1887 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
1888 POINT mousePos;
1889
1890 /*
1891 * Get the current mouse position in screen coordinates.
1892 */
1893 mousePos.x = LOWORD(lParam);
1894 mousePos.y = HIWORD(lParam);
1895 ClientToScreen(hwnd, &mousePos);
1896
1897 /*
1898 * Notify everyone that the button state changed
1899 * TODO: Check if the "escape" key was pressed.
1900 */
1901 OLEDD_TrackStateChange(trackerInfo, mousePos, wParam);
1902
1903 break;
1904 }
1905 }
1906
1907 /*
1908 * This is a window proc after all. Let's call the default.
1909 */
1910 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1911}
1912
1913/***
1914 * OLEDD_TrackMouseMove()
1915 *
1916 * This method is invoked while a drag and drop operation is in effect.
1917 * it will generate the appropriate callbacks in the drop source
1918 * and drop target. It will also provide the expected feedback to
1919 * the user.
1920 *
1921 * params:
1922 * trackerInfo - Pointer to the structure identifying the
1923 * drag & drop operation that is currently
1924 * active.
1925 * mousePos - Current position of the mouse in screen
1926 * coordinates.
1927 * keyState - Contains the state of the shift keys and the
1928 * mouse buttons (MK_LBUTTON and the like)
1929 */
1930static void OLEDD_TrackMouseMove(
1931 TrackerWindowInfo* trackerInfo,
1932 POINT mousePos,
1933 DWORD keyState)
1934{
1935 HWND hwndNewTarget = 0;
1936 HRESULT hr = S_OK;
1937
1938 /*
1939 * Get the handle of the window under the mouse
1940 */
1941 hwndNewTarget = WindowFromPoint(mousePos);
1942
1943 /*
1944 * Every time, we re-initialize the effects passed to the
1945 * IDropTarget to the effects allowed by the source.
1946 */
1947 *trackerInfo->pdwEffect = trackerInfo->dwOKEffect;
1948
1949 /*
1950 * If we are hovering over the same target as before, send the
1951 * DragOver notification
1952 */
1953 if ( (trackerInfo->curDragTarget != 0) &&
1954 (trackerInfo->curDragTargetHWND==hwndNewTarget) )
1955 {
1956 POINTL mousePosParam;
1957
1958 /*
1959 * The documentation tells me that the coordinate should be in the target
1960 * window's coordinate space. However, the tests I made tell me the
1961 * coordinates should be in screen coordinates.
1962 */
1963 mousePosParam.x = mousePos.x;
1964 mousePosParam.y = mousePos.y;
1965
1966 IDropTarget_DragOver(trackerInfo->curDragTarget,
1967 keyState,
1968 mousePosParam,
1969 trackerInfo->pdwEffect);
1970 }
1971 else
1972 {
1973 DropTargetNode* newDropTargetNode = 0;
1974
1975 /*
1976 * If we changed window, we have to notify our old target and check for
1977 * the new one.
1978 */
1979 if (trackerInfo->curDragTarget!=0)
1980 {
1981 IDropTarget_DragLeave(trackerInfo->curDragTarget);
1982 }
1983
1984 /*
1985 * Make sure we're hovering over a window.
1986 */
1987 if (hwndNewTarget!=0)
1988 {
1989 /*
1990 * Find-out if there is a drag target under the mouse
1991 */
1992 HWND nexttar = hwndNewTarget;
1993 do {
1994 newDropTargetNode = OLEDD_FindDropTarget(nexttar);
1995 } while (!newDropTargetNode && (nexttar = GetParent(nexttar)) != 0);
1996 if(nexttar) hwndNewTarget = nexttar;
1997
1998 trackerInfo->curDragTargetHWND = hwndNewTarget;
1999 trackerInfo->curDragTarget = newDropTargetNode ? newDropTargetNode->dropTarget : 0;
2000
2001 /*
2002 * If there is, notify it that we just dragged-in
2003 */
2004 if (trackerInfo->curDragTarget!=0)
2005 {
2006 POINTL mousePosParam;
2007
2008 /*
2009 * The documentation tells me that the coordinate should be in the target
2010 * window's coordinate space. However, the tests I made tell me the
2011 * coordinates should be in screen coordinates.
2012 */
2013 mousePosParam.x = mousePos.x;
2014 mousePosParam.y = mousePos.y;
2015
2016 IDropTarget_DragEnter(trackerInfo->curDragTarget,
2017 trackerInfo->dataObject,
2018 keyState,
2019 mousePosParam,
2020 trackerInfo->pdwEffect);
2021 }
2022 }
2023 else
2024 {
2025 /*
2026 * The mouse is not over a window so we don't track anything.
2027 */
2028 trackerInfo->curDragTargetHWND = 0;
2029 trackerInfo->curDragTarget = 0;
2030 }
2031 }
2032
2033 /*
2034 * Now that we have done that, we have to tell the source to give
2035 * us feedback on the work being done by the target. If we don't
2036 * have a target, simulate no effect.
2037 */
2038 if (trackerInfo->curDragTarget==0)
2039 {
2040 *trackerInfo->pdwEffect = DROPEFFECT_NONE;
2041 }
2042
2043 hr = IDropSource_GiveFeedback(trackerInfo->dropSource,
2044 *trackerInfo->pdwEffect);
2045
2046 /*
2047 * When we ask for feedback from the drop source, sometimes it will
2048 * do all the necessary work and sometimes it will not handle it
2049 * when that's the case, we must display the standard drag and drop
2050 * cursors.
2051 */
2052 if (hr==DRAGDROP_S_USEDEFAULTCURSORS)
2053 {
2054 if (*trackerInfo->pdwEffect & DROPEFFECT_MOVE)
2055 {
2056 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(1)));
2057 }
2058 else if (*trackerInfo->pdwEffect & DROPEFFECT_COPY)
2059 {
2060 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(2)));
2061 }
2062 else if (*trackerInfo->pdwEffect & DROPEFFECT_LINK)
2063 {
2064 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(3)));
2065 }
2066 else
2067 {
2068 SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(0)));
2069 }
2070 }
2071}
2072
2073/***
2074 * OLEDD_TrackStateChange()
2075 *
2076 * This method is invoked while a drag and drop operation is in effect.
2077 * It is used to notify the drop target/drop source callbacks when
2078 * the state of the keyboard or mouse button change.
2079 *
2080 * params:
2081 * trackerInfo - Pointer to the structure identifying the
2082 * drag & drop operation that is currently
2083 * active.
2084 * mousePos - Current position of the mouse in screen
2085 * coordinates.
2086 * keyState - Contains the state of the shift keys and the
2087 * mouse buttons (MK_LBUTTON and the like)
2088 */
2089static void OLEDD_TrackStateChange(
2090 TrackerWindowInfo* trackerInfo,
2091 POINT mousePos,
2092 DWORD keyState)
2093{
2094 /*
2095 * Ask the drop source what to do with the operation.
2096 */
2097 trackerInfo->returnValue = IDropSource_QueryContinueDrag(
2098 trackerInfo->dropSource,
2099 trackerInfo->escPressed,
2100 keyState);
2101
2102 /*
2103 * All the return valued will stop the operation except the S_OK
2104 * return value.
2105 */
2106 if (trackerInfo->returnValue!=S_OK)
2107 {
2108 /*
2109 * Make sure the message loop in DoDragDrop stops
2110 */
2111 trackerInfo->trackingDone = TRUE;
2112
2113 /*
2114 * Release the mouse in case the drop target decides to show a popup
2115 * or a menu or something.
2116 */
2117 ReleaseCapture();
2118
2119 /*
2120 * If we end-up over a target, drop the object in the target or
2121 * inform the target that the operation was cancelled.
2122 */
2123 if (trackerInfo->curDragTarget!=0)
2124 {
2125 switch (trackerInfo->returnValue)
2126 {
2127 /*
2128 * If the source wants us to complete the operation, we tell
2129 * the drop target that we just dropped the object in it.
2130 */
2131 case DRAGDROP_S_DROP:
2132 {
2133 POINTL mousePosParam;
2134
2135 /*
2136 * The documentation tells me that the coordinate should be
2137 * in the target window's coordinate space. However, the tests
2138 * I made tell me the coordinates should be in screen coordinates.
2139 */
2140 mousePosParam.x = mousePos.x;
2141 mousePosParam.y = mousePos.y;
2142
2143 IDropTarget_Drop(trackerInfo->curDragTarget,
2144 trackerInfo->dataObject,
2145 keyState,
2146 mousePosParam,
2147 trackerInfo->pdwEffect);
2148 break;
2149 }
2150 /*
2151 * If the source told us that we should cancel, fool the drop
2152 * target by telling it that the mouse left it's window.
2153 * Also set the drop effect to "NONE" in case the application
2154 * ignores the result of DoDragDrop.
2155 */
2156 case DRAGDROP_S_CANCEL:
2157 IDropTarget_DragLeave(trackerInfo->curDragTarget);
2158 *trackerInfo->pdwEffect = DROPEFFECT_NONE;
2159 break;
2160 }
2161 }
2162 }
2163}
2164
2165/***
2166 * OLEDD_GetButtonState()
2167 *
2168 * This method will use the current state of the keyboard to build
2169 * a button state mask equivalent to the one passed in the
2170 * WM_MOUSEMOVE wParam.
2171 */
2172static DWORD OLEDD_GetButtonState()
2173{
2174 BYTE keyboardState[256];
2175 DWORD keyMask = 0;
2176
2177 GetKeyboardState(keyboardState);
2178
2179 if ( (keyboardState[VK_SHIFT] & 0x80) !=0)
2180 keyMask |= MK_SHIFT;
2181
2182 if ( (keyboardState[VK_CONTROL] & 0x80) !=0)
2183 keyMask |= MK_CONTROL;
2184
2185 if ( (keyboardState[VK_LBUTTON] & 0x80) !=0)
2186 keyMask |= MK_LBUTTON;
2187
2188 if ( (keyboardState[VK_RBUTTON] & 0x80) !=0)
2189 keyMask |= MK_RBUTTON;
2190
2191 if ( (keyboardState[VK_MBUTTON] & 0x80) !=0)
2192 keyMask |= MK_MBUTTON;
2193
2194 return keyMask;
2195}
2196
2197/***
2198 * OLEDD_GetButtonState()
2199 *
2200 * This method will read the default value of the registry key in
2201 * parameter and extract a DWORD value from it. The registry key value
2202 * can be in a string key or a DWORD key.
2203 *
2204 * params:
2205 * regKey - Key to read the default value from
2206 * pdwValue - Pointer to the location where the DWORD
2207 * value is returned. This value is not modified
2208 * if the value is not found.
2209 */
2210
2211static void OLEUTL_ReadRegistryDWORDValue(
2212 HKEY regKey,
2213 DWORD* pdwValue)
2214{
2215 char buffer[20];
2216 DWORD dwKeyType;
2217 DWORD cbData = 20;
2218 LONG lres;
2219
2220 lres = RegQueryValueExA(regKey,
2221 "",
2222 NULL,
2223 &dwKeyType,
2224 (LPBYTE)buffer,
2225 &cbData);
2226
2227 if (lres==ERROR_SUCCESS)
2228 {
2229 switch (dwKeyType)
2230 {
2231 case REG_DWORD:
2232 *pdwValue = *(DWORD*)buffer;
2233 break;
2234 case REG_EXPAND_SZ:
2235 case REG_MULTI_SZ:
2236 case REG_SZ:
2237 *pdwValue = (DWORD)strtoul(buffer, NULL, 10);
2238 break;
2239 }
2240 }
2241}
2242#ifdef __WIN32OS2__
2243#include <dbglog.h>
2244
2245/***********************************************************************
2246* IEnumFORMATETC implementation
2247*/
2248
2249typedef struct
2250{
2251 /* IUnknown fields */
2252 ICOM_VFIELD(IEnumFORMATETC);
2253 DWORD ref;
2254 /* IEnumFORMATETC fields */
2255 UINT posFmt;
2256 UINT countFmt;
2257 LPFORMATETC pFmt;
2258} IEnumFORMATETCImpl;
2259
2260static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj);
2261static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface);
2262static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface);
2263static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC* rgelt, ULONG* pceltFethed);
2264static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt);
2265static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface);
2266static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
2267
2268static struct ICOM_VTABLE(IEnumFORMATETC) efvt =
2269{
2270 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2271 IEnumFORMATETC_fnQueryInterface,
2272 IEnumFORMATETC_fnAddRef,
2273 IEnumFORMATETC_fnRelease,
2274 IEnumFORMATETC_fnNext,
2275 IEnumFORMATETC_fnSkip,
2276 IEnumFORMATETC_fnReset,
2277 IEnumFORMATETC_fnClone
2278};
2279
2280static LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[])
2281{
2282 IEnumFORMATETCImpl* ef;
2283 DWORD size=cfmt * sizeof(FORMATETC);
2284
2285 ef=(IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl));
2286
2287 if(ef)
2288 {
2289 ef->ref=1;
2290 ICOM_VTBL(ef)=&efvt;
2291
2292 ef->countFmt = cfmt;
2293 ef->pFmt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2294
2295 if (ef->pFmt)
2296 {
2297 memcpy(ef->pFmt, afmt, size);
2298 }
2299 }
2300
2301 TRACE("(%p)->(%u,%p)\n",ef, cfmt, afmt);
2302 return (LPENUMFORMATETC)ef;
2303}
2304
2305static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
2306{
2307 ICOM_THIS(IEnumFORMATETCImpl,iface);
2308 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2309
2310 *ppvObj = NULL;
2311
2312 if(IsEqualIID(riid, &IID_IUnknown))
2313 {
2314 *ppvObj = This;
2315 }
2316 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
2317 {
2318 *ppvObj = (IEnumFORMATETC*)This;
2319 }
2320
2321 if(*ppvObj)
2322 {
2323 IUnknown_AddRef((IUnknown*)(*ppvObj));
2324 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
2325 return S_OK;
2326 }
2327 TRACE("-- Interface: E_NOINTERFACE\n");
2328 return E_NOINTERFACE;
2329
2330}
2331
2332static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface)
2333{
2334 ICOM_THIS(IEnumFORMATETCImpl,iface);
2335 TRACE("(%p)->(count=%lu)\n",This, This->ref);
2336 return ++(This->ref);
2337}
2338
2339static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface)
2340{
2341 ICOM_THIS(IEnumFORMATETCImpl,iface);
2342 TRACE("(%p)->()\n",This);
2343
2344 if (!--(This->ref))
2345 {
2346 TRACE(" destroying IEnumFORMATETC(%p)\n",This);
2347 if (This->pFmt)
2348 {
2349 HeapFree(GetProcessHeap(),0, This->pFmt);
2350 }
2351 HeapFree(GetProcessHeap(),0,This);
2352 return 0;
2353 }
2354 return This->ref;
2355}
2356
2357static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
2358{
2359 ICOM_THIS(IEnumFORMATETCImpl,iface);
2360 int i;
2361
2362 TRACE("(%p)->(%lu,%p)\n", This, celt, rgelt);
2363
2364 if(!This->pFmt)return S_FALSE;
2365 if(!rgelt) return E_INVALIDARG;
2366 if (pceltFethed) *pceltFethed = 0;
2367
2368 for(i = 0; This->posFmt < This->countFmt && celt > i; i++)
2369 {
2370 *rgelt++ = This->pFmt[This->posFmt++];
2371 }
2372
2373 if (pceltFethed) *pceltFethed = i;
2374
2375 return ((i == celt) ? S_OK : S_FALSE);
2376}
2377
2378static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt)
2379{
2380 ICOM_THIS(IEnumFORMATETCImpl,iface);
2381 TRACE("(%p)->(num=%lu)\n", This, celt);
2382
2383 if((This->posFmt + celt) >= This->countFmt) return S_FALSE;
2384 This->posFmt += celt;
2385 return S_OK;
2386}
2387
2388static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface)
2389{
2390 ICOM_THIS(IEnumFORMATETCImpl,iface);
2391 TRACE("(%p)->()\n", This);
2392
2393 This->posFmt = 0;
2394 return S_OK;
2395}
2396
2397static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
2398{
2399 ICOM_THIS(IEnumFORMATETCImpl,iface);
2400 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
2401
2402 if (!ppenum) return E_INVALIDARG;
2403 *ppenum = IEnumFORMATETC_Constructor(This->countFmt, This->pFmt);
2404 return S_OK;
2405}
2406
2407/***********************************************************************
2408* IDataObject implementation
2409*/
2410
2411
2412typedef struct
2413{
2414 /* IUnknown fields */
2415 ICOM_VFIELD(IDataObject);
2416 DWORD ref;
2417
2418 /* IDataObject fields */
2419 LPFORMATETC pFormatEtc;
2420 LPSTGMEDIUM pStgMedium;
2421 DWORD cDataCount;
2422} IDataObjectImpl;
2423
2424static struct ICOM_VTABLE(IDataObject) dtovt;
2425
2426/**************************************************************************
2427* IDataObject_Constructor
2428*/
2429static LPDATAOBJECT IDataObject_Constructor()
2430{
2431 IDataObjectImpl* dto;
2432
2433 dto = (IDataObjectImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDataObjectImpl));
2434
2435 if (dto)
2436 {
2437 dto->ref = 1;
2438 ICOM_VTBL(dto) = &dtovt;
2439 }
2440
2441 return (LPDATAOBJECT)dto;
2442}
2443
2444/***************************************************************************
2445* IDataObject_QueryInterface
2446*/
2447static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID * ppvObj)
2448{
2449 ICOM_THIS(IDataObjectImpl,iface);
2450 dprintf(("IDataObject_fnQueryInterface (%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj));
2451
2452 *ppvObj = NULL;
2453
2454 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
2455 {
2456 *ppvObj = This;
2457 }
2458 else if(IsEqualIID(riid, &IID_IDataObject)) /*IDataObject*/
2459 {
2460 *ppvObj = (IDataObject*)This;
2461 }
2462
2463 if(*ppvObj)
2464 {
2465 IUnknown_AddRef((IUnknown*)*ppvObj);
2466 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
2467 return S_OK;
2468 }
2469 TRACE("-- Interface: E_NOINTERFACE\n");
2470 return E_NOINTERFACE;
2471}
2472
2473/**************************************************************************
2474* IDataObject_AddRef
2475*/
2476static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface)
2477{
2478 ICOM_THIS(IDataObjectImpl,iface);
2479
2480 dprintf(("IDataObject_fnAddRef (%p)->(count=%lu)\n",This, This->ref));
2481
2482 return ++(This->ref);
2483}
2484
2485/**************************************************************************
2486* IDataObject_Release
2487*/
2488static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface)
2489{
2490 ICOM_THIS(IDataObjectImpl,iface);
2491 dprintf(("IDataObject_fnRelease (%p)->()\n",This));
2492
2493 if (!--(This->ref))
2494 {
2495 TRACE(" destroying IDataObject(%p)\n",This);
2496 HeapFree(GetProcessHeap(),0,This);
2497 return 0;
2498 }
2499 return This->ref;
2500}
2501
2502/**************************************************************************
2503* IDataObject_fnGetData
2504*/
2505static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
2506{
2507 int i;
2508
2509 ICOM_THIS(IDataObjectImpl,iface);
2510
2511 if(pformatetcIn == NULL || pmedium == NULL)
2512 return E_INVALIDARG;
2513
2514 dprintf(("IDataObject_fnGetData %x %x", pformatetcIn, pmedium));
2515
2516 if(pformatetcIn->cfFormat != CF_HDROP)
2517 {
2518 FIXME("-- expected clipformat not implemented\n");
2519 return (E_INVALIDARG);
2520 }
2521
2522 /* check our formats table what we have */
2523 for (i=0; i<This->cDataCount; i++)
2524 {
2525 if ((This->pFormatEtc[i].cfFormat == pformatetcIn->cfFormat)
2526 && (This->pFormatEtc[i].tymed == pformatetcIn->tymed))
2527 {
2528 pmedium->u.hGlobal = This->pStgMedium[i].u.hGlobal;
2529 break;
2530 }
2531 }
2532 if (pmedium->u.hGlobal)
2533 {
2534 pmedium->tymed = TYMED_HGLOBAL;
2535 pmedium->pUnkForRelease = NULL;
2536 return S_OK;
2537 }
2538 return E_OUTOFMEMORY;
2539}
2540
2541static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium)
2542{
2543 ICOM_THIS(IDataObjectImpl,iface);
2544
2545 dprintf(("IDataObject_fnGetDataHere %x %x STUB", pformatetc, pmedium));
2546 return E_NOTIMPL;
2547}
2548
2549static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc)
2550{
2551 ICOM_THIS(IDataObjectImpl,iface);
2552 UINT i;
2553
2554 dprintf(("IDataObject_fnQueryGetData (%p)->(fmt=0x%08x tym=0x%08lx)\n", This, pformatetc->cfFormat, pformatetc->tymed));
2555
2556 if(!(DVASPECT_CONTENT & pformatetc->dwAspect))
2557 return DV_E_DVASPECT;
2558
2559 if(This->pFormatEtc == NULL) {
2560 return DV_E_TYMED;
2561 }
2562 /* check our formats table what we have */
2563 for (i=0; i<This->cDataCount; i++)
2564 {
2565 if ((This->pFormatEtc[i].cfFormat == pformatetc->cfFormat)
2566 && (This->pFormatEtc[i].tymed == pformatetc->tymed))
2567 {
2568 return S_OK;
2569 }
2570 }
2571
2572 return DV_E_TYMED;
2573}
2574
2575static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
2576{
2577 ICOM_THIS(IDataObjectImpl,iface);
2578
2579 dprintf(("IDataObject_fnGetCanonicalFormatEtc STUB"));
2580 return DATA_S_SAMEFORMATETC;
2581}
2582
2583static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
2584{
2585 LPFORMATETC pfeNew, pfeTemp;
2586 LPSTGMEDIUM psmNew, psmTemp;
2587 ICOM_THIS(IDataObjectImpl,iface);
2588
2589 //no need for more than one item
2590 if(This->cDataCount != 0) {
2591 DebugInt3();
2592 return E_OUTOFMEMORY;
2593 }
2594 This->cDataCount++;
2595
2596 pfeNew = malloc(sizeof(FORMATETC) * This->cDataCount);
2597 psmNew = malloc(sizeof(STGMEDIUM) * This->cDataCount);
2598
2599 if(pfeNew && psmNew)
2600 {
2601 memset(pfeNew, 0, sizeof(FORMATETC) * This->cDataCount);
2602 memset(psmNew, 0, sizeof(STGMEDIUM) * This->cDataCount);
2603
2604 /* copy the existing data */
2605 if(This->pFormatEtc)
2606 {
2607 memcpy(pfeNew, This->pFormatEtc, sizeof(FORMATETC) * (This->cDataCount - 1));
2608 }
2609 if(This->pStgMedium)
2610 {
2611 memcpy(psmNew, This->pStgMedium, sizeof(STGMEDIUM) * (This->cDataCount - 1));
2612 }
2613
2614 /* add the new data */
2615 pfeNew[This->cDataCount - 1] = *pformatetc;
2616 if(fRelease)
2617 {
2618 psmNew[This->cDataCount - 1] = *pmedium;
2619 }
2620 else
2621 {
2622 DebugInt3();
2623// CopyStgMedium(pmedium, &psmNew[This->cDataCount - 1]);
2624 }
2625
2626 pfeTemp = This->pFormatEtc;
2627 This->pFormatEtc = pfeNew;
2628 pfeNew = pfeTemp;
2629
2630 psmTemp = This->pStgMedium;
2631 This->pStgMedium = psmNew;
2632 psmNew = psmTemp;
2633 }
2634
2635 if(pfeNew)
2636 free(pfeNew);
2637
2638 if(psmNew)
2639 free(psmNew);
2640
2641 if(This->pFormatEtc && This->pStgMedium)
2642 return S_OK;
2643
2644 return E_OUTOFMEMORY;
2645}
2646
2647static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
2648{
2649 ICOM_THIS(IDataObjectImpl,iface);
2650
2651 TRACE("(%p)->()\n", This);
2652 *ppenumFormatEtc=NULL;
2653
2654 /* only get data */
2655 if (DATADIR_GET == dwDirection)
2656 {
2657 *ppenumFormatEtc = IEnumFORMATETC_Constructor(This->cDataCount, This->pFormatEtc);
2658 return (*ppenumFormatEtc) ? S_OK : E_FAIL;
2659 }
2660
2661 return E_NOTIMPL;
2662}
2663
2664static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
2665{
2666 ICOM_THIS(IDataObjectImpl,iface);
2667
2668 dprintf(("IDataObject_fnDAdvise STUB"));
2669 return E_NOTIMPL;
2670}
2671static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection)
2672{
2673 ICOM_THIS(IDataObjectImpl,iface);
2674
2675 dprintf(("IDataObject_fnDUnadvise STUB"));
2676 return E_NOTIMPL;
2677}
2678static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise)
2679{
2680 ICOM_THIS(IDataObjectImpl,iface);
2681
2682 dprintf(("IDataObject_fnEnumDAdvise STUB"));
2683 return OLE_E_ADVISENOTSUPPORTED;
2684}
2685
2686static struct ICOM_VTABLE(IDataObject) dtovt =
2687{
2688 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2689 IDataObject_fnQueryInterface,
2690 IDataObject_fnAddRef,
2691 IDataObject_fnRelease,
2692 IDataObject_fnGetData,
2693 IDataObject_fnGetDataHere,
2694 IDataObject_fnQueryGetData,
2695 IDataObject_fnGetCanonicalFormatEtc,
2696 IDataObject_fnSetData,
2697 IDataObject_fnEnumFormatEtc,
2698 IDataObject_fnDAdvise,
2699 IDataObject_fnDUnadvise,
2700 IDataObject_fnEnumDAdvise
2701};
2702
2703//******************************************************************************
2704//******************************************************************************
2705BOOL WINAPI OLEDD_AcceptsDragDrop(HWND hwnd)
2706{
2707 DropTargetNode *pTarget;
2708
2709 /*
2710 * Find-out if there is a drag target under the mouse
2711 */
2712 HWND nexttar = hwnd;
2713 do {
2714 pTarget = OLEDD_FindDropTarget(nexttar);
2715 }
2716 while(!pTarget && (nexttar = GetParent(nexttar)) != 0);
2717
2718 if(pTarget != NULL) {
2719 dprintf(("OLEDD_AcceptsDragDrop %x accepted", hwnd));
2720 return TRUE;
2721 }
2722 dprintf(("OLEDD_AcceptsDragDrop %x refused", hwnd));
2723 return FALSE;
2724}
2725//******************************************************************************
2726//******************************************************************************
2727BOOL WINAPI OLEDD_DropFiles(HWND hwnd)
2728{
2729 DropTargetNode *pTarget;
2730 DWORD keyState = 0;
2731 POINTL mousePosParam;
2732 POINT mousePos;
2733 HWND nexttar = hwnd;
2734
2735 dprintf(("OLEDD_DropFiles %x", hwnd));
2736
2737 do {
2738 pTarget = OLEDD_FindDropTarget(nexttar);
2739 }
2740 while(!pTarget && (nexttar = GetParent(nexttar)) != 0);
2741 if(pTarget == NULL) {
2742 return FALSE;
2743 }
2744
2745 /*
2746 * The documentation tells me that the coordinate should be in the target
2747 * window's coordinate space. However, the tests I made tell me the
2748 * coordinates should be in screen coordinates.
2749 */
2750 GetCursorPos(&mousePos);
2751 mousePosParam.x = mousePos.x;
2752 mousePosParam.y = mousePos.y;
2753
2754 if(GetKeyState(VK_SHIFT) & 0x8000) keyState |= MK_SHIFT;
2755 if(GetKeyState(VK_CONTROL) & 0x8000) keyState |= MK_CONTROL;
2756 if(GetKeyState(VK_MENU) & 0x8000) keyState |= MK_ALT;
2757 if(GetKeyState(VK_LBUTTON) & 0x8000) keyState |= MK_LBUTTON;
2758 if(GetKeyState(VK_RBUTTON) & 0x8000) keyState |= MK_RBUTTON;
2759 if(GetKeyState(VK_MBUTTON) & 0x8000) keyState |= MK_MBUTTON;
2760
2761 return IDropTarget_Drop(pTarget->dropTarget, pTarget->pDataObject,
2762 keyState, mousePosParam, &pTarget->dwEffect) == S_OK;
2763}
2764//******************************************************************************
2765//******************************************************************************
2766BOOL WIN32API OLEDD_DragOver(HWND hwnd, DWORD dwEffect)
2767{
2768 DropTargetNode *pTarget;
2769 DWORD keyState = 0;
2770 POINTL mousePosParam;
2771 POINT mousePos;
2772 HWND nexttar = hwnd;
2773
2774 dprintf(("OLEDD_DragOver %x %d", hwnd, dwEffect));
2775
2776 do {
2777 pTarget = OLEDD_FindDropTarget(nexttar);
2778 }
2779 while(!pTarget && (nexttar = GetParent(nexttar)) != 0);
2780 if(pTarget == NULL) {
2781 return FALSE;
2782 }
2783
2784 /*
2785 * The documentation tells me that the coordinate should be in the target
2786 * window's coordinate space. However, the tests I made tell me the
2787 * coordinates should be in screen coordinates.
2788 */
2789 GetCursorPos(&mousePos);
2790 mousePosParam.x = mousePos.x;
2791 mousePosParam.y = mousePos.y;
2792
2793 if(GetKeyState(VK_SHIFT) & 0x8000) keyState |= MK_SHIFT;
2794 if(GetKeyState(VK_CONTROL) & 0x8000) keyState |= MK_CONTROL;
2795 if(GetKeyState(VK_MENU) & 0x8000) keyState |= MK_ALT;
2796 if(GetKeyState(VK_LBUTTON) & 0x8000) keyState |= MK_LBUTTON;
2797 if(GetKeyState(VK_RBUTTON) & 0x8000) keyState |= MK_RBUTTON;
2798 if(GetKeyState(VK_MBUTTON) & 0x8000) keyState |= MK_MBUTTON;
2799 return IDropTarget_DragOver(pTarget->dropTarget, keyState, mousePosParam, &dwEffect) == S_OK;
2800}
2801//******************************************************************************
2802//******************************************************************************
2803BOOL WIN32API OLEDD_DragEnter(HWND hwnd, HDROP hDrop, DWORD dwEffect)
2804{
2805 FORMATETC fe;
2806 STGMEDIUM medium;
2807 DropTargetNode *pTarget;
2808 DWORD keyState = 0;
2809 POINTL mousePosParam;
2810 POINT mousePos;
2811 HWND nexttar = hwnd;
2812
2813 dprintf(("OLEDD_DragEnter %x %x %d", hwnd, hDrop, dwEffect));
2814
2815 do {
2816 pTarget = OLEDD_FindDropTarget(nexttar);
2817 }
2818 while(!pTarget && (nexttar = GetParent(nexttar)) != 0);
2819 if(pTarget == NULL) {
2820 return FALSE;
2821 }
2822
2823 /*
2824 * The documentation tells me that the coordinate should be in the target
2825 * window's coordinate space. However, the tests I made tell me the
2826 * coordinates should be in screen coordinates.
2827 */
2828 GetCursorPos(&mousePos);
2829 mousePosParam.x = mousePos.x;
2830 mousePosParam.y = mousePos.y;
2831
2832 if(GetKeyState(VK_SHIFT) & 0x8000) keyState |= MK_SHIFT;
2833 if(GetKeyState(VK_CONTROL) & 0x8000) keyState |= MK_CONTROL;
2834 if(GetKeyState(VK_MENU) & 0x8000) keyState |= MK_ALT;
2835 if(GetKeyState(VK_LBUTTON) & 0x8000) keyState |= MK_LBUTTON;
2836 if(GetKeyState(VK_RBUTTON) & 0x8000) keyState |= MK_RBUTTON;
2837 if(GetKeyState(VK_MBUTTON) & 0x8000) keyState |= MK_MBUTTON;
2838
2839 fe.cfFormat = CF_HDROP;
2840 fe.ptd = NULL;
2841 fe.dwAspect = DVASPECT_CONTENT;
2842 fe.lindex = -1;
2843 fe.tymed = TYMED_HGLOBAL;
2844
2845 medium.u.hGlobal = hDrop;
2846 medium.tymed = TYMED_HGLOBAL;
2847 medium.pUnkForRelease = NULL;
2848
2849 pTarget->fDragEnter = TRUE;
2850 pTarget->dwEffect = dwEffect;
2851
2852 //just in case dragleave wasn't called...
2853 if(pTarget->hDrop) {
2854 GlobalFree(pTarget->hDrop);
2855 }
2856 if(pTarget->pDataObject) {
2857 IDataObject_Release(pTarget->pDataObject);
2858 }
2859
2860 pTarget->hDrop = hDrop;
2861 pTarget->pDataObject = IDataObject_Constructor();
2862 IDataObject_SetData(pTarget->pDataObject, &fe, &medium, TRUE);
2863 return IDropTarget_DragEnter(pTarget->dropTarget, pTarget->pDataObject, keyState, mousePosParam, &dwEffect) == S_OK;
2864}
2865//******************************************************************************
2866//******************************************************************************
2867BOOL WIN32API OLEDD_DragLeave(HWND hwnd)
2868{
2869 DropTargetNode *pTarget;
2870
2871 dprintf(("OLEDD_DragLeave %x", hwnd));
2872
2873 pTarget = OLEDD_FindDropTarget(hwnd);
2874 if(pTarget == NULL) {
2875 return FALSE;
2876 }
2877 pTarget->fDragEnter = FALSE;
2878 if(pTarget->hDrop) {
2879 GlobalFree(pTarget->hDrop);
2880 pTarget->hDrop = 0;
2881 }
2882 if(pTarget->pDataObject) {
2883 IDataObject_Release(pTarget->pDataObject);
2884 pTarget->pDataObject = NULL;
2885 }
2886 return IDropTarget_DragLeave(pTarget->dropTarget) == S_OK;
2887}
2888//******************************************************************************
2889//******************************************************************************
2890#endif
2891
2892#ifndef __WIN32OS2__
2893/******************************************************************************
2894 * OleMetaFilePictFromIconAndLabel (OLE2.56)
2895 *
2896 * Returns a global memory handle to a metafile which contains the icon and
2897 * label given.
2898 * I guess the result of that should look somehow like desktop icons.
2899 * If no hIcon is given, we load the icon via lpszSourceFile and iIconIndex.
2900 * This code might be wrong at some places.
2901 */
2902HGLOBAL16 WINAPI OleMetaFilePictFromIconAndLabel16(
2903 HICON16 hIcon,
2904 LPCOLESTR16 lpszLabel,
2905 LPCOLESTR16 lpszSourceFile,
2906 UINT16 iIconIndex
2907) {
2908 METAFILEPICT16 *mf;
2909 HGLOBAL16 hmf;
2910 HDC16 hdc;
2911
2912 FIXME("(%04x, '%s', '%s', %d): incorrect metrics, please try to correct them !\n\n\n", hIcon, lpszLabel, lpszSourceFile, iIconIndex);
2913
2914 if (!hIcon) {
2915 if (lpszSourceFile) {
2916 HINSTANCE16 hInstance = LoadLibrary16(lpszSourceFile);
2917
2918 /* load the icon at index from lpszSourceFile */
2919 hIcon = (HICON16)LoadIconA(hInstance, (LPCSTR)(DWORD)iIconIndex);
2920 FreeLibrary16(hInstance);
2921 } else
2922 return (HGLOBAL)NULL;
2923 }
2924
2925 hdc = CreateMetaFile16(NULL);
2926 DrawIcon(hdc, 0, 0, hIcon); /* FIXME */
2927 TextOutA(hdc, 0, 0, lpszLabel, 1); /* FIXME */
2928 hmf = GlobalAlloc16(0, sizeof(METAFILEPICT16));
2929 mf = (METAFILEPICT16 *)GlobalLock16(hmf);
2930 mf->mm = MM_ANISOTROPIC;
2931 mf->xExt = 20; /* FIXME: bogus */
2932 mf->yExt = 20; /* dito */
2933 mf->hMF = CloseMetaFile16(hdc);
2934 return hmf;
2935}
2936#endif
2937
2938/******************************************************************************
2939 * DllDebugObjectRPCHook (OLE32.62)
2940 * turns on and off internal debugging, pointer is only used on macintosh
2941 */
2942
2943BOOL WINAPI DllDebugObjectRPCHook(BOOL b, void *dummy)
2944{
2945 FIXME("stub\n");
2946 return TRUE;
2947}
2948
Note: See TracBrowser for help on using the repository browser.