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.

1154 lines
29 KiB

  1. //+---------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1993 - 1994.
  5. //
  6. // File: olebind.cxx
  7. //
  8. // Contents: Test OLE COM
  9. //
  10. // Classes:
  11. //
  12. // Functions: TestSetMoniker
  13. // ` DoTest
  14. // ConvertPath
  15. // CreateFile
  16. // CleanUpFiles
  17. // InitFiles
  18. // main
  19. //
  20. // History: 31-Dec-93 ErikGav Chicago port
  21. // 15-Nov-94 BruceMa Added this header
  22. // 15-Nov-94 BruceMa Make long file name test work on
  23. // Chicago
  24. // 11-Jan-95 BruceMa Chicago now use the NT alorithm for
  25. // short file names
  26. // 17-Jan-95 BruceMa Modify registry so olebind works on
  27. // Cairo when running multi-threaded
  28. //
  29. //----------------------------------------------------------------------
  30. #include <windows.h>
  31. #include "widewrap.h"
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <sys/types.h>
  35. #include <sys/stat.h>
  36. #include <errno.h>
  37. #include <io.h>
  38. #include <ole2.h>
  39. #include <com.hxx>
  40. #include "olebind.hxx"
  41. #include "tmoniker.h"
  42. #include <tchar.h>
  43. const char *szOleBindError = "OLEBIND - Fatal Error";
  44. char wszErrBuf[512];
  45. #pragma hdrstop
  46. BOOL SetRegistryThreadingModel(WCHAR *peszFile, WCHAR *pwszThreadingModel);
  47. BOOL ResetRegistryThreadingModel(WCHAR *pwszFile);
  48. #define FILE_SHARE_DELETE 0x00000004
  49. #define INPROC_PATH1 L"p1.ut1"
  50. #define INPROC_PATH2 L"p2.ut1"
  51. #define LOCAL_SERVER_PATH1 L"p1.ut2"
  52. #define LOCAL_SERVER_PATH2 L"p2.ut2"
  53. #define LOCAL_SERVER_PATH4 L"p2.ut4"
  54. WCHAR InprocPath1[MAX_PATH];
  55. WCHAR InprocPath2[MAX_PATH];
  56. WCHAR LocalServerPath1[MAX_PATH];
  57. WCHAR LocalServerPath2[MAX_PATH];
  58. WCHAR LocalServerPath4[MAX_PATH];
  59. #define LONG_SHORT_DIR L"\\LongDire"
  60. #define LONG_DIR L"\\LongDirectory"
  61. #define LONG_SHORT_NAME L"\\Short.Fil"
  62. #define LONG_LONG_NAME L"\\LongFileName.File"
  63. #define LONG_LONG_SHORT_EQUIV L"\\LongFi~1.Fil"
  64. WCHAR LongDir[MAX_PATH];
  65. WCHAR LongDirShort[MAX_PATH];
  66. WCHAR LongDirLong[MAX_PATH];
  67. WCHAR LongDirLongSe[MAX_PATH];
  68. // DON"T MODIFY THIS
  69. const DWORD dwRESERVED = 0l;
  70. // string version of process id
  71. WCHAR wszPid[10];
  72. int TestSetMoniker(IUnknown *punk)
  73. {
  74. HRESULT hr;
  75. XOleObject poleobject;
  76. XMoniker pmk;
  77. XMalloc pIMalloc;
  78. XBindCtx pbc;
  79. hr = punk->QueryInterface(IID_IOleObject, (void **) &poleobject);
  80. // Create an item moniker to the object
  81. hr = CreateItemMoniker(L"\\", L"1", &pmk);
  82. TEST_FAILED_HR(FAILED(hr), "TestSetMoniker:CreateItemMoniker failed")
  83. // Set the moniker
  84. hr = poleobject->SetMoniker(OLEWHICHMK_CONTAINER, pmk);
  85. TEST_FAILED_HR(FAILED(hr), "TestSetMoniker:SetMoniker failed")
  86. pmk.Set(NULL);
  87. // Get the moniker back
  88. hr = poleobject->GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
  89. OLEWHICHMK_CONTAINER, &pmk);
  90. TEST_FAILED_HR(FAILED(hr), "TestSetMoniker:GetMoniker failed")
  91. // Get & Verify name is as expected
  92. WCHAR *pwszName;
  93. hr = CreateBindCtx(0, &pbc);
  94. TEST_FAILED_HR(FAILED(hr),
  95. "CreateBindCtx TestSetMoniker:GetDisplayName failed!")
  96. hr = pmk->GetDisplayName(pbc, NULL, &pwszName);
  97. TEST_FAILED_HR(FAILED(hr), "TestSetMoniker:GetDisplayName failed")
  98. TEST_FAILED((wcscmp(pwszName, L"\\1") != 0),
  99. "TestSetMoniker: Returned name mismatch!\n")
  100. // Test OleIsRunning
  101. hr = OleIsRunning(poleobject);
  102. TEST_FAILED_HR(FAILED(hr), "OleIsRunning call failed")
  103. // Free resources
  104. hr = CoGetMalloc(MEMCTX_TASK, &pIMalloc);
  105. TEST_FAILED_HR(FAILED(hr), "CoGetMalloc failed")
  106. pIMalloc->Free(pwszName);
  107. return 0;
  108. }
  109. static GUID CLSID_Invalid =
  110. {0xfffffffe,0xffff,0xffff,{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}};
  111. // prototypes for private entry points. These are here to support VB94.
  112. STDAPI CoGetState(IUnknown **ppUnkState);
  113. STDAPI CoSetState(IUnknown *pUnkState);
  114. int DoTest(
  115. GUID guidToTest,
  116. LPWSTR pszPath1,
  117. LPWSTR pszPath2)
  118. {
  119. XMoniker pmnk; // ptr to moniker
  120. XUnknown pUnk;
  121. XUnknown punk;
  122. XUnknown pUnkTheSame;
  123. XOleItemContainer poleitmcon;
  124. XDispatch pdispatch;
  125. XBindCtx pbc1;
  126. XBindCtx pbc2;
  127. XUnknown pUnkState1;
  128. XUnknown pUnkState2;
  129. XUnknown pUnkState3;
  130. XUnknown pUnkState4;
  131. XUnknown pUnkState5;
  132. HRESULT hr;
  133. DWORD grfOpt = 0;
  134. // Test the private CoSetState/CoGetState APIs. We just need an
  135. // IUnknown so we will use a BindCtx for this.
  136. // test Set/Get
  137. hr = CreateBindCtx(0, &pbc1);
  138. TEST_FAILED_HR(FAILED(hr), "Create BindCtx 1 failed");
  139. hr = pbc1->QueryInterface(IID_IUnknown, (void **)&pUnkState1);
  140. TEST_FAILED_HR(FAILED(hr), "QI for IUnknown 1 failed.");
  141. hr = CoSetState(pUnkState1);
  142. TEST_FAILED_HR(hr != S_OK, "CoSetState failed.");
  143. hr = CoGetState(&pUnkState2);
  144. TEST_FAILED_HR(hr != S_OK, "CoGetState failed.");
  145. if ((IUnknown *)pUnkState2 != (IUnknown *)pUnkState1)
  146. TEST_FAILED(TRUE, "GetState returned wrong value.\n");
  147. // test replacement
  148. hr = CreateBindCtx(0, &pbc2);
  149. TEST_FAILED_HR(FAILED(hr), "Create BindCtx 2 failed");
  150. hr = pbc2->QueryInterface(IID_IUnknown, (void **)&pUnkState3);
  151. TEST_FAILED_HR(FAILED(hr), "QI for IUnknown 2 failed.");
  152. hr = CoSetState(pUnkState3);
  153. TEST_FAILED_HR(hr != S_OK, "CoSetState failed.");
  154. hr = CoGetState(&pUnkState4);
  155. TEST_FAILED_HR(hr != S_OK, "CoGetState failed.");
  156. if ((IUnknown *)pUnkState4 != (IUnknown *)pUnkState3)
  157. TEST_FAILED(TRUE, "GetState returned wrong value.");
  158. // test Set/Get NULL
  159. hr = CoSetState(NULL);
  160. TEST_FAILED_HR(hr != S_OK, "CoSetState NULL failed.");
  161. hr = CoGetState(&pUnkState5);
  162. TEST_FAILED_HR(hr != S_FALSE, "CoGetState NULL failed.");
  163. if ((IUnknown *)pUnkState5 != NULL)
  164. TEST_FAILED(TRUE, "GetState NULL returned wrong value.");
  165. // Test for a bogus class
  166. hr = CoGetClassObject(CLSID_Invalid, CLSCTX_SERVER, NULL,
  167. IID_IClassFactory, (void **) &pUnk);
  168. TEST_FAILED_HR(SUCCEEDED(hr),
  169. "CoGetClassObject succeed on invalid class!");
  170. // Bind to something that does not exist either in the registry
  171. // or anywhere else.
  172. hr = CreateFileMoniker(L"C:\\KKK.KKK", &pmnk);
  173. hr = BindMoniker(pmnk, grfOpt, IID_IUnknown, (void **)&pUnk);
  174. pmnk.Set(NULL);
  175. TEST_FAILED_HR(SUCCEEDED(hr),
  176. "Succeeded binding a moniker to a file that doesn't exist!");
  177. /*
  178. * Create a file moniker to start with
  179. */
  180. hr = CreateFileMoniker(pszPath1, &pmnk);
  181. TEST_FAILED_HR(FAILED(hr), "CreateFileMoniker Failed");
  182. hr = BindMoniker(pmnk, grfOpt, IID_IUnknown, (void **)&pUnk);
  183. TEST_FAILED_HR(FAILED(hr),
  184. "BindMoniker to file Failed")
  185. // Confirm bind to same object produces same object pointer
  186. hr = BindMoniker(pmnk, grfOpt, IID_IUnknown, (void **)&pUnkTheSame);
  187. TEST_FAILED_HR(FAILED(hr),
  188. "BindMoniker to file Failed")
  189. #ifdef NOT_YET
  190. TEST_FAILED((pUnkTheSame != pUnk), "Object pointers not ==\n")
  191. #endif // NOT_YET
  192. pUnkTheSame.Set(NULL);
  193. pmnk.Set(NULL);
  194. /*
  195. * OK - we've bound to the IUnknown interface, lets
  196. * QueryInterface to something more interesting (for test reasons)
  197. */
  198. hr = pUnk->QueryInterface(IID_IOleItemContainer,
  199. (LPVOID FAR*) &poleitmcon);
  200. TEST_FAILED_HR(FAILED(hr), "Query Interface Failed")
  201. /*
  202. * Make sure we get an error when QI'ing for something the server
  203. * does not support.
  204. */
  205. hr = pUnk->QueryInterface(IID_IDispatch,
  206. (LPVOID FAR*) &pdispatch);
  207. TEST_FAILED_HR(SUCCEEDED(hr),
  208. "QueryInterface to unsupported interface")
  209. pdispatch.Set(NULL);
  210. pUnk.Set(NULL);
  211. /*
  212. * Call get the class ID using IPersistFile
  213. */
  214. hr = poleitmcon->GetObject(L"1", 1, NULL, IID_IUnknown,
  215. (void **) &punk);
  216. TEST_FAILED_HR(FAILED(hr), "GetObject Failed")
  217. TEST_FAILED((punk == NULL),
  218. "GetObject returned a NULL for punk\n")
  219. poleitmcon.Set(NULL);
  220. if (TestSetMoniker(punk))
  221. {
  222. return 1;
  223. }
  224. hr = punk->QueryInterface(IID_IOleLink, (LPVOID FAR*) &poleitmcon);
  225. TEST_FAILED_HR(SUCCEEDED(hr),
  226. "Query Interface to invalid interface succeeded")
  227. punk.Set(NULL);
  228. // Do moniker tests:
  229. if (TestBindCtx())
  230. {
  231. return TRUE;
  232. }
  233. if (TestROT(guidToTest))
  234. {
  235. return TRUE;
  236. }
  237. return TestMoniker(pszPath1, pszPath2);
  238. }
  239. // TRUE on failure
  240. BOOL TestPrematureDeath()
  241. {
  242. XMoniker pmnk;
  243. XUnknown pUnk;
  244. HRESULT hr;
  245. TCHAR tszFileName[MAX_PATH+1];
  246. HANDLE hTouchFile;
  247. SYSTEMTIME st1, st2;
  248. FILETIME ft1, ft2;
  249. LONG l;
  250. DWORD dw;
  251. ZeroMemory(&st1, sizeof(st1));
  252. ZeroMemory(&st2, sizeof(st2));
  253. hr = CreateFileMoniker(LocalServerPath4, &pmnk);
  254. TEST_FAILED_HR(FAILED(hr), "CreateFileMoniker Failed")
  255. GetSystemDirectory(tszFileName, MAX_PATH+1);
  256. _tcscat(tszFileName, TEXT("\\failtst.tst"));
  257. hTouchFile = CreateFileT(tszFileName,
  258. GENERIC_READ|GENERIC_WRITE,
  259. FILE_SHARE_READ|FILE_SHARE_WRITE,
  260. NULL,
  261. OPEN_ALWAYS,
  262. FILE_ATTRIBUTE_NORMAL,
  263. NULL);
  264. if(hTouchFile == INVALID_HANDLE_VALUE)
  265. {
  266. wsprintfA(&wszErrBuf[0], "Couldn't open touch file - err = %x.\n", GetLastError());
  267. MessageBoxA(NULL, &wszErrBuf[0], szOleBindError, MB_OK);
  268. return TRUE;
  269. }
  270. GetSystemTime(&st1);
  271. WriteFile(hTouchFile, &st1, sizeof(st1), &dw, NULL);
  272. l = GetTickCount();
  273. // This takes awhile, so tell the user
  274. printf("SCM dead server test (60 sec) started\n");
  275. hr = BindMoniker(pmnk, 0, IID_IUnknown, (void **)&pUnk);
  276. TEST_FAILED_HR((hr != CO_E_SERVER_EXEC_FAILURE),
  277. "Unexpected hr from BindMoniker in premature death test")
  278. // Tell the BVT guys
  279. printf("SCM dead server test succeeded\n");
  280. //
  281. // The above bind should have caused fail.exe to execute and write a new
  282. // time to the file as proof of execution.
  283. //
  284. SetFilePointer(hTouchFile, 0, NULL, FILE_BEGIN);
  285. ReadFile(hTouchFile, &st2, sizeof(st2), &dw, NULL);
  286. CloseHandle(hTouchFile);
  287. DeleteFileT(tszFileName);
  288. SystemTimeToFileTime(&st1, &ft1);
  289. SystemTimeToFileTime(&st2, &ft2);
  290. if (0 == CompareFileTime(&ft1, &ft2))
  291. {
  292. wsprintfA(&wszErrBuf[0], "Test not configured properly: PROGID50(fail.exe) did not run.");
  293. MessageBoxA(NULL, &wszErrBuf[0], szOleBindError, MB_OK);
  294. return TRUE;
  295. }
  296. if (GetTickCount() - l > 2*60*1000)
  297. {
  298. wsprintfA(&wszErrBuf[0], "Premature death test failed: too long to detect death.");
  299. MessageBoxA(NULL, &wszErrBuf[0], szOleBindError, MB_OK);
  300. return TRUE;
  301. }
  302. return FALSE;
  303. }
  304. char * ConvertPath(LPWSTR pwsz)
  305. {
  306. static char szPath[MAX_PATH];
  307. wcstombs(szPath, pwsz, wcslen(pwsz) + 1);
  308. return szPath;
  309. }
  310. int CreateFile(LPWSTR pwszPath)
  311. {
  312. // Try to create the file
  313. int fh = _creat(ConvertPath(pwszPath), _S_IWRITE|S_IREAD);
  314. // Did file create fail?
  315. if (fh != -1)
  316. {
  317. // Write some data to file -- makes sure docfile won't delete
  318. // the file.
  319. _write(fh, "This is a test file\n", sizeof("This is a test file\n"));
  320. // No -- then set to success and close the newly created file
  321. _close(fh);
  322. fh = 0;
  323. }
  324. return fh;
  325. }
  326. void CleanUpFiles(void)
  327. {
  328. // Delete all the test files.
  329. remove(ConvertPath(InprocPath1));
  330. remove(ConvertPath(InprocPath2));
  331. remove(ConvertPath(LocalServerPath1));
  332. remove(ConvertPath(LocalServerPath2));
  333. remove(ConvertPath(LocalServerPath4));
  334. remove(ConvertPath(LongDirShort));
  335. remove(ConvertPath(LongDirLong));
  336. #if !defined(_CHICAGO_)
  337. RemoveDirectory(LongDir);
  338. #else
  339. RemoveDirectory(ConvertPath(LongDir));
  340. #endif
  341. }
  342. int InitFiles(void)
  343. {
  344. BOOL fRet;
  345. TCHAR szCurDir[MAX_PATH];
  346. TCHAR szTmpLongDir[MAX_PATH];
  347. WCHAR wcCurDir[MAX_PATH];
  348. WCHAR wcLong[MAX_PATH], *pwcEnd;
  349. DWORD cCurDir = GetCurrentDirectory(MAX_PATH, szCurDir);
  350. #ifdef UNICODE
  351. wcscpy(wcCurDir, szCurDir);
  352. #else
  353. mbstowcs(wcCurDir, szCurDir, MAX_PATH);
  354. #endif
  355. // Is the current directory the root of a drive?
  356. if (wcCurDir[cCurDir - 1] == '\\')
  357. {
  358. // We bring the string on char back to take into account
  359. // the fact the string we will concatenate begins with a slash.
  360. wcCurDir[cCurDir - 1] = 0;
  361. }
  362. // get the pid. we use the pid to identify the files for a particular
  363. // run of the test (so we may run multiple instances simultaneously
  364. // without interference).
  365. DWORD dwPid = GetCurrentProcessId();
  366. char szPid[9];
  367. _itoa(dwPid, szPid, 16);
  368. wszPid[0] = L'\\';
  369. #if defined(_CHICAGO_)
  370. szPid[4] = '\0'; // This is an all platform bug, but zap for Chicago.
  371. #endif
  372. mbstowcs(&wszPid[1], szPid, strlen(szPid)+1);
  373. wcscpy(InprocPath1, wcCurDir);
  374. wcscat(InprocPath1, wszPid);
  375. wcscat(InprocPath1, INPROC_PATH1);
  376. wcscpy(InprocPath2, wcCurDir);
  377. wcscat(InprocPath2, wszPid);
  378. wcscat(InprocPath2, INPROC_PATH2);
  379. wcscpy(LocalServerPath1, wcCurDir);
  380. wcscat(LocalServerPath1, wszPid);
  381. wcscat(LocalServerPath1, LOCAL_SERVER_PATH1);
  382. wcscpy(LocalServerPath2, wcCurDir);
  383. wcscat(LocalServerPath2, wszPid);
  384. wcscat(LocalServerPath2, LOCAL_SERVER_PATH2);
  385. wcscpy(LocalServerPath4, wcCurDir);
  386. wcscat(LocalServerPath4, wszPid);
  387. wcscat(LocalServerPath4, LOCAL_SERVER_PATH4);
  388. wcscpy(wcLong, wcCurDir);
  389. wcscat(wcLong, LONG_DIR);
  390. wcscpy(LongDir, wcLong);
  391. pwcEnd = wcLong+wcslen(wcLong);
  392. wcscpy(pwcEnd, LONG_SHORT_NAME);
  393. wcscpy(LongDirShort, wcLong);
  394. wcscpy(pwcEnd, LONG_LONG_NAME);
  395. wcscpy(LongDirLong, wcLong);
  396. #ifdef _CHICAGO_
  397. wcscpy(LongDirLongSe, wcCurDir);
  398. wcscat(LongDirLongSe, LONG_DIR);
  399. #else
  400. wcscpy(pwcEnd, LONG_LONG_SHORT_EQUIV);
  401. wcscpy(LongDirLongSe, wcLong);
  402. #endif // _CHICAGO_
  403. // Delete any files that exist
  404. CleanUpFiles();
  405. // Create a file for each test file needed.
  406. TEST_FAILED(CreateFile(InprocPath1),
  407. "Couldn't create first test file!\n");
  408. TEST_FAILED(CreateFile(InprocPath2),
  409. "Couldn't create second test file!\n");
  410. TEST_FAILED(CreateFile(LocalServerPath1),
  411. "Couldn't create third test file!\n");
  412. TEST_FAILED(CreateFile(LocalServerPath2),
  413. "Couldn't create fourth test file!\n");
  414. TEST_FAILED(CreateFile(LocalServerPath4),
  415. "Couldn't create fifth test file!\n");
  416. #if !defined(_CHICAGO_)
  417. fRet = CreateDirectory(LongDir, NULL);
  418. #else
  419. fRet = CreateDirectory(ConvertPath(LongDir), NULL);
  420. #endif
  421. TEST_FAILED(!fRet, "Couldn't create long directory\n");
  422. TEST_FAILED(CreateFile(LongDirShort),
  423. "Couldn't create short file in long directory\n");
  424. TEST_FAILED(CreateFile(LongDirLong),
  425. "Couldn't create long file in long directory\n");
  426. #ifdef UNICODE
  427. TEST_FAILED(!GetShortPathName(LongDirLong,
  428. LongDirLongSe,
  429. sizeof(LongDirLongSe)),
  430. "Couldn't GetShortPathname of long directory\n");
  431. #else
  432. TEST_FAILED(!GetShortPathNameT(ConvertPath(LongDirLong),
  433. szCurDir,
  434. sizeof(szCurDir)),
  435. "Couldn't GetShortPathname of long directory\n");
  436. mbstowcs(LongDirLongSe, szCurDir, strlen(szCurDir)+1);
  437. #endif
  438. return 0;
  439. }
  440. DWORD CallCoInitUninit(void *)
  441. {
  442. // Initialize
  443. HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  444. if (SUCCEEDED(hr))
  445. {
  446. // Uninitialize
  447. CoUninitialize();
  448. }
  449. // Return value from function. Note that this is not really used because
  450. // there is a potential race
  451. return (DWORD) hr;
  452. }
  453. BOOL DoFreeThreadMultiInitTest(void)
  454. {
  455. //
  456. // Get an OLE object in another process
  457. //
  458. IClassFactory *pIClassFactory;
  459. HRESULT hr = CoGetClassObject(
  460. CLSID_AdvBnd,
  461. CLSCTX_LOCAL_SERVER,
  462. NULL,
  463. IID_IClassFactory,
  464. (void **) &pIClassFactory);
  465. TEST_FAILED_HR((hr != NOERROR),
  466. "DoFreeThreadMultiInitTest CoGetClassObject")
  467. //
  468. // Create another thread which does a matching call to
  469. // CoInitialize/Uninitialize and then exits.
  470. //
  471. // Create the thread
  472. DWORD dwIdUnused;
  473. HANDLE hInitThread = CreateThread(
  474. NULL, // Security - none
  475. 0, // Stack - use the same as the primary thread
  476. CallCoInitUninit, // Entry point for thread
  477. NULL, // Parameter to the thread - not used.
  478. 0, // Run this thread immediately (if not sooner).
  479. &dwIdUnused); // Id of thread - not used.
  480. // Did the create succeed?
  481. TEST_FAILED_LAST_ERROR((NULL == hInitThread),
  482. "DoFreeThreadMultiInitTest CreateThread")
  483. // Wait for the thread to do its work
  484. DWORD dwRes = WaitForSingleObject(hInitThread, INFINITE);
  485. // Did something terrible happen?
  486. TEST_FAILED_LAST_ERROR((WAIT_FAILED == dwRes),
  487. "DoFreeThreadMultiInitTest WaitForSingleObject")
  488. // Get the result from the thread
  489. BOOL fGetExitCode = GetExitCodeThread(hInitThread, (DWORD *) &hr);
  490. TEST_FAILED_LAST_ERROR(!fGetExitCode,
  491. "DoFreeThreadMultiInitTest GetExitCodeThread")
  492. // Free handles we no longer need
  493. CloseHandle(hInitThread);
  494. //
  495. // Validate the object we originally got is still alive and well.
  496. //
  497. IUnknown *punk;
  498. hr = pIClassFactory->CreateInstance(NULL, IID_IUnknown, (void **) &punk);
  499. TEST_FAILED_HR((hr != NOERROR),
  500. "DoFreeThreadMultiInitTest CoGetClassObject")
  501. // Free the objects we got in this routine.
  502. pIClassFactory->Release();
  503. punk->Release();
  504. return FALSE;
  505. }
  506. //+--------------------------------------------------------------
  507. // Function: Main
  508. //
  509. // Synopsis: Executes the BasicBnd test
  510. //
  511. // Effects: None
  512. //
  513. //
  514. // Returns: Exits with exit code 0 if success, 1 otherwise
  515. //
  516. // History: 05-Mar-92 Sarahj Created
  517. //
  518. //---------------------------------------------------------------
  519. int _cdecl main(int argc, char *argv[])
  520. {
  521. BOOL fFailed = FALSE;
  522. HRESULT hr;
  523. if (argc > 1)
  524. {
  525. if (!strcmp(argv[1], "M"))
  526. goto multithreading;
  527. }
  528. // BUGBUG: 1-18-95 To be implemented BruceMa
  529. // Correlate the platform we're running on and the platform
  530. // we built for
  531. // Write thread mode to initialization file.
  532. fFailed = !WriteProfileString(
  533. TEXT("TestSrv"),
  534. TEXT("ThreadMode"),
  535. TEXT("ApartmentThreaded"));
  536. if (fFailed)
  537. {
  538. wsprintfA(&wszErrBuf[0], "Failed writing TestSrv profile string.");
  539. MessageBoxA(NULL, &wszErrBuf[0], szOleBindError, MB_OK);
  540. goto exit_main;
  541. }
  542. fFailed = !WriteProfileString(
  543. TEXT("OleSrv"),
  544. TEXT("ThreadMode"),
  545. TEXT("ApartmentThreaded"));
  546. if (fFailed)
  547. {
  548. wsprintfA(&wszErrBuf[0], "Failed writing OleSrv profile string.");
  549. MessageBoxA(NULL, &wszErrBuf[0], szOleBindError, MB_OK);
  550. goto exit_main;
  551. }
  552. // Set up test files
  553. fFailed = InitFiles();
  554. if (fFailed)
  555. {
  556. goto exit_main;
  557. }
  558. // Test repeated calls to CoInitialize
  559. hr = CoInitialize(NULL);
  560. TEST_FAILED_HR(FAILED(hr), "CoInitialize Failed")
  561. // must be called before any other OLE API
  562. hr = OleInitialize(NULL);
  563. TEST_FAILED_HR(FAILED(hr), "OleInitialize Failed")
  564. // Call CoUnitialize and see how the rest of the program works!
  565. CoUninitialize();
  566. // Test stdmalloc
  567. if (fFailed = TestStdMalloc())
  568. {
  569. goto exit_init;
  570. }
  571. fFailed =
  572. DoTest(CLSID_BasicBnd, InprocPath1, InprocPath2);
  573. if (fFailed)
  574. {
  575. printf( "\nOLE failed in Single Threaded Apartment pass.\n" );
  576. goto exit_init;
  577. }
  578. printf("BasicBnd tests succeeded\n");
  579. fFailed =
  580. DoTest(CLSID_AdvBnd, LocalServerPath1, LocalServerPath1);
  581. if (fFailed)
  582. {
  583. printf( "\nOLE failed in Single Threaded Apartment pass.\n" );
  584. goto exit_init;
  585. }
  586. printf("AdvBnd tests succeeded\n");
  587. if (TestPrematureDeath())
  588. {
  589. printf("\nOLE failed testing server premature death.\n");
  590. goto exit_init;
  591. }
  592. OleUninitialize();
  593. CleanUpFiles();
  594. multithreading:
  595. #ifdef MULTI_THREADING
  596. // Run the whole thing all over again.
  597. // Write thread mode to initialization file.
  598. fFailed = !WriteProfileString(
  599. TEXT("TestSrv"),
  600. TEXT("ThreadMode"),
  601. TEXT("ApartmentThreaded"));
  602. if (fFailed)
  603. {
  604. wsprintfA(&wszErrBuf[0], "Failed writing TestSrv profile string.");
  605. MessageBoxA(NULL, &wszErrBuf[0], szOleBindError, MB_OK);
  606. goto exit_main;
  607. }
  608. fFailed = !WriteProfileString(
  609. TEXT("OleSrv"),
  610. TEXT("ThreadMode"),
  611. TEXT("MultiThreaded"));
  612. if (fFailed)
  613. {
  614. wsprintfA(&wszErrBuf[0], "Failed writing OleSrv profile string.");
  615. MessageBoxA(NULL, &wszErrBuf[0], szOleBindError, MB_OK);
  616. goto exit_main;
  617. }
  618. // Set up test files
  619. if (InitFiles())
  620. {
  621. fFailed = TRUE;
  622. goto exit_main;
  623. }
  624. // Mark the dll in the registry as "ThreadingdModel: Free"
  625. if (!SetRegistryThreadingModel(InprocPath1, L"Free"))
  626. {
  627. wsprintfA(&wszErrBuf[0], "Failed trying to set reg ThreadingModel.");
  628. MessageBoxA(NULL, &wszErrBuf[0], szOleBindError, MB_OK);
  629. goto exit_main;
  630. }
  631. // Test repeated calls to CoInitialize
  632. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  633. TEST_FAILED_HR(FAILED(hr), "CoInitializeEx Multi Threaded Failed")
  634. // must be called before any other OLE API
  635. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  636. TEST_FAILED_HR(FAILED(hr), "CoInitializeEx Multi Threaded Failed")
  637. // Call CoUnitialize and see how the rest of the program works!
  638. CoUninitialize();
  639. // Test stdmalloc
  640. if (fFailed = TestStdMalloc())
  641. {
  642. goto exit_init;
  643. }
  644. fFailed =
  645. DoTest(CLSID_BasicBnd, InprocPath1, InprocPath2);
  646. if (fFailed)
  647. {
  648. printf( "\nOLE failed in Multi Threaded Apartment pass.\n" );
  649. goto exit_init;
  650. }
  651. fFailed =
  652. DoTest(CLSID_AdvBnd, LocalServerPath1, LocalServerPath1);
  653. if (fFailed)
  654. {
  655. printf( "\nOLE failed in Multi Threaded Apartment pass.\n" );
  656. goto exit_init;
  657. }
  658. // Do CoInitialize/Uninitialize on second thread to make sure
  659. // that other threads initialize/uninitialize do not effect
  660. // the running of the test.
  661. if (fFailed = DoFreeThreadMultiInitTest())
  662. {
  663. printf( "\nOLE failed in Multi Threaded InitTest.\n" );
  664. goto exit_init;
  665. }
  666. #endif // MULTI_THREADING
  667. exit_init:
  668. CoUninitialize();
  669. // Remove the dll's threading model registration
  670. ResetRegistryThreadingModel(InprocPath1);
  671. exit_main:
  672. CleanUpFiles();
  673. if (!fFailed)
  674. {
  675. printf("\nOLE: PASSED\n");
  676. }
  677. else
  678. {
  679. printf("\nOLE: FAILED\n");
  680. }
  681. return fFailed;
  682. }
  683. //+--------------------------------------------------------
  684. //
  685. // Function: SetRegistryThreadingModel
  686. //
  687. // Algorithm: Set the threading model for the InprocServer32 associated
  688. // with the file pwszFile tp pwszThreadingModel
  689. //
  690. // History: 17-Jan-95 BruceMa Created
  691. //
  692. //---------------------------------------------------------
  693. BOOL SetRegistryThreadingModel(WCHAR *pwszFile, WCHAR *pwszThreadingModel)
  694. {
  695. DWORD dwRESERVED = 0;
  696. WCHAR wszExt[8];
  697. HKEY hKey;
  698. WCHAR wszProgId[32];
  699. DWORD dwValueType;
  700. WCHAR wszCLSID[64];
  701. HKEY hClsidKey;
  702. HKEY hInproc32Key;
  703. ULONG cbValue;
  704. // Strip the extension off the file name
  705. int k = wcslen(pwszFile) - 1;
  706. while (k > 0 && pwszFile[k] != L'.')
  707. {
  708. k--;
  709. }
  710. if (k >= 0 && pwszFile[k] == L'.')
  711. {
  712. for (int j = 0; pwszFile[k]; j++, k++)
  713. {
  714. wszExt[j] = pwszFile[k];
  715. }
  716. wszExt[j] = L'\0';
  717. }
  718. else
  719. {
  720. return FALSE;
  721. }
  722. // Open the key for the specified extension
  723. if (RegOpenKeyEx(HKEY_CLASSES_ROOT, wszExt, dwRESERVED,
  724. KEY_READ, &hKey) != ERROR_SUCCESS)
  725. {
  726. return FALSE;
  727. }
  728. // Read the ProgId for the extension
  729. cbValue = 32;
  730. if (RegQueryValueEx(hKey, NULL, NULL, &dwValueType,
  731. (LPBYTE) wszProgId, &cbValue) != ERROR_SUCCESS)
  732. {
  733. CloseHandle(hKey);
  734. return FALSE;
  735. }
  736. // Open the ProgIdKey
  737. CloseHandle(hKey);
  738. if (RegOpenKeyEx(HKEY_CLASSES_ROOT, wszProgId, dwRESERVED,
  739. KEY_READ, &hKey) != ERROR_SUCCESS)
  740. {
  741. return FALSE;
  742. }
  743. // Open the associated CLSID key
  744. if (RegOpenKeyEx(hKey, L"CLSID", dwRESERVED,
  745. KEY_READ, &hClsidKey) != ERROR_SUCCESS)
  746. {
  747. CloseHandle(hKey);
  748. return FALSE;
  749. }
  750. // Read the CLSID associated with the ProgId
  751. cbValue = 128;
  752. if (RegQueryValueEx(hClsidKey, NULL, NULL, &dwValueType,
  753. (LPBYTE) wszCLSID, &cbValue) != ERROR_SUCCESS)
  754. {
  755. CloseHandle(hClsidKey);
  756. CloseHandle(hKey);
  757. return FALSE;
  758. }
  759. // Open the HKEY_CLASSES_ROOT\CLSID key
  760. CloseHandle(hClsidKey);
  761. CloseHandle(hKey);
  762. if (RegOpenKeyEx(HKEY_CLASSES_ROOT, L"CLSID", dwRESERVED,
  763. KEY_READ, &hKey) != ERROR_SUCCESS)
  764. {
  765. return FALSE;
  766. }
  767. // Open the key to our clsid
  768. if (RegOpenKeyEx(hKey, wszCLSID, dwRESERVED,
  769. KEY_READ, &hClsidKey) != ERROR_SUCCESS)
  770. {
  771. CloseHandle(hKey);
  772. return FALSE;
  773. }
  774. // Open the InprocServer32 key
  775. CloseHandle(hKey);
  776. if (RegOpenKeyEx(hClsidKey, L"InprocServer32", dwRESERVED,
  777. KEY_SET_VALUE, &hInproc32Key) != ERROR_SUCCESS)
  778. {
  779. CloseHandle(hClsidKey);
  780. return FALSE;
  781. }
  782. // Set the threading model for this InprocServer32 key
  783. CloseHandle(hClsidKey);
  784. if (RegSetValueEx(hInproc32Key, L"ThreadingModel", dwRESERVED,
  785. REG_SZ, (LPBYTE) pwszThreadingModel,
  786. (wcslen(pwszThreadingModel)+1) * sizeof(WCHAR))
  787. != ERROR_SUCCESS)
  788. {
  789. CloseHandle(hInproc32Key);
  790. return FALSE;
  791. }
  792. // Close the InprocServer32 key and return success
  793. CloseHandle(hInproc32Key);
  794. return TRUE;
  795. }
  796. //+--------------------------------------------------------
  797. //
  798. // Function: ResetRegistryThreadingModel
  799. //
  800. // Algorithm: Remove the threading model for the InprocServer32 associated
  801. // with the file pwszFile
  802. //
  803. // History: 17-Jan-95 BruceMa Created
  804. //
  805. //---------------------------------------------------------
  806. BOOL ResetRegistryThreadingModel(WCHAR *pwszFile)
  807. {
  808. DWORD dwRESERVED = 0;
  809. WCHAR wszExt[8];
  810. HKEY hKey;
  811. WCHAR wszProgId[32];
  812. DWORD dwValueType;
  813. WCHAR wszCLSID[64];
  814. HKEY hClsidKey;
  815. HKEY hInproc32Key;
  816. ULONG cbValue;
  817. // Strip the extension off the file name
  818. int k = wcslen(pwszFile) - 1;
  819. while (k > 0 && pwszFile[k] != L'.')
  820. {
  821. k--;
  822. }
  823. if (k >= 0 && pwszFile[k] == L'.')
  824. {
  825. for (int j = 0; pwszFile[k]; j++, k++)
  826. {
  827. wszExt[j] = pwszFile[k];
  828. }
  829. wszExt[j] = L'\0';
  830. }
  831. else
  832. {
  833. return FALSE;
  834. }
  835. // Open the key for the specified extension
  836. if (RegOpenKeyEx(HKEY_CLASSES_ROOT, wszExt, dwRESERVED,
  837. KEY_READ, &hKey) != ERROR_SUCCESS)
  838. {
  839. return FALSE;
  840. }
  841. // Read the ProgId for the extension
  842. cbValue = 32;
  843. if (RegQueryValueEx(hKey, NULL, NULL, &dwValueType,
  844. (LPBYTE) wszProgId, &cbValue) != ERROR_SUCCESS)
  845. {
  846. CloseHandle(hKey);
  847. return FALSE;
  848. }
  849. // Open the ProgIdKey
  850. CloseHandle(hKey);
  851. if (RegOpenKeyEx(HKEY_CLASSES_ROOT, wszProgId, dwRESERVED,
  852. KEY_READ, &hKey) != ERROR_SUCCESS)
  853. {
  854. return FALSE;
  855. }
  856. // Open the associated CLSID key
  857. if (RegOpenKeyEx(hKey, L"CLSID", dwRESERVED,
  858. KEY_READ, &hClsidKey) != ERROR_SUCCESS)
  859. {
  860. CloseHandle(hKey);
  861. return FALSE;
  862. }
  863. // Read the CLSID associated with the ProgId
  864. cbValue = 128;
  865. if (RegQueryValueEx(hClsidKey, NULL, NULL, &dwValueType,
  866. (LPBYTE) wszCLSID, &cbValue) != ERROR_SUCCESS)
  867. {
  868. CloseHandle(hClsidKey);
  869. CloseHandle(hKey);
  870. return FALSE;
  871. }
  872. // Open the HKEY_CLASSES_ROOT\CLSID key
  873. CloseHandle(hClsidKey);
  874. CloseHandle(hKey);
  875. if (RegOpenKeyEx(HKEY_CLASSES_ROOT, L"CLSID", dwRESERVED,
  876. KEY_READ, &hKey) != ERROR_SUCCESS)
  877. {
  878. return FALSE;
  879. }
  880. // Open the key to our clsid
  881. if (RegOpenKeyEx(hKey, wszCLSID, dwRESERVED,
  882. KEY_READ, &hClsidKey) != ERROR_SUCCESS)
  883. {
  884. CloseHandle(hKey);
  885. return FALSE;
  886. }
  887. // Open the InprocServer32 key
  888. CloseHandle(hKey);
  889. if (RegOpenKeyEx(hClsidKey, L"InprocServer32", dwRESERVED,
  890. KEY_SET_VALUE, &hInproc32Key) != ERROR_SUCCESS)
  891. {
  892. CloseHandle(hClsidKey);
  893. return FALSE;
  894. }
  895. // Reset the threading model for this InprocServer32 key
  896. CloseHandle(hClsidKey);
  897. if (RegDeleteValue(hInproc32Key, TEXT("ThreadingModel")) != ERROR_SUCCESS)
  898. {
  899. CloseHandle(hInproc32Key);
  900. return FALSE;
  901. }
  902. // Close the InprocServer32 key and return success
  903. CloseHandle(hInproc32Key);
  904. return TRUE;
  905. }