//+------------------------------------------------------------------------- // // 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 #include // For chicago build #include #include #include #include #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; }