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

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

Disabled mouse cursor changes in drag 'n drop code. (causes mouse cursor changes when clicking on item in file open dialog)

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