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

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

custom build fix

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