mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
437 lines
9.9 KiB
437 lines
9.9 KiB
/*
|
|
* olepig.c - Module for indirect calling of OLE32.DLL functions.
|
|
*/
|
|
|
|
|
|
/*
|
|
|
|
This sucks. OLE32.DLL should be redesigned and reimplemented so that it can
|
|
be dynalinked to like a well-behaved DLL. OLE32.DLL is currently so slow and
|
|
piggy that we are forced to delay loading it until absolutely necessary.
|
|
|
|
*/
|
|
|
|
|
|
/* Headers
|
|
**********/
|
|
|
|
#include "all.h"
|
|
#pragma hdrstop
|
|
|
|
#include <ole2ver.h>
|
|
|
|
#include "olestock.h"
|
|
#include "olepig.h"
|
|
#include "resstr.h"
|
|
|
|
#ifdef FEATURE_OCX
|
|
#include "contain.hpp"
|
|
#endif
|
|
|
|
/* Constants
|
|
************/
|
|
|
|
#define OLE_PIG_MODULE "ole32.dll"
|
|
|
|
|
|
/* Types
|
|
********/
|
|
|
|
/* OLE APIs */
|
|
|
|
#ifndef FEATURE_OCX
|
|
typedef struct _olevtbl
|
|
{
|
|
DWORD (STDAPICALLTYPE *CoBuildVersion)(void);
|
|
HRESULT (STDAPICALLTYPE *OleInitialize)(PIMalloc);
|
|
void (STDAPICALLTYPE *OleUninitialize)(void);
|
|
|
|
HRESULT (STDAPICALLTYPE *DoDragDrop)(PIDataObject, PIDropSource, DWORD, PDWORD);
|
|
HRESULT (STDAPICALLTYPE *OleSetClipboard)(PIDataObject);
|
|
HRESULT (STDAPICALLTYPE *OleFlushClipboard)(void);
|
|
}
|
|
OLEVTBL;
|
|
DECLARE_STANDARD_TYPES(OLEVTBL);
|
|
#endif
|
|
|
|
/* Module Variables
|
|
*******************/
|
|
|
|
#pragma data_seg(DATA_SEG_PER_INSTANCE)
|
|
|
|
/* OLE module handle */
|
|
|
|
#ifdef FEATURE_OCX
|
|
PRIVATE_DATA HINSTANCE MhmodOLE = NULL;
|
|
#else
|
|
PRIVATE_DATA HANDLE MhmodOLE = NULL;
|
|
#endif
|
|
|
|
/* pointer to vtable of OLE functions */
|
|
|
|
PRIVATE_DATA POLEVTBL Mpolevtbl = NULL;
|
|
|
|
/* TLS slot used to store OLE thread initialization state */
|
|
|
|
PRIVATE_DATA DWORD MdwOLEInitSlot = TLS_OUT_OF_INDEXES;
|
|
|
|
#pragma data_seg()
|
|
|
|
|
|
/***************************** Private Functions *****************************/
|
|
|
|
/* Module Prototypes
|
|
********************/
|
|
|
|
PRIVATE_CODE BOOL IsOLELoaded(void);
|
|
#ifndef FEATURE_OCX
|
|
PRIVATE_CODE BOOL LoadOLE(void);
|
|
#endif
|
|
PRIVATE_CODE void UnloadOLE(void);
|
|
PRIVATE_CODE BOOL InitializeOLE(void);
|
|
PRIVATE_CODE BOOL GetOLEProc(PCSTR, FARPROC *);
|
|
PRIVATE_CODE BOOL FillOLEVTable(void);
|
|
|
|
#ifdef DEBUG
|
|
|
|
PRIVATE_CODE BOOL IsValidPCOLEVTBL(PCOLEVTBL);
|
|
PRIVATE_CODE BOOL OLELoadedStateOK(void);
|
|
PRIVATE_CODE BOOL OLENotLoadedStateOK(void);
|
|
PRIVATE_CODE BOOL OLEStateOk(void);
|
|
|
|
#endif
|
|
|
|
|
|
PRIVATE_CODE BOOL IsOLELoaded(void)
|
|
{
|
|
ASSERT(OLEStateOk());
|
|
|
|
return(MhmodOLE != NULL);
|
|
}
|
|
|
|
|
|
PRIVATE_CODE BOOL LoadOLE(void)
|
|
{
|
|
BOOL bResult;
|
|
|
|
if (IsOLELoaded())
|
|
bResult = TRUE;
|
|
else
|
|
{
|
|
bResult = FALSE;
|
|
|
|
MhmodOLE = LoadLibrary(OLE_PIG_MODULE);
|
|
|
|
if (MhmodOLE)
|
|
{
|
|
if (FillOLEVTable())
|
|
{
|
|
DWORD dwBuildVersion;
|
|
|
|
dwBuildVersion = Mpolevtbl->CoBuildVersion();
|
|
|
|
/* Require same major version and same or newer minor version. */
|
|
|
|
if (HIWORD(dwBuildVersion) == rmm &&
|
|
LOWORD(dwBuildVersion) >= rup)
|
|
{
|
|
bResult = TRUE;
|
|
|
|
TRACE_OUT(("LoadOLE(): %s loaded. Oink oink!",
|
|
OLE_PIG_MODULE));
|
|
}
|
|
else
|
|
WARNING_OUT(("LoadOLE(): Bad %s version %u.%u. This module was built with %s version %u.%u.",
|
|
OLE_PIG_MODULE,
|
|
(UINT)HIWORD(dwBuildVersion),
|
|
(UINT)LOWORD(dwBuildVersion),
|
|
OLE_PIG_MODULE,
|
|
(UINT)rmm,
|
|
(UINT)rup));
|
|
}
|
|
else
|
|
WARNING_OUT(("LoadOLE(): FillOLEVTable() failed."));
|
|
}
|
|
else
|
|
WARNING_OUT(("LoadOLE(): LoadLibrary(%s) failed.",
|
|
OLE_PIG_MODULE));
|
|
|
|
if (! bResult)
|
|
UnloadOLE();
|
|
}
|
|
|
|
if (bResult)
|
|
{
|
|
bResult = InitializeOLE();
|
|
|
|
if (! bResult)
|
|
WARNING_OUT(("LoadOLE(): %s loaded, but InitializeOLE() failed.",
|
|
OLE_PIG_MODULE));
|
|
}
|
|
|
|
ASSERT(OLEStateOk());
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
|
|
PRIVATE_CODE void UnloadOLE(void)
|
|
{
|
|
if (Mpolevtbl)
|
|
{
|
|
Mpolevtbl->OleUninitialize();
|
|
|
|
GTR_FREE(Mpolevtbl);
|
|
Mpolevtbl = NULL;
|
|
|
|
TRACE_OUT(("UnloadOLE(): Freed %s vtable.",
|
|
OLE_PIG_MODULE));
|
|
}
|
|
|
|
if (MhmodOLE)
|
|
{
|
|
FreeLibrary(MhmodOLE);
|
|
MhmodOLE = NULL;
|
|
|
|
TRACE_OUT(("UnloadOLE(): Freed %s.",
|
|
OLE_PIG_MODULE));
|
|
}
|
|
|
|
ASSERT(OLENotLoadedStateOK());
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
PRIVATE_CODE BOOL InitializeOLE(void)
|
|
{
|
|
BOOL bResult;
|
|
|
|
ASSERT(IsOLELoaded());
|
|
ASSERT(MdwOLEInitSlot != TLS_OUT_OF_INDEXES);
|
|
|
|
if (TlsGetValue(MdwOLEInitSlot))
|
|
bResult = TRUE;
|
|
else
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = Mpolevtbl->OleInitialize(NULL);
|
|
|
|
bResult = (SUCCEEDED(hr) ||
|
|
hr == CO_E_ALREADYINITIALIZED);
|
|
|
|
if (hr == CO_E_ALREADYINITIALIZED)
|
|
WARNING_OUT(("InitializeOLE(): OLE already initialized for thread %lx. OleInitialize() returned %s.",
|
|
GetCurrentThreadId(),
|
|
GetHRESULTString(hr)));
|
|
|
|
if (bResult)
|
|
{
|
|
EVAL(TlsSetValue(MdwOLEInitSlot, (PVOID)TRUE));
|
|
|
|
TRACE_OUT(("InitializeOLE(): OLE initialized for thread %lx. Using apartment threading model.",
|
|
GetCurrentThreadId()));
|
|
}
|
|
else
|
|
WARNING_OUT(("InitializeOLE(): OleInitialize() failed for thread %lx, returning %s.",
|
|
GetCurrentThreadId(),
|
|
GetHRESULTString(hr)));
|
|
}
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
|
|
PRIVATE_CODE BOOL GetOLEProc(PCSTR pcszProc, FARPROC *pfp)
|
|
{
|
|
ASSERT(IS_VALID_STRING_PTR(pcszProc, CSTR));
|
|
ASSERT(IS_VALID_WRITE_PTR(pfp, FARPROC));
|
|
|
|
ASSERT(IS_VALID_HANDLE(MhmodOLE, MODULE));
|
|
|
|
*pfp = GetProcAddress(MhmodOLE, pcszProc);
|
|
|
|
if (*pfp)
|
|
TRACE_OUT(("GetOLEProc(): Got address of %s!%s.",
|
|
OLE_PIG_MODULE,
|
|
pcszProc));
|
|
else
|
|
WARNING_OUT(("GetOLEProc(): Failed to get address of %s!%s.",
|
|
OLE_PIG_MODULE,
|
|
pcszProc));
|
|
|
|
ASSERT(! *pfp ||
|
|
IS_VALID_CODE_PTR(*pfp, FARPROC));
|
|
|
|
return(*pfp != NULL);
|
|
}
|
|
|
|
|
|
PRIVATE_CODE BOOL FillOLEVTable(void)
|
|
{
|
|
BOOL bResult;
|
|
|
|
ASSERT(IS_VALID_HANDLE(MhmodOLE, MODULE));
|
|
|
|
Mpolevtbl = GTR_MALLOC(sizeof(*Mpolevtbl));
|
|
|
|
if (Mpolevtbl)
|
|
{
|
|
bResult = (GetOLEProc("CoBuildVersion", &(FARPROC)(Mpolevtbl->CoBuildVersion)) &&
|
|
GetOLEProc("OleInitialize", &(FARPROC)(Mpolevtbl->OleInitialize)) &&
|
|
GetOLEProc("OleUninitialize", &(FARPROC)(Mpolevtbl->OleUninitialize)) &&
|
|
#ifdef FEATURE_OCX
|
|
GetOLEProc("CLSIDFromString", &(FARPROC)(Mpolevtbl->CLSIDFromString)) &&
|
|
GetOLEProc("CLSIDFromProgID", &(FARPROC)(Mpolevtbl->CLSIDFromProgID)) &&
|
|
GetOLEProc("CoCreateInstance", &(FARPROC)(Mpolevtbl->CoCreateInstance)) &&
|
|
#endif
|
|
GetOLEProc("DoDragDrop", &(FARPROC)(Mpolevtbl->DoDragDrop)) &&
|
|
GetOLEProc("OleSetClipboard", &(FARPROC)(Mpolevtbl->OleSetClipboard)) &&
|
|
GetOLEProc("OleFlushClipboard", &(FARPROC)(Mpolevtbl->OleFlushClipboard)));
|
|
|
|
if (bResult)
|
|
TRACE_OUT(("FillOLEVTable(): OLE vtable filled successfully."));
|
|
else
|
|
{
|
|
GTR_FREE(Mpolevtbl);
|
|
Mpolevtbl = NULL;
|
|
|
|
WARNING_OUT(("FillOLEVTable(): Failed to fill OLE vtable."));
|
|
}
|
|
}
|
|
else
|
|
bResult = FALSE;
|
|
|
|
ASSERT(! bResult ||
|
|
OLELoadedStateOK());
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
PRIVATE_CODE BOOL IsValidPCOLEVTBL(PCOLEVTBL pcolevtbl)
|
|
{
|
|
return(IS_VALID_READ_PTR(pcolevtbl, COLEVTBL) &&
|
|
IS_VALID_CODE_PTR(pcolevtbl->CoBuildVersion, CoBuildVersion) &&
|
|
IS_VALID_CODE_PTR(pcolevtbl->OleInitialize, OleInitialize) &&
|
|
IS_VALID_CODE_PTR(pcolevtbl->OleUninitialize, OleUninitialize) &&
|
|
#ifdef FEATURE_OCX
|
|
IS_VALID_CODE_PTR(pcolevtbl->CLSIDFromString, CLSIDFromString) &&
|
|
IS_VALID_CODE_PTR(pcolevtbl->CLSIDFromProgID, CLSIDFromProgID) &&
|
|
IS_VALID_CODE_PTR(pcolevtbl->CoCreateInstance, CoCreateInstance) &&
|
|
#endif
|
|
IS_VALID_CODE_PTR(pcolevtbl->DoDragDrop, DoDragDrop) &&
|
|
IS_VALID_CODE_PTR(pcolevtbl->OleSetClipboard, OleSetClipboard) &&
|
|
IS_VALID_CODE_PTR(pcolevtbl->OleFlushClipboard, OleFlushClipboard));
|
|
}
|
|
|
|
|
|
PRIVATE_CODE BOOL OLELoadedStateOK(void)
|
|
{
|
|
return(IS_VALID_HANDLE(MhmodOLE, MODULE) &&
|
|
IS_VALID_STRUCT_PTR(Mpolevtbl, COLEVTBL));
|
|
}
|
|
|
|
|
|
PRIVATE_CODE BOOL OLENotLoadedStateOK(void)
|
|
{
|
|
return(! MhmodOLE &&
|
|
! Mpolevtbl);
|
|
}
|
|
|
|
|
|
PRIVATE_CODE BOOL OLEStateOk(void)
|
|
{
|
|
return(OLENotLoadedStateOK() ||
|
|
OLELoadedStateOK());
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/****************************** Public Functions *****************************/
|
|
|
|
|
|
PUBLIC_CODE BOOL ProcessInitOLEPigModule(void)
|
|
{
|
|
BOOL bResult;
|
|
|
|
ASSERT(MdwOLEInitSlot == TLS_OUT_OF_INDEXES);
|
|
|
|
MdwOLEInitSlot = TlsAlloc();
|
|
|
|
bResult = (MdwOLEInitSlot != TLS_OUT_OF_INDEXES);
|
|
|
|
if (bResult)
|
|
{
|
|
EVAL(TlsSetValue(MdwOLEInitSlot, (PVOID)FALSE));
|
|
|
|
TRACE_OUT(("ProcessInitOLEPigModule(): Using thread local storage slot %lu for OLE initialization state.",
|
|
MdwOLEInitSlot));
|
|
}
|
|
else
|
|
ERROR_OUT(("ProcessInitOLEPigModule(): TlsAlloc() failed to allocate thread local storage for OLE initialization state."));
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
|
|
PUBLIC_CODE void ProcessExitOLEPigModule(void)
|
|
{
|
|
#ifdef FEATURE_OCX
|
|
DestroyContainer();
|
|
#endif
|
|
UnloadOLE();
|
|
|
|
if (MdwOLEInitSlot != TLS_OUT_OF_INDEXES)
|
|
{
|
|
EVAL(TlsFree(MdwOLEInitSlot));
|
|
MdwOLEInitSlot= TLS_OUT_OF_INDEXES;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
HRESULT STDAPICALLTYPE DoDragDrop(PIDataObject pido, PIDropSource pids,
|
|
DWORD dwAvailEffects, PDWORD pdwEffect)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (LoadOLE())
|
|
hr = Mpolevtbl->DoDragDrop(pido, pids, dwAvailEffects, pdwEffect);
|
|
else
|
|
hr = E_FAIL;
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT STDAPICALLTYPE OleSetClipboard(PIDataObject pido)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (LoadOLE())
|
|
hr = Mpolevtbl->OleSetClipboard(pido);
|
|
else
|
|
hr = E_FAIL;
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT STDAPICALLTYPE OleFlushClipboard(void)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (LoadOLE())
|
|
hr = Mpolevtbl->OleFlushClipboard();
|
|
else
|
|
hr = E_FAIL;
|
|
|
|
return(hr);
|
|
}
|
|
|