+++ /dev/null
-
-/*
- * 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 <assert.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-#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->hwndTarget<curNode->hwndTarget)
- {
- /*
- * 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 (hwndOfTarget<curNode->hwndTarget)
- {
- /*
- * 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 (hwndOfTarget<curNode->hwndTarget)
- {
- /*
- * 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;
-}