601 lines
20 KiB
C++
601 lines
20 KiB
C++
//+------------------------------------------------------------------
|
|
//
|
|
// File: tdllhost.cxx
|
|
//
|
|
// Contents: test for dll hosting
|
|
//
|
|
//--------------------------------------------------------------------
|
|
#include <tstmain.hxx>
|
|
#include "tdllhost.h"
|
|
|
|
|
|
// BUGBUG: these should be in a public place somewhere.
|
|
DEFINE_OLEGUID(CLSID_Balls, 0x0000013a, 1, 8);
|
|
DEFINE_OLEGUID(CLSID_Cubes, 0x0000013b, 1, 8);
|
|
DEFINE_OLEGUID(CLSID_LoopSrv, 0x0000013c, 1, 8);
|
|
|
|
DEFINE_OLEGUID(CLSID_QI, 0x00000140, 0, 8);
|
|
const GUID CLSID_QI =
|
|
{0x00000140,0x0000,0x0008,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
|
|
|
|
const GUID CLSID_QIHANDLER1 =
|
|
{0x00000141,0x0000,0x0008,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
|
|
|
|
|
|
const TCHAR *pszRegValThreadModel = TEXT("ThreadingModel");
|
|
const TCHAR *pszSingleModel = TEXT("Single");
|
|
const TCHAR *pszApartmentModel = TEXT("Apartment");
|
|
const TCHAR *pszMultiThreadedModel = TEXT("Free");
|
|
const TCHAR *pszBothModel = TEXT("Both");
|
|
|
|
BOOL gfApt;
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// Structures and Function Prototypes
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
typedef struct tagLoadDLLParams
|
|
{
|
|
DWORD dwCallingTID; // tid of calling thread
|
|
DWORD dwCoInitFlag; // flag to initialize OLE with
|
|
DWORD dwItfFlag; // flag if the resulting object should be a proxy
|
|
BOOL RetVal; // return value
|
|
HANDLE hEvent; // thread completion event
|
|
} SLoadDLLParam;
|
|
|
|
typedef enum tagITFFLAGS
|
|
{
|
|
ITF_REAL = 1, // expect ptr to real object
|
|
ITF_PROXY = 2 // expect ptr to proxy object
|
|
} ITFFLAGS;
|
|
|
|
|
|
// worker subroutines
|
|
BOOL SpinThread(DWORD dwInitFlag, DWORD dwItfFlag);
|
|
DWORD _stdcall LoadDLLOnThread(void *param);
|
|
BOOL LoadClassObject(DWORD dwItfFlag);
|
|
BOOL SetRegForDll(REFCLSID rclsid, const TCHAR *pszThreadModel);
|
|
|
|
|
|
// test routines - return value of TRUE return means the test passed
|
|
BOOL TestLoadSingleThreaded(void);
|
|
BOOL TestLoadApartmentThreaded(void);
|
|
BOOL TestLoadMultiThreaded(void);
|
|
BOOL TestLoadBothThreaded(void);
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestDllHost - main test driver. read the ini file to determine
|
|
// which tests to run.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL TestDllHost(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
|
|
gfApt = (gInitFlag == COINIT_APARTMENTTHREADED) ? TRUE : FALSE;
|
|
|
|
// the driver did a CoInitialize, we dont want one so do CoUninit.
|
|
CoUninitialize();
|
|
|
|
if (GetProfileInt(TEXT("DllHost Test"),TEXT("LoadSingleThreaded"),1))
|
|
RetVal &= TestLoadSingleThreaded();
|
|
|
|
if (GetProfileInt(TEXT("DllHost Test"),TEXT("LoadApartmentThreaded"),1))
|
|
RetVal &= TestLoadApartmentThreaded();
|
|
|
|
if (GetProfileInt(TEXT("DllHost Test"),TEXT("LoadMultiThreaded"),1))
|
|
RetVal &= TestLoadMultiThreaded();
|
|
|
|
if (GetProfileInt(TEXT("DllHost Test"),TEXT("LoadBothThreaded"),1))
|
|
RetVal &= TestLoadBothThreaded();
|
|
|
|
// re-initialize so we dont get a complaint from OLE in debug builds
|
|
// about an unbalanced call to Uninitialize.
|
|
CoInitializeEx(NULL, gInitFlag);
|
|
|
|
return RetVal;
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestLoadSingleThreaded
|
|
//
|
|
// Tests loading a single-threaded DLL
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL TestLoadSingleThreaded(void)
|
|
{
|
|
BOOL RetVal = TRUE, RetVal2 = TRUE;
|
|
HRESULT hRes = S_OK;
|
|
|
|
OUTPUT ("\n\nStarting TestLoadSingleThreaded\n");
|
|
|
|
// First, mark the DLL appropriately in the registry.
|
|
RetVal2 = SetRegForDll(CLSID_QI, pszSingleModel);
|
|
TEST_FAILED(!RetVal2, "SetRegForDLL Failed\n");
|
|
|
|
|
|
hRes = CoInitializeEx(NULL, gInitFlag);
|
|
TEST_FAILED(FAILED(hRes), "CoInitializeEx Failed\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
OUTPUT ("\n Load Single-Threaded DLL on Main Thread\n");
|
|
|
|
RetVal2 = LoadClassObject((gfApt) ? ITF_REAL : ITF_PROXY);
|
|
TEST_FAILED(!RetVal2, "SingleThreadedDLL on Main Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Single-Threaded DLL on Main Thread\n");
|
|
|
|
OUTPUT ("\n Load Single-Threaded DLL on Main Thread\n");
|
|
|
|
RetVal2 = LoadClassObject((gfApt) ? ITF_REAL : ITF_PROXY);
|
|
TEST_FAILED(!RetVal2, "SingleThreadedDLL on Main Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Single-Threaded DLL on Main Thread\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
OUTPUT ("\n Load Single-Threaded DLL on Different Apartment Thread\n");
|
|
|
|
hRes = SpinThread(COINIT_APARTMENTTHREADED, ITF_PROXY);
|
|
TEST_FAILED(!RetVal2, "SingleThreadedDLL on Apartment Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Single-Threaded DLL on Different Apartment Thread\n");
|
|
|
|
OUTPUT ("\n Second Load Single-Threaded DLL on Different Apartment Thread\n");
|
|
|
|
hRes = SpinThread(COINIT_APARTMENTTHREADED, ITF_PROXY);
|
|
TEST_FAILED(!RetVal2, "Single-ThreadedDLL on Apartment Thread Failed\n");
|
|
|
|
OUTPUT (" Second Done Load Single-Threaded DLL on Different Apartment Thread\n");
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
OUTPUT ("\n Load Single-Thread DLL on Multi-Threaded Apartment Thread\n");
|
|
|
|
hRes = SpinThread(COINIT_MULTITHREADED, ITF_PROXY);
|
|
TEST_FAILED(!RetVal2, "SingleThreadedDLL on Multi Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Single-Thread DLL on Multi-Threaded Apartment Thread\n");
|
|
|
|
OUTPUT ("\n Load Single-Thread DLL on Multi-Threaded Apartment Thread\n");
|
|
|
|
hRes = SpinThread(COINIT_MULTITHREADED, ITF_PROXY);
|
|
TEST_FAILED(!RetVal2, "SingleThreadedDLL on Multi Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Single-Thread DLL on Multi-Threaded Apartment Thread\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
CoUninitialize();
|
|
|
|
BOOL fResult = TestResult(RetVal, "TestLoadSingleThreaded");
|
|
Sleep(2000);
|
|
return fResult;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestLoadApartmentThreaded
|
|
//
|
|
// Tests loading an apartment-threaded DLL
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL TestLoadApartmentThreaded(void)
|
|
{
|
|
BOOL RetVal = TRUE, RetVal2 = FALSE;
|
|
HRESULT hRes = S_OK;
|
|
|
|
OUTPUT ("\n\nStarting TestLoadApartmentThreaded\n");
|
|
|
|
// First, mark the DLL appropriately in the registry.
|
|
RetVal2 = SetRegForDll(CLSID_QI, pszApartmentModel);
|
|
TEST_FAILED(!RetVal2, "SetRegForDLL Failed\n");
|
|
|
|
hRes = CoInitializeEx(NULL, gInitFlag);
|
|
TEST_FAILED(FAILED(hRes), "CoInitializeEx Failed\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
OUTPUT ("\n Load Apartment-Threaded DLL on Main Thread\n");
|
|
|
|
RetVal2 = LoadClassObject((gfApt) ? ITF_REAL : ITF_PROXY);
|
|
TEST_FAILED(!RetVal2, "Apartment-ThreadedDLL on Main Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Apartment-Threaded DLL on Main Thread\n");
|
|
|
|
OUTPUT ("\n Load Apartment-Threaded DLL on Main Thread\n");
|
|
|
|
RetVal2 = LoadClassObject((gfApt) ? ITF_REAL : ITF_PROXY);
|
|
TEST_FAILED(!RetVal2, "Apartment-ThreadedDLL on Main Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Apartment-Threaded DLL on Main Thread\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
OUTPUT ("\n Load Apartment-Threaded DLL on Different Apartment Thread\n");
|
|
|
|
hRes = SpinThread(COINIT_APARTMENTTHREADED, ITF_REAL);
|
|
TEST_FAILED(!RetVal2, "Apartment-ThreadedDLL on Apartment Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Apartment-Threaded DLL on Different Apartment Thread\n");
|
|
|
|
OUTPUT ("\n Second Load Apartment-Threaded DLL on Different Apartment Thread\n");
|
|
|
|
hRes = SpinThread(COINIT_APARTMENTTHREADED, ITF_REAL);
|
|
TEST_FAILED(!RetVal2, "Apartment-ThreadedDLL on Apartment Thread Failed\n");
|
|
|
|
OUTPUT (" Second Done Load Apartment-Threaded DLL on Different Apartment Thread\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
OUTPUT ("\n Load Apartment-Thread DLL on Multi-Threaded Apartment Thread\n");
|
|
|
|
hRes = SpinThread(COINIT_MULTITHREADED, ITF_PROXY);
|
|
TEST_FAILED(!RetVal2, "Apartment-ThreadedDLL on Multi Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Apartment-Thread DLL on Multi-Threaded Apartment Thread\n");
|
|
|
|
OUTPUT ("\n Load Apartment-Thread DLL on Multi-Threaded Apartment Thread\n");
|
|
|
|
hRes = SpinThread(COINIT_MULTITHREADED, ITF_PROXY);
|
|
TEST_FAILED(!RetVal2, "Apartment-ThreadedDLL on Multi Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Apartment-Thread DLL on Multi-Threaded Apartment Thread\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
CoUninitialize();
|
|
|
|
BOOL fResult = TestResult(RetVal, "TestLoadApartmentThreaded");
|
|
Sleep(2000);
|
|
return fResult;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestLoadMultiThreaded
|
|
//
|
|
// Tests loading a multi-threaded DLL
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL TestLoadMultiThreaded(void)
|
|
{
|
|
BOOL RetVal = TRUE, RetVal2 = FALSE;;
|
|
HRESULT hRes = S_OK;
|
|
|
|
OUTPUT ("\n\nStarting TestLoadMultiThreaded\n");
|
|
|
|
// First, mark the DLL appropriately in the registry.
|
|
RetVal2 = SetRegForDll(CLSID_QI, pszMultiThreadedModel);
|
|
TEST_FAILED(!RetVal2, "SetRegForDLL Failed\n");
|
|
|
|
hRes = CoInitializeEx(NULL, gInitFlag);
|
|
TEST_FAILED(FAILED(hRes), "CoInitializeEx Failed\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
OUTPUT ("\n Load Free-Threaded DLL on Main Thread\n");
|
|
|
|
RetVal2 = LoadClassObject((gfApt) ? ITF_PROXY : ITF_REAL);
|
|
TEST_FAILED(!RetVal2, "Free-ThreadedDLL on Main Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Free-Threaded DLL on Main Thread\n");
|
|
|
|
OUTPUT ("\n Load Free-Threaded DLL on Main Thread\n");
|
|
|
|
RetVal2 = LoadClassObject((gfApt) ? ITF_PROXY : ITF_REAL);
|
|
TEST_FAILED(!RetVal2, "Free-ThreadedDLL on Main Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Free-Threaded DLL on Main Thread\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
OUTPUT ("\n Load Free-Threaded DLL on Different Apartment Thread\n");
|
|
|
|
hRes = SpinThread(COINIT_APARTMENTTHREADED, ITF_PROXY);
|
|
TEST_FAILED(!RetVal2, "Free-ThreadedDLL on Apartment Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Free-Threaded DLL on Different Apartment Thread\n");
|
|
|
|
OUTPUT ("\n Second Load Free-Threaded DLL on Different Apartment Thread\n");
|
|
|
|
hRes = SpinThread(COINIT_APARTMENTTHREADED, ITF_PROXY);
|
|
TEST_FAILED(!RetVal2, "Free-ThreadedDLL on Apartment Thread Failed\n");
|
|
|
|
OUTPUT (" Second Done Load Apartment-Threaded DLL on Different Apartment Thread\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
OUTPUT ("\n Load Apartment-Thread DLL on Multi-Threaded Apartment Thread\n");
|
|
|
|
hRes = SpinThread(COINIT_MULTITHREADED, ITF_REAL);
|
|
TEST_FAILED(!RetVal2, "Free-ThreadedDLL on Multi Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Free-Thread DLL on Multi-Threaded Apartment Thread\n");
|
|
|
|
OUTPUT ("\n Load Apartment-Thread DLL on Multi-Threaded Apartment Thread\n");
|
|
|
|
hRes = SpinThread(COINIT_MULTITHREADED, ITF_REAL);
|
|
TEST_FAILED(!RetVal2, "Free-ThreadedDLL on Multi Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Free-Thread DLL on Multi-Threaded Apartment Thread\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
CoUninitialize();
|
|
|
|
BOOL fResult = TestResult(RetVal, "TestLoadMultiThreaded");
|
|
Sleep(2000);
|
|
return fResult;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestLoadBothThreaded
|
|
//
|
|
// Tests loading a both-threaded DLL
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL TestLoadBothThreaded(void)
|
|
{
|
|
BOOL RetVal = TRUE, RetVal2 = FALSE;;
|
|
HRESULT hRes = S_OK;
|
|
|
|
OUTPUT ("\n\nStarting TestLoadBothThreaded\n");
|
|
|
|
// First, mark the DLL appropriately in the registry.
|
|
RetVal2 = SetRegForDll(CLSID_QI, pszBothModel);
|
|
TEST_FAILED(!RetVal2, "SetRegForDLL Failed\n");
|
|
|
|
hRes = CoInitializeEx(NULL, gInitFlag);
|
|
TEST_FAILED(FAILED(hRes), "CoInitializeEx Failed\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
OUTPUT ("\n Load Both-Threaded DLL on Main Thread\n");
|
|
|
|
RetVal2 = LoadClassObject(ITF_REAL);
|
|
TEST_FAILED(!RetVal2, "Both-ThreadedDLL on Main Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Both-Threaded DLL on Main Thread\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
OUTPUT ("\n Load Both-Threaded DLL on Different Apartment Thread\n");
|
|
|
|
hRes = SpinThread(COINIT_APARTMENTTHREADED, ITF_REAL);
|
|
TEST_FAILED(!RetVal2, "Free-ThreadedDLL on Apartment Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Free-Threaded DLL on Different Apartment Thread\n");
|
|
|
|
OUTPUT ("\n Second Load Free-Threaded DLL on Different Apartment Thread\n");
|
|
|
|
hRes = SpinThread(COINIT_APARTMENTTHREADED, ITF_REAL);
|
|
TEST_FAILED(!RetVal2, "Free-ThreadedDLL on Apartment Thread Failed\n");
|
|
|
|
OUTPUT (" Second Done Load Free-Threaded DLL on Different Apartment Thread\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
OUTPUT ("\n Load Apartment-Thread DLL on Multi-Threaded Apartment Thread\n");
|
|
|
|
hRes = SpinThread(COINIT_MULTITHREADED, ITF_REAL);
|
|
TEST_FAILED(!RetVal2, "Free-ThreadedDLL on Multi Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Free-Thread DLL on Multi-Threaded Apartment Thread\n");
|
|
|
|
OUTPUT ("\n Load Apartment-Thread DLL on Multi-Threaded Apartment Thread\n");
|
|
|
|
hRes = SpinThread(COINIT_MULTITHREADED, ITF_REAL);
|
|
TEST_FAILED(!RetVal2, "Free-ThreadedDLL on Multi Thread Failed\n");
|
|
|
|
OUTPUT (" Done Load Free-Thread DLL on Multi-Threaded Apartment Thread\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
CoUninitialize();
|
|
|
|
BOOL fResult = TestResult(RetVal, "TestLoadBothThreaded");
|
|
Sleep(2000);
|
|
return fResult;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// Function: SpinThread
|
|
//
|
|
// Synopsis: Creates a thread to do some work for us. Waits for it to
|
|
// complete. Returns the results.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL SpinThread(DWORD dwInitFlag, DWORD dwItfFlag)
|
|
{
|
|
BOOL RetVal = FALSE;
|
|
|
|
// set up paramters to pass to the thread
|
|
|
|
SLoadDLLParam LoadParam;
|
|
LoadParam.dwCallingTID = GetCurrentThreadId();
|
|
LoadParam.dwCoInitFlag = dwInitFlag;
|
|
LoadParam.dwItfFlag = dwItfFlag;
|
|
LoadParam.RetVal = FALSE;
|
|
LoadParam.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
|
|
// create the thread
|
|
|
|
DWORD dwThrdId = 0;
|
|
HANDLE hThrd = CreateThread(NULL, 0,
|
|
LoadDLLOnThread,
|
|
&LoadParam, 0, &dwThrdId);
|
|
if (hThrd)
|
|
{
|
|
// enter a message loop and wait for the other thread to run
|
|
// We stay here until the thread posts a QUIT message.
|
|
|
|
MSG msg;
|
|
while (GetMessage(&msg, NULL, 0, 0))
|
|
{
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
// close the thread handle
|
|
CloseHandle(hThrd);
|
|
}
|
|
else
|
|
{
|
|
HRESULT hRes = GetLastError();
|
|
TEST_FAILED(hRes, "CreateThread failed\n")
|
|
LoadParam.RetVal = RetVal;
|
|
}
|
|
|
|
// wait for the other thread to complete
|
|
WaitForSingleObject(LoadParam.hEvent, 0xffffffff);
|
|
CloseHandle(LoadParam.hEvent);
|
|
|
|
return LoadParam.RetVal;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// Function: LoadDLLOnThread
|
|
//
|
|
// Synopsis: Initializes COM, loads the class object and creates an
|
|
// instance, releases them, Posts a message to wake up the
|
|
// calling thread, Uninitializes COM, then exits.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
DWORD _stdcall LoadDLLOnThread(void *param)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hRes = S_OK;
|
|
SLoadDLLParam *pLoadParam = (SLoadDLLParam *)param;
|
|
|
|
OUTPUT (" - LoadDLLOnThread Entered\n");
|
|
hRes = CoInitializeEx(NULL, pLoadParam->dwCoInitFlag);
|
|
TEST_FAILED(FAILED(hRes), "CoInitialize failed\n")
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
// attempt to load the class object on this thread.
|
|
pLoadParam->RetVal = LoadClassObject(pLoadParam->dwItfFlag);
|
|
CoUninitialize();
|
|
}
|
|
|
|
// post a message to the server thread to exit now that we are done.
|
|
PostThreadMessage(pLoadParam->dwCallingTID, WM_QUIT, 0, 0);
|
|
SetEvent(pLoadParam->hEvent);
|
|
|
|
OUTPUT (" - LoadDLLOnThread Exit\n");
|
|
return RetVal;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// Function: LoadClassObject
|
|
//
|
|
// Synopsis: Loads the class object, creates an instance, releases
|
|
// them, returns the results.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL LoadClassObject(DWORD dwItfFlag)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
IClassFactory *pICF = NULL;
|
|
IUnknown *pIPM = NULL;
|
|
|
|
// try to load the dll class object
|
|
HRESULT hRes = CoGetClassObject(CLSID_QI, CLSCTX_INPROC_SERVER, NULL,
|
|
IID_IClassFactory, (void **)&pICF);
|
|
|
|
TEST_FAILED(FAILED(hRes), "CoGetClassObject failed\n");
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
hRes = pICF->QueryInterface(IID_IProxyManager, (void **)&pIPM);
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
pIPM->Release();
|
|
TEST_FAILED(dwItfFlag != ITF_PROXY, "Got Proxy when expected Real\n");
|
|
}
|
|
else
|
|
{
|
|
TEST_FAILED(dwItfFlag != ITF_REAL, "Got Real when expected Proxy\n");
|
|
}
|
|
|
|
// CODEWORK: create an instance, then release them
|
|
|
|
// release the class object.
|
|
OUTPUT (" - CoGetClassObject succeeded\n");
|
|
|
|
ULONG ulRefCnt = pICF->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pICF RefCnt not zero\n");
|
|
pICF = NULL;
|
|
OUTPUT (" - Released ClassObject\n");
|
|
}
|
|
|
|
return RetVal;
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: SetRegForDll, private
|
|
//
|
|
// Synopsis: Set registry entry for a DLL
|
|
//
|
|
// Arguments: [rclsid] - clsid for reg entry
|
|
// [pszThreadModel] - threading model can be NULL.
|
|
//
|
|
// Returns: TRUE - Registry entry set successfully.
|
|
// FALSE - Registry entry set successfully.
|
|
//
|
|
// History: 01-Nov-94 Ricksa Created
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL SetRegForDll(REFCLSID rclsid, const TCHAR *pszThreadModel)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
HKEY hKeyClass = NULL;
|
|
HKEY hKeyDll = NULL;
|
|
TCHAR aszWkBuf[MAX_PATH]; // String buffer used for various purposes
|
|
|
|
// Build clsid registry key
|
|
wsprintf(aszWkBuf,
|
|
TEXT("CLSID\\{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"),
|
|
rclsid.Data1, rclsid.Data2, rclsid.Data3,
|
|
rclsid.Data4[0], rclsid.Data4[1],
|
|
rclsid.Data4[2], rclsid.Data4[3],
|
|
rclsid.Data4[4], rclsid.Data4[5],
|
|
rclsid.Data4[6], rclsid.Data4[7]);
|
|
|
|
// Create the key for the class
|
|
if (RegCreateKey(HKEY_CLASSES_ROOT, aszWkBuf, &hKeyClass) == ERROR_SUCCESS)
|
|
{
|
|
// Create the key for the DLL
|
|
if (RegCreateKey(hKeyClass, TEXT("InprocServer32"), &hKeyDll) == ERROR_SUCCESS)
|
|
{
|
|
// Set the value for the Threading Model
|
|
if (RegSetValueEx(hKeyDll, pszRegValThreadModel, 0,
|
|
REG_SZ,
|
|
(const unsigned char*) pszThreadModel,
|
|
(wcslen(pszThreadModel) + 1) * sizeof(WCHAR))
|
|
== ERROR_SUCCESS)
|
|
{
|
|
fResult = TRUE;
|
|
}
|
|
|
|
RegCloseKey(hKeyDll);
|
|
}
|
|
|
|
RegCloseKey(hKeyClass);
|
|
}
|
|
|
|
return fResult;
|
|
}
|