Leaked source code of windows server 2003
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.

1131 lines
29 KiB

  1. //+-------------------------------------------------------------------
  2. //
  3. // File: uthread.cpp
  4. //
  5. // Contents: Unit test for various OLE threading model features
  6. //
  7. // Classes: SSTParamBlock
  8. // SSTParamBlock
  9. // SBTParamBlock
  10. //
  11. // Functions: CreateTestThread
  12. // VerifyTestObject
  13. // CheckForDllExistence
  14. // GetDllDirectory
  15. // SetRegForDll
  16. // SetSingleThreadRegEntry
  17. // SetAptThreadRegEntry
  18. // SetBothThreadRegEntry
  19. // SingleThreadTestThread
  20. // AptTestThread
  21. // BothTestThread
  22. // SetUpRegistry
  23. // TestSingleThread
  24. // TestAptThread
  25. // TestBothDll
  26. // TestFreeAllLibraries
  27. // ThreadUnitTest
  28. //
  29. // History: 31-Oct-94 Ricksa
  30. //
  31. //--------------------------------------------------------------------
  32. #include <windows.h>
  33. #include <ole2.h>
  34. #include <uthread.h>
  35. #include <cotest.h>
  36. // Test single threaded DLL - all operations s/b executed on the main thread.
  37. // Pointers between threads s/b different. Test loading class object from
  38. // different than the main thread.
  39. // Test apartment model - all operations should occur on the thread the
  40. // object was created on. This should also test the helper APIs. Pointers
  41. // between threads s/b different. This tests helper APIs.
  42. // Both model DLL. We want to make sure that the marshaling works between
  43. // threads so that you get the same pointer. This tests new marshal context.
  44. // Test Free Unused Libraries from non-main thread. Test FreeUnused libraries
  45. // from main thread.
  46. //+-------------------------------------------------------------------------
  47. //
  48. // Class: SSTParamBlock
  49. //
  50. // Purpose: Parameter block for single threaded dll test.
  51. //
  52. // Interface:
  53. //
  54. // History: 01-Nov-92 Ricksa Created
  55. //
  56. //--------------------------------------------------------------------------
  57. struct SSTParamBlock
  58. {
  59. HANDLE hEvent;
  60. BOOL fResult;
  61. IClassFactory * pcf;
  62. };
  63. //+-------------------------------------------------------------------------
  64. //
  65. // Class: SSTParamBlock
  66. //
  67. // Purpose: Parameter block for apt model threaded dll test.
  68. //
  69. // Interface:
  70. //
  71. // History: 01-Nov-92 Ricksa Created
  72. //
  73. //--------------------------------------------------------------------------
  74. struct SATParamBlock
  75. {
  76. HANDLE hEvent;
  77. BOOL fResult;
  78. IClassFactory * pcf;
  79. IStream * pstrm;
  80. };
  81. //+-------------------------------------------------------------------------
  82. //
  83. // Class: SBTParamBlock
  84. //
  85. // Purpose: Parameter block for both model dll test.
  86. //
  87. // Interface:
  88. //
  89. // History: 02-Nov-92 Ricksa Created
  90. //
  91. //--------------------------------------------------------------------------
  92. struct SBTParamBlock
  93. {
  94. HANDLE hEvent;
  95. BOOL fResult;
  96. IClassFactory * pcf;
  97. IStream * pstrm;
  98. };
  99. const TCHAR *pszRegValThreadModel = TEXT("ThreadingModel");
  100. const TCHAR *pszApartmentModel = TEXT("Apartment");
  101. const TCHAR *pszBoth = TEXT("Both");
  102. //+-------------------------------------------------------------------
  103. //
  104. // Function: ThreadWaitForEvent, private
  105. //
  106. // Synopsis: Process messages until event becomes signaled
  107. //
  108. // Arguments: [lphObject] - handle to become signaled
  109. //
  110. // History: 02-Nov-94 Ricksa Created
  111. //
  112. //--------------------------------------------------------------------
  113. void ThreadWaitForEvent(HANDLE hObject)
  114. {
  115. // message loop lasts until we get a WM_QUIT message
  116. // upon which we shall return from the function
  117. while (TRUE)
  118. {
  119. // wait for any message sent or posted to this queue
  120. // or for one of the passed handles to become signaled
  121. DWORD result = MsgWaitForMultipleObjects(1, &hObject,
  122. FALSE, INFINITE, QS_ALLINPUT);
  123. // result tells us the type of event we have:
  124. // a message or a signaled handle
  125. // if there are one or more messages in the queue ...
  126. if (result == (WAIT_OBJECT_0 + 1))
  127. {
  128. // block-local variable
  129. MSG msg;
  130. // read all of the messages in this next loop
  131. // removing each message as we read it
  132. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  133. {
  134. // if it's a quit message we're out of here
  135. if (msg.message == WM_QUIT)
  136. {
  137. return;
  138. }
  139. // otherwise dispatch it
  140. DispatchMessage(&msg);
  141. }
  142. continue;
  143. }
  144. // Event got signaled so we are done.
  145. break;
  146. }
  147. }
  148. //+-------------------------------------------------------------------
  149. //
  150. // Function: CreateTestThread, private
  151. //
  152. // Synopsis: Create a test thread in standard way
  153. //
  154. // Arguments: [lpStartAddr] - start routine address
  155. // [pvThreadArg] - argument to pass to the thread
  156. //
  157. // Returns: TRUE - Thread created successfully
  158. // FALSE - Thread could not be created.
  159. //
  160. // History: 02-Nov-94 Ricksa Created
  161. //
  162. //--------------------------------------------------------------------
  163. BOOL CreateTestThread(
  164. LPTHREAD_START_ROUTINE lpStartAddr,
  165. void *pvThreadArg)
  166. {
  167. // Where to put the thread ID that we don't care about
  168. DWORD dwThreadId;
  169. // Create thread to load single threaded object
  170. HANDLE hThread = CreateThread(
  171. NULL, // Default security descriptor
  172. 0, // Default stack
  173. lpStartAddr, // Start routine
  174. pvThreadArg, // Parameters to pass to the thread
  175. 0, // Thread runs immediately after creation
  176. &dwThreadId); // Where to return thread id (unused).
  177. CloseHandle(hThread);
  178. return hThread != NULL;
  179. }
  180. //+-------------------------------------------------------------------
  181. //
  182. // Function: VerifyTestObject, private
  183. //
  184. // Synopsis: Create a test DLL object in standard way
  185. //
  186. // Arguments: [pcf] - start routine address
  187. // [rclsid] - clsid to check
  188. //
  189. // Returns: TRUE - Object behaved as expected
  190. // FALSE - Object did not behave
  191. //
  192. // History: 02-Nov-94 Ricksa Created
  193. //
  194. //--------------------------------------------------------------------
  195. BOOL VerifyTestObject(
  196. IClassFactory *pcf,
  197. REFCLSID rclsid)
  198. {
  199. // Result from test
  200. BOOL fResult = FALSE;
  201. // Pointer to unknown for the object
  202. IUnknown *punk = NULL;
  203. // Pointer to IPersist interface
  204. IPersist *pIPersist = NULL;
  205. // Create an instance of an object
  206. if (pcf->CreateInstance(NULL, IID_IUnknown, (void **) &punk) == NOERROR)
  207. {
  208. // Do a QI to confirm object behaves correctly
  209. if (punk->QueryInterface(IID_IPersist, (void **) &pIPersist) == NOERROR)
  210. {
  211. CLSID clsidTest;
  212. // Make sure we can actually call through to the proxy object.
  213. if ((pIPersist->GetClassID(&clsidTest) == NOERROR)
  214. && IsEqualCLSID(clsidTest, rclsid))
  215. {
  216. fResult = TRUE;
  217. }
  218. }
  219. }
  220. if (punk != NULL)
  221. {
  222. punk->Release();
  223. }
  224. if (pIPersist != NULL)
  225. {
  226. pIPersist->Release();
  227. }
  228. return fResult;
  229. }
  230. //+-------------------------------------------------------------------
  231. //
  232. // Function: GetFullDllName, private
  233. //
  234. // Synopsis: Get the directory for the registration for the test.
  235. //
  236. // Arguments: [pszDllName] - DLL name
  237. // [pszFullDllName] - output buffer for DLL path
  238. //
  239. // Returns: TRUE - we could get the path for the DLL
  240. // FALSE - we couldn't figure out what to use.
  241. //
  242. // History: 31-Oct-94 Ricksa Created
  243. //
  244. // Notes:
  245. //
  246. //--------------------------------------------------------------------
  247. BOOL GetFullDllName(const TCHAR *pszDllName, TCHAR *pszFullDllName)
  248. {
  249. // Use windows to tell us what DLL we would load.
  250. HINSTANCE hinstDll = LoadLibraryEx(pszDllName, NULL,
  251. DONT_RESOLVE_DLL_REFERENCES | LOAD_WITH_ALTERED_SEARCH_PATH);
  252. if (hinstDll == NULL)
  253. {
  254. // We could not find the DLL so there isn't much purpose in
  255. // continuing the test.
  256. MessageBox(NULL, TEXT("LoadLibraryEx Failed!"),
  257. TEXT("FATAL ERROR"), MB_OK);
  258. return FALSE;
  259. }
  260. // Get the DLLs path name
  261. if (!GetModuleFileName(hinstDll, pszFullDllName, MAX_PATH))
  262. {
  263. // How can this fail?? -- anyway we better tell someone.
  264. MessageBox(NULL, TEXT("Threading Test GetModuleFileName Failed!"),
  265. TEXT("FATAL ERROR"), MB_OK);
  266. return FALSE;
  267. }
  268. FreeLibrary(hinstDll);
  269. return TRUE;
  270. }
  271. //+-------------------------------------------------------------------
  272. //
  273. // Function: SetRegForDll, private
  274. //
  275. // Synopsis: Set registry entry for a DLL
  276. //
  277. // Arguments: [rclsid] - clsid for reg entry
  278. // [pszDir] - directory for DLL path
  279. // [pszDllName] - name to use for DLL
  280. // [pszThreadModel] - threading model can be NULL.
  281. //
  282. // Returns: TRUE - Registry entry set successfully.
  283. // FALSE - Registry entry set successfully.
  284. //
  285. // History: 01-Nov-94 Ricksa Created
  286. //
  287. //--------------------------------------------------------------------
  288. BOOL SetRegForDll(
  289. REFCLSID rclsid,
  290. const TCHAR *pszDllName,
  291. const TCHAR *pszThreadModel)
  292. {
  293. // Result returned by function
  294. BOOL fResult = FALSE;
  295. // String buffer used for various purposes
  296. TCHAR aszWkBuf[MAX_PATH];
  297. // Key to class
  298. HKEY hKeyClass = NULL;
  299. // Key to DLL entry
  300. HKEY hKeyDll = NULL;
  301. // Build clsid registry key
  302. wsprintf(aszWkBuf,
  303. TEXT("CLSID\\{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"),
  304. rclsid.Data1, rclsid.Data2, rclsid.Data3,
  305. rclsid.Data4[0], rclsid.Data4[1],
  306. rclsid.Data4[2], rclsid.Data4[3],
  307. rclsid.Data4[4], rclsid.Data4[5],
  308. rclsid.Data4[6], rclsid.Data4[7]);
  309. // Create the key for the class
  310. if (ERROR_SUCCESS != RegCreateKey(HKEY_CLASSES_ROOT, aszWkBuf, &hKeyClass))
  311. {
  312. goto SetSingleThreadRegEntryExit;
  313. }
  314. // Create the key for the DLL
  315. if (ERROR_SUCCESS != RegCreateKey(hKeyClass, TEXT("InprocServer32"),
  316. &hKeyDll))
  317. {
  318. goto SetSingleThreadRegEntryExit;
  319. }
  320. // Build the DLL name
  321. if (!GetFullDllName(pszDllName, &aszWkBuf[0]))
  322. {
  323. goto SetSingleThreadRegEntryExit;
  324. }
  325. OutputDebugString(&aszWkBuf[0]);
  326. // Set the value for the DLL name
  327. if (ERROR_SUCCESS != RegSetValue(hKeyDll, NULL, REG_SZ, aszWkBuf,
  328. lstrlen(aszWkBuf)))
  329. {
  330. goto SetSingleThreadRegEntryExit;
  331. }
  332. // Set the threading model if there is one
  333. if (pszThreadModel != NULL)
  334. {
  335. // Set the value for the DLL name
  336. if (ERROR_SUCCESS != RegSetValueEx(hKeyDll, pszRegValThreadModel, 0,
  337. REG_SZ, (const unsigned char*) pszThreadModel,
  338. lstrlen(pszThreadModel) + 1))
  339. {
  340. goto SetSingleThreadRegEntryExit;
  341. }
  342. }
  343. fResult = TRUE;
  344. SetSingleThreadRegEntryExit:
  345. if (hKeyClass != NULL)
  346. {
  347. RegCloseKey(hKeyClass);
  348. }
  349. if (hKeyDll != NULL)
  350. {
  351. RegCloseKey(hKeyDll);
  352. }
  353. if (!fResult)
  354. {
  355. wsprintf(aszWkBuf, TEXT("Registry Setup For %s Failed"), pszDllName);
  356. MessageBox(NULL, aszWkBuf, TEXT("FATAL ERROR"), MB_OK);
  357. }
  358. return fResult;
  359. }
  360. //+-------------------------------------------------------------------
  361. //
  362. // Function: SingleThreadTestThread, private
  363. //
  364. // Synopsis: Verify single threaded object call correctly from non
  365. // main thread.
  366. //
  367. // Arguments: [pvCtrlData] - control data for the thread
  368. //
  369. // Returns: 0 - interesting values returned through pvCtrlData.
  370. //
  371. // History: 31-Oct-94 Ricksa Created
  372. //
  373. //--------------------------------------------------------------------
  374. DWORD SingleThreadTestThread(void *pvCtrlData)
  375. {
  376. // Data shared with main thread
  377. SSTParamBlock *psstp = (SSTParamBlock *) pvCtrlData;
  378. psstp->fResult = FALSE;
  379. // Local class factory object.
  380. IClassFactory *pcf = NULL;
  381. // IUnknown ptrs used for multiple purposes
  382. IUnknown *punk = NULL;
  383. // Initialize thread
  384. if (CoInitialize(NULL) != NOERROR)
  385. {
  386. goto SingleThreadTestThreadExit;
  387. }
  388. // Get the class object
  389. if (CoGetClassObject(clsidSingleThreadedDll, CLSCTX_INPROC, NULL,
  390. IID_IClassFactory, (void **) &pcf) != NOERROR)
  391. {
  392. goto SingleThreadTestThreadExit;
  393. }
  394. // Make sure main thread's ptr is not the same as this thread's ptr.
  395. if (pcf == psstp->pcf)
  396. {
  397. goto SingleThreadTestThreadExit;
  398. }
  399. // Confirm that class object is a proxy
  400. if (pcf->QueryInterface(IID_IProxyManager, (void **) &punk) == NOERROR)
  401. {
  402. // Verify that we can play with an object.
  403. psstp->fResult = VerifyTestObject(pcf, clsidSingleThreadedDll);
  404. }
  405. SingleThreadTestThreadExit:
  406. if (pcf != NULL)
  407. {
  408. pcf->Release();
  409. }
  410. if (punk != NULL)
  411. {
  412. punk->Release();
  413. }
  414. // Exit the thread.
  415. SetEvent(psstp->hEvent);
  416. return 0;
  417. }
  418. //+-------------------------------------------------------------------
  419. //
  420. // Function: AptTestThread, private
  421. //
  422. // Synopsis: Verify apt threaded object call correctly from thread
  423. // if was not created on.
  424. //
  425. // Arguments: [pvCtrlData] - control data for the thread
  426. //
  427. // Returns: 0 - interesting values returned through pvCtrlData.
  428. //
  429. // History: 02-Nov-94 Ricksa Created
  430. //
  431. //--------------------------------------------------------------------
  432. DWORD AptTestThread(void *pvCtrlData)
  433. {
  434. // Data shared with main thread
  435. SATParamBlock *psatpb = (SATParamBlock *) pvCtrlData;
  436. psatpb->fResult = FALSE;
  437. // Class factory object unmarshaled from other thread.
  438. IClassFactory *pcfUnmarshal = NULL;
  439. // Class factory gotten from this thread
  440. IClassFactory *pcfThisThread = NULL;
  441. // IUnknown ptrs used for multiple purposes
  442. IUnknown *punk = NULL;
  443. // Initialize thread
  444. if (CoInitialize(NULL) != NOERROR)
  445. {
  446. goto AptTestThreadExit;
  447. }
  448. // Get the class object from the marshaled stream
  449. if (CoGetInterfaceAndReleaseStream(psatpb->pstrm, IID_IClassFactory,
  450. (void **) &pcfUnmarshal) != NOERROR)
  451. {
  452. goto AptTestThreadExit;
  453. }
  454. // Caller doesn't have to release this now.
  455. psatpb->pstrm = NULL;
  456. // Make sure main thread's ptr is not the same as this thread's ptr.
  457. if (pcfUnmarshal == psatpb->pcf)
  458. {
  459. goto AptTestThreadExit;
  460. }
  461. // Confirm that class object is a proxy
  462. if (pcfUnmarshal->QueryInterface(IID_IProxyManager, (void **) &punk)
  463. != NOERROR)
  464. {
  465. goto AptTestThreadExit;
  466. }
  467. // Release the interface we got back and NULL it let the exit routine
  468. // known that it does not have to clean this object up.
  469. punk->Release();
  470. punk = NULL;
  471. if (!VerifyTestObject(pcfUnmarshal, clsidAptThreadedDll))
  472. {
  473. goto AptTestThreadExit;
  474. }
  475. // Get the class factory for this thread
  476. if (CoGetClassObject(clsidAptThreadedDll, CLSCTX_INPROC, NULL,
  477. IID_IClassFactory, (void **) &pcfThisThread) != NOERROR)
  478. {
  479. goto AptTestThreadExit;
  480. }
  481. // Make sure that it isn't the same as the one we unmarshaled
  482. if (pcfUnmarshal == pcfThisThread)
  483. {
  484. goto AptTestThreadExit;
  485. }
  486. // Make sure the one we got for this not a proxy.
  487. if (pcfThisThread->QueryInterface(IID_IProxyManager, (void **) &punk)
  488. != NOERROR)
  489. {
  490. psatpb->fResult = VerifyTestObject(pcfThisThread, clsidAptThreadedDll);
  491. }
  492. AptTestThreadExit:
  493. if (pcfUnmarshal != NULL)
  494. {
  495. pcfUnmarshal->Release();
  496. }
  497. if (pcfThisThread != NULL)
  498. {
  499. pcfThisThread->Release();
  500. }
  501. if (punk != NULL)
  502. {
  503. punk->Release();
  504. }
  505. // Exit the thread.
  506. SetEvent(psatpb->hEvent);
  507. return 0;
  508. }
  509. //+-------------------------------------------------------------------
  510. //
  511. // Function: BothTestThread, private
  512. //
  513. // Synopsis: Verify a DLL that supports both models is marshaled
  514. // correctly.
  515. //
  516. // Arguments: [pvCtrlData] - control data for the thread
  517. //
  518. // Returns: 0 - interesting values returned through pvCtrlData.
  519. //
  520. // History: 02-Nov-94 Ricksa Created
  521. //
  522. //--------------------------------------------------------------------
  523. DWORD BothTestThread(void *pvCtrlData)
  524. {
  525. // Data shared with main thread
  526. SBTParamBlock *psbtpb = (SBTParamBlock *) pvCtrlData;
  527. psbtpb->fResult = FALSE;
  528. // Class factory object unmarshaled from other thread.
  529. IClassFactory *pcfUnmarshal = NULL;
  530. // IUnknown ptrs used for multiple purposes
  531. IUnknown *punk = NULL;
  532. IUnknown *pIPersist = NULL;
  533. // Initialize thread
  534. if (CoInitialize(NULL) != NOERROR)
  535. {
  536. goto BothTestThreadExit;
  537. }
  538. // Get the class object from the marshaled stream
  539. if (CoGetInterfaceAndReleaseStream(psbtpb->pstrm, IID_IClassFactory,
  540. (void **) &pcfUnmarshal) != NOERROR)
  541. {
  542. goto BothTestThreadExit;
  543. }
  544. // Caller doesn't have to release this now.
  545. psbtpb->pstrm = NULL;
  546. // Make sure main thread's ptr is not the same as this thread's ptr.
  547. if (pcfUnmarshal != psbtpb->pcf)
  548. {
  549. goto BothTestThreadExit;
  550. }
  551. // Confirm that class object is a proxy
  552. if (pcfUnmarshal->QueryInterface(IID_IProxyManager, (void **) &punk)
  553. != NOERROR)
  554. {
  555. // Make sure object created by the class works as expected
  556. psbtpb->fResult = VerifyTestObject(pcfUnmarshal, clsidBothThreadedDll);
  557. }
  558. BothTestThreadExit:
  559. if (pcfUnmarshal != NULL)
  560. {
  561. pcfUnmarshal->Release();
  562. }
  563. if (punk != NULL)
  564. {
  565. punk->Release();
  566. }
  567. // Exit the thread.
  568. SetEvent(psbtpb->hEvent);
  569. return 0;
  570. }
  571. //+-------------------------------------------------------------------
  572. //
  573. // Function: SetUpRegistry, private
  574. //
  575. // Synopsis: Make sure registry is set up appropriately for the test
  576. //
  577. // Returns: TRUE - Registry set up successfully
  578. // FALSE - Registry could not be set up
  579. //
  580. // History: 31-Oct-94 Ricksa Created
  581. //
  582. //--------------------------------------------------------------------
  583. BOOL SetUpRegistry(void)
  584. {
  585. BOOL fRet = FALSE;
  586. // Update the registry with the correct information
  587. fRet = SetRegForDll(clsidSingleThreadedDll, pszSingleThreadedDll, NULL)
  588. && SetRegForDll(clsidAptThreadedDll, pszAptThreadedDll,
  589. pszApartmentModel)
  590. && SetRegForDll(clsidBothThreadedDll, pszBothThreadedDll, pszBoth);
  591. // Give Registry a chance to get updated
  592. Sleep(1000);
  593. return fRet;
  594. }
  595. //+-------------------------------------------------------------------
  596. //
  597. // Function: TestSingleThread, private
  598. //
  599. // Synopsis: Driver to verify testing of single threaded behavior
  600. //
  601. // Returns: TRUE - Test Passed
  602. // FALSE - Test Failed
  603. //
  604. // History: 31-Oct-94 Ricksa Created
  605. //
  606. //--------------------------------------------------------------------
  607. BOOL TestSingleThread(void)
  608. {
  609. // Result of test - default to FALSE.
  610. BOOL fResult = FALSE;
  611. // Create an event for test to wait for completion of test.
  612. SSTParamBlock sstp;
  613. sstp.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  614. sstp.pcf = NULL;
  615. if (sstp.hEvent == NULL)
  616. {
  617. goto TestSingleThreadExit;
  618. }
  619. // Create a class object and put in a parameter block
  620. if (CoGetClassObject(clsidSingleThreadedDll, CLSCTX_INPROC, NULL,
  621. IID_IClassFactory, (void **) &sstp.pcf) != NOERROR)
  622. {
  623. goto TestSingleThreadExit;
  624. }
  625. // Create the thread.
  626. if (CreateTestThread(SingleThreadTestThread, &sstp))
  627. {
  628. // Wait for test to complete - ignore deadlock for now at least. The
  629. // test thread is simple enough that it should not be a problem.
  630. ThreadWaitForEvent(sstp.hEvent);
  631. // Get result from thread
  632. fResult = sstp.fResult;
  633. }
  634. TestSingleThreadExit:
  635. if (sstp.hEvent != NULL)
  636. {
  637. CloseHandle(sstp.hEvent);
  638. }
  639. if (sstp.pcf != NULL)
  640. {
  641. sstp.pcf->Release();
  642. }
  643. // Let user know this didn't work
  644. if (!fResult)
  645. {
  646. MessageBox(NULL, TEXT("Single Threaded Test Failed"),
  647. TEXT("FATAL ERROR"), MB_OK);
  648. }
  649. // Return results of test
  650. return fResult;
  651. }
  652. //+-------------------------------------------------------------------
  653. //
  654. // Function: TestAptThread, private
  655. //
  656. // Synopsis: Test an apartment model object. The most important
  657. // aspect of this is that it tests the helper APIs.
  658. //
  659. // Returns: TRUE - Test Passed
  660. // FALSE - Test Failed
  661. //
  662. // History: 31-Oct-94 Ricksa Created
  663. //
  664. //--------------------------------------------------------------------
  665. BOOL TestAptThread(void)
  666. {
  667. // Return result for test
  668. BOOL fResult = FALSE;
  669. // Block for passing parameters to the test thread
  670. SATParamBlock satpb;
  671. satpb.pstrm = NULL;
  672. satpb.pcf = NULL;
  673. // Create an event for test to wait for completion of test.
  674. satpb.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  675. if (satpb.hEvent == NULL)
  676. {
  677. goto TestAptThreadExit;
  678. }
  679. satpb.pcf = NULL;
  680. // Create a class object and put in parameter block
  681. if (CoGetClassObject(clsidAptThreadedDll, CLSCTX_INPROC, NULL,
  682. IID_IClassFactory, (void **) &satpb.pcf) != NOERROR)
  683. {
  684. goto TestAptThreadExit;
  685. }
  686. // Create stream using helper API
  687. if (CoMarshalInterThreadInterfaceInStream(IID_IClassFactory,
  688. satpb.pcf, &satpb.pstrm) != NOERROR)
  689. {
  690. goto TestAptThreadExit;
  691. }
  692. // Create thread to do apartment model test
  693. if (CreateTestThread(AptTestThread, &satpb))
  694. {
  695. // Wait for test to complete - ignore deadlock for now at least. The
  696. // test thread is simple enough that it should not be a problem.
  697. ThreadWaitForEvent(satpb.hEvent);
  698. // Get result from thread
  699. fResult = satpb.fResult;
  700. }
  701. TestAptThreadExit:
  702. // Clean up any resources
  703. if (satpb.hEvent != NULL)
  704. {
  705. CloseHandle(satpb.hEvent);
  706. }
  707. if (satpb.pcf != NULL)
  708. {
  709. satpb.pcf->Release();
  710. }
  711. if (satpb.pstrm != NULL)
  712. {
  713. satpb.pstrm->Release();
  714. }
  715. // Let user know this didn't work
  716. if (!fResult)
  717. {
  718. MessageBox(NULL, TEXT("Apartment Threaded Test Failed"),
  719. TEXT("FATAL ERROR"), MB_OK);
  720. }
  721. // Return results of test
  722. return fResult;
  723. }
  724. //+-------------------------------------------------------------------
  725. //
  726. // Function: TestBothDll, private
  727. //
  728. // Synopsis: Test using DLL that purports to support both free
  729. // threading and apt model. The most important aspect
  730. // of this test is that it tests the marshal context.
  731. //
  732. // Returns: TRUE - Test Passed
  733. // FALSE - Test Failed
  734. //
  735. // History: 31-Oct-94 Ricksa Created
  736. //
  737. //--------------------------------------------------------------------
  738. BOOL TestBothDll(void)
  739. {
  740. // Return result for test
  741. BOOL fResult = FALSE;
  742. // Block for passing parameters to the test thread
  743. SBTParamBlock sbtpb;
  744. sbtpb.pstrm = NULL;
  745. sbtpb.pcf = NULL;
  746. IClassFactory *pcfFromMarshal = NULL;
  747. IStream *pstmForMarshal = NULL;
  748. HGLOBAL hglobForStream = NULL;
  749. // Create an event for test to wait for completion of test.
  750. sbtpb.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  751. if (sbtpb.hEvent == NULL)
  752. {
  753. goto TestBothDllExit;
  754. }
  755. // Create a class object and put in parameter block
  756. if (CoGetClassObject(clsidBothThreadedDll, CLSCTX_INPROC, NULL,
  757. IID_IClassFactory, (void **) &sbtpb.pcf) != NOERROR)
  758. {
  759. goto TestBothDllExit;
  760. }
  761. // Marshal this for the local context and unmarshal it and
  762. // see if we get the same result.
  763. if ((hglobForStream = GlobalAlloc(GMEM_MOVEABLE, 100)) == NULL)
  764. {
  765. GetLastError();
  766. goto TestBothDllExit;
  767. }
  768. if (CreateStreamOnHGlobal(hglobForStream, TRUE, &pstmForMarshal) != NOERROR)
  769. {
  770. goto TestBothDllExit;
  771. }
  772. if (CoMarshalInterface(pstmForMarshal, IID_IClassFactory, sbtpb.pcf,
  773. MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL) != NOERROR)
  774. {
  775. goto TestBothDllExit;
  776. }
  777. // Reset the stream to the begining
  778. {
  779. LARGE_INTEGER li;
  780. LISet32(li, 0);
  781. pstmForMarshal->Seek(li, STREAM_SEEK_SET, NULL);
  782. }
  783. if (CoUnmarshalInterface(pstmForMarshal, IID_IClassFactory,
  784. (void **) &pcfFromMarshal) != NOERROR)
  785. {
  786. goto TestBothDllExit;
  787. }
  788. if (sbtpb.pcf != pcfFromMarshal)
  789. {
  790. goto TestBothDllExit;
  791. }
  792. // Create stream using helper API
  793. if (CoMarshalInterThreadInterfaceInStream(IID_IClassFactory,
  794. sbtpb.pcf, &sbtpb.pstrm) != NOERROR)
  795. {
  796. goto TestBothDllExit;
  797. }
  798. // Create thread to do apartment model test
  799. if (CreateTestThread(BothTestThread, &sbtpb))
  800. {
  801. // Wait for test to complete - ignore deadlock for now at least. The
  802. // test thread is simple enough that it should not be a problem.
  803. WaitForSingleObject(sbtpb.hEvent, INFINITE);
  804. // Get result from thread
  805. fResult = sbtpb.fResult;
  806. }
  807. TestBothDllExit:
  808. // Clean up any resources
  809. if (sbtpb.hEvent != NULL)
  810. {
  811. CloseHandle(sbtpb.hEvent);
  812. }
  813. if (sbtpb.pcf != NULL)
  814. {
  815. sbtpb.pcf->Release();
  816. }
  817. if (sbtpb.pstrm != NULL)
  818. {
  819. sbtpb.pstrm->Release();
  820. }
  821. if (pcfFromMarshal != NULL)
  822. {
  823. pcfFromMarshal->Release();
  824. }
  825. if (pstmForMarshal != NULL)
  826. {
  827. pstmForMarshal->Release();
  828. }
  829. else if (hglobForStream != NULL)
  830. {
  831. GlobalFree(hglobForStream);
  832. }
  833. // Let user know this didn't work
  834. if (!fResult)
  835. {
  836. MessageBox(NULL, TEXT("Both Threaded Test Failed"),
  837. TEXT("FATAL ERROR"), MB_OK);
  838. }
  839. // Return results of test
  840. return fResult;
  841. }
  842. //+-------------------------------------------------------------------
  843. //
  844. // Function: TestFreeAllLibraries, private
  845. //
  846. // Synopsis: Test free from non-main thread. This is really to
  847. // just make sure that nothing really bad happens when
  848. // we do this.
  849. //
  850. // Returns: TRUE - Test Passed
  851. // FALSE - Test Failed
  852. //
  853. // History: 31-Oct-94 Ricksa Created
  854. //
  855. //--------------------------------------------------------------------
  856. BOOL TestFreeAllLibraries(void)
  857. {
  858. CoFreeUnusedLibraries();
  859. return TRUE;
  860. }
  861. //+-------------------------------------------------------------------
  862. //
  863. // Function: ThreadUnitTest, public
  864. //
  865. // Synopsis: Test various messaging enhancements to OLE
  866. //
  867. // Returns: TRUE - Test Passed
  868. // FALSE - Test Failed
  869. //
  870. // History: 31-Oct-94 Ricksa Created
  871. //
  872. //--------------------------------------------------------------------
  873. HRESULT ThreadUnitTest(void)
  874. {
  875. HRESULT hr = E_FAIL;
  876. // Make sure OLE is initialized
  877. HRESULT hrInit = OleInitialize(NULL);
  878. if (FAILED(hrInit))
  879. {
  880. MessageBox(NULL, TEXT("ThreadUnitTest: OleInitialize FAILED"),
  881. TEXT("FATAL ERROR"), MB_OK);
  882. goto ThreadUnitTestExit;
  883. }
  884. // Set up the registry
  885. if (!SetUpRegistry())
  886. {
  887. goto ThreadUnitTestExit;
  888. }
  889. // Test Single Threaded DLL
  890. if (!TestSingleThread())
  891. {
  892. goto ThreadUnitTestExit;
  893. }
  894. // Test an aparment model DLL
  895. if (!TestAptThread())
  896. {
  897. goto ThreadUnitTestExit;
  898. }
  899. // Test a both DLL
  900. if (!TestBothDll())
  901. {
  902. goto ThreadUnitTestExit;
  903. }
  904. // Test CoFreeAllLibraries
  905. if (TestFreeAllLibraries())
  906. {
  907. hr = NOERROR;
  908. }
  909. ThreadUnitTestExit:
  910. OleUninitialize();
  911. return hr;
  912. }