|
|
/*
* olepig.c - Module for indirect calling of OLE32.DLL functions. */
/*
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 "project.h"
#pragma hdrstop
#include <ole2ver.h>
/* Constants
************/
#define OLE_PIG_MODULE TEXT("ole32.dll")
/* Types
********/
/* OLE APIs */
typedef struct _olevtbl { DWORD (STDAPICALLTYPE *CoBuildVersion)(void); HRESULT (STDAPICALLTYPE *CoCreateInstance)(REFCLSID, PIUnknown, DWORD, REFIID, PVOID *); HRESULT (STDAPICALLTYPE *CoGetMalloc)(DWORD, PIMalloc *); HRESULT (STDAPICALLTYPE *CreateBindCtx)(DWORD, PIBindCtx *); HRESULT (STDAPICALLTYPE *CreateFileMoniker)(LPCOLESTR, PIMoniker *); HRESULT (STDAPICALLTYPE *OleInitialize)(PIMalloc); HRESULT (STDAPICALLTYPE *StgOpenStorage)(const OLECHAR *, PIStorage, DWORD, SNB, DWORD, PIStorage *); } OLEVTBL; DECLARE_STANDARD_TYPES(OLEVTBL);
/* Module Variables
*******************/
/* OLE module handle */
PRIVATE_DATA HANDLE MhmodOLE = NULL;
/* 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;
/***************************** Private Functions *****************************/
/* Module Prototypes
********************/
PRIVATE_CODE BOOL IsOLELoaded(void); PRIVATE_CODE BOOL LoadOLE(void); PRIVATE_CODE void UnloadOLE(void); PRIVATE_CODE BOOL InitializeOLE(void); PRIVATE_CODE BOOL GetOLEProc(LPSTR, PROC *); 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
/*
** IsOLELoaded() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE BOOL IsOLELoaded(void) { ASSERT(OLEStateOk());
return(MhmodOLE != NULL); }
/*
** LoadOLE() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ 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((TEXT("LoadOLE(): %s loaded. Oink oink!"), OLE_PIG_MODULE)); } else WARNING_OUT((TEXT("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((TEXT("LoadOLE(): FillOLEVTable() failed."))); } else WARNING_OUT((TEXT("LoadOLE(): LoadLibrary(%s) failed."), OLE_PIG_MODULE));
if (! bResult) UnloadOLE(); }
if (bResult) { bResult = InitializeOLE();
if (! bResult) WARNING_OUT((TEXT("LoadOLE(): %s loaded, but InitializeOLE() failed."), OLE_PIG_MODULE)); }
ASSERT(OLEStateOk());
return(bResult); }
/*
** UnloadOLE() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE void UnloadOLE(void) { if (Mpolevtbl) { FreeMemory(Mpolevtbl); Mpolevtbl = NULL;
TRACE_OUT((TEXT("UnloadOLE(): Freed %s vtable."), OLE_PIG_MODULE)); }
if (MhmodOLE) { /* Don't call CoUninitialize() here. OLE32.DLL will. */
FreeLibrary(MhmodOLE); MhmodOLE = NULL;
TRACE_OUT((TEXT("UnloadOLE(): Freed %s."), OLE_PIG_MODULE)); }
ASSERT(OLENotLoadedStateOK());
return; }
/*
** InitializeOLE() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ 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((TEXT("InitializeOLE(): OLE already initialized for thread %lx. OleInitialize() returned %s."), GetCurrentThreadId(), GetHRESULTString(hr)));
if (bResult) { EVAL(TlsSetValue(MdwOLEInitSlot, (PVOID)TRUE));
TRACE_OUT((TEXT("InitializeOLE(): OLE initialized for thread %lx. Using apartment threading model."), GetCurrentThreadId())); } else WARNING_OUT((TEXT("InitializeOLE(): OleInitialize() failed for thread %lx, returning %s."), GetCurrentThreadId(), GetHRESULTString(hr))); }
return(bResult); }
/*
** GetOLEProc() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE BOOL GetOLEProc(LPSTR pcszProc, PROC *pfp) { //ASSERT(IS_VALID_STRING_PTR(pcszProc, CSTR));
ASSERT(IS_VALID_WRITE_PTR(pfp, PROC));
ASSERT(IS_VALID_HANDLE(MhmodOLE, MODULE));
*pfp = GetProcAddress(MhmodOLE, pcszProc);
if (*pfp) TRACE_OUT((TEXT("GetOLEProc(): Got address of %s!%s."), OLE_PIG_MODULE, pcszProc)); else WARNING_OUT((TEXT("GetOLEProc(): Failed to get address of %s!%s."), OLE_PIG_MODULE, pcszProc));
ASSERT(! *pfp || IS_VALID_CODE_PTR(*pfp, PROC));
return(*pfp != NULL); }
/*
** FillOLEVTable() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE BOOL FillOLEVTable(void) { BOOL bResult;
ASSERT(IS_VALID_HANDLE(MhmodOLE, MODULE));
bResult = AllocateMemory(sizeof(*Mpolevtbl), &Mpolevtbl);
if (bResult) { bResult = (GetOLEProc("CoBuildVersion", &(PROC)(Mpolevtbl->CoBuildVersion)) && GetOLEProc("CoCreateInstance", &(PROC)(Mpolevtbl->CoCreateInstance)) && GetOLEProc("CoGetMalloc", &(PROC)(Mpolevtbl->CoGetMalloc)) && GetOLEProc("CreateBindCtx", &(PROC)(Mpolevtbl->CreateBindCtx)) && GetOLEProc("CreateFileMoniker", &(PROC)(Mpolevtbl->CreateFileMoniker)) && GetOLEProc("OleInitialize", &(PROC)(Mpolevtbl->OleInitialize)) && GetOLEProc("StgOpenStorage", &(PROC)(Mpolevtbl->StgOpenStorage)));
if (bResult) TRACE_OUT((TEXT("FillOLEVTable(): OLE vtable filled successfully."))); else { FreeMemory(Mpolevtbl); Mpolevtbl = NULL;
WARNING_OUT((TEXT("FillOLEVTable(): Failed to fill OLE vtable."))); } } else WARNING_OUT((TEXT("FillOLEVTable(): Out of memory.")));
ASSERT(! bResult || OLELoadedStateOK());
return(bResult); }
#ifdef DEBUG
/*
** IsValidPCOLEVTBL() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE BOOL IsValidPCOLEVTBL(PCOLEVTBL pcolevtbl) { return(IS_VALID_READ_PTR(pcolevtbl, PCOLEVTBL) && IS_VALID_CODE_PTR(pcolevtbl->CoBuildVersion, CoBuildVersion) && IS_VALID_CODE_PTR(pcolevtbl->CoCreateInstance, CoCreateInstance) && IS_VALID_CODE_PTR(pcolevtbl->CoGetMalloc, CoGetMalloc) && IS_VALID_CODE_PTR(pcolevtbl->CreateBindCtx, CreateBindCtx) && IS_VALID_CODE_PTR(pcolevtbl->CreateFileMoniker, CreateFileMoniker) && IS_VALID_CODE_PTR(pcolevtbl->OleInitialize, OleInitialize) && IS_VALID_CODE_PTR(pcolevtbl->StgOpenStorage, StgOpenStorage)); }
/*
** OLELoadedStateOK() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE BOOL OLELoadedStateOK(void) { return(IS_VALID_HANDLE(MhmodOLE, MODULE) && IS_VALID_STRUCT_PTR(Mpolevtbl, COLEVTBL)); }
/*
** OLENotLoadedStateOK() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE BOOL OLENotLoadedStateOK(void) { return(! MhmodOLE && ! Mpolevtbl); }
/*
** OLEStateOk() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE BOOL OLEStateOk(void) { return(OLELoadedStateOK() || OLENotLoadedStateOK); }
#endif
/****************************** Public Functions *****************************/
/*
** ProcessInitOLEPigModule() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ 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((TEXT("ProcessInitOLEPigModule(): Using thread local storage slot %lu for OLE initialization state."), MdwOLEInitSlot)); } else ERROR_OUT((TEXT("ProcessInitOLEPigModule(): TlsAlloc() failed to allocate thread local storage for OLE initialization state.")));
return(bResult); }
/*
** ProcessExitOLEPigModule() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE void ProcessExitOLEPigModule(void) { UnloadOLE();
if (MdwOLEInitSlot != TLS_OUT_OF_INDEXES) { EVAL(TlsFree(MdwOLEInitSlot)); MdwOLEInitSlot= TLS_OUT_OF_INDEXES; }
return; }
/*
** CoCreateInstance() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ HRESULT STDAPICALLTYPE CoCreateInstance(REFCLSID rclsid, PIUnknown piunkOuter, DWORD dwClsCtx, REFIID riid, PVOID *ppv) { HRESULT hr;
if (LoadOLE()) hr = Mpolevtbl->CoCreateInstance(rclsid, piunkOuter, dwClsCtx, riid, ppv); else hr = E_FAIL;
return(hr); }
/*
** CoGetMalloc() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ HRESULT STDAPICALLTYPE CoGetMalloc(DWORD dwMemContext, PIMalloc *ppimalloc) { HRESULT hr;
if (LoadOLE()) hr = Mpolevtbl->CoGetMalloc(dwMemContext, ppimalloc); else hr = E_FAIL;
return(hr); }
/*
** CreateBindCtx() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ HRESULT STDAPICALLTYPE CreateBindCtx(DWORD dwReserved, PIBindCtx *ppibindctx) { HRESULT hr;
if (LoadOLE()) hr = Mpolevtbl->CreateBindCtx(dwReserved, ppibindctx); else hr = E_FAIL;
return(hr); }
/*
** CreateFileMoniker() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ HRESULT STDAPICALLTYPE CreateFileMoniker(LPCOLESTR pwszPath, PIMoniker *ppimk) { HRESULT hr;
if (LoadOLE()) hr = Mpolevtbl->CreateFileMoniker(pwszPath, ppimk); else hr = E_FAIL;
return(hr); }
/*
** StgOpenStorage() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ HRESULT STDAPICALLTYPE StgOpenStorage(LPCOLESTR pwszName, PIStorage pistgPriority, DWORD dwMode, SNB snbExclude, DWORD dwReserved, PIStorage *ppistgOpen) { HRESULT hr;
if (LoadOLE()) hr = Mpolevtbl->StgOpenStorage(pwszName, pistgPriority, dwMode, snbExclude, dwReserved, ppistgOpen); else hr = E_FAIL;
return(hr); }
|