Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

618 lines
12 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: rotut.cxx
  7. //
  8. // Contents: Unit Test for ROT
  9. //
  10. // Classes: MISSING
  11. //
  12. // Functions: MISSING
  13. //
  14. // History: 16-Oct-93 Ricksa Created
  15. //
  16. //--------------------------------------------------------------------------
  17. #include <windows.h>
  18. #include <widewrap.h> // For chicago build
  19. #include <ole2.h>
  20. #include <stdio.h>
  21. #include <safepnt.hxx>
  22. #include <com.hxx>
  23. #define TEST_FAILED(x, y) \
  24. if (x) \
  25. { \
  26. printf("%s:%d %s\n", __FILE__, __LINE__, y); \
  27. return TRUE; \
  28. }
  29. GUID clsidLocal =
  30. {0xbbbbbbbb,0xbbbb,0xbbbb,{0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb}};
  31. CHAR szTmpCurrrentDirectory[MAX_PATH];
  32. WCHAR szCurrentDirectory[MAX_PATH];
  33. SAFE_INTERFACE_PTR(CSafeROT, IRunningObjectTable)
  34. SAFE_INTERFACE_PTR(CSafeUnk, IUnknown)
  35. SAFE_INTERFACE_PTR(CSafePersist, IPersist)
  36. SAFE_INTERFACE_PTR(CSafeEnumMoniker, IEnumMoniker)
  37. SAFE_INTERFACE_PTR(CSafeMoniker, IMoniker)
  38. SAFE_INTERFACE_PTR(CSafeStorage, IStorage)
  39. class COleInit
  40. {
  41. public:
  42. COleInit(HRESULT& hr);
  43. ~COleInit(void);
  44. private:
  45. // No private data
  46. };
  47. inline COleInit::COleInit(HRESULT& hr)
  48. {
  49. hr = OleInitialize(NULL);
  50. }
  51. inline COleInit::~COleInit(void)
  52. {
  53. // Do the clean up
  54. OleUninitialize();
  55. }
  56. class CRotTestObject : public IPersist
  57. {
  58. public:
  59. CRotTestObject(WCHAR *pwszID);
  60. // IUnknown Interface
  61. STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  62. STDMETHODIMP_(ULONG)AddRef(void);
  63. STDMETHODIMP_(ULONG)Release(void);
  64. STDMETHODIMP GetClassID(LPCLSID pclsid);
  65. private:
  66. WCHAR _awcID[256];
  67. ULONG _cRefs;
  68. };
  69. CRotTestObject::CRotTestObject(WCHAR *pwszID) : _cRefs(1)
  70. {
  71. wcscpy(_awcID, pwszID);
  72. }
  73. STDMETHODIMP CRotTestObject::QueryInterface(REFIID riid, void **ppv)
  74. {
  75. if ((memcmp((void *) &riid, (void *) &IID_IUnknown, sizeof(GUID)) == 0)
  76. || (memcmp((void *) &riid, (void *) &IID_IPersist, sizeof(GUID)) == 0))
  77. {
  78. _cRefs++;
  79. *ppv = (IUnknown *) this;
  80. return S_OK;
  81. }
  82. *ppv = NULL;
  83. return E_NOINTERFACE;
  84. }
  85. STDMETHODIMP_(ULONG) CRotTestObject::AddRef(void)
  86. {
  87. _cRefs++;
  88. return (ULONG) _awcID;
  89. }
  90. STDMETHODIMP_(ULONG) CRotTestObject::Release(void)
  91. {
  92. if (--_cRefs == 0)
  93. {
  94. delete this;
  95. }
  96. return _cRefs;
  97. }
  98. STDMETHODIMP CRotTestObject::GetClassID(LPCLSID pclsid)
  99. {
  100. memcpy(pclsid, &clsidLocal, sizeof(clsidLocal));
  101. return S_OK;
  102. }
  103. BOOL VerifyRegistration(
  104. IMoniker *pmk,
  105. REFCLSID clsidExpected,
  106. FILETIME *pFileTimeExpected)
  107. {
  108. CSafeROT prot;
  109. HRESULT hr = GetRunningObjectTable(0, &prot);
  110. TEST_FAILED(FAILED(hr),
  111. "VerifyRegistration:GetRunningObjectTable failed!\n")
  112. // Verify the object is running
  113. hr = prot->IsRunning(pmk);
  114. TEST_FAILED((hr != S_OK),
  115. "VerifyRegistration:Unexpected return from IsRunning\n")
  116. // Test Get Object
  117. CSafeUnk punk;
  118. hr = prot->GetObject(pmk, &punk);
  119. TEST_FAILED((hr != S_OK),
  120. "VerifyRegistration:Unexpected from GetObject\n")
  121. // Confirm object class
  122. CSafePersist prst;
  123. hr = punk->QueryInterface(IID_IPersist, (void **) &prst);
  124. TEST_FAILED((hr != S_OK),
  125. "VerifyRegistration:QI to IPersist failed\n")
  126. CLSID clsid;
  127. hr = prst->GetClassID(&clsid);
  128. TEST_FAILED((hr != S_OK),
  129. "VerifyRegistration:GetClassID on IPersist failed\n")
  130. TEST_FAILED((memcmp(&clsid, &clsidExpected, sizeof(clsid)) != 0),
  131. "VerifyRegistration:GetClassID mismatch with expected\n")
  132. // Test get the time
  133. FILETIME filetime;
  134. hr = prot->GetTimeOfLastChange(pmk, &filetime);
  135. TEST_FAILED((hr != S_OK), "VerifyRegistration:GetTimeOfLastChange Failed\n")
  136. TEST_FAILED((memcmp(&filetime, pFileTimeExpected, sizeof(filetime)) != 0),
  137. "VerifyRegistration:GetTimeOfLastChange != NoteChangeTime value")
  138. // Enumerate all the running monikers
  139. CSafeEnumMoniker penummk;
  140. hr = prot->EnumRunning(&penummk);
  141. TEST_FAILED(FAILED(hr), "VerifyRegistration:EnumRunning Failed\n")
  142. // Cycle through running object table
  143. BOOL fFound = FALSE;
  144. IMoniker *pmkTable;
  145. int cIdx = 0;
  146. int cOurMoniker;
  147. while (SUCCEEDED(hr = penummk->Next(1, &pmkTable, NULL))
  148. && (hr != S_FALSE))
  149. {
  150. if (pmk->IsEqual(pmkTable) == S_OK)
  151. {
  152. fFound = TRUE;
  153. cOurMoniker = cIdx;
  154. pmkTable->Release();
  155. break;
  156. }
  157. pmkTable->Release();
  158. cIdx++;
  159. }
  160. TEST_FAILED(FAILED(hr),
  161. "VerifyRegistration:ROT Moniker Enumeration ended in failure")
  162. TEST_FAILED((!fFound),
  163. "VerifyRegistration:Did not find our moniker in the table");
  164. // Reset the pointer
  165. hr = penummk->Reset();
  166. TEST_FAILED(FAILED(hr),
  167. "VerifyRegistration:ROT IEnumMoniker::Reset Failed");
  168. // Skip to our moniker
  169. hr = penummk->Skip(cOurMoniker);
  170. TEST_FAILED(FAILED(hr),
  171. "VerifyRegistration:ROT IEnumMoniker::Skip Failed");
  172. // Read it from the enumerator
  173. hr = penummk->Next(1, &pmkTable, NULL);
  174. TEST_FAILED(FAILED(hr),
  175. "VerifyRegistration:ROT IEnumMoniker::Next Failed");
  176. TEST_FAILED((pmk->IsEqual(pmkTable) != S_OK),
  177. "VerifyRegistration:ROT IEnumMoniker::Next after skip monikers !=");
  178. // If we get to here the test passed
  179. return FALSE;
  180. }
  181. BOOL VerifyNotRunning(IMoniker *pmk)
  182. {
  183. CSafeROT prot;
  184. HRESULT hr = GetRunningObjectTable(0, &prot);
  185. TEST_FAILED(FAILED(hr), "GetRunningObjectTable failed!\n")
  186. // Check result from IsRunning
  187. hr = prot->IsRunning(pmk);
  188. TEST_FAILED((hr != S_FALSE),
  189. "Unexpected return from IsRunning\n")
  190. // Test Get Object
  191. CSafeUnk punk;
  192. hr = prot->GetObject(pmk, &punk);
  193. TEST_FAILED((hr != MK_E_UNAVAILABLE), "Unexpected from GetObject\n")
  194. // Test get the time
  195. FILETIME filetime2;
  196. hr = prot->GetTimeOfLastChange(pmk, &filetime2);
  197. TEST_FAILED((hr != MK_E_UNAVAILABLE), "GetTimeOfLastChange Failed\n")
  198. // Enumerate all the running monikers
  199. CSafeEnumMoniker penummk;
  200. hr = prot->EnumRunning(&penummk);
  201. TEST_FAILED(FAILED(hr), "EnumRunning Failed\n")
  202. // Cycle through running object table
  203. BOOL fFound = FALSE;
  204. IMoniker *pmkTable;
  205. while (SUCCEEDED(hr = penummk->Next(1, &pmkTable, NULL))
  206. && (hr != S_FALSE))
  207. {
  208. if (pmk->IsEqual(pmkTable) == S_OK)
  209. {
  210. pmkTable->Release();
  211. fFound = TRUE;
  212. break;
  213. }
  214. pmkTable->Release();
  215. }
  216. TEST_FAILED(FAILED(hr), "ROT Moniker Enumeration ended in failure")
  217. TEST_FAILED((fFound), "Found our non-running moniker in the table");
  218. // If we get to here the test passed
  219. return FALSE;
  220. }
  221. BOOL TestInvalidParameters(void)
  222. {
  223. CSafeROT prot;
  224. HRESULT hr = GetRunningObjectTable(0, &prot);
  225. // Test set the time
  226. FILETIME filetime;
  227. memset(&filetime, 'A', sizeof(filetime));
  228. // Test with invalid pointer
  229. hr = prot->Revoke(0xFFFFFFFF);
  230. TEST_FAILED((hr != E_INVALIDARG),
  231. "WrongResult from Revoke Invalid Address");
  232. hr = prot->NoteChangeTime(0xFFFFFFFF, &filetime);
  233. TEST_FAILED((hr != E_INVALIDARG),
  234. "WrongResult from NoteChangeTime Invalid Address");
  235. // Test with valid pointer but invalid data
  236. DWORD dwValidAddress[30];
  237. hr = prot->Revoke((DWORD) dwValidAddress);
  238. TEST_FAILED((hr != E_INVALIDARG),
  239. "WrongResult from Revoke Invalid Data");
  240. hr = prot->NoteChangeTime((DWORD) dwValidAddress, &filetime);
  241. TEST_FAILED((hr != E_INVALIDARG),
  242. "WrongResult from NoteChangeTime Invalid Data");
  243. return FALSE;
  244. }
  245. BOOL TestLocalROT(void)
  246. {
  247. CSafeMoniker pmk2;
  248. CSafeROT prot;
  249. HRESULT hr = GetRunningObjectTable(0, &prot);
  250. TEST_FAILED(FAILED(hr), "GetRunningObjectTable failed!\n")
  251. // Make sure that we can do something on the pointer that
  252. // we got back.
  253. prot->AddRef();
  254. prot->Release();
  255. // Create an IUnknown pointer for the class.
  256. CSafeUnk punk;
  257. punk.Attach(new CRotTestObject(L"First Test Object"));
  258. hr = CreateItemMoniker(L"\\", L"Bob", &pmk2);
  259. TEST_FAILED(FAILED(hr), "CreateItemMoniker for \\Bob failed\n")
  260. // Make sure new object is not running
  261. TEST_FAILED(VerifyNotRunning(pmk2), "TestLocalROT:Object Already running\n")
  262. // Cookie for deregistering object
  263. DWORD dwRegister;
  264. hr = prot->Register(0, punk, pmk2, &dwRegister);
  265. TEST_FAILED(FAILED(hr), "TestLocalROT:Register in ROT for \\Bob failed\n")
  266. // Test set the time
  267. FILETIME filetime;
  268. memset(&filetime, 'A', sizeof(filetime));
  269. hr = prot->NoteChangeTime(dwRegister, &filetime);
  270. TEST_FAILED((hr != S_OK), "TestLocalROT:NoteChangeTime Failed\n")
  271. // Verify that this is running
  272. TEST_FAILED(VerifyRegistration(pmk2, clsidLocal, &filetime),
  273. "TestLocalROT: Registration failed\n");
  274. // Revoke registration
  275. hr = prot->Revoke(dwRegister);
  276. TEST_FAILED((hr != S_OK), "TestLocalROT:Revoke failed\n");
  277. // Verify no longer registered
  278. TEST_FAILED(VerifyNotRunning(pmk2),
  279. "TestLocalROT:VerifyNotRunning failed\n")
  280. // If we get to here the test passed
  281. return FALSE;
  282. }
  283. void CreatePath(int iId, WCHAR *pwszPath)
  284. {
  285. wsprintf(pwszPath, L"%s\\%s%ld", szCurrentDirectory, L"ROTUT", iId);
  286. }
  287. BOOL CreateObjectAndBind(WCHAR *pwszPath, IUnknown **ppunk)
  288. {
  289. HRESULT hr;
  290. // create a storage for the object
  291. {
  292. CSafeStorage pstg;
  293. hr = StgCreateDocfile(pwszPath,
  294. STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, &pstg);
  295. TEST_FAILED(FAILED(hr), "CreateObjectAndBind:StgCreateDocfile failed")
  296. // Write the class id to the storage
  297. hr = pstg->SetClass(CLSID_AdvBnd);
  298. }
  299. TEST_FAILED(FAILED(hr), "CreateObjectAndBind IStorage::SetClass Failed")
  300. // Bind to the path
  301. CSafeMoniker pmk;
  302. hr = CreateFileMoniker(pwszPath, &pmk);
  303. TEST_FAILED(FAILED(hr), "CreateObjectAndBind:CreateFileMoniker failed")
  304. hr = BindMoniker(pmk, 0, IID_IUnknown, (void **) ppunk);
  305. TEST_FAILED(FAILED(hr), "CreateObjectAndBind:BindMoniker failed")
  306. // Test set the time
  307. FILETIME filetime;
  308. memset(&filetime, 'B', sizeof(filetime));
  309. // Verify that it is running
  310. TEST_FAILED(VerifyRegistration(pmk, CLSID_AdvBnd, &filetime),
  311. "CreateObjectAndBind: Registration failed\n");
  312. return FALSE;
  313. }
  314. BOOL RemoteROT(void)
  315. {
  316. // Create an object of the class
  317. WCHAR szPath[MAX_PATH];
  318. CreatePath(0, szPath);
  319. CSafeUnk punk;
  320. // Bind to the object
  321. if (CreateObjectAndBind(szPath, &punk))
  322. {
  323. printf("RemoteRot: Failed on CreateObjectAndBind\n");
  324. return TRUE;
  325. }
  326. // Release object
  327. punk->Release();
  328. punk.Detach();
  329. // Bind to the path
  330. CSafeMoniker pmk;
  331. HRESULT hr = CreateFileMoniker(szPath, &pmk);
  332. TEST_FAILED(FAILED(hr), "RemoteROT:CreateFileMoniker failed")
  333. // Verify that it is freed
  334. TEST_FAILED(VerifyNotRunning(pmk),
  335. "RemoteROT:VerifyNotRunning failed\n")
  336. DeleteFile(szPath);
  337. return FALSE;
  338. }
  339. #define MAX_TO_TEST 100
  340. IUnknown *apunk[MAX_TO_TEST];
  341. BOOL TestManyRegistrations(void)
  342. {
  343. // Create an object of the class
  344. WCHAR szPath[MAX_PATH];
  345. for (int i = 0; i < MAX_TO_TEST; i++)
  346. {
  347. // Create name of bound object
  348. CreatePath(i, szPath);
  349. // Create object
  350. printf("Many create %ld\n", i);
  351. if (CreateObjectAndBind(szPath, &apunk[i]))
  352. {
  353. printf("TestManyRegistrations failed on %ld\n", i);
  354. return TRUE;
  355. }
  356. }
  357. for (i = 0; i < MAX_TO_TEST; i++)
  358. {
  359. printf("Many Release %ld\n", i);
  360. // Create name of bound object
  361. CreatePath(i, szPath);
  362. // Bind to the path
  363. CSafeMoniker pmk;
  364. HRESULT hr = CreateFileMoniker(szPath, &pmk);
  365. TEST_FAILED(FAILED(hr),
  366. "TestManyRegistrations:CreateFileMoniker failed")
  367. // Release object
  368. apunk[i]->Release();
  369. // Verify object is not running
  370. if (VerifyNotRunning(pmk))
  371. {
  372. printf("TestManyRegistrations:VerifyNotRunning failed on %ld\n", i);
  373. return TRUE;
  374. }
  375. DeleteFile(szPath);
  376. }
  377. return FALSE;
  378. }
  379. int _cdecl main(int argc, TCHAR **argv)
  380. {
  381. // Get the current directory
  382. int len = GetCurrentDirectoryA(sizeof(szTmpCurrrentDirectory),
  383. szTmpCurrrentDirectory);
  384. // Convert to UNICODE
  385. mbstowcs(szCurrentDirectory, szTmpCurrrentDirectory, len + 1);
  386. // Result of test - TRUE == passed
  387. BOOL fTest = FALSE;
  388. // Initialize Ole
  389. HRESULT hr;
  390. COleInit oleinit(hr);
  391. if (FAILED(hr))
  392. {
  393. printf("OleInitialize Failed\n");
  394. return -1;
  395. }
  396. // Test Invalidad Parameters and Local ROT
  397. if (!TestInvalidParameters() && !TestLocalROT())
  398. {
  399. // Test Remote Registration for object
  400. if (!RemoteROT())
  401. {
  402. // Test Large Registration
  403. if (!TestManyRegistrations())
  404. {
  405. fTest = TRUE;
  406. }
  407. }
  408. }
  409. if (fTest)
  410. {
  411. printf("Test Passed\n");
  412. }
  413. else
  414. {
  415. printf("Test FAILED!!!\n");
  416. }
  417. return 0;
  418. }