619 lines
12 KiB
C++
619 lines
12 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1993.
|
|
//
|
|
// File: rotut.cxx
|
|
//
|
|
// Contents: Unit Test for ROT
|
|
//
|
|
// Classes: MISSING
|
|
//
|
|
// Functions: MISSING
|
|
//
|
|
// History: 16-Oct-93 Ricksa Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
#include <windows.h>
|
|
#include <widewrap.h> // For chicago build
|
|
#include <ole2.h>
|
|
#include <stdio.h>
|
|
#include <safepnt.hxx>
|
|
#include <com.hxx>
|
|
|
|
#define TEST_FAILED(x, y) \
|
|
if (x) \
|
|
{ \
|
|
printf("%s:%d %s\n", __FILE__, __LINE__, y); \
|
|
return TRUE; \
|
|
}
|
|
|
|
GUID clsidLocal =
|
|
{0xbbbbbbbb,0xbbbb,0xbbbb,{0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb}};
|
|
|
|
CHAR szTmpCurrrentDirectory[MAX_PATH];
|
|
WCHAR szCurrentDirectory[MAX_PATH];
|
|
|
|
|
|
SAFE_INTERFACE_PTR(CSafeROT, IRunningObjectTable)
|
|
SAFE_INTERFACE_PTR(CSafeUnk, IUnknown)
|
|
SAFE_INTERFACE_PTR(CSafePersist, IPersist)
|
|
SAFE_INTERFACE_PTR(CSafeEnumMoniker, IEnumMoniker)
|
|
SAFE_INTERFACE_PTR(CSafeMoniker, IMoniker)
|
|
SAFE_INTERFACE_PTR(CSafeStorage, IStorage)
|
|
|
|
class COleInit
|
|
{
|
|
public:
|
|
COleInit(HRESULT& hr);
|
|
|
|
~COleInit(void);
|
|
private:
|
|
|
|
// No private data
|
|
};
|
|
|
|
inline COleInit::COleInit(HRESULT& hr)
|
|
{
|
|
hr = OleInitialize(NULL);
|
|
}
|
|
|
|
inline COleInit::~COleInit(void)
|
|
{
|
|
// Do the clean up
|
|
OleUninitialize();
|
|
}
|
|
|
|
|
|
|
|
class CRotTestObject : public IPersist
|
|
{
|
|
public:
|
|
CRotTestObject(WCHAR *pwszID);
|
|
|
|
// IUnknown Interface
|
|
STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
|
|
|
|
STDMETHODIMP_(ULONG)AddRef(void);
|
|
|
|
STDMETHODIMP_(ULONG)Release(void);
|
|
|
|
STDMETHODIMP GetClassID(LPCLSID pclsid);
|
|
|
|
private:
|
|
|
|
WCHAR _awcID[256];
|
|
|
|
ULONG _cRefs;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
CRotTestObject::CRotTestObject(WCHAR *pwszID) : _cRefs(1)
|
|
{
|
|
wcscpy(_awcID, pwszID);
|
|
}
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP CRotTestObject::QueryInterface(REFIID riid, void **ppv)
|
|
{
|
|
if ((memcmp((void *) &riid, (void *) &IID_IUnknown, sizeof(GUID)) == 0)
|
|
|| (memcmp((void *) &riid, (void *) &IID_IPersist, sizeof(GUID)) == 0))
|
|
{
|
|
_cRefs++;
|
|
*ppv = (IUnknown *) this;
|
|
return S_OK;
|
|
}
|
|
|
|
*ppv = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CRotTestObject::AddRef(void)
|
|
{
|
|
_cRefs++;
|
|
return (ULONG) _awcID;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CRotTestObject::Release(void)
|
|
{
|
|
if (--_cRefs == 0)
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
return _cRefs;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP CRotTestObject::GetClassID(LPCLSID pclsid)
|
|
{
|
|
memcpy(pclsid, &clsidLocal, sizeof(clsidLocal));
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL VerifyRegistration(
|
|
IMoniker *pmk,
|
|
REFCLSID clsidExpected,
|
|
FILETIME *pFileTimeExpected)
|
|
{
|
|
CSafeROT prot;
|
|
|
|
HRESULT hr = GetRunningObjectTable(0, &prot);
|
|
|
|
TEST_FAILED(FAILED(hr),
|
|
"VerifyRegistration:GetRunningObjectTable failed!\n")
|
|
|
|
// Verify the object is running
|
|
hr = prot->IsRunning(pmk);
|
|
|
|
TEST_FAILED((hr != S_OK),
|
|
"VerifyRegistration:Unexpected return from IsRunning\n")
|
|
|
|
// Test Get Object
|
|
CSafeUnk punk;
|
|
|
|
hr = prot->GetObject(pmk, &punk);
|
|
|
|
TEST_FAILED((hr != S_OK),
|
|
"VerifyRegistration:Unexpected from GetObject\n")
|
|
|
|
// Confirm object class
|
|
CSafePersist prst;
|
|
|
|
hr = punk->QueryInterface(IID_IPersist, (void **) &prst);
|
|
|
|
TEST_FAILED((hr != S_OK),
|
|
"VerifyRegistration:QI to IPersist failed\n")
|
|
|
|
CLSID clsid;
|
|
|
|
hr = prst->GetClassID(&clsid);
|
|
|
|
TEST_FAILED((hr != S_OK),
|
|
"VerifyRegistration:GetClassID on IPersist failed\n")
|
|
|
|
TEST_FAILED((memcmp(&clsid, &clsidExpected, sizeof(clsid)) != 0),
|
|
"VerifyRegistration:GetClassID mismatch with expected\n")
|
|
|
|
// Test get the time
|
|
FILETIME filetime;
|
|
|
|
hr = prot->GetTimeOfLastChange(pmk, &filetime);
|
|
|
|
TEST_FAILED((hr != S_OK), "VerifyRegistration:GetTimeOfLastChange Failed\n")
|
|
|
|
TEST_FAILED((memcmp(&filetime, pFileTimeExpected, sizeof(filetime)) != 0),
|
|
"VerifyRegistration:GetTimeOfLastChange != NoteChangeTime value")
|
|
|
|
// Enumerate all the running monikers
|
|
CSafeEnumMoniker penummk;
|
|
|
|
hr = prot->EnumRunning(&penummk);
|
|
|
|
TEST_FAILED(FAILED(hr), "VerifyRegistration:EnumRunning Failed\n")
|
|
|
|
// Cycle through running object table
|
|
BOOL fFound = FALSE;
|
|
IMoniker *pmkTable;
|
|
int cIdx = 0;
|
|
int cOurMoniker;
|
|
|
|
while (SUCCEEDED(hr = penummk->Next(1, &pmkTable, NULL))
|
|
&& (hr != S_FALSE))
|
|
{
|
|
if (pmk->IsEqual(pmkTable) == S_OK)
|
|
{
|
|
fFound = TRUE;
|
|
cOurMoniker = cIdx;
|
|
pmkTable->Release();
|
|
break;
|
|
}
|
|
|
|
pmkTable->Release();
|
|
|
|
cIdx++;
|
|
}
|
|
|
|
TEST_FAILED(FAILED(hr),
|
|
"VerifyRegistration:ROT Moniker Enumeration ended in failure")
|
|
|
|
TEST_FAILED((!fFound),
|
|
"VerifyRegistration:Did not find our moniker in the table");
|
|
|
|
// Reset the pointer
|
|
hr = penummk->Reset();
|
|
|
|
TEST_FAILED(FAILED(hr),
|
|
"VerifyRegistration:ROT IEnumMoniker::Reset Failed");
|
|
|
|
// Skip to our moniker
|
|
hr = penummk->Skip(cOurMoniker);
|
|
|
|
TEST_FAILED(FAILED(hr),
|
|
"VerifyRegistration:ROT IEnumMoniker::Skip Failed");
|
|
|
|
// Read it from the enumerator
|
|
hr = penummk->Next(1, &pmkTable, NULL);
|
|
|
|
TEST_FAILED(FAILED(hr),
|
|
"VerifyRegistration:ROT IEnumMoniker::Next Failed");
|
|
|
|
TEST_FAILED((pmk->IsEqual(pmkTable) != S_OK),
|
|
"VerifyRegistration:ROT IEnumMoniker::Next after skip monikers !=");
|
|
|
|
// If we get to here the test passed
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
BOOL VerifyNotRunning(IMoniker *pmk)
|
|
{
|
|
CSafeROT prot;
|
|
|
|
HRESULT hr = GetRunningObjectTable(0, &prot);
|
|
|
|
TEST_FAILED(FAILED(hr), "GetRunningObjectTable failed!\n")
|
|
|
|
// Check result from IsRunning
|
|
hr = prot->IsRunning(pmk);
|
|
|
|
TEST_FAILED((hr != S_FALSE),
|
|
"Unexpected return from IsRunning\n")
|
|
|
|
// Test Get Object
|
|
CSafeUnk punk;
|
|
|
|
hr = prot->GetObject(pmk, &punk);
|
|
|
|
TEST_FAILED((hr != MK_E_UNAVAILABLE), "Unexpected from GetObject\n")
|
|
|
|
// Test get the time
|
|
FILETIME filetime2;
|
|
|
|
hr = prot->GetTimeOfLastChange(pmk, &filetime2);
|
|
|
|
TEST_FAILED((hr != MK_E_UNAVAILABLE), "GetTimeOfLastChange Failed\n")
|
|
|
|
// Enumerate all the running monikers
|
|
CSafeEnumMoniker penummk;
|
|
|
|
hr = prot->EnumRunning(&penummk);
|
|
|
|
TEST_FAILED(FAILED(hr), "EnumRunning Failed\n")
|
|
|
|
// Cycle through running object table
|
|
BOOL fFound = FALSE;
|
|
IMoniker *pmkTable;
|
|
|
|
while (SUCCEEDED(hr = penummk->Next(1, &pmkTable, NULL))
|
|
&& (hr != S_FALSE))
|
|
{
|
|
if (pmk->IsEqual(pmkTable) == S_OK)
|
|
{
|
|
pmkTable->Release();
|
|
fFound = TRUE;
|
|
break;
|
|
}
|
|
|
|
pmkTable->Release();
|
|
}
|
|
|
|
TEST_FAILED(FAILED(hr), "ROT Moniker Enumeration ended in failure")
|
|
|
|
TEST_FAILED((fFound), "Found our non-running moniker in the table");
|
|
|
|
// If we get to here the test passed
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL TestInvalidParameters(void)
|
|
{
|
|
CSafeROT prot;
|
|
|
|
HRESULT hr = GetRunningObjectTable(0, &prot);
|
|
|
|
// Test set the time
|
|
FILETIME filetime;
|
|
memset(&filetime, 'A', sizeof(filetime));
|
|
|
|
// Test with invalid pointer
|
|
hr = prot->Revoke(0xFFFFFFFF);
|
|
|
|
TEST_FAILED((hr != E_INVALIDARG),
|
|
"WrongResult from Revoke Invalid Address");
|
|
|
|
hr = prot->NoteChangeTime(0xFFFFFFFF, &filetime);
|
|
|
|
TEST_FAILED((hr != E_INVALIDARG),
|
|
"WrongResult from NoteChangeTime Invalid Address");
|
|
|
|
// Test with valid pointer but invalid data
|
|
DWORD dwValidAddress[30];
|
|
|
|
hr = prot->Revoke((DWORD) dwValidAddress);
|
|
|
|
TEST_FAILED((hr != E_INVALIDARG),
|
|
"WrongResult from Revoke Invalid Data");
|
|
|
|
hr = prot->NoteChangeTime((DWORD) dwValidAddress, &filetime);
|
|
|
|
TEST_FAILED((hr != E_INVALIDARG),
|
|
"WrongResult from NoteChangeTime Invalid Data");
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL TestLocalROT(void)
|
|
{
|
|
CSafeMoniker pmk2;
|
|
CSafeROT prot;
|
|
|
|
HRESULT hr = GetRunningObjectTable(0, &prot);
|
|
|
|
TEST_FAILED(FAILED(hr), "GetRunningObjectTable failed!\n")
|
|
|
|
// Make sure that we can do something on the pointer that
|
|
// we got back.
|
|
prot->AddRef();
|
|
prot->Release();
|
|
|
|
// Create an IUnknown pointer for the class.
|
|
CSafeUnk punk;
|
|
punk.Attach(new CRotTestObject(L"First Test Object"));
|
|
|
|
hr = CreateItemMoniker(L"\\", L"Bob", &pmk2);
|
|
|
|
TEST_FAILED(FAILED(hr), "CreateItemMoniker for \\Bob failed\n")
|
|
|
|
// Make sure new object is not running
|
|
TEST_FAILED(VerifyNotRunning(pmk2), "TestLocalROT:Object Already running\n")
|
|
|
|
// Cookie for deregistering object
|
|
DWORD dwRegister;
|
|
|
|
hr = prot->Register(0, punk, pmk2, &dwRegister);
|
|
|
|
TEST_FAILED(FAILED(hr), "TestLocalROT:Register in ROT for \\Bob failed\n")
|
|
|
|
// Test set the time
|
|
FILETIME filetime;
|
|
|
|
memset(&filetime, 'A', sizeof(filetime));
|
|
|
|
hr = prot->NoteChangeTime(dwRegister, &filetime);
|
|
|
|
TEST_FAILED((hr != S_OK), "TestLocalROT:NoteChangeTime Failed\n")
|
|
|
|
// Verify that this is running
|
|
TEST_FAILED(VerifyRegistration(pmk2, clsidLocal, &filetime),
|
|
"TestLocalROT: Registration failed\n");
|
|
|
|
// Revoke registration
|
|
hr = prot->Revoke(dwRegister);
|
|
|
|
TEST_FAILED((hr != S_OK), "TestLocalROT:Revoke failed\n");
|
|
|
|
// Verify no longer registered
|
|
TEST_FAILED(VerifyNotRunning(pmk2),
|
|
"TestLocalROT:VerifyNotRunning failed\n")
|
|
|
|
// If we get to here the test passed
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
void CreatePath(int iId, WCHAR *pwszPath)
|
|
{
|
|
wsprintf(pwszPath, L"%s\\%s%ld", szCurrentDirectory, L"ROTUT", iId);
|
|
}
|
|
|
|
|
|
BOOL CreateObjectAndBind(WCHAR *pwszPath, IUnknown **ppunk)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// create a storage for the object
|
|
{
|
|
CSafeStorage pstg;
|
|
|
|
hr = StgCreateDocfile(pwszPath,
|
|
STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, &pstg);
|
|
|
|
TEST_FAILED(FAILED(hr), "CreateObjectAndBind:StgCreateDocfile failed")
|
|
|
|
// Write the class id to the storage
|
|
hr = pstg->SetClass(CLSID_AdvBnd);
|
|
}
|
|
|
|
TEST_FAILED(FAILED(hr), "CreateObjectAndBind IStorage::SetClass Failed")
|
|
|
|
// Bind to the path
|
|
CSafeMoniker pmk;
|
|
|
|
hr = CreateFileMoniker(pwszPath, &pmk);
|
|
|
|
TEST_FAILED(FAILED(hr), "CreateObjectAndBind:CreateFileMoniker failed")
|
|
|
|
hr = BindMoniker(pmk, 0, IID_IUnknown, (void **) ppunk);
|
|
|
|
TEST_FAILED(FAILED(hr), "CreateObjectAndBind:BindMoniker failed")
|
|
|
|
// Test set the time
|
|
FILETIME filetime;
|
|
|
|
memset(&filetime, 'B', sizeof(filetime));
|
|
|
|
// Verify that it is running
|
|
TEST_FAILED(VerifyRegistration(pmk, CLSID_AdvBnd, &filetime),
|
|
"CreateObjectAndBind: Registration failed\n");
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
BOOL RemoteROT(void)
|
|
{
|
|
// Create an object of the class
|
|
WCHAR szPath[MAX_PATH];
|
|
|
|
CreatePath(0, szPath);
|
|
|
|
CSafeUnk punk;
|
|
|
|
// Bind to the object
|
|
if (CreateObjectAndBind(szPath, &punk))
|
|
{
|
|
printf("RemoteRot: Failed on CreateObjectAndBind\n");
|
|
return TRUE;
|
|
}
|
|
|
|
// Release object
|
|
punk->Release();
|
|
punk.Detach();
|
|
|
|
// Bind to the path
|
|
CSafeMoniker pmk;
|
|
|
|
HRESULT hr = CreateFileMoniker(szPath, &pmk);
|
|
|
|
TEST_FAILED(FAILED(hr), "RemoteROT:CreateFileMoniker failed")
|
|
|
|
// Verify that it is freed
|
|
TEST_FAILED(VerifyNotRunning(pmk),
|
|
"RemoteROT:VerifyNotRunning failed\n")
|
|
|
|
DeleteFile(szPath);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
#define MAX_TO_TEST 100
|
|
IUnknown *apunk[MAX_TO_TEST];
|
|
|
|
|
|
|
|
BOOL TestManyRegistrations(void)
|
|
{
|
|
// Create an object of the class
|
|
WCHAR szPath[MAX_PATH];
|
|
|
|
for (int i = 0; i < MAX_TO_TEST; i++)
|
|
{
|
|
// Create name of bound object
|
|
CreatePath(i, szPath);
|
|
|
|
// Create object
|
|
printf("Many create %ld\n", i);
|
|
|
|
if (CreateObjectAndBind(szPath, &apunk[i]))
|
|
{
|
|
printf("TestManyRegistrations failed on %ld\n", i);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < MAX_TO_TEST; i++)
|
|
{
|
|
printf("Many Release %ld\n", i);
|
|
|
|
// Create name of bound object
|
|
CreatePath(i, szPath);
|
|
|
|
// Bind to the path
|
|
CSafeMoniker pmk;
|
|
|
|
HRESULT hr = CreateFileMoniker(szPath, &pmk);
|
|
|
|
TEST_FAILED(FAILED(hr),
|
|
"TestManyRegistrations:CreateFileMoniker failed")
|
|
|
|
// Release object
|
|
apunk[i]->Release();
|
|
|
|
// Verify object is not running
|
|
if (VerifyNotRunning(pmk))
|
|
{
|
|
printf("TestManyRegistrations:VerifyNotRunning failed on %ld\n", i);
|
|
return TRUE;
|
|
}
|
|
|
|
DeleteFile(szPath);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
int _cdecl main(int argc, TCHAR **argv)
|
|
{
|
|
// Get the current directory
|
|
int len = GetCurrentDirectoryA(sizeof(szTmpCurrrentDirectory),
|
|
szTmpCurrrentDirectory);
|
|
|
|
// Convert to UNICODE
|
|
mbstowcs(szCurrentDirectory, szTmpCurrrentDirectory, len + 1);
|
|
|
|
// Result of test - TRUE == passed
|
|
BOOL fTest = FALSE;
|
|
|
|
// Initialize Ole
|
|
HRESULT hr;
|
|
|
|
COleInit oleinit(hr);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
printf("OleInitialize Failed\n");
|
|
return -1;
|
|
}
|
|
|
|
// Test Invalidad Parameters and Local ROT
|
|
if (!TestInvalidParameters() && !TestLocalROT())
|
|
{
|
|
// Test Remote Registration for object
|
|
if (!RemoteROT())
|
|
{
|
|
// Test Large Registration
|
|
if (!TestManyRegistrations())
|
|
{
|
|
fTest = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fTest)
|
|
{
|
|
printf("Test Passed\n");
|
|
}
|
|
else
|
|
{
|
|
printf("Test FAILED!!!\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|