NT4/private/windows/rover/filesync/core/olepig.c
2020-09-30 17:12:29 +02:00

632 lines
12 KiB
C

/*
* 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 "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
*******************/
#pragma data_seg(DATA_SEG_PER_INSTANCE)
/* 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;
#pragma data_seg()
/***************************** 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);
}