summaryrefslogtreecommitdiffstats
path: root/private/oleutest/balls/client/dllhost/tdllhost.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'private/oleutest/balls/client/dllhost/tdllhost.cxx')
-rw-r--r--private/oleutest/balls/client/dllhost/tdllhost.cxx600
1 files changed, 600 insertions, 0 deletions
diff --git a/private/oleutest/balls/client/dllhost/tdllhost.cxx b/private/oleutest/balls/client/dllhost/tdllhost.cxx
new file mode 100644
index 000000000..97d91e6f1
--- /dev/null
+++ b/private/oleutest/balls/client/dllhost/tdllhost.cxx
@@ -0,0 +1,600 @@
+//+------------------------------------------------------------------
+//
+// 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;
+}