📄 ole2.c
字号:
/*
* OLE2 library
*
* Copyright 1995 Martin von Loewis
* Copyright 1999 Francis Beaudet
* Copyright 1999 Noel Borthwick
* Copyright 1999, 2000 Marcus Meissner
* Copyright 2005 Juan Lang
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include <assert.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#define COBJMACROS
#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 "ole2.h"
#include "ole2ver.h"
#include "wine/unicode.h"
#include "compobj_private.h"
#include "wine/list.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
WINE_DECLARE_DEBUG_CHANNEL(accel);
/******************************************************************************
* 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 list entry;
} 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;
POINTL curMousePos; /* current position of the mouse in screen coordinates */
DWORD dwKeyState; /* current state of the shift and ctrl keys and the mouse buttons */
} 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 LONG 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 struct list targetListHead = LIST_INIT(targetListHead);
/******************************************************************************
* 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(void);
static void OLEMenu_UnInitialize(void);
static BOOL OLEMenu_InstallHooks( DWORD tid );
static BOOL OLEMenu_UnInstallHooks( DWORD tid );
static OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid );
static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos );
static BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor );
static LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam);
/******************************************************************************
* These are the prototypes of the OLE Clipboard initialization methods (in clipboard.c)
*/
extern void OLEClipbrd_UnInitialize(void);
extern void OLEClipbrd_Initialize(void);
/******************************************************************************
* These are the prototypes of the utility methods used for OLE Drag n Drop
*/
static void OLEDD_Initialize(void);
static DropTargetNode* OLEDD_FindDropTarget(
HWND hwndOfTarget);
static void OLEDD_FreeDropTarget(DropTargetNode*, BOOL);
static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam);
static void OLEDD_TrackMouseMove(
TrackerWindowInfo* trackerInfo);
static void OLEDD_TrackStateChange(
TrackerWindowInfo* trackerInfo);
static DWORD OLEDD_GetButtonState(void);
/******************************************************************************
* 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 (!COM_CurrentInfo()->ole_inits++ &&
InterlockedIncrement(&OLE_moduleLockCount) == 1)
{
/*
* Initialize the libraries.
*/
TRACE("() - Initializing the OLE libraries\n");
/*
* OLE Clipboard
*/
OLEClipbrd_Initialize();
/*
* Drag and Drop
*/
OLEDD_Initialize();
/*
* OLE shared menu
*/
OLEMenu_Initialize();
}
return hr;
}
/******************************************************************************
* OleUninitialize [OLE2.3]
* OleUninitialize [OLE32.@]
*/
void WINAPI OleUninitialize(void)
{
TRACE("()\n");
/*
* If we hit the bottom of the lock stack, free the libraries.
*/
if (!--COM_CurrentInfo()->ole_inits && !InterlockedDecrement(&OLE_moduleLockCount))
{
/*
* Actually free the libraries.
*/
TRACE("() - Freeing the last reference count\n");
/*
* OLE Clipboard
*/
OLEClipbrd_UnInitialize();
/*
* OLE shared menu
*/
OLEMenu_UnInitialize();
}
/*
* Then, uninitialize the COM libraries.
*/
CoUninitialize();
}
/******************************************************************************
* OleInitializeWOW [OLE32.@]
*/
HRESULT WINAPI OleInitializeWOW(DWORD x, DWORD y) {
FIXME("(0x%08x, 0x%08x),stub!\n",x, y);
return 0;
}
/***********************************************************************
* RegisterDragDrop (OLE32.@)
*/
HRESULT WINAPI RegisterDragDrop(
HWND hwnd,
LPDROPTARGET pDropTarget)
{
DropTargetNode* dropTargetInfo;
TRACE("(%p,%p)\n", hwnd, pDropTarget);
if (!COM_CurrentApt())
{
ERR("COM not initialized\n");
return CO_E_NOTINITIALIZED;
}
if (!pDropTarget)
return E_INVALIDARG;
if (!IsWindow(hwnd))
{
ERR("invalid hwnd %p\n", hwnd);
return DRAGDROP_E_INVALIDHWND;
}
/*
* 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;
/*
* Don't forget that this is an interface pointer, need to nail it down since
* we keep a copy of it.
*/
IDropTarget_AddRef(pDropTarget);
dropTargetInfo->dropTarget = pDropTarget;
list_add_tail(&targetListHead, &dropTargetInfo->entry);
return S_OK;
}
/***********************************************************************
* RevokeDragDrop (OLE32.@)
*/
HRESULT WINAPI RevokeDragDrop(
HWND hwnd)
{
DropTargetNode* dropTargetInfo;
TRACE("(%p)\n", hwnd);
if (!IsWindow(hwnd))
{
ERR("invalid hwnd %p\n", hwnd);
return DRAGDROP_E_INVALIDHWND;
}
/*
* First, check if the window is already registered.
*/
dropTargetInfo = OLEDD_FindDropTarget(hwnd);
/*
* If it ain't in there, it's an error.
*/
if (dropTargetInfo==NULL)
return DRAGDROP_E_NOTREGISTERED;
OLEDD_FreeDropTarget(dropTargetInfo, TRUE);
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;
LPSTR buffer;
HRESULT retVal;
/*
* Initialize the out parameter.
*/
*pszUserType = NULL;
/*
* Build the key name we're looking for
*/
sprintf( keyName, "CLSID\\{%08x-%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, %d, %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,
(LPBYTE) 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 */
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -