diff --git a/reactos/lib/ole32/ole2.c b/reactos/lib/ole32/ole2.c deleted file mode 100644 index 0479164138b..00000000000 --- a/reactos/lib/ole32/ole2.c +++ /dev/null @@ -1,2541 +0,0 @@ - -/* - * OLE2 library - * - * Copyright 1995 Martin von Loewis - * Copyright 1999 Francis Beaudet - * Copyright 1999 Noel Borthwick - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#include -#include -#include -#include -#include - -#define NONAMELESSUNION -#define NONAMELESSSTRUCT -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "winreg.h" -#include "commctrl.h" -#include "ole2.h" -#include "ole2ver.h" -#include "wownt32.h" - -#include "wine/winbase16.h" -#include "wine/wingdi16.h" -#include "wine/winuser16.h" -#include "ole32_main.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(ole); -WINE_DECLARE_DEBUG_CHANNEL(accel); - -#define HICON_16(h32) (LOWORD(h32)) -#define HICON_32(h16) ((HICON)(ULONG_PTR)(h16)) -#define HINSTANCE_32(h16) ((HINSTANCE)(ULONG_PTR)(h16)) - -/****************************************************************************** - * These are static/global variables and internal data structures that the - * OLE module uses to maintain it's state. - */ -typedef struct tagDropTargetNode -{ - HWND hwndTarget; - IDropTarget* dropTarget; - struct tagDropTargetNode* prevDropTarget; - struct tagDropTargetNode* nextDropTarget; -} DropTargetNode; - -typedef struct tagTrackerWindowInfo -{ - IDataObject* dataObject; - IDropSource* dropSource; - DWORD dwOKEffect; - DWORD* pdwEffect; - BOOL trackingDone; - HRESULT returnValue; - - BOOL escPressed; - HWND curTargetHWND; /* window the mouse is hovering over */ - HWND curDragTargetHWND; /* might be a ancestor of curTargetHWND */ - IDropTarget* curDragTarget; -} TrackerWindowInfo; - -typedef struct tagOleMenuDescriptor /* OleMenuDescriptor */ -{ - HWND hwndFrame; /* The containers frame window */ - HWND hwndActiveObject; /* The active objects window */ - OLEMENUGROUPWIDTHS mgw; /* OLE menu group widths for the shared menu */ - HMENU hmenuCombined; /* The combined menu */ - BOOL bIsServerItem; /* True if the currently open popup belongs to the server */ -} OleMenuDescriptor; - -typedef struct tagOleMenuHookItem /* OleMenu hook item in per thread hook list */ -{ - DWORD tid; /* Thread Id */ - HANDLE hHeap; /* Heap this is allocated from */ - HHOOK GetMsg_hHook; /* message hook for WH_GETMESSAGE */ - HHOOK CallWndProc_hHook; /* message hook for WH_CALLWNDPROC */ - struct tagOleMenuHookItem *next; -} OleMenuHookItem; - -static OleMenuHookItem *hook_list; - -/* - * This is the lock count on the OLE library. It is controlled by the - * OLEInitialize/OLEUninitialize methods. - */ -static ULONG OLE_moduleLockCount = 0; - -/* - * Name of our registered window class. - */ -static const char OLEDD_DRAGTRACKERCLASS[] = "WineDragDropTracker32"; - -/* - * This is the head of the Drop target container. - */ -static DropTargetNode* targetListHead = NULL; - -/****************************************************************************** - * These are the prototypes of miscelaneous utility methods - */ -static void OLEUTL_ReadRegistryDWORDValue(HKEY regKey, DWORD* pdwValue); - -/****************************************************************************** - * These are the prototypes of the utility methods used to manage a shared menu - */ -static void OLEMenu_Initialize(); -static void OLEMenu_UnInitialize(); -BOOL OLEMenu_InstallHooks( DWORD tid ); -BOOL OLEMenu_UnInstallHooks( DWORD tid ); -OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid ); -static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos ); -BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor ); -LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam); -LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam); - -/****************************************************************************** - * These are the prototypes of the OLE Clipboard initialization methods (in clipboard.c) - */ -void OLEClipbrd_UnInitialize(); -void OLEClipbrd_Initialize(); - -/****************************************************************************** - * These are the prototypes of the utility methods used for OLE Drag n Drop - */ -static void OLEDD_Initialize(); -static void OLEDD_UnInitialize(); -static void OLEDD_InsertDropTarget( - DropTargetNode* nodeToAdd); -static DropTargetNode* OLEDD_ExtractDropTarget( - HWND hwndOfTarget); -static DropTargetNode* OLEDD_FindDropTarget( - HWND hwndOfTarget); -static LRESULT WINAPI OLEDD_DragTrackerWindowProc( - HWND hwnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam); -static void OLEDD_TrackMouseMove( - TrackerWindowInfo* trackerInfo, - POINT mousePos, - DWORD keyState); -static void OLEDD_TrackStateChange( - TrackerWindowInfo* trackerInfo, - POINT mousePos, - DWORD keyState); -static DWORD OLEDD_GetButtonState(); - - -/****************************************************************************** - * OleBuildVersion [OLE2.1] - * OleBuildVersion [OLE32.@] - */ -DWORD WINAPI OleBuildVersion(void) -{ - TRACE("Returning version %d, build %d.\n", rmm, rup); - return (rmm<<16)+rup; -} - -/*********************************************************************** - * OleInitialize (OLE2.2) - * OleInitialize (OLE32.@) - */ -HRESULT WINAPI OleInitialize(LPVOID reserved) -{ - HRESULT hr; - - TRACE("(%p)\n", reserved); - - /* - * The first duty of the OleInitialize is to initialize the COM libraries. - */ - hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); - - /* - * If the CoInitializeEx call failed, the OLE libraries can't be - * initialized. - */ - if (FAILED(hr)) - return hr; - - /* - * Then, it has to initialize the OLE specific modules. - * This includes: - * Clipboard - * Drag and Drop - * Object linking and Embedding - * In-place activation - */ - if (OLE_moduleLockCount==0) - { - /* - * Initialize the libraries. - */ - TRACE("() - Initializing the OLE libraries\n"); - - /* - * OLE Clipboard - */ - OLEClipbrd_Initialize(); - - /* - * Drag and Drop - */ - OLEDD_Initialize(); - - /* - * OLE shared menu - */ - OLEMenu_Initialize(); - } - - /* - * Then, we increase the lock count on the OLE module. - */ - OLE_moduleLockCount++; - - return hr; -} - -/****************************************************************************** - * CoGetCurrentProcess [COMPOBJ.34] - * CoGetCurrentProcess [OLE32.@] - * - * NOTES - * Is DWORD really the correct return type for this function? - */ -DWORD WINAPI CoGetCurrentProcess(void) -{ - return GetCurrentProcessId(); -} - -/****************************************************************************** - * OleUninitialize [OLE2.3] - * OleUninitialize [OLE32.@] - */ -void WINAPI OleUninitialize(void) -{ - TRACE("()\n"); - - /* - * Decrease the lock count on the OLE module. - */ - OLE_moduleLockCount--; - - /* - * If we hit the bottom of the lock stack, free the libraries. - */ - if (OLE_moduleLockCount==0) - { - /* - * Actually free the libraries. - */ - TRACE("() - Freeing the last reference count\n"); - - /* - * OLE Clipboard - */ - OLEClipbrd_UnInitialize(); - - /* - * Drag and Drop - */ - OLEDD_UnInitialize(); - - /* - * OLE shared menu - */ - OLEMenu_UnInitialize(); - } - - /* - * Then, uninitialize the COM libraries. - */ - CoUninitialize(); -} - -/****************************************************************************** - * CoRegisterMessageFilter [OLE32.@] - */ -HRESULT WINAPI CoRegisterMessageFilter( - LPMESSAGEFILTER lpMessageFilter, /* [in] Pointer to interface */ - LPMESSAGEFILTER *lplpMessageFilter /* [out] Indirect pointer to prior instance if non-NULL */ -) { - FIXME("stub\n"); - if (lplpMessageFilter) { - *lplpMessageFilter = NULL; - } - return S_OK; -} - -/****************************************************************************** - * OleInitializeWOW [OLE32.@] - */ -HRESULT WINAPI OleInitializeWOW(DWORD x) { - FIXME("(0x%08lx),stub!\n",x); - return 0; -} - -/*********************************************************************** - * RegisterDragDrop (OLE32.@) - */ -HRESULT WINAPI RegisterDragDrop( - HWND hwnd, - LPDROPTARGET pDropTarget) -{ - DropTargetNode* dropTargetInfo; - - TRACE("(%p,%p)\n", hwnd, pDropTarget); - - /* - * First, check if the window is already registered. - */ - dropTargetInfo = OLEDD_FindDropTarget(hwnd); - - if (dropTargetInfo!=NULL) - return DRAGDROP_E_ALREADYREGISTERED; - - /* - * If it's not there, we can add it. We first create a node for it. - */ - dropTargetInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(DropTargetNode)); - - if (dropTargetInfo==NULL) - return E_OUTOFMEMORY; - - dropTargetInfo->hwndTarget = hwnd; - dropTargetInfo->prevDropTarget = NULL; - dropTargetInfo->nextDropTarget = NULL; - - /* - * Don't forget that this is an interface pointer, need to nail it down since - * we keep a copy of it. - */ - dropTargetInfo->dropTarget = pDropTarget; - IDropTarget_AddRef(dropTargetInfo->dropTarget); - - OLEDD_InsertDropTarget(dropTargetInfo); - - return S_OK; -} - -/*********************************************************************** - * RevokeDragDrop (OLE32.@) - */ -HRESULT WINAPI RevokeDragDrop( - HWND hwnd) -{ - DropTargetNode* dropTargetInfo; - - TRACE("(%p)\n", hwnd); - - /* - * First, check if the window is already registered. - */ - dropTargetInfo = OLEDD_ExtractDropTarget(hwnd); - - /* - * If it ain't in there, it's an error. - */ - if (dropTargetInfo==NULL) - return DRAGDROP_E_NOTREGISTERED; - - /* - * If it's in there, clean-up it's used memory and - * references - */ - IDropTarget_Release(dropTargetInfo->dropTarget); - HeapFree(GetProcessHeap(), 0, dropTargetInfo); - - return S_OK; -} - -/*********************************************************************** - * OleRegGetUserType (OLE32.@) - * - * This implementation of OleRegGetUserType ignores the dwFormOfType - * parameter and always returns the full name of the object. This is - * not too bad since this is the case for many objects because of the - * way they are registered. - */ -HRESULT WINAPI OleRegGetUserType( - REFCLSID clsid, - DWORD dwFormOfType, - LPOLESTR* pszUserType) -{ - char keyName[60]; - DWORD dwKeyType; - DWORD cbData; - HKEY clsidKey; - LONG hres; - LPBYTE buffer; - HRESULT retVal; - /* - * Initialize the out parameter. - */ - *pszUserType = NULL; - - /* - * Build the key name we're looking for - */ - sprintf( keyName, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\", - clsid->Data1, clsid->Data2, clsid->Data3, - clsid->Data4[0], clsid->Data4[1], clsid->Data4[2], clsid->Data4[3], - clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7] ); - - TRACE("(%s, %ld, %p)\n", keyName, dwFormOfType, pszUserType); - - /* - * Open the class id Key - */ - hres = RegOpenKeyA(HKEY_CLASSES_ROOT, - keyName, - &clsidKey); - - if (hres != ERROR_SUCCESS) - return REGDB_E_CLASSNOTREG; - - /* - * Retrieve the size of the name string. - */ - cbData = 0; - - hres = RegQueryValueExA(clsidKey, - "", - NULL, - &dwKeyType, - NULL, - &cbData); - - if (hres!=ERROR_SUCCESS) - { - RegCloseKey(clsidKey); - return REGDB_E_READREGDB; - } - - /* - * Allocate a buffer for the registry value. - */ - *pszUserType = CoTaskMemAlloc(cbData*2); - - if (*pszUserType==NULL) - { - RegCloseKey(clsidKey); - return E_OUTOFMEMORY; - } - - buffer = HeapAlloc(GetProcessHeap(), 0, cbData); - - if (buffer == NULL) - { - RegCloseKey(clsidKey); - CoTaskMemFree(*pszUserType); - *pszUserType=NULL; - return E_OUTOFMEMORY; - } - - hres = RegQueryValueExA(clsidKey, - "", - NULL, - &dwKeyType, - buffer, - &cbData); - - RegCloseKey(clsidKey); - - - if (hres!=ERROR_SUCCESS) - { - CoTaskMemFree(*pszUserType); - *pszUserType=NULL; - - retVal = REGDB_E_READREGDB; - } - else - { - MultiByteToWideChar( CP_ACP, 0, buffer, -1, *pszUserType, cbData /*FIXME*/ ); - retVal = S_OK; - } - HeapFree(GetProcessHeap(), 0, buffer); - - return retVal; -} - -/*********************************************************************** - * DoDragDrop [OLE32.@] - */ -HRESULT WINAPI DoDragDrop ( - IDataObject *pDataObject, /* [in] ptr to the data obj */ - IDropSource* pDropSource, /* [in] ptr to the source obj */ - DWORD dwOKEffect, /* [in] effects allowed by the source */ - DWORD *pdwEffect) /* [out] ptr to effects of the source */ -{ - TrackerWindowInfo trackerInfo; - HWND hwndTrackWindow; - MSG msg; - - TRACE("(DataObject %p, DropSource %p)\n", pDataObject, pDropSource); - - /* - * Setup the drag n drop tracking window. - */ - if (!IsValidInterface((LPUNKNOWN)pDropSource)) - return E_INVALIDARG; - - trackerInfo.dataObject = pDataObject; - trackerInfo.dropSource = pDropSource; - trackerInfo.dwOKEffect = dwOKEffect; - trackerInfo.pdwEffect = pdwEffect; - trackerInfo.trackingDone = FALSE; - trackerInfo.escPressed = FALSE; - trackerInfo.curDragTargetHWND = 0; - trackerInfo.curTargetHWND = 0; - trackerInfo.curDragTarget = 0; - - hwndTrackWindow = CreateWindowA(OLEDD_DRAGTRACKERCLASS, - "TrackerWindow", - WS_POPUP, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - 0, - 0, - 0, - (LPVOID)&trackerInfo); - - if (hwndTrackWindow!=0) - { - /* - * Capture the mouse input - */ - SetCapture(hwndTrackWindow); - - /* - * Pump messages. All mouse input should go the the capture window. - */ - while (!trackerInfo.trackingDone && GetMessageA(&msg, 0, 0, 0) ) - { - if ( (msg.message >= WM_KEYFIRST) && - (msg.message <= WM_KEYLAST) ) - { - /* - * When keyboard messages are sent to windows on this thread, we - * want to ignore notify the drop source that the state changed. - * in the case of the Escape key, we also notify the drop source - * we give it a special meaning. - */ - if ( (msg.message==WM_KEYDOWN) && - (msg.wParam==VK_ESCAPE) ) - { - trackerInfo.escPressed = TRUE; - } - - /* - * Notify the drop source. - */ - OLEDD_TrackStateChange(&trackerInfo, - msg.pt, - OLEDD_GetButtonState()); - } - else - { - /* - * Dispatch the messages only when it's not a keyboard message. - */ - DispatchMessageA(&msg); - } - } - - /* - * Destroy the temporary window. - */ - DestroyWindow(hwndTrackWindow); - - return trackerInfo.returnValue; - } - - return E_FAIL; -} - -/*********************************************************************** - * OleQueryLinkFromData [OLE32.@] - */ -HRESULT WINAPI OleQueryLinkFromData( - IDataObject* pSrcDataObject) -{ - FIXME("(%p),stub!\n", pSrcDataObject); - return S_OK; -} - -/*********************************************************************** - * OleRegGetMiscStatus [OLE32.@] - */ -HRESULT WINAPI OleRegGetMiscStatus( - REFCLSID clsid, - DWORD dwAspect, - DWORD* pdwStatus) -{ - char keyName[60]; - HKEY clsidKey; - HKEY miscStatusKey; - HKEY aspectKey; - LONG result; - - /* - * Initialize the out parameter. - */ - *pdwStatus = 0; - - /* - * Build the key name we're looking for - */ - sprintf( keyName, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\", - clsid->Data1, clsid->Data2, clsid->Data3, - clsid->Data4[0], clsid->Data4[1], clsid->Data4[2], clsid->Data4[3], - clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7] ); - - TRACE("(%s, %ld, %p)\n", keyName, dwAspect, pdwStatus); - - /* - * Open the class id Key - */ - result = RegOpenKeyA(HKEY_CLASSES_ROOT, - keyName, - &clsidKey); - - if (result != ERROR_SUCCESS) - return REGDB_E_CLASSNOTREG; - - /* - * Get the MiscStatus - */ - result = RegOpenKeyA(clsidKey, - "MiscStatus", - &miscStatusKey); - - - if (result != ERROR_SUCCESS) - { - RegCloseKey(clsidKey); - return REGDB_E_READREGDB; - } - - /* - * Read the default value - */ - OLEUTL_ReadRegistryDWORDValue(miscStatusKey, pdwStatus); - - /* - * Open the key specific to the requested aspect. - */ - sprintf(keyName, "%ld", dwAspect); - - result = RegOpenKeyA(miscStatusKey, - keyName, - &aspectKey); - - if (result == ERROR_SUCCESS) - { - OLEUTL_ReadRegistryDWORDValue(aspectKey, pdwStatus); - RegCloseKey(aspectKey); - } - - /* - * Cleanup - */ - RegCloseKey(miscStatusKey); - RegCloseKey(clsidKey); - - return S_OK; -} - -/****************************************************************************** - * OleSetContainedObject [OLE32.@] - */ -HRESULT WINAPI OleSetContainedObject( - LPUNKNOWN pUnknown, - BOOL fContained) -{ - IRunnableObject* runnable = NULL; - HRESULT hres; - - TRACE("(%p,%x), stub!\n", pUnknown, fContained); - - hres = IUnknown_QueryInterface(pUnknown, - &IID_IRunnableObject, - (void**)&runnable); - - if (SUCCEEDED(hres)) - { - hres = IRunnableObject_SetContainedObject(runnable, fContained); - - IRunnableObject_Release(runnable); - - return hres; - } - - return S_OK; -} - -/****************************************************************************** - * OleLoad [OLE32.@] - */ -HRESULT WINAPI OleLoad( - LPSTORAGE pStg, - REFIID riid, - LPOLECLIENTSITE pClientSite, - LPVOID* ppvObj) -{ - IPersistStorage* persistStorage = NULL; - IOleObject* oleObject = NULL; - STATSTG storageInfo; - HRESULT hres; - - TRACE("(%p,%p,%p,%p)\n", pStg, riid, pClientSite, ppvObj); - - /* - * TODO, Conversion ... OleDoAutoConvert - */ - - /* - * Get the class ID for the object. - */ - hres = IStorage_Stat(pStg, &storageInfo, STATFLAG_NONAME); - - /* - * Now, try and create the handler for the object - */ - hres = CoCreateInstance(&storageInfo.clsid, - NULL, - CLSCTX_INPROC_HANDLER, - &IID_IOleObject, - (void**)&oleObject); - - /* - * If that fails, as it will most times, load the default - * OLE handler. - */ - if (FAILED(hres)) - { - hres = OleCreateDefaultHandler(&storageInfo.clsid, - NULL, - &IID_IOleObject, - (void**)&oleObject); - } - - /* - * If we couldn't find a handler... this is bad. Abort the whole thing. - */ - if (FAILED(hres)) - return hres; - - /* - * Inform the new object of it's client site. - */ - hres = IOleObject_SetClientSite(oleObject, pClientSite); - - /* - * Initialize the object with it's IPersistStorage interface. - */ - hres = IOleObject_QueryInterface(oleObject, - &IID_IPersistStorage, - (void**)&persistStorage); - - if (SUCCEEDED(hres)) - { - IPersistStorage_Load(persistStorage, pStg); - - IPersistStorage_Release(persistStorage); - persistStorage = NULL; - } - - /* - * Return the requested interface to the caller. - */ - hres = IOleObject_QueryInterface(oleObject, riid, ppvObj); - - /* - * Cleanup interfaces used internally - */ - IOleObject_Release(oleObject); - - return hres; -} - -/*********************************************************************** - * OleSave [OLE32.@] - */ -HRESULT WINAPI OleSave( - LPPERSISTSTORAGE pPS, - LPSTORAGE pStg, - BOOL fSameAsLoad) -{ - HRESULT hres; - CLSID objectClass; - - TRACE("(%p,%p,%x)\n", pPS, pStg, fSameAsLoad); - - /* - * First, we transfer the class ID (if available) - */ - hres = IPersistStorage_GetClassID(pPS, &objectClass); - - if (SUCCEEDED(hres)) - { - WriteClassStg(pStg, &objectClass); - } - - /* - * Then, we ask the object to save itself to the - * storage. If it is successful, we commit the storage. - */ - hres = IPersistStorage_Save(pPS, pStg, fSameAsLoad); - - if (SUCCEEDED(hres)) - { - IStorage_Commit(pStg, - STGC_DEFAULT); - } - - return hres; -} - - -/****************************************************************************** - * OleLockRunning [OLE32.@] - */ -HRESULT WINAPI OleLockRunning(LPUNKNOWN pUnknown, BOOL fLock, BOOL fLastUnlockCloses) -{ - IRunnableObject* runnable = NULL; - HRESULT hres; - - TRACE("(%p,%x,%x)\n", pUnknown, fLock, fLastUnlockCloses); - - hres = IUnknown_QueryInterface(pUnknown, - &IID_IRunnableObject, - (void**)&runnable); - - if (SUCCEEDED(hres)) - { - hres = IRunnableObject_LockRunning(runnable, fLock, fLastUnlockCloses); - - IRunnableObject_Release(runnable); - - return hres; - } - else - return E_INVALIDARG; -} - - -/************************************************************************** - * Internal methods to manage the shared OLE menu in response to the - * OLE***MenuDescriptor API - */ - -/*** - * OLEMenu_Initialize() - * - * Initializes the OLEMENU data structures. - */ -static void OLEMenu_Initialize() -{ -} - -/*** - * OLEMenu_UnInitialize() - * - * Releases the OLEMENU data structures. - */ -static void OLEMenu_UnInitialize() -{ -} - -/************************************************************************* - * OLEMenu_InstallHooks - * Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC - * - * RETURNS: TRUE if message hooks were successfully installed - * FALSE on failure - */ -BOOL OLEMenu_InstallHooks( DWORD tid ) -{ - OleMenuHookItem *pHookItem = NULL; - - /* Create an entry for the hook table */ - if ( !(pHookItem = HeapAlloc(GetProcessHeap(), 0, - sizeof(OleMenuHookItem)) ) ) - return FALSE; - - pHookItem->tid = tid; - pHookItem->hHeap = GetProcessHeap(); - - /* Install a thread scope message hook for WH_GETMESSAGE */ - pHookItem->GetMsg_hHook = SetWindowsHookExA( WH_GETMESSAGE, OLEMenu_GetMsgProc, - 0, GetCurrentThreadId() ); - if ( !pHookItem->GetMsg_hHook ) - goto CLEANUP; - - /* Install a thread scope message hook for WH_CALLWNDPROC */ - pHookItem->CallWndProc_hHook = SetWindowsHookExA( WH_CALLWNDPROC, OLEMenu_CallWndProc, - 0, GetCurrentThreadId() ); - if ( !pHookItem->CallWndProc_hHook ) - goto CLEANUP; - - /* Insert the hook table entry */ - pHookItem->next = hook_list; - hook_list = pHookItem; - - return TRUE; - -CLEANUP: - /* Unhook any hooks */ - if ( pHookItem->GetMsg_hHook ) - UnhookWindowsHookEx( pHookItem->GetMsg_hHook ); - if ( pHookItem->CallWndProc_hHook ) - UnhookWindowsHookEx( pHookItem->CallWndProc_hHook ); - /* Release the hook table entry */ - HeapFree(pHookItem->hHeap, 0, pHookItem ); - - return FALSE; -} - -/************************************************************************* - * OLEMenu_UnInstallHooks - * UnInstall thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC - * - * RETURNS: TRUE if message hooks were successfully installed - * FALSE on failure - */ -BOOL OLEMenu_UnInstallHooks( DWORD tid ) -{ - OleMenuHookItem *pHookItem = NULL; - OleMenuHookItem **ppHook = &hook_list; - - while (*ppHook) - { - if ((*ppHook)->tid == tid) - { - pHookItem = *ppHook; - *ppHook = pHookItem->next; - break; - } - ppHook = &(*ppHook)->next; - } - if (!pHookItem) return FALSE; - - /* Uninstall the hooks installed for this thread */ - if ( !UnhookWindowsHookEx( pHookItem->GetMsg_hHook ) ) - goto CLEANUP; - if ( !UnhookWindowsHookEx( pHookItem->CallWndProc_hHook ) ) - goto CLEANUP; - - /* Release the hook table entry */ - HeapFree(pHookItem->hHeap, 0, pHookItem ); - - return TRUE; - -CLEANUP: - /* Release the hook table entry */ - if (pHookItem) - HeapFree(pHookItem->hHeap, 0, pHookItem ); - - return FALSE; -} - -/************************************************************************* - * OLEMenu_IsHookInstalled - * Tests if OLEMenu hooks have been installed for a thread - * - * RETURNS: The pointer and index of the hook table entry for the tid - * NULL and -1 for the index if no hooks were installed for this thread - */ -OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid ) -{ - OleMenuHookItem *pHookItem = NULL; - - /* Do a simple linear search for an entry whose tid matches ours. - * We really need a map but efficiency is not a concern here. */ - for (pHookItem = hook_list; pHookItem; pHookItem = pHookItem->next) - { - if ( tid == pHookItem->tid ) - return pHookItem; - } - - return NULL; -} - -/*********************************************************************** - * OLEMenu_FindMainMenuIndex - * - * Used by OLEMenu API to find the top level group a menu item belongs to. - * On success pnPos contains the index of the item in the top level menu group - * - * RETURNS: TRUE if the ID was found, FALSE on failure - */ -static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos ) -{ - UINT i, nItems; - - nItems = GetMenuItemCount( hMainMenu ); - - for (i = 0; i < nItems; i++) - { - HMENU hsubmenu; - - /* Is the current item a submenu? */ - if ( (hsubmenu = GetSubMenu(hMainMenu, i)) ) - { - /* If the handle is the same we're done */ - if ( hsubmenu == hPopupMenu ) - { - if (pnPos) - *pnPos = i; - return TRUE; - } - /* Recursively search without updating pnPos */ - else if ( OLEMenu_FindMainMenuIndex( hsubmenu, hPopupMenu, NULL ) ) - { - if (pnPos) - *pnPos = i; - return TRUE; - } - } - } - - return FALSE; -} - -/*********************************************************************** - * OLEMenu_SetIsServerMenu - * - * Checks whether a popup menu belongs to a shared menu group which is - * owned by the server, and sets the menu descriptor state accordingly. - * All menu messages from these groups should be routed to the server. - * - * RETURNS: TRUE if the popup menu is part of a server owned group - * FASE if the popup menu is part of a container owned group - */ -BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor ) -{ - UINT nPos = 0, nWidth, i; - - pOleMenuDescriptor->bIsServerItem = FALSE; - - /* Don't bother searching if the popup is the combined menu itself */ - if ( hmenu == pOleMenuDescriptor->hmenuCombined ) - return FALSE; - - /* Find the menu item index in the shared OLE menu that this item belongs to */ - if ( !OLEMenu_FindMainMenuIndex( pOleMenuDescriptor->hmenuCombined, hmenu, &nPos ) ) - return FALSE; - - /* The group widths array has counts for the number of elements - * in the groups File, Edit, Container, Object, Window, Help. - * The Edit, Object & Help groups belong to the server object - * and the other three belong to the container. - * Loop through the group widths and locate the group we are a member of. - */ - for ( i = 0, nWidth = 0; i < 6; i++ ) - { - nWidth += pOleMenuDescriptor->mgw.width[i]; - if ( nPos < nWidth ) - { - /* Odd elements are server menu widths */ - pOleMenuDescriptor->bIsServerItem = (i%2) ? TRUE : FALSE; - break; - } - } - - return pOleMenuDescriptor->bIsServerItem; -} - -/************************************************************************* - * OLEMenu_CallWndProc - * Thread scope WH_CALLWNDPROC hook proc filter function (callback) - * This is invoked from a message hook installed in OleSetMenuDescriptor. - */ -LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam) -{ - LPCWPSTRUCT pMsg = NULL; - HOLEMENU hOleMenu = 0; - OleMenuDescriptor *pOleMenuDescriptor = NULL; - OleMenuHookItem *pHookItem = NULL; - WORD fuFlags; - - TRACE("%i, %04x, %08x\n", code, wParam, (unsigned)lParam ); - - /* Check if we're being asked to process the message */ - if ( HC_ACTION != code ) - goto NEXTHOOK; - - /* Retrieve the current message being dispatched from lParam */ - pMsg = (LPCWPSTRUCT)lParam; - - /* Check if the message is destined for a window we are interested in: - * If the window has an OLEMenu property we may need to dispatch - * the menu message to its active objects window instead. */ - - hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" ); - if ( !hOleMenu ) - goto NEXTHOOK; - - /* Get the menu descriptor */ - pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu ); - if ( !pOleMenuDescriptor ) /* Bad descriptor! */ - goto NEXTHOOK; - - /* Process menu messages */ - switch( pMsg->message ) - { - case WM_INITMENU: - { - /* Reset the menu descriptor state */ - pOleMenuDescriptor->bIsServerItem = FALSE; - - /* Send this message to the server as well */ - SendMessageA( pOleMenuDescriptor->hwndActiveObject, - pMsg->message, pMsg->wParam, pMsg->lParam ); - goto NEXTHOOK; - } - - case WM_INITMENUPOPUP: - { - /* Save the state for whether this is a server owned menu */ - OLEMenu_SetIsServerMenu( (HMENU)pMsg->wParam, pOleMenuDescriptor ); - break; - } - - case WM_MENUSELECT: - { - fuFlags = HIWORD(pMsg->wParam); /* Get flags */ - if ( fuFlags & MF_SYSMENU ) - goto NEXTHOOK; - - /* Save the state for whether this is a server owned popup menu */ - else if ( fuFlags & MF_POPUP ) - OLEMenu_SetIsServerMenu( (HMENU)pMsg->lParam, pOleMenuDescriptor ); - - break; - } - - case WM_DRAWITEM: - { - LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) pMsg->lParam; - if ( pMsg->wParam != 0 || lpdis->CtlType != ODT_MENU ) - goto NEXTHOOK; /* Not a menu message */ - - break; - } - - default: - goto NEXTHOOK; - } - - /* If the message was for the server dispatch it accordingly */ - if ( pOleMenuDescriptor->bIsServerItem ) - { - SendMessageA( pOleMenuDescriptor->hwndActiveObject, - pMsg->message, pMsg->wParam, pMsg->lParam ); - } - -NEXTHOOK: - if ( pOleMenuDescriptor ) - GlobalUnlock( hOleMenu ); - - /* Lookup the hook item for the current thread */ - if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) ) - { - /* This should never fail!! */ - WARN("could not retrieve hHook for current thread!\n" ); - return 0; - } - - /* Pass on the message to the next hooker */ - return CallNextHookEx( pHookItem->CallWndProc_hHook, code, wParam, lParam ); -} - -/************************************************************************* - * OLEMenu_GetMsgProc - * Thread scope WH_GETMESSAGE hook proc filter function (callback) - * This is invoked from a message hook installed in OleSetMenuDescriptor. - */ -LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam) -{ - LPMSG pMsg = NULL; - HOLEMENU hOleMenu = 0; - OleMenuDescriptor *pOleMenuDescriptor = NULL; - OleMenuHookItem *pHookItem = NULL; - WORD wCode; - - TRACE("%i, %04x, %08x\n", code, wParam, (unsigned)lParam ); - - /* Check if we're being asked to process a messages */ - if ( HC_ACTION != code ) - goto NEXTHOOK; - - /* Retrieve the current message being dispatched from lParam */ - pMsg = (LPMSG)lParam; - - /* Check if the message is destined for a window we are interested in: - * If the window has an OLEMenu property we may need to dispatch - * the menu message to its active objects window instead. */ - - hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" ); - if ( !hOleMenu ) - goto NEXTHOOK; - - /* Process menu messages */ - switch( pMsg->message ) - { - case WM_COMMAND: - { - wCode = HIWORD(pMsg->wParam); /* Get notification code */ - if ( wCode ) - goto NEXTHOOK; /* Not a menu message */ - break; - } - default: - goto NEXTHOOK; - } - - /* Get the menu descriptor */ - pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu ); - if ( !pOleMenuDescriptor ) /* Bad descriptor! */ - goto NEXTHOOK; - - /* If the message was for the server dispatch it accordingly */ - if ( pOleMenuDescriptor->bIsServerItem ) - { - /* Change the hWnd in the message to the active objects hWnd. - * The message loop which reads this message will automatically - * dispatch it to the embedded objects window. */ - pMsg->hwnd = pOleMenuDescriptor->hwndActiveObject; - } - -NEXTHOOK: - if ( pOleMenuDescriptor ) - GlobalUnlock( hOleMenu ); - - /* Lookup the hook item for the current thread */ - if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) ) - { - /* This should never fail!! */ - WARN("could not retrieve hHook for current thread!\n" ); - return FALSE; - } - - /* Pass on the message to the next hooker */ - return CallNextHookEx( pHookItem->GetMsg_hHook, code, wParam, lParam ); -} - -/*********************************************************************** - * OleCreateMenuDescriptor [OLE32.@] - * Creates an OLE menu descriptor for OLE to use when dispatching - * menu messages and commands. - * - * PARAMS: - * hmenuCombined - Handle to the objects combined menu - * lpMenuWidths - Pointer to array of 6 LONG's indicating menus per group - * - */ -HOLEMENU WINAPI OleCreateMenuDescriptor( - HMENU hmenuCombined, - LPOLEMENUGROUPWIDTHS lpMenuWidths) -{ - HOLEMENU hOleMenu; - OleMenuDescriptor *pOleMenuDescriptor; - int i; - - if ( !hmenuCombined || !lpMenuWidths ) - return 0; - - /* Create an OLE menu descriptor */ - if ( !(hOleMenu = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, - sizeof(OleMenuDescriptor) ) ) ) - return 0; - - pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu ); - if ( !pOleMenuDescriptor ) - return 0; - - /* Initialize menu group widths and hmenu */ - for ( i = 0; i < 6; i++ ) - pOleMenuDescriptor->mgw.width[i] = lpMenuWidths->width[i]; - - pOleMenuDescriptor->hmenuCombined = hmenuCombined; - pOleMenuDescriptor->bIsServerItem = FALSE; - GlobalUnlock( hOleMenu ); - - return hOleMenu; -} - -/*********************************************************************** - * OleDestroyMenuDescriptor [OLE32.@] - * Destroy the shared menu descriptor - */ -HRESULT WINAPI OleDestroyMenuDescriptor( - HOLEMENU hmenuDescriptor) -{ - if ( hmenuDescriptor ) - GlobalFree( hmenuDescriptor ); - return S_OK; -} - -/*********************************************************************** - * OleSetMenuDescriptor [OLE32.@] - * Installs or removes OLE dispatching code for the containers frame window - * FIXME: The lpFrame and lpActiveObject parameters are currently ignored - * OLE should install context sensitive help F1 filtering for the app when - * these are non null. - * - * PARAMS: - * hOleMenu Handle to composite menu descriptor - * hwndFrame Handle to containers frame window - * hwndActiveObject Handle to objects in-place activation window - * lpFrame Pointer to IOleInPlaceFrame on containers window - * lpActiveObject Pointer to IOleInPlaceActiveObject on active in-place object - * - * RETURNS: - * S_OK - menu installed correctly - * E_FAIL, E_INVALIDARG, E_UNEXPECTED - failure - */ -HRESULT WINAPI OleSetMenuDescriptor( - HOLEMENU hOleMenu, - HWND hwndFrame, - HWND hwndActiveObject, - LPOLEINPLACEFRAME lpFrame, - LPOLEINPLACEACTIVEOBJECT lpActiveObject) -{ - OleMenuDescriptor *pOleMenuDescriptor = NULL; - - /* Check args */ - if ( !hwndFrame || (hOleMenu && !hwndActiveObject) ) - return E_INVALIDARG; - - if ( lpFrame || lpActiveObject ) - { - FIXME("(%x, %p, %p, %p, %p), Context sensitive help filtering not implemented!\n", - (unsigned int)hOleMenu, - hwndFrame, - hwndActiveObject, - lpFrame, - lpActiveObject); - } - - /* Set up a message hook to intercept the containers frame window messages. - * The message filter is responsible for dispatching menu messages from the - * shared menu which are intended for the object. - */ - - if ( hOleMenu ) /* Want to install dispatching code */ - { - /* If OLEMenu hooks are already installed for this thread, fail - * Note: This effectively means that OleSetMenuDescriptor cannot - * be called twice in succession on the same frame window - * without first calling it with a null hOleMenu to uninstall */ - if ( OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) - return E_FAIL; - - /* Get the menu descriptor */ - pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu ); - if ( !pOleMenuDescriptor ) - return E_UNEXPECTED; - - /* Update the menu descriptor */ - pOleMenuDescriptor->hwndFrame = hwndFrame; - pOleMenuDescriptor->hwndActiveObject = hwndActiveObject; - - GlobalUnlock( hOleMenu ); - pOleMenuDescriptor = NULL; - - /* Add a menu descriptor windows property to the frame window */ - SetPropA( hwndFrame, "PROP_OLEMenuDescriptor", hOleMenu ); - - /* Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC */ - if ( !OLEMenu_InstallHooks( GetCurrentThreadId() ) ) - return E_FAIL; - } - else /* Want to uninstall dispatching code */ - { - /* Uninstall the hooks */ - if ( !OLEMenu_UnInstallHooks( GetCurrentThreadId() ) ) - return E_FAIL; - - /* Remove the menu descriptor property from the frame window */ - RemovePropA( hwndFrame, "PROP_OLEMenuDescriptor" ); - } - - return S_OK; -} - -/****************************************************************************** - * IsAccelerator [OLE32.@] - * Mostly copied from controls/menu.c TranslateAccelerator implementation - */ -BOOL WINAPI IsAccelerator(HACCEL hAccel, int cAccelEntries, LPMSG lpMsg, WORD* lpwCmd) -{ -#if 0 /* Not implemented for ReactOS */ - /* YES, Accel16! */ - LPACCEL16 lpAccelTbl; - int i; - - if(!lpMsg) return FALSE; - if (!hAccel || !(lpAccelTbl = (LPACCEL16)LockResource16(HACCEL_16(hAccel)))) - { - WARN_(accel)("invalid accel handle=%p\n", hAccel); - return FALSE; - } - if((lpMsg->message != WM_KEYDOWN && - lpMsg->message != WM_KEYUP && - lpMsg->message != WM_SYSKEYDOWN && - lpMsg->message != WM_SYSKEYUP && - lpMsg->message != WM_CHAR)) return FALSE; - - TRACE_(accel)("hAccel=%p, cAccelEntries=%d," - "msg->hwnd=%p, msg->message=%04x, wParam=%08x, lParam=%08lx\n", - hAccel, cAccelEntries, - lpMsg->hwnd, lpMsg->message, lpMsg->wParam, lpMsg->lParam); - for(i = 0; i < cAccelEntries; i++) - { - if(lpAccelTbl[i].key != lpMsg->wParam) - continue; - - if(lpMsg->message == WM_CHAR) - { - if(!(lpAccelTbl[i].fVirt & FALT) && !(lpAccelTbl[i].fVirt & FVIRTKEY)) - { - TRACE_(accel)("found accel for WM_CHAR: ('%c')\n", lpMsg->wParam & 0xff); - goto found; - } - } - else - { - if(lpAccelTbl[i].fVirt & FVIRTKEY) - { - INT mask = 0; - TRACE_(accel)("found accel for virt_key %04x (scan %04x)\n", - lpMsg->wParam, HIWORD(lpMsg->lParam) & 0xff); - if(GetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT; - if(GetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL; - if(GetKeyState(VK_MENU) & 0x8000) mask |= FALT; - if(mask == (lpAccelTbl[i].fVirt & (FSHIFT | FCONTROL | FALT))) goto found; - TRACE_(accel)("incorrect SHIFT/CTRL/ALT-state\n"); - } - else - { - if(!(lpMsg->lParam & 0x01000000)) /* no special_key */ - { - if((lpAccelTbl[i].fVirt & FALT) && (lpMsg->lParam & 0x20000000)) - { /* ^^ ALT pressed */ - TRACE_(accel)("found accel for Alt-%c\n", lpMsg->wParam & 0xff); - goto found; - } - } - } - } - } - - WARN_(accel)("couldn't translate accelerator key\n"); - return FALSE; - -found: - if(lpwCmd) *lpwCmd = lpAccelTbl[i].cmd; - return TRUE; -#else - return FALSE; -#endif -} - -/*********************************************************************** - * ReleaseStgMedium [OLE32.@] - */ -void WINAPI ReleaseStgMedium( - STGMEDIUM* pmedium) -{ - switch (pmedium->tymed) - { - case TYMED_HGLOBAL: - { - if ( (pmedium->pUnkForRelease==0) && - (pmedium->u.hGlobal!=0) ) - GlobalFree(pmedium->u.hGlobal); - break; - } - case TYMED_FILE: - { - if (pmedium->u.lpszFileName!=0) - { - if (pmedium->pUnkForRelease==0) - { - DeleteFileW(pmedium->u.lpszFileName); - } - - CoTaskMemFree(pmedium->u.lpszFileName); - } - break; - } - case TYMED_ISTREAM: - { - if (pmedium->u.pstm!=0) - { - IStream_Release(pmedium->u.pstm); - } - break; - } - case TYMED_ISTORAGE: - { - if (pmedium->u.pstg!=0) - { - IStorage_Release(pmedium->u.pstg); - } - break; - } - case TYMED_GDI: - { - if ( (pmedium->pUnkForRelease==0) && - (pmedium->u.hBitmap!=0) ) - DeleteObject(pmedium->u.hBitmap); - break; - } - case TYMED_MFPICT: - { - if ( (pmedium->pUnkForRelease==0) && - (pmedium->u.hMetaFilePict!=0) ) - { - LPMETAFILEPICT pMP = GlobalLock(pmedium->u.hMetaFilePict); - DeleteMetaFile(pMP->hMF); - GlobalUnlock(pmedium->u.hMetaFilePict); - GlobalFree(pmedium->u.hMetaFilePict); - } - break; - } - case TYMED_ENHMF: - { - if ( (pmedium->pUnkForRelease==0) && - (pmedium->u.hEnhMetaFile!=0) ) - { - DeleteEnhMetaFile(pmedium->u.hEnhMetaFile); - } - break; - } - case TYMED_NULL: - default: - break; - } - pmedium->tymed=TYMED_NULL; - - /* - * After cleaning up, the unknown is released - */ - if (pmedium->pUnkForRelease!=0) - { - IUnknown_Release(pmedium->pUnkForRelease); - pmedium->pUnkForRelease = 0; - } -} - -/*** - * OLEDD_Initialize() - * - * Initializes the OLE drag and drop data structures. - */ -static void OLEDD_Initialize() -{ - WNDCLASSA wndClass; - - ZeroMemory (&wndClass, sizeof(WNDCLASSA)); - wndClass.style = CS_GLOBALCLASS; - wndClass.lpfnWndProc = (WNDPROC)OLEDD_DragTrackerWindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(TrackerWindowInfo*); - wndClass.hCursor = 0; - wndClass.hbrBackground = 0; - wndClass.lpszClassName = OLEDD_DRAGTRACKERCLASS; - - RegisterClassA (&wndClass); -} - -/*** - * OLEDD_UnInitialize() - * - * Releases the OLE drag and drop data structures. - */ -static void OLEDD_UnInitialize() -{ - /* - * Simply empty the list. - */ - while (targetListHead!=NULL) - { - RevokeDragDrop(targetListHead->hwndTarget); - } -} - -/*** - * OLEDD_InsertDropTarget() - * - * Insert the target node in the tree. - */ -static void OLEDD_InsertDropTarget(DropTargetNode* nodeToAdd) -{ - DropTargetNode* curNode; - DropTargetNode** parentNodeLink; - - /* - * Iterate the tree to find the insertion point. - */ - curNode = targetListHead; - parentNodeLink = &targetListHead; - - while (curNode!=NULL) - { - if (nodeToAdd->hwndTargethwndTarget) - { - /* - * If the node we want to add has a smaller HWND, go left - */ - parentNodeLink = &curNode->prevDropTarget; - curNode = curNode->prevDropTarget; - } - else if (nodeToAdd->hwndTarget>curNode->hwndTarget) - { - /* - * If the node we want to add has a larger HWND, go right - */ - parentNodeLink = &curNode->nextDropTarget; - curNode = curNode->nextDropTarget; - } - else - { - /* - * The item was found in the list. It shouldn't have been there - */ - assert(FALSE); - return; - } - } - - /* - * If we get here, we have found a spot for our item. The parentNodeLink - * pointer points to the pointer that we have to modify. - * The curNode should be NULL. We just have to establish the link and Voila! - */ - assert(curNode==NULL); - assert(parentNodeLink!=NULL); - assert(*parentNodeLink==NULL); - - *parentNodeLink=nodeToAdd; -} - -/*** - * OLEDD_ExtractDropTarget() - * - * Removes the target node from the tree. - */ -static DropTargetNode* OLEDD_ExtractDropTarget(HWND hwndOfTarget) -{ - DropTargetNode* curNode; - DropTargetNode** parentNodeLink; - - /* - * Iterate the tree to find the insertion point. - */ - curNode = targetListHead; - parentNodeLink = &targetListHead; - - while (curNode!=NULL) - { - if (hwndOfTargethwndTarget) - { - /* - * If the node we want to add has a smaller HWND, go left - */ - parentNodeLink = &curNode->prevDropTarget; - curNode = curNode->prevDropTarget; - } - else if (hwndOfTarget>curNode->hwndTarget) - { - /* - * If the node we want to add has a larger HWND, go right - */ - parentNodeLink = &curNode->nextDropTarget; - curNode = curNode->nextDropTarget; - } - else - { - /* - * The item was found in the list. Detach it from it's parent and - * re-insert it's kids in the tree. - */ - assert(parentNodeLink!=NULL); - assert(*parentNodeLink==curNode); - - /* - * We arbitrately re-attach the left sub-tree to the parent. - */ - *parentNodeLink = curNode->prevDropTarget; - - /* - * And we re-insert the right subtree - */ - if (curNode->nextDropTarget!=NULL) - { - OLEDD_InsertDropTarget(curNode->nextDropTarget); - } - - /* - * The node we found is still a valid node once we complete - * the unlinking of the kids. - */ - curNode->nextDropTarget=NULL; - curNode->prevDropTarget=NULL; - - return curNode; - } - } - - /* - * If we get here, the node is not in the tree - */ - return NULL; -} - -/*** - * OLEDD_FindDropTarget() - * - * Finds information about the drop target. - */ -static DropTargetNode* OLEDD_FindDropTarget(HWND hwndOfTarget) -{ - DropTargetNode* curNode; - - /* - * Iterate the tree to find the HWND value. - */ - curNode = targetListHead; - - while (curNode!=NULL) - { - if (hwndOfTargethwndTarget) - { - /* - * If the node we want to add has a smaller HWND, go left - */ - curNode = curNode->prevDropTarget; - } - else if (hwndOfTarget>curNode->hwndTarget) - { - /* - * If the node we want to add has a larger HWND, go right - */ - curNode = curNode->nextDropTarget; - } - else - { - /* - * The item was found in the list. - */ - return curNode; - } - } - - /* - * If we get here, the item is not in the list - */ - return NULL; -} - -/*** - * OLEDD_DragTrackerWindowProc() - * - * This method is the WindowProcedure of the drag n drop tracking - * window. During a drag n Drop operation, an invisible window is created - * to receive the user input and act upon it. This procedure is in charge - * of this behavior. - */ -static LRESULT WINAPI OLEDD_DragTrackerWindowProc( - HWND hwnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - switch (uMsg) - { - case WM_CREATE: - { - LPCREATESTRUCTA createStruct = (LPCREATESTRUCTA)lParam; - - SetWindowLongA(hwnd, 0, (LONG)createStruct->lpCreateParams); - - - break; - } - case WM_MOUSEMOVE: - { - TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0); - POINT mousePos; - - /* - * Get the current mouse position in screen coordinates. - */ - mousePos.x = LOWORD(lParam); - mousePos.y = HIWORD(lParam); - ClientToScreen(hwnd, &mousePos); - - /* - * Track the movement of the mouse. - */ - OLEDD_TrackMouseMove(trackerInfo, mousePos, wParam); - - break; - } - case WM_LBUTTONUP: - case WM_MBUTTONUP: - case WM_RBUTTONUP: - case WM_LBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_RBUTTONDOWN: - { - TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0); - POINT mousePos; - - /* - * Get the current mouse position in screen coordinates. - */ - mousePos.x = LOWORD(lParam); - mousePos.y = HIWORD(lParam); - ClientToScreen(hwnd, &mousePos); - - /* - * Notify everyone that the button state changed - * TODO: Check if the "escape" key was pressed. - */ - OLEDD_TrackStateChange(trackerInfo, mousePos, wParam); - - break; - } - } - - /* - * This is a window proc after all. Let's call the default. - */ - return DefWindowProcA (hwnd, uMsg, wParam, lParam); -} - -/*** - * OLEDD_TrackMouseMove() - * - * This method is invoked while a drag and drop operation is in effect. - * it will generate the appropriate callbacks in the drop source - * and drop target. It will also provide the expected feedback to - * the user. - * - * params: - * trackerInfo - Pointer to the structure identifying the - * drag & drop operation that is currently - * active. - * mousePos - Current position of the mouse in screen - * coordinates. - * keyState - Contains the state of the shift keys and the - * mouse buttons (MK_LBUTTON and the like) - */ -static void OLEDD_TrackMouseMove( - TrackerWindowInfo* trackerInfo, - POINT mousePos, - DWORD keyState) -{ - HWND hwndNewTarget = 0; - HRESULT hr = S_OK; - - /* - * Get the handle of the window under the mouse - */ - hwndNewTarget = WindowFromPoint(mousePos); - - /* - * Every time, we re-initialize the effects passed to the - * IDropTarget to the effects allowed by the source. - */ - *trackerInfo->pdwEffect = trackerInfo->dwOKEffect; - - /* - * If we are hovering over the same target as before, send the - * DragOver notification - */ - if ( (trackerInfo->curDragTarget != 0) && - (trackerInfo->curTargetHWND == hwndNewTarget) ) - { - POINTL mousePosParam; - - /* - * The documentation tells me that the coordinate should be in the target - * window's coordinate space. However, the tests I made tell me the - * coordinates should be in screen coordinates. - */ - mousePosParam.x = mousePos.x; - mousePosParam.y = mousePos.y; - - IDropTarget_DragOver(trackerInfo->curDragTarget, - keyState, - mousePosParam, - trackerInfo->pdwEffect); - } - else - { - DropTargetNode* newDropTargetNode = 0; - - /* - * If we changed window, we have to notify our old target and check for - * the new one. - */ - if (trackerInfo->curDragTarget!=0) - { - IDropTarget_DragLeave(trackerInfo->curDragTarget); - } - - /* - * Make sure we're hovering over a window. - */ - if (hwndNewTarget!=0) - { - /* - * Find-out if there is a drag target under the mouse - */ - HWND nexttar = hwndNewTarget; - trackerInfo->curTargetHWND = hwndNewTarget; - - do { - newDropTargetNode = OLEDD_FindDropTarget(nexttar); - } while (!newDropTargetNode && (nexttar = GetParent(nexttar)) != 0); - if(nexttar) hwndNewTarget = nexttar; - - trackerInfo->curDragTargetHWND = hwndNewTarget; - trackerInfo->curDragTarget = newDropTargetNode ? newDropTargetNode->dropTarget : 0; - - /* - * If there is, notify it that we just dragged-in - */ - if (trackerInfo->curDragTarget!=0) - { - POINTL mousePosParam; - - /* - * The documentation tells me that the coordinate should be in the target - * window's coordinate space. However, the tests I made tell me the - * coordinates should be in screen coordinates. - */ - mousePosParam.x = mousePos.x; - mousePosParam.y = mousePos.y; - - IDropTarget_DragEnter(trackerInfo->curDragTarget, - trackerInfo->dataObject, - keyState, - mousePosParam, - trackerInfo->pdwEffect); - } - } - else - { - /* - * The mouse is not over a window so we don't track anything. - */ - trackerInfo->curDragTargetHWND = 0; - trackerInfo->curTargetHWND = 0; - trackerInfo->curDragTarget = 0; - } - } - - /* - * Now that we have done that, we have to tell the source to give - * us feedback on the work being done by the target. If we don't - * have a target, simulate no effect. - */ - if (trackerInfo->curDragTarget==0) - { - *trackerInfo->pdwEffect = DROPEFFECT_NONE; - } - - hr = IDropSource_GiveFeedback(trackerInfo->dropSource, - *trackerInfo->pdwEffect); - - /* - * When we ask for feedback from the drop source, sometimes it will - * do all the necessary work and sometimes it will not handle it - * when that's the case, we must display the standard drag and drop - * cursors. - */ - if (hr==DRAGDROP_S_USEDEFAULTCURSORS) - { - if (*trackerInfo->pdwEffect & DROPEFFECT_MOVE) - { - SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(1))); - } - else if (*trackerInfo->pdwEffect & DROPEFFECT_COPY) - { - SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(2))); - } - else if (*trackerInfo->pdwEffect & DROPEFFECT_LINK) - { - SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(3))); - } - else - { - SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCEA(0))); - } - } -} - -/*** - * OLEDD_TrackStateChange() - * - * This method is invoked while a drag and drop operation is in effect. - * It is used to notify the drop target/drop source callbacks when - * the state of the keyboard or mouse button change. - * - * params: - * trackerInfo - Pointer to the structure identifying the - * drag & drop operation that is currently - * active. - * mousePos - Current position of the mouse in screen - * coordinates. - * keyState - Contains the state of the shift keys and the - * mouse buttons (MK_LBUTTON and the like) - */ -static void OLEDD_TrackStateChange( - TrackerWindowInfo* trackerInfo, - POINT mousePos, - DWORD keyState) -{ - /* - * Ask the drop source what to do with the operation. - */ - trackerInfo->returnValue = IDropSource_QueryContinueDrag( - trackerInfo->dropSource, - trackerInfo->escPressed, - keyState); - - /* - * All the return valued will stop the operation except the S_OK - * return value. - */ - if (trackerInfo->returnValue!=S_OK) - { - /* - * Make sure the message loop in DoDragDrop stops - */ - trackerInfo->trackingDone = TRUE; - - /* - * Release the mouse in case the drop target decides to show a popup - * or a menu or something. - */ - ReleaseCapture(); - - /* - * If we end-up over a target, drop the object in the target or - * inform the target that the operation was cancelled. - */ - if (trackerInfo->curDragTarget!=0) - { - switch (trackerInfo->returnValue) - { - /* - * If the source wants us to complete the operation, we tell - * the drop target that we just dropped the object in it. - */ - case DRAGDROP_S_DROP: - { - POINTL mousePosParam; - - /* - * The documentation tells me that the coordinate should be - * in the target window's coordinate space. However, the tests - * I made tell me the coordinates should be in screen coordinates. - */ - mousePosParam.x = mousePos.x; - mousePosParam.y = mousePos.y; - - IDropTarget_Drop(trackerInfo->curDragTarget, - trackerInfo->dataObject, - keyState, - mousePosParam, - trackerInfo->pdwEffect); - break; - } - /* - * If the source told us that we should cancel, fool the drop - * target by telling it that the mouse left it's window. - * Also set the drop effect to "NONE" in case the application - * ignores the result of DoDragDrop. - */ - case DRAGDROP_S_CANCEL: - IDropTarget_DragLeave(trackerInfo->curDragTarget); - *trackerInfo->pdwEffect = DROPEFFECT_NONE; - break; - } - } - } -} - -/*** - * OLEDD_GetButtonState() - * - * This method will use the current state of the keyboard to build - * a button state mask equivalent to the one passed in the - * WM_MOUSEMOVE wParam. - */ -static DWORD OLEDD_GetButtonState() -{ - BYTE keyboardState[256]; - DWORD keyMask = 0; - - GetKeyboardState(keyboardState); - - if ( (keyboardState[VK_SHIFT] & 0x80) !=0) - keyMask |= MK_SHIFT; - - if ( (keyboardState[VK_CONTROL] & 0x80) !=0) - keyMask |= MK_CONTROL; - - if ( (keyboardState[VK_LBUTTON] & 0x80) !=0) - keyMask |= MK_LBUTTON; - - if ( (keyboardState[VK_RBUTTON] & 0x80) !=0) - keyMask |= MK_RBUTTON; - - if ( (keyboardState[VK_MBUTTON] & 0x80) !=0) - keyMask |= MK_MBUTTON; - - return keyMask; -} - -/*** - * OLEDD_GetButtonState() - * - * This method will read the default value of the registry key in - * parameter and extract a DWORD value from it. The registry key value - * can be in a string key or a DWORD key. - * - * params: - * regKey - Key to read the default value from - * pdwValue - Pointer to the location where the DWORD - * value is returned. This value is not modified - * if the value is not found. - */ - -static void OLEUTL_ReadRegistryDWORDValue( - HKEY regKey, - DWORD* pdwValue) -{ - char buffer[20]; - DWORD dwKeyType; - DWORD cbData = 20; - LONG lres; - - lres = RegQueryValueExA(regKey, - "", - NULL, - &dwKeyType, - (LPBYTE)buffer, - &cbData); - - if (lres==ERROR_SUCCESS) - { - switch (dwKeyType) - { - case REG_DWORD: - *pdwValue = *(DWORD*)buffer; - break; - case REG_EXPAND_SZ: - case REG_MULTI_SZ: - case REG_SZ: - *pdwValue = (DWORD)strtoul(buffer, NULL, 10); - break; - } - } -} - -/****************************************************************************** - * OleDraw (OLE32.@) - * - * The operation of this function is documented literally in the WinAPI - * documentation to involve a QueryInterface for the IViewObject interface, - * followed by a call to IViewObject::Draw. - */ -HRESULT WINAPI OleDraw( - IUnknown *pUnk, - DWORD dwAspect, - HDC hdcDraw, - LPCRECT lprcBounds) -{ - HRESULT hres; - IViewObject *viewobject; - - hres = IUnknown_QueryInterface(pUnk, - &IID_IViewObject, - (void**)&viewobject); - - if (SUCCEEDED(hres)) - { - RECTL rectl; - - rectl.left = lprcBounds->left; - rectl.right = lprcBounds->right; - rectl.top = lprcBounds->top; - rectl.bottom = lprcBounds->bottom; - hres = IViewObject_Draw(viewobject, dwAspect, -1, 0, 0, 0, hdcDraw, &rectl, 0, 0, 0); - - IViewObject_Release(viewobject); - return hres; - } - else - { - return DV_E_NOIVIEWOBJECT; - } -} - -/*********************************************************************** - * OleTranslateAccelerator [OLE32.@] - */ -HRESULT WINAPI OleTranslateAccelerator (LPOLEINPLACEFRAME lpFrame, - LPOLEINPLACEFRAMEINFO lpFrameInfo, LPMSG lpmsg) -{ - WORD wID; - - TRACE("(%p,%p,%p)\n", lpFrame, lpFrameInfo, lpmsg); - - if (IsAccelerator(lpFrameInfo->haccel,lpFrameInfo->cAccelEntries,lpmsg,&wID)) - return IOleInPlaceFrame_TranslateAccelerator(lpFrame,lpmsg,wID); - - return S_FALSE; -} - -/****************************************************************************** - * OleCreate [OLE32.@] - * - */ -HRESULT WINAPI OleCreate( - REFCLSID rclsid, - REFIID riid, - DWORD renderopt, - LPFORMATETC pFormatEtc, - LPOLECLIENTSITE pClientSite, - LPSTORAGE pStg, - LPVOID* ppvObj) -{ - HRESULT hres, hres1; - IUnknown * pUnk = NULL; - - FIXME("\n\t%s\n\t%s semi-stub!\n", debugstr_guid(rclsid), debugstr_guid(riid)); - - if (SUCCEEDED((hres = CoCreateInstance(rclsid, 0, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER|CLSCTX_LOCAL_SERVER , riid, (LPVOID*)&pUnk)))) - { - if (pClientSite) - { - IOleObject * pOE; - IPersistStorage * pPS; - if (SUCCEEDED((hres = IUnknown_QueryInterface( pUnk, &IID_IOleObject, (LPVOID*)&pOE)))) - { - TRACE("trying to set clientsite %p\n", pClientSite); - hres1 = IOleObject_SetClientSite(pOE, pClientSite); - TRACE("-- result 0x%08lx\n", hres1); - IOleObject_Release(pOE); - } - if (SUCCEEDED((hres = IUnknown_QueryInterface( pUnk, &IID_IPersistStorage, (LPVOID*)&pPS)))) - { - TRACE("trying to set stg %p\n", pStg); - hres1 = IPersistStorage_InitNew(pPS, pStg); - TRACE("-- result 0x%08lx\n", hres1); - IPersistStorage_Release(pPS); - } - } - } - - *ppvObj = pUnk; - - TRACE("-- %p \n", pUnk); - return hres; -} - -/*********************************************************************** - * OLE_FreeClipDataArray [internal] - * - * NOTES: - * frees the data associated with an array of CLIPDATAs - */ -static void OLE_FreeClipDataArray(ULONG count, CLIPDATA * pClipDataArray) -{ - ULONG i; - for (i = 0; i < count; i++) - if (pClipDataArray[i].pClipData) - CoTaskMemFree(pClipDataArray[i].pClipData); -} - -HRESULT WINAPI FreePropVariantArray(ULONG,PROPVARIANT*); - -/*********************************************************************** - * PropVariantClear [OLE32.@] - */ -HRESULT WINAPI PropVariantClear(PROPVARIANT * pvar) /* [in/out] */ -{ - TRACE("(%p)\n", pvar); - - if (!pvar) - return S_OK; - - switch(pvar->vt) - { - case VT_STREAM: - case VT_STREAMED_OBJECT: - case VT_STORAGE: - case VT_STORED_OBJECT: - IUnknown_Release((LPUNKNOWN)pvar->u.pStream); - break; - case VT_CLSID: - case VT_LPSTR: - case VT_LPWSTR: - /* pick an arbitary typed pointer - we don't care about the type - * as we are just freeing it */ - CoTaskMemFree(pvar->u.puuid); - break; - case VT_BLOB: - case VT_BLOB_OBJECT: - CoTaskMemFree(pvar->u.blob.pBlobData); - break; - case VT_BSTR: - FIXME("Need to load OLEAUT32 for SysFreeString\n"); - /* SysFreeString(pvar->u.bstrVal); */ - break; - case VT_CF: - if (pvar->u.pclipdata) - { - OLE_FreeClipDataArray(1, pvar->u.pclipdata); - CoTaskMemFree(pvar->u.pclipdata); - } - break; - default: - if (pvar->vt & VT_ARRAY) - { - FIXME("Need to call SafeArrayDestroy\n"); - /* SafeArrayDestroy(pvar->u.caub); */ - } - switch (pvar->vt & VT_VECTOR) - { - case VT_VARIANT: - FreePropVariantArray(pvar->u.capropvar.cElems, pvar->u.capropvar.pElems); - break; - case VT_CF: - OLE_FreeClipDataArray(pvar->u.caclipdata.cElems, pvar->u.caclipdata.pElems); - break; - case VT_BSTR: - case VT_LPSTR: - case VT_LPWSTR: - FIXME("Freeing of vector sub-type not supported yet\n"); - } - if (pvar->vt & VT_VECTOR) - { - /* pick an arbitary VT_VECTOR structure - they all have the same - * memory layout */ - CoTaskMemFree(pvar->u.capropvar.pElems); - } - } - - ZeroMemory(pvar, sizeof(*pvar)); - - return S_OK; -} - -/*********************************************************************** - * PropVariantCopy [OLE32.@] - */ -HRESULT WINAPI PropVariantCopy(PROPVARIANT *pvarDest, /* [out] */ - const PROPVARIANT *pvarSrc) /* [in] */ -{ - ULONG len; - TRACE("(%p, %p): stub:\n", pvarDest, pvarSrc); - - /* this will deal with most cases */ - CopyMemory(pvarDest, pvarSrc, sizeof(*pvarDest)); - - switch(pvarSrc->vt) - { - case VT_STREAM: - case VT_STREAMED_OBJECT: - case VT_STORAGE: - case VT_STORED_OBJECT: - IUnknown_AddRef((LPUNKNOWN)pvarDest->u.pStream); - break; - case VT_CLSID: - pvarDest->u.puuid = CoTaskMemAlloc(sizeof(CLSID)); - CopyMemory(pvarDest->u.puuid, pvarSrc->u.puuid, sizeof(CLSID)); - break; - case VT_LPSTR: - len = strlen(pvarSrc->u.pszVal); - pvarDest->u.pszVal = CoTaskMemAlloc(len); - CopyMemory(pvarDest->u.pszVal, pvarSrc->u.pszVal, len); - break; - case VT_LPWSTR: - len = lstrlenW(pvarSrc->u.pwszVal); - pvarDest->u.pwszVal = CoTaskMemAlloc(len); - CopyMemory(pvarDest->u.pwszVal, pvarSrc->u.pwszVal, len); - break; - case VT_BLOB: - case VT_BLOB_OBJECT: - if (pvarSrc->u.blob.pBlobData) - { - len = pvarSrc->u.blob.cbSize; - pvarDest->u.blob.pBlobData = CoTaskMemAlloc(len); - CopyMemory(pvarDest->u.blob.pBlobData, pvarSrc->u.blob.pBlobData, len); - } - break; - case VT_BSTR: - FIXME("Need to copy BSTR\n"); - break; - case VT_CF: - if (pvarSrc->u.pclipdata) - { - len = pvarSrc->u.pclipdata->cbSize - sizeof(pvarSrc->u.pclipdata->ulClipFmt); - CoTaskMemAlloc(len); - CopyMemory(pvarDest->u.pclipdata->pClipData, pvarSrc->u.pclipdata->pClipData, len); - } - break; - default: - if (pvarSrc->vt & VT_ARRAY) - { - FIXME("Need to call SafeArrayCopy\n"); - /* SafeArrayCopy(...); */ - } - if (pvarSrc->vt & VT_VECTOR) - { - int elemSize; - switch(pvarSrc->vt & VT_VECTOR) - { - case VT_I1: elemSize = sizeof(pvarSrc->u.cVal); break; - case VT_UI1: elemSize = sizeof(pvarSrc->u.bVal); break; - case VT_I2: elemSize = sizeof(pvarSrc->u.iVal); break; - case VT_UI2: elemSize = sizeof(pvarSrc->u.uiVal); break; - case VT_BOOL: elemSize = sizeof(pvarSrc->u.boolVal); break; - case VT_I4: elemSize = sizeof(pvarSrc->u.lVal); break; - case VT_UI4: elemSize = sizeof(pvarSrc->u.ulVal); break; - case VT_R4: elemSize = sizeof(pvarSrc->u.fltVal); break; - case VT_R8: elemSize = sizeof(pvarSrc->u.dblVal); break; - case VT_ERROR: elemSize = sizeof(pvarSrc->u.scode); break; - case VT_I8: elemSize = sizeof(pvarSrc->u.hVal); break; - case VT_UI8: elemSize = sizeof(pvarSrc->u.uhVal); break; - case VT_CY: elemSize = sizeof(pvarSrc->u.cyVal); break; - case VT_DATE: elemSize = sizeof(pvarSrc->u.date); break; - case VT_FILETIME: elemSize = sizeof(pvarSrc->u.filetime); break; - case VT_CLSID: elemSize = sizeof(*pvarSrc->u.puuid); break; - case VT_CF: elemSize = sizeof(*pvarSrc->u.pclipdata); break; - - case VT_BSTR: - case VT_LPSTR: - case VT_LPWSTR: - case VT_VARIANT: - default: - FIXME("Invalid element type: %ul\n", pvarSrc->vt & VT_VECTOR); - return E_INVALIDARG; - } - len = pvarSrc->u.capropvar.cElems; - pvarDest->u.capropvar.pElems = CoTaskMemAlloc(len * elemSize); - if (pvarSrc->vt == (VT_VECTOR | VT_VARIANT)) - { - ULONG i; - for (i = 0; i < len; i++) - PropVariantCopy(&pvarDest->u.capropvar.pElems[i], &pvarSrc->u.capropvar.pElems[i]); - } - else if (pvarSrc->vt == (VT_VECTOR | VT_CF)) - { - FIXME("Copy clipformats\n"); - } - else if (pvarSrc->vt == (VT_VECTOR | VT_BSTR)) - { - FIXME("Copy BSTRs\n"); - } - else if (pvarSrc->vt == (VT_VECTOR | VT_LPSTR)) - { - FIXME("Copy LPSTRs\n"); - } - else if (pvarSrc->vt == (VT_VECTOR | VT_LPSTR)) - { - FIXME("Copy LPWSTRs\n"); - } - else - CopyMemory(pvarDest->u.capropvar.pElems, pvarSrc->u.capropvar.pElems, len * elemSize); - } - } - - return S_OK; -} - -/*********************************************************************** - * FreePropVariantArray [OLE32.@] - */ -HRESULT WINAPI FreePropVariantArray(ULONG cVariants, /* [in] */ - PROPVARIANT *rgvars) /* [in/out] */ -{ - ULONG i; - - TRACE("(%lu, %p)\n", cVariants, rgvars); - - for(i = 0; i < cVariants; i++) - PropVariantClear(&rgvars[i]); - - return S_OK; -} - -/****************************************************************************** - * DllDebugObjectRPCHook (OLE32.@) - * turns on and off internal debugging, pointer is only used on macintosh - */ - -BOOL WINAPI DllDebugObjectRPCHook(BOOL b, void *dummy) -{ - FIXME("stub\n"); - return TRUE; -}