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

Last change on this file since 10367 was 10185, checked in by sandervl, 22 years ago

Updates

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