windows-nt/Source/XPSP1/NT/com/oleutest/olebind/olebind.cxx
2020-09-26 16:20:57 +08:00

1155 lines
29 KiB
C++

//+---------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1993 - 1994.
//
// File: olebind.cxx
//
// Contents: Test OLE COM
//
// Classes:
//
// Functions: TestSetMoniker
// ` DoTest
// ConvertPath
// CreateFile
// CleanUpFiles
// InitFiles
// main
//
// History: 31-Dec-93 ErikGav Chicago port
// 15-Nov-94 BruceMa Added this header
// 15-Nov-94 BruceMa Make long file name test work on
// Chicago
// 11-Jan-95 BruceMa Chicago now use the NT alorithm for
// short file names
// 17-Jan-95 BruceMa Modify registry so olebind works on
// Cairo when running multi-threaded
//
//----------------------------------------------------------------------
#include <windows.h>
#include "widewrap.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <io.h>
#include <ole2.h>
#include <com.hxx>
#include "olebind.hxx"
#include "tmoniker.h"
#include <tchar.h>
const char *szOleBindError = "OLEBIND - Fatal Error";
char wszErrBuf[512];
#pragma hdrstop
BOOL SetRegistryThreadingModel(WCHAR *peszFile, WCHAR *pwszThreadingModel);
BOOL ResetRegistryThreadingModel(WCHAR *pwszFile);
#define FILE_SHARE_DELETE 0x00000004
#define INPROC_PATH1 L"p1.ut1"
#define INPROC_PATH2 L"p2.ut1"
#define LOCAL_SERVER_PATH1 L"p1.ut2"
#define LOCAL_SERVER_PATH2 L"p2.ut2"
#define LOCAL_SERVER_PATH4 L"p2.ut4"
WCHAR InprocPath1[MAX_PATH];
WCHAR InprocPath2[MAX_PATH];
WCHAR LocalServerPath1[MAX_PATH];
WCHAR LocalServerPath2[MAX_PATH];
WCHAR LocalServerPath4[MAX_PATH];
#define LONG_SHORT_DIR L"\\LongDire"
#define LONG_DIR L"\\LongDirectory"
#define LONG_SHORT_NAME L"\\Short.Fil"
#define LONG_LONG_NAME L"\\LongFileName.File"
#define LONG_LONG_SHORT_EQUIV L"\\LongFi~1.Fil"
WCHAR LongDir[MAX_PATH];
WCHAR LongDirShort[MAX_PATH];
WCHAR LongDirLong[MAX_PATH];
WCHAR LongDirLongSe[MAX_PATH];
// DON"T MODIFY THIS
const DWORD dwRESERVED = 0l;
// string version of process id
WCHAR wszPid[10];
int TestSetMoniker(IUnknown *punk)
{
HRESULT hr;
XOleObject poleobject;
XMoniker pmk;
XMalloc pIMalloc;
XBindCtx pbc;
hr = punk->QueryInterface(IID_IOleObject, (void **) &poleobject);
// Create an item moniker to the object
hr = CreateItemMoniker(L"\\", L"1", &pmk);
TEST_FAILED_HR(FAILED(hr), "TestSetMoniker:CreateItemMoniker failed")
// Set the moniker
hr = poleobject->SetMoniker(OLEWHICHMK_CONTAINER, pmk);
TEST_FAILED_HR(FAILED(hr), "TestSetMoniker:SetMoniker failed")
pmk.Set(NULL);
// Get the moniker back
hr = poleobject->GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
OLEWHICHMK_CONTAINER, &pmk);
TEST_FAILED_HR(FAILED(hr), "TestSetMoniker:GetMoniker failed")
// Get & Verify name is as expected
WCHAR *pwszName;
hr = CreateBindCtx(0, &pbc);
TEST_FAILED_HR(FAILED(hr),
"CreateBindCtx TestSetMoniker:GetDisplayName failed!")
hr = pmk->GetDisplayName(pbc, NULL, &pwszName);
TEST_FAILED_HR(FAILED(hr), "TestSetMoniker:GetDisplayName failed")
TEST_FAILED((wcscmp(pwszName, L"\\1") != 0),
"TestSetMoniker: Returned name mismatch!\n")
// Test OleIsRunning
hr = OleIsRunning(poleobject);
TEST_FAILED_HR(FAILED(hr), "OleIsRunning call failed")
// Free resources
hr = CoGetMalloc(MEMCTX_TASK, &pIMalloc);
TEST_FAILED_HR(FAILED(hr), "CoGetMalloc failed")
pIMalloc->Free(pwszName);
return 0;
}
static GUID CLSID_Invalid =
{0xfffffffe,0xffff,0xffff,{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}};
// prototypes for private entry points. These are here to support VB94.
STDAPI CoGetState(IUnknown **ppUnkState);
STDAPI CoSetState(IUnknown *pUnkState);
int DoTest(
GUID guidToTest,
LPWSTR pszPath1,
LPWSTR pszPath2)
{
XMoniker pmnk; // ptr to moniker
XUnknown pUnk;
XUnknown punk;
XUnknown pUnkTheSame;
XOleItemContainer poleitmcon;
XDispatch pdispatch;
XBindCtx pbc1;
XBindCtx pbc2;
XUnknown pUnkState1;
XUnknown pUnkState2;
XUnknown pUnkState3;
XUnknown pUnkState4;
XUnknown pUnkState5;
HRESULT hr;
DWORD grfOpt = 0;
// Test the private CoSetState/CoGetState APIs. We just need an
// IUnknown so we will use a BindCtx for this.
// test Set/Get
hr = CreateBindCtx(0, &pbc1);
TEST_FAILED_HR(FAILED(hr), "Create BindCtx 1 failed");
hr = pbc1->QueryInterface(IID_IUnknown, (void **)&pUnkState1);
TEST_FAILED_HR(FAILED(hr), "QI for IUnknown 1 failed.");
hr = CoSetState(pUnkState1);
TEST_FAILED_HR(hr != S_OK, "CoSetState failed.");
hr = CoGetState(&pUnkState2);
TEST_FAILED_HR(hr != S_OK, "CoGetState failed.");
if ((IUnknown *)pUnkState2 != (IUnknown *)pUnkState1)
TEST_FAILED(TRUE, "GetState returned wrong value.\n");
// test replacement
hr = CreateBindCtx(0, &pbc2);
TEST_FAILED_HR(FAILED(hr), "Create BindCtx 2 failed");
hr = pbc2->QueryInterface(IID_IUnknown, (void **)&pUnkState3);
TEST_FAILED_HR(FAILED(hr), "QI for IUnknown 2 failed.");
hr = CoSetState(pUnkState3);
TEST_FAILED_HR(hr != S_OK, "CoSetState failed.");
hr = CoGetState(&pUnkState4);
TEST_FAILED_HR(hr != S_OK, "CoGetState failed.");
if ((IUnknown *)pUnkState4 != (IUnknown *)pUnkState3)
TEST_FAILED(TRUE, "GetState returned wrong value.");
// test Set/Get NULL
hr = CoSetState(NULL);
TEST_FAILED_HR(hr != S_OK, "CoSetState NULL failed.");
hr = CoGetState(&pUnkState5);
TEST_FAILED_HR(hr != S_FALSE, "CoGetState NULL failed.");
if ((IUnknown *)pUnkState5 != NULL)
TEST_FAILED(TRUE, "GetState NULL returned wrong value.");
// Test for a bogus class
hr = CoGetClassObject(CLSID_Invalid, CLSCTX_SERVER, NULL,
IID_IClassFactory, (void **) &pUnk);
TEST_FAILED_HR(SUCCEEDED(hr),
"CoGetClassObject succeed on invalid class!");
// Bind to something that does not exist either in the registry
// or anywhere else.
hr = CreateFileMoniker(L"C:\\KKK.KKK", &pmnk);
hr = BindMoniker(pmnk, grfOpt, IID_IUnknown, (void **)&pUnk);
pmnk.Set(NULL);
TEST_FAILED_HR(SUCCEEDED(hr),
"Succeeded binding a moniker to a file that doesn't exist!");
/*
* Create a file moniker to start with
*/
hr = CreateFileMoniker(pszPath1, &pmnk);
TEST_FAILED_HR(FAILED(hr), "CreateFileMoniker Failed");
hr = BindMoniker(pmnk, grfOpt, IID_IUnknown, (void **)&pUnk);
TEST_FAILED_HR(FAILED(hr),
"BindMoniker to file Failed")
// Confirm bind to same object produces same object pointer
hr = BindMoniker(pmnk, grfOpt, IID_IUnknown, (void **)&pUnkTheSame);
TEST_FAILED_HR(FAILED(hr),
"BindMoniker to file Failed")
#ifdef NOT_YET
TEST_FAILED((pUnkTheSame != pUnk), "Object pointers not ==\n")
#endif // NOT_YET
pUnkTheSame.Set(NULL);
pmnk.Set(NULL);
/*
* OK - we've bound to the IUnknown interface, lets
* QueryInterface to something more interesting (for test reasons)
*/
hr = pUnk->QueryInterface(IID_IOleItemContainer,
(LPVOID FAR*) &poleitmcon);
TEST_FAILED_HR(FAILED(hr), "Query Interface Failed")
/*
* Make sure we get an error when QI'ing for something the server
* does not support.
*/
hr = pUnk->QueryInterface(IID_IDispatch,
(LPVOID FAR*) &pdispatch);
TEST_FAILED_HR(SUCCEEDED(hr),
"QueryInterface to unsupported interface")
pdispatch.Set(NULL);
pUnk.Set(NULL);
/*
* Call get the class ID using IPersistFile
*/
hr = poleitmcon->GetObject(L"1", 1, NULL, IID_IUnknown,
(void **) &punk);
TEST_FAILED_HR(FAILED(hr), "GetObject Failed")
TEST_FAILED((punk == NULL),
"GetObject returned a NULL for punk\n")
poleitmcon.Set(NULL);
if (TestSetMoniker(punk))
{
return 1;
}
hr = punk->QueryInterface(IID_IOleLink, (LPVOID FAR*) &poleitmcon);
TEST_FAILED_HR(SUCCEEDED(hr),
"Query Interface to invalid interface succeeded")
punk.Set(NULL);
// Do moniker tests:
if (TestBindCtx())
{
return TRUE;
}
if (TestROT(guidToTest))
{
return TRUE;
}
return TestMoniker(pszPath1, pszPath2);
}
// TRUE on failure
BOOL TestPrematureDeath()
{
XMoniker pmnk;
XUnknown pUnk;
HRESULT hr;
TCHAR tszFileName[MAX_PATH+1];
HANDLE hTouchFile;
SYSTEMTIME st1, st2;
FILETIME ft1, ft2;
LONG l;
DWORD dw;
ZeroMemory(&st1, sizeof(st1));
ZeroMemory(&st2, sizeof(st2));
hr = CreateFileMoniker(LocalServerPath4, &pmnk);
TEST_FAILED_HR(FAILED(hr), "CreateFileMoniker Failed")
GetSystemDirectory(tszFileName, MAX_PATH+1);
_tcscat(tszFileName, TEXT("\\failtst.tst"));
hTouchFile = CreateFileT(tszFileName,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hTouchFile == INVALID_HANDLE_VALUE)
{
wsprintfA(&wszErrBuf[0], "Couldn't open touch file - err = %x.\n", GetLastError());
MessageBoxA(NULL, &wszErrBuf[0], szOleBindError, MB_OK);
return TRUE;
}
GetSystemTime(&st1);
WriteFile(hTouchFile, &st1, sizeof(st1), &dw, NULL);
l = GetTickCount();
// This takes awhile, so tell the user
printf("SCM dead server test (60 sec) started\n");
hr = BindMoniker(pmnk, 0, IID_IUnknown, (void **)&pUnk);
TEST_FAILED_HR((hr != CO_E_SERVER_EXEC_FAILURE),
"Unexpected hr from BindMoniker in premature death test")
// Tell the BVT guys
printf("SCM dead server test succeeded\n");
//
// The above bind should have caused fail.exe to execute and write a new
// time to the file as proof of execution.
//
SetFilePointer(hTouchFile, 0, NULL, FILE_BEGIN);
ReadFile(hTouchFile, &st2, sizeof(st2), &dw, NULL);
CloseHandle(hTouchFile);
DeleteFileT(tszFileName);
SystemTimeToFileTime(&st1, &ft1);
SystemTimeToFileTime(&st2, &ft2);
if (0 == CompareFileTime(&ft1, &ft2))
{
wsprintfA(&wszErrBuf[0], "Test not configured properly: PROGID50(fail.exe) did not run.");
MessageBoxA(NULL, &wszErrBuf[0], szOleBindError, MB_OK);
return TRUE;
}
if (GetTickCount() - l > 2*60*1000)
{
wsprintfA(&wszErrBuf[0], "Premature death test failed: too long to detect death.");
MessageBoxA(NULL, &wszErrBuf[0], szOleBindError, MB_OK);
return TRUE;
}
return FALSE;
}
char * ConvertPath(LPWSTR pwsz)
{
static char szPath[MAX_PATH];
wcstombs(szPath, pwsz, wcslen(pwsz) + 1);
return szPath;
}
int CreateFile(LPWSTR pwszPath)
{
// Try to create the file
int fh = _creat(ConvertPath(pwszPath), _S_IWRITE|S_IREAD);
// Did file create fail?
if (fh != -1)
{
// Write some data to file -- makes sure docfile won't delete
// the file.
_write(fh, "This is a test file\n", sizeof("This is a test file\n"));
// No -- then set to success and close the newly created file
_close(fh);
fh = 0;
}
return fh;
}
void CleanUpFiles(void)
{
// Delete all the test files.
remove(ConvertPath(InprocPath1));
remove(ConvertPath(InprocPath2));
remove(ConvertPath(LocalServerPath1));
remove(ConvertPath(LocalServerPath2));
remove(ConvertPath(LocalServerPath4));
remove(ConvertPath(LongDirShort));
remove(ConvertPath(LongDirLong));
#if !defined(_CHICAGO_)
RemoveDirectory(LongDir);
#else
RemoveDirectory(ConvertPath(LongDir));
#endif
}
int InitFiles(void)
{
BOOL fRet;
TCHAR szCurDir[MAX_PATH];
TCHAR szTmpLongDir[MAX_PATH];
WCHAR wcCurDir[MAX_PATH];
WCHAR wcLong[MAX_PATH], *pwcEnd;
DWORD cCurDir = GetCurrentDirectory(MAX_PATH, szCurDir);
#ifdef UNICODE
wcscpy(wcCurDir, szCurDir);
#else
mbstowcs(wcCurDir, szCurDir, MAX_PATH);
#endif
// Is the current directory the root of a drive?
if (wcCurDir[cCurDir - 1] == '\\')
{
// We bring the string on char back to take into account
// the fact the string we will concatenate begins with a slash.
wcCurDir[cCurDir - 1] = 0;
}
// get the pid. we use the pid to identify the files for a particular
// run of the test (so we may run multiple instances simultaneously
// without interference).
DWORD dwPid = GetCurrentProcessId();
char szPid[9];
_itoa(dwPid, szPid, 16);
wszPid[0] = L'\\';
#if defined(_CHICAGO_)
szPid[4] = '\0'; // This is an all platform bug, but zap for Chicago.
#endif
mbstowcs(&wszPid[1], szPid, strlen(szPid)+1);
wcscpy(InprocPath1, wcCurDir);
wcscat(InprocPath1, wszPid);
wcscat(InprocPath1, INPROC_PATH1);
wcscpy(InprocPath2, wcCurDir);
wcscat(InprocPath2, wszPid);
wcscat(InprocPath2, INPROC_PATH2);
wcscpy(LocalServerPath1, wcCurDir);
wcscat(LocalServerPath1, wszPid);
wcscat(LocalServerPath1, LOCAL_SERVER_PATH1);
wcscpy(LocalServerPath2, wcCurDir);
wcscat(LocalServerPath2, wszPid);
wcscat(LocalServerPath2, LOCAL_SERVER_PATH2);
wcscpy(LocalServerPath4, wcCurDir);
wcscat(LocalServerPath4, wszPid);
wcscat(LocalServerPath4, LOCAL_SERVER_PATH4);
wcscpy(wcLong, wcCurDir);
wcscat(wcLong, LONG_DIR);
wcscpy(LongDir, wcLong);
pwcEnd = wcLong+wcslen(wcLong);
wcscpy(pwcEnd, LONG_SHORT_NAME);
wcscpy(LongDirShort, wcLong);
wcscpy(pwcEnd, LONG_LONG_NAME);
wcscpy(LongDirLong, wcLong);
#ifdef _CHICAGO_
wcscpy(LongDirLongSe, wcCurDir);
wcscat(LongDirLongSe, LONG_DIR);
#else
wcscpy(pwcEnd, LONG_LONG_SHORT_EQUIV);
wcscpy(LongDirLongSe, wcLong);
#endif // _CHICAGO_
// Delete any files that exist
CleanUpFiles();
// Create a file for each test file needed.
TEST_FAILED(CreateFile(InprocPath1),
"Couldn't create first test file!\n");
TEST_FAILED(CreateFile(InprocPath2),
"Couldn't create second test file!\n");
TEST_FAILED(CreateFile(LocalServerPath1),
"Couldn't create third test file!\n");
TEST_FAILED(CreateFile(LocalServerPath2),
"Couldn't create fourth test file!\n");
TEST_FAILED(CreateFile(LocalServerPath4),
"Couldn't create fifth test file!\n");
#if !defined(_CHICAGO_)
fRet = CreateDirectory(LongDir, NULL);
#else
fRet = CreateDirectory(ConvertPath(LongDir), NULL);
#endif
TEST_FAILED(!fRet, "Couldn't create long directory\n");
TEST_FAILED(CreateFile(LongDirShort),
"Couldn't create short file in long directory\n");
TEST_FAILED(CreateFile(LongDirLong),
"Couldn't create long file in long directory\n");
#ifdef UNICODE
TEST_FAILED(!GetShortPathName(LongDirLong,
LongDirLongSe,
sizeof(LongDirLongSe)),
"Couldn't GetShortPathname of long directory\n");
#else
TEST_FAILED(!GetShortPathNameT(ConvertPath(LongDirLong),
szCurDir,
sizeof(szCurDir)),
"Couldn't GetShortPathname of long directory\n");
mbstowcs(LongDirLongSe, szCurDir, strlen(szCurDir)+1);
#endif
return 0;
}
DWORD CallCoInitUninit(void *)
{
// Initialize
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (SUCCEEDED(hr))
{
// Uninitialize
CoUninitialize();
}
// Return value from function. Note that this is not really used because
// there is a potential race
return (DWORD) hr;
}
BOOL DoFreeThreadMultiInitTest(void)
{
//
// Get an OLE object in another process
//
IClassFactory *pIClassFactory;
HRESULT hr = CoGetClassObject(
CLSID_AdvBnd,
CLSCTX_LOCAL_SERVER,
NULL,
IID_IClassFactory,
(void **) &pIClassFactory);
TEST_FAILED_HR((hr != NOERROR),
"DoFreeThreadMultiInitTest CoGetClassObject")
//
// Create another thread which does a matching call to
// CoInitialize/Uninitialize and then exits.
//
// Create the thread
DWORD dwIdUnused;
HANDLE hInitThread = CreateThread(
NULL, // Security - none
0, // Stack - use the same as the primary thread
CallCoInitUninit, // Entry point for thread
NULL, // Parameter to the thread - not used.
0, // Run this thread immediately (if not sooner).
&dwIdUnused); // Id of thread - not used.
// Did the create succeed?
TEST_FAILED_LAST_ERROR((NULL == hInitThread),
"DoFreeThreadMultiInitTest CreateThread")
// Wait for the thread to do its work
DWORD dwRes = WaitForSingleObject(hInitThread, INFINITE);
// Did something terrible happen?
TEST_FAILED_LAST_ERROR((WAIT_FAILED == dwRes),
"DoFreeThreadMultiInitTest WaitForSingleObject")
// Get the result from the thread
BOOL fGetExitCode = GetExitCodeThread(hInitThread, (DWORD *) &hr);
TEST_FAILED_LAST_ERROR(!fGetExitCode,
"DoFreeThreadMultiInitTest GetExitCodeThread")
// Free handles we no longer need
CloseHandle(hInitThread);
//
// Validate the object we originally got is still alive and well.
//
IUnknown *punk;
hr = pIClassFactory->CreateInstance(NULL, IID_IUnknown, (void **) &punk);
TEST_FAILED_HR((hr != NOERROR),
"DoFreeThreadMultiInitTest CoGetClassObject")
// Free the objects we got in this routine.
pIClassFactory->Release();
punk->Release();
return FALSE;
}
//+--------------------------------------------------------------
// Function: Main
//
// Synopsis: Executes the BasicBnd test
//
// Effects: None
//
//
// Returns: Exits with exit code 0 if success, 1 otherwise
//
// History: 05-Mar-92 Sarahj Created
//
//---------------------------------------------------------------
int _cdecl main(int argc, char *argv[])
{
BOOL fFailed = FALSE;
HRESULT hr;
if (argc > 1)
{
if (!strcmp(argv[1], "M"))
goto multithreading;
}
// BUGBUG: 1-18-95 To be implemented BruceMa
// Correlate the platform we're running on and the platform
// we built for
// Write thread mode to initialization file.
fFailed = !WriteProfileString(
TEXT("TestSrv"),
TEXT("ThreadMode"),
TEXT("ApartmentThreaded"));
if (fFailed)
{
wsprintfA(&wszErrBuf[0], "Failed writing TestSrv profile string.");
MessageBoxA(NULL, &wszErrBuf[0], szOleBindError, MB_OK);
goto exit_main;
}
fFailed = !WriteProfileString(
TEXT("OleSrv"),
TEXT("ThreadMode"),
TEXT("ApartmentThreaded"));
if (fFailed)
{
wsprintfA(&wszErrBuf[0], "Failed writing OleSrv profile string.");
MessageBoxA(NULL, &wszErrBuf[0], szOleBindError, MB_OK);
goto exit_main;
}
// Set up test files
fFailed = InitFiles();
if (fFailed)
{
goto exit_main;
}
// Test repeated calls to CoInitialize
hr = CoInitialize(NULL);
TEST_FAILED_HR(FAILED(hr), "CoInitialize Failed")
// must be called before any other OLE API
hr = OleInitialize(NULL);
TEST_FAILED_HR(FAILED(hr), "OleInitialize Failed")
// Call CoUnitialize and see how the rest of the program works!
CoUninitialize();
// Test stdmalloc
if (fFailed = TestStdMalloc())
{
goto exit_init;
}
fFailed =
DoTest(CLSID_BasicBnd, InprocPath1, InprocPath2);
if (fFailed)
{
printf( "\nOLE failed in Single Threaded Apartment pass.\n" );
goto exit_init;
}
printf("BasicBnd tests succeeded\n");
fFailed =
DoTest(CLSID_AdvBnd, LocalServerPath1, LocalServerPath1);
if (fFailed)
{
printf( "\nOLE failed in Single Threaded Apartment pass.\n" );
goto exit_init;
}
printf("AdvBnd tests succeeded\n");
if (TestPrematureDeath())
{
printf("\nOLE failed testing server premature death.\n");
goto exit_init;
}
OleUninitialize();
CleanUpFiles();
multithreading:
#ifdef MULTI_THREADING
// Run the whole thing all over again.
// Write thread mode to initialization file.
fFailed = !WriteProfileString(
TEXT("TestSrv"),
TEXT("ThreadMode"),
TEXT("ApartmentThreaded"));
if (fFailed)
{
wsprintfA(&wszErrBuf[0], "Failed writing TestSrv profile string.");
MessageBoxA(NULL, &wszErrBuf[0], szOleBindError, MB_OK);
goto exit_main;
}
fFailed = !WriteProfileString(
TEXT("OleSrv"),
TEXT("ThreadMode"),
TEXT("MultiThreaded"));
if (fFailed)
{
wsprintfA(&wszErrBuf[0], "Failed writing OleSrv profile string.");
MessageBoxA(NULL, &wszErrBuf[0], szOleBindError, MB_OK);
goto exit_main;
}
// Set up test files
if (InitFiles())
{
fFailed = TRUE;
goto exit_main;
}
// Mark the dll in the registry as "ThreadingdModel: Free"
if (!SetRegistryThreadingModel(InprocPath1, L"Free"))
{
wsprintfA(&wszErrBuf[0], "Failed trying to set reg ThreadingModel.");
MessageBoxA(NULL, &wszErrBuf[0], szOleBindError, MB_OK);
goto exit_main;
}
// Test repeated calls to CoInitialize
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
TEST_FAILED_HR(FAILED(hr), "CoInitializeEx Multi Threaded Failed")
// must be called before any other OLE API
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
TEST_FAILED_HR(FAILED(hr), "CoInitializeEx Multi Threaded Failed")
// Call CoUnitialize and see how the rest of the program works!
CoUninitialize();
// Test stdmalloc
if (fFailed = TestStdMalloc())
{
goto exit_init;
}
fFailed =
DoTest(CLSID_BasicBnd, InprocPath1, InprocPath2);
if (fFailed)
{
printf( "\nOLE failed in Multi Threaded Apartment pass.\n" );
goto exit_init;
}
fFailed =
DoTest(CLSID_AdvBnd, LocalServerPath1, LocalServerPath1);
if (fFailed)
{
printf( "\nOLE failed in Multi Threaded Apartment pass.\n" );
goto exit_init;
}
// Do CoInitialize/Uninitialize on second thread to make sure
// that other threads initialize/uninitialize do not effect
// the running of the test.
if (fFailed = DoFreeThreadMultiInitTest())
{
printf( "\nOLE failed in Multi Threaded InitTest.\n" );
goto exit_init;
}
#endif // MULTI_THREADING
exit_init:
CoUninitialize();
// Remove the dll's threading model registration
ResetRegistryThreadingModel(InprocPath1);
exit_main:
CleanUpFiles();
if (!fFailed)
{
printf("\nOLE: PASSED\n");
}
else
{
printf("\nOLE: FAILED\n");
}
return fFailed;
}
//+--------------------------------------------------------
//
// Function: SetRegistryThreadingModel
//
// Algorithm: Set the threading model for the InprocServer32 associated
// with the file pwszFile tp pwszThreadingModel
//
// History: 17-Jan-95 BruceMa Created
//
//---------------------------------------------------------
BOOL SetRegistryThreadingModel(WCHAR *pwszFile, WCHAR *pwszThreadingModel)
{
DWORD dwRESERVED = 0;
WCHAR wszExt[8];
HKEY hKey;
WCHAR wszProgId[32];
DWORD dwValueType;
WCHAR wszCLSID[64];
HKEY hClsidKey;
HKEY hInproc32Key;
ULONG cbValue;
// Strip the extension off the file name
int k = wcslen(pwszFile) - 1;
while (k > 0 && pwszFile[k] != L'.')
{
k--;
}
if (k >= 0 && pwszFile[k] == L'.')
{
for (int j = 0; pwszFile[k]; j++, k++)
{
wszExt[j] = pwszFile[k];
}
wszExt[j] = L'\0';
}
else
{
return FALSE;
}
// Open the key for the specified extension
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, wszExt, dwRESERVED,
KEY_READ, &hKey) != ERROR_SUCCESS)
{
return FALSE;
}
// Read the ProgId for the extension
cbValue = 32;
if (RegQueryValueEx(hKey, NULL, NULL, &dwValueType,
(LPBYTE) wszProgId, &cbValue) != ERROR_SUCCESS)
{
CloseHandle(hKey);
return FALSE;
}
// Open the ProgIdKey
CloseHandle(hKey);
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, wszProgId, dwRESERVED,
KEY_READ, &hKey) != ERROR_SUCCESS)
{
return FALSE;
}
// Open the associated CLSID key
if (RegOpenKeyEx(hKey, L"CLSID", dwRESERVED,
KEY_READ, &hClsidKey) != ERROR_SUCCESS)
{
CloseHandle(hKey);
return FALSE;
}
// Read the CLSID associated with the ProgId
cbValue = 128;
if (RegQueryValueEx(hClsidKey, NULL, NULL, &dwValueType,
(LPBYTE) wszCLSID, &cbValue) != ERROR_SUCCESS)
{
CloseHandle(hClsidKey);
CloseHandle(hKey);
return FALSE;
}
// Open the HKEY_CLASSES_ROOT\CLSID key
CloseHandle(hClsidKey);
CloseHandle(hKey);
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, L"CLSID", dwRESERVED,
KEY_READ, &hKey) != ERROR_SUCCESS)
{
return FALSE;
}
// Open the key to our clsid
if (RegOpenKeyEx(hKey, wszCLSID, dwRESERVED,
KEY_READ, &hClsidKey) != ERROR_SUCCESS)
{
CloseHandle(hKey);
return FALSE;
}
// Open the InprocServer32 key
CloseHandle(hKey);
if (RegOpenKeyEx(hClsidKey, L"InprocServer32", dwRESERVED,
KEY_SET_VALUE, &hInproc32Key) != ERROR_SUCCESS)
{
CloseHandle(hClsidKey);
return FALSE;
}
// Set the threading model for this InprocServer32 key
CloseHandle(hClsidKey);
if (RegSetValueEx(hInproc32Key, L"ThreadingModel", dwRESERVED,
REG_SZ, (LPBYTE) pwszThreadingModel,
(wcslen(pwszThreadingModel)+1) * sizeof(WCHAR))
!= ERROR_SUCCESS)
{
CloseHandle(hInproc32Key);
return FALSE;
}
// Close the InprocServer32 key and return success
CloseHandle(hInproc32Key);
return TRUE;
}
//+--------------------------------------------------------
//
// Function: ResetRegistryThreadingModel
//
// Algorithm: Remove the threading model for the InprocServer32 associated
// with the file pwszFile
//
// History: 17-Jan-95 BruceMa Created
//
//---------------------------------------------------------
BOOL ResetRegistryThreadingModel(WCHAR *pwszFile)
{
DWORD dwRESERVED = 0;
WCHAR wszExt[8];
HKEY hKey;
WCHAR wszProgId[32];
DWORD dwValueType;
WCHAR wszCLSID[64];
HKEY hClsidKey;
HKEY hInproc32Key;
ULONG cbValue;
// Strip the extension off the file name
int k = wcslen(pwszFile) - 1;
while (k > 0 && pwszFile[k] != L'.')
{
k--;
}
if (k >= 0 && pwszFile[k] == L'.')
{
for (int j = 0; pwszFile[k]; j++, k++)
{
wszExt[j] = pwszFile[k];
}
wszExt[j] = L'\0';
}
else
{
return FALSE;
}
// Open the key for the specified extension
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, wszExt, dwRESERVED,
KEY_READ, &hKey) != ERROR_SUCCESS)
{
return FALSE;
}
// Read the ProgId for the extension
cbValue = 32;
if (RegQueryValueEx(hKey, NULL, NULL, &dwValueType,
(LPBYTE) wszProgId, &cbValue) != ERROR_SUCCESS)
{
CloseHandle(hKey);
return FALSE;
}
// Open the ProgIdKey
CloseHandle(hKey);
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, wszProgId, dwRESERVED,
KEY_READ, &hKey) != ERROR_SUCCESS)
{
return FALSE;
}
// Open the associated CLSID key
if (RegOpenKeyEx(hKey, L"CLSID", dwRESERVED,
KEY_READ, &hClsidKey) != ERROR_SUCCESS)
{
CloseHandle(hKey);
return FALSE;
}
// Read the CLSID associated with the ProgId
cbValue = 128;
if (RegQueryValueEx(hClsidKey, NULL, NULL, &dwValueType,
(LPBYTE) wszCLSID, &cbValue) != ERROR_SUCCESS)
{
CloseHandle(hClsidKey);
CloseHandle(hKey);
return FALSE;
}
// Open the HKEY_CLASSES_ROOT\CLSID key
CloseHandle(hClsidKey);
CloseHandle(hKey);
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, L"CLSID", dwRESERVED,
KEY_READ, &hKey) != ERROR_SUCCESS)
{
return FALSE;
}
// Open the key to our clsid
if (RegOpenKeyEx(hKey, wszCLSID, dwRESERVED,
KEY_READ, &hClsidKey) != ERROR_SUCCESS)
{
CloseHandle(hKey);
return FALSE;
}
// Open the InprocServer32 key
CloseHandle(hKey);
if (RegOpenKeyEx(hClsidKey, L"InprocServer32", dwRESERVED,
KEY_SET_VALUE, &hInproc32Key) != ERROR_SUCCESS)
{
CloseHandle(hClsidKey);
return FALSE;
}
// Reset the threading model for this InprocServer32 key
CloseHandle(hClsidKey);
if (RegDeleteValue(hInproc32Key, TEXT("ThreadingModel")) != ERROR_SUCCESS)
{
CloseHandle(hInproc32Key);
return FALSE;
}
// Close the InprocServer32 key and return success
CloseHandle(hInproc32Key);
return TRUE;
}