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.

760 lines
20 KiB

  1. /*
  2. **++
  3. **
  4. ** Copyright (c) 2000-2001 Microsoft Corporation
  5. **
  6. **
  7. ** Module Name:
  8. **
  9. ** simsnap.cpp
  10. **
  11. **
  12. ** Abstract:
  13. **
  14. ** Test program to drive the VSS Writer Shim contained in VssAPI.DLL
  15. **
  16. **
  17. ** Author:
  18. **
  19. ** Michael C. Johnson [mikejohn] 24-May-2000
  20. **
  21. **
  22. ** Revision History:
  23. **
  24. ** X-5 MCJ Michael C. Johnson 18-Sep-2000
  25. ** 176860: Add the missing calling convention specifiers
  26. **
  27. ** X-4 MCJ Michael C. Johnson 23-Jun-2000
  28. ** Set the writer failure status.
  29. **
  30. ** X-3 MCJ Michael C. Johnson 15-Jun-2000
  31. ** Add some additional event routines and the ability to act
  32. ** as various types of writer.
  33. **
  34. ** X-2 MCJ Michael C. Johnson 26-May-2000
  35. ** Add some extra tests to validate shim is properly sensitive
  36. ** to volume name array contents.
  37. **--
  38. */
  39. /*
  40. ** Defines
  41. **
  42. **
  43. ** C4290: C++ Exception Specification ignored
  44. ** warning C4511: 'CVssCOMApplication' : copy constructor could not be generated
  45. ** warning C4127: conditional expression is constant
  46. */
  47. #pragma warning(disable:4290)
  48. #pragma warning(disable:4511)
  49. #pragma warning(disable:4127)
  50. /*
  51. ** Includes
  52. */
  53. #include <windows.h>
  54. #include <wtypes.h>
  55. #include <stddef.h>
  56. #include <stdlib.h>
  57. #include <stdio.h>
  58. #include <time.h>
  59. #include <assert.h>
  60. #include <vss.h>
  61. #include <vswriter.h>
  62. #define GET_STATUS_FROM_BOOL(_bSucceeded) ((_bSucceeded) ? NOERROR : HRESULT_FROM_WIN32 (GetLastError()))
  63. #define GET_STATUS_FROM_HANDLE(_handle) ((NULL != (_handle)) ? NOERROR : HRESULT_FROM_WIN32 (GetLastError()))
  64. #define GET_STATUS_FROM_POINTER(_ptr) ((NULL != (_ptr)) ? NOERROR : E_OUTOFMEMORY)
  65. #define SIZEOF_ARRAY(_aBase) (sizeof (_aBase) / sizeof ((_aBase)[0]))
  66. typedef enum FAIL_PHASE
  67. {
  68. PHASE_UNDEFINED = 0,
  69. PHASE_IDENTIFY,
  70. PHASE_PREPARE_FOR_BACKUP,
  71. PHASE_PREPARE_FOR_SNAPSHOT,
  72. PHASE_FREEZE,
  73. PHASE_THAW,
  74. PHASE_ABORT,
  75. PHASE_BACKUP_COMPLETE,
  76. PHASE_RESTORE
  77. } FAIL_PHASE;
  78. HRESULT SelectFailureStatus (VOID)
  79. {
  80. HRESULT hrStatus;
  81. switch (rand () / (RAND_MAX / 5))
  82. {
  83. case 0: hrStatus = VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT; break;
  84. case 1: hrStatus = VSS_E_WRITERERROR_OUTOFRESOURCES; break;
  85. case 2: hrStatus = VSS_E_WRITERERROR_TIMEOUT; break;
  86. case 3: hrStatus = VSS_E_WRITERERROR_NONRETRYABLE; break;
  87. case 4: hrStatus = VSS_E_WRITERERROR_RETRYABLE; break;
  88. default:
  89. assert (FALSE);
  90. break;
  91. }
  92. return (hrStatus);
  93. }
  94. LPCWSTR GetStringFromFailureType (HRESULT hrStatus)
  95. {
  96. LPCWSTR pwszFailureType;
  97. switch (hrStatus)
  98. {
  99. case NOERROR: pwszFailureType = L""; break;
  100. case VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT: pwszFailureType = L"InconsistentSnapshot"; break;
  101. case VSS_E_WRITERERROR_OUTOFRESOURCES: pwszFailureType = L"OutOfResources"; break;
  102. case VSS_E_WRITERERROR_TIMEOUT: pwszFailureType = L"Timeout"; break;
  103. case VSS_E_WRITERERROR_NONRETRYABLE: pwszFailureType = L"Non-Retryable"; break;
  104. case VSS_E_WRITERERROR_RETRYABLE: pwszFailureType = L"Retryable"; break;
  105. default: pwszFailureType = L"UNDEFINED"; break;
  106. }
  107. return (pwszFailureType);
  108. }
  109. LPCWSTR GetStringFromWriterType (VSS_USAGE_TYPE wtWriterType)
  110. {
  111. LPCWSTR pwszWriterType;
  112. switch (wtWriterType)
  113. {
  114. case VSS_UT_BOOTABLESYSTEMSTATE: pwszWriterType = L"BootableSystemState"; break;
  115. case VSS_UT_SYSTEMSERVICE: pwszWriterType = L"SystemServiceState"; break;
  116. case VSS_UT_USERDATA: pwszWriterType = L"UserData"; break;
  117. case VSS_UT_OTHER: pwszWriterType = L"Other"; break;
  118. default: pwszWriterType = L"UNDEFINED"; break;
  119. }
  120. return (pwszWriterType);
  121. }
  122. LPCWSTR GetStringFromFailPhase (FAIL_PHASE fpFailPhase)
  123. {
  124. LPCWSTR pwszFailPhase;
  125. switch (fpFailPhase)
  126. {
  127. case PHASE_IDENTIFY: pwszFailPhase = L"Identify"; break;
  128. case PHASE_PREPARE_FOR_BACKUP: pwszFailPhase = L"PrepareForBackup"; break;
  129. case PHASE_PREPARE_FOR_SNAPSHOT: pwszFailPhase = L"PrepareForSnapshot"; break;
  130. case PHASE_FREEZE: pwszFailPhase = L"Freeze"; break;
  131. case PHASE_THAW: pwszFailPhase = L"Thaw"; break;
  132. case PHASE_ABORT: pwszFailPhase = L"Abort"; break;
  133. case PHASE_BACKUP_COMPLETE: pwszFailPhase = L"BackupComplete"; break;
  134. case PHASE_RESTORE: pwszFailPhase = L"Restore"; break;
  135. default: pwszFailPhase = L"UNDEFINED"; break;
  136. }
  137. return (pwszFailPhase);
  138. }
  139. static volatile BOOL bContinue = TRUE;
  140. static volatile FAIL_PHASE fpFailPhase = PHASE_FREEZE;
  141. static volatile BOOL bHungWriter = FALSE;
  142. static volatile BOOL dwHungWriterTimeout = 120000; // Two minutes
  143. class CVssWriterFailSnap : public CVssWriter
  144. {
  145. public:
  146. bool STDMETHODCALLTYPE OnIdentify (IVssCreateWriterMetadata *pIVssCreateWriterMetadata);
  147. bool STDMETHODCALLTYPE OnPrepareBackup (IVssWriterComponents *pIVssWriterComponents);
  148. bool STDMETHODCALLTYPE OnPrepareSnapshot ();
  149. bool STDMETHODCALLTYPE OnFreeze ();
  150. bool STDMETHODCALLTYPE OnThaw ();
  151. bool STDMETHODCALLTYPE OnAbort ();
  152. bool STDMETHODCALLTYPE OnBackupComplete (IVssWriterComponents *pIVssWriterComponents);
  153. bool STDMETHODCALLTYPE OnPostRestore (IVssWriterComponents *pIVssWriterComponents);
  154. };
  155. bool STDMETHODCALLTYPE CVssWriterFailSnap::OnIdentify (IVssCreateWriterMetadata *pIVssCreateWriterMetadata)
  156. {
  157. bool bPhaseSucceeded = (PHASE_IDENTIFY != fpFailPhase);
  158. HRESULT hrStatus = SelectFailureStatus ();
  159. if (bPhaseSucceeded)
  160. {
  161. hrStatus = pIVssCreateWriterMetadata->AddComponent (VSS_CT_FILEGROUP,
  162. NULL,
  163. L"Failsnap Writer Component",
  164. L"Failsnap Writer Caption",
  165. NULL, // icon
  166. 0,
  167. true,
  168. false,
  169. false);
  170. bPhaseSucceeded = SUCCEEDED (hrStatus);
  171. }
  172. wprintf (L"\nThreadId 0x%04x - Received event - OnIdentify ()%s%s",
  173. GetCurrentThreadId (),
  174. bPhaseSucceeded ? L"" : L" - FAILED ",
  175. GetStringFromFailureType (hrStatus));
  176. // simulate a hung writer
  177. if (!bPhaseSucceeded && bHungWriter)
  178. {
  179. wprintf(L"Sleeping %ld seconds\n", dwHungWriterTimeout/1000);
  180. ::Sleep(dwHungWriterTimeout);
  181. wprintf(L"Wake up.\n");
  182. }
  183. if (!bPhaseSucceeded)
  184. {
  185. SetWriterFailure (hrStatus);
  186. }
  187. return (bPhaseSucceeded);
  188. }
  189. bool STDMETHODCALLTYPE CVssWriterFailSnap::OnPrepareBackup (IVssWriterComponents *pIVssWriterComponents)
  190. {
  191. bool bPhaseSucceeded = (PHASE_PREPARE_FOR_BACKUP != fpFailPhase);
  192. HRESULT hrStatus = bPhaseSucceeded ? NOERROR : SelectFailureStatus ();
  193. // simulate a hung writer
  194. if (!bPhaseSucceeded && bHungWriter)
  195. {
  196. wprintf(L"Sleeping %ld seconds\n", dwHungWriterTimeout/1000);
  197. ::Sleep(dwHungWriterTimeout);
  198. wprintf(L"Wake up.\n");
  199. }
  200. if (!bPhaseSucceeded)
  201. {
  202. SetWriterFailure (hrStatus);
  203. }
  204. return (bPhaseSucceeded);
  205. }
  206. bool STDMETHODCALLTYPE CVssWriterFailSnap::OnPrepareSnapshot ()
  207. {
  208. bool bPhaseSucceeded = (PHASE_PREPARE_FOR_SNAPSHOT != fpFailPhase);
  209. HRESULT hrStatus = bPhaseSucceeded ? NOERROR : SelectFailureStatus ();
  210. wprintf (L"\nThreadId 0x%04x - Received event - OnPrepareSnapshot ()%s%s",
  211. GetCurrentThreadId (),
  212. bPhaseSucceeded ? L"" : L" - FAILED ",
  213. GetStringFromFailureType (hrStatus));
  214. // simulate a hung writer
  215. if (!bPhaseSucceeded && bHungWriter)
  216. {
  217. wprintf(L"Sleeping %ld seconds\n", dwHungWriterTimeout/1000);
  218. ::Sleep(dwHungWriterTimeout);
  219. wprintf(L"Wake up.\n");
  220. }
  221. if (!bPhaseSucceeded)
  222. {
  223. SetWriterFailure (hrStatus);
  224. }
  225. return (bPhaseSucceeded);
  226. }
  227. bool STDMETHODCALLTYPE CVssWriterFailSnap::OnFreeze ()
  228. {
  229. bool bPhaseSucceeded = (PHASE_FREEZE != fpFailPhase);
  230. HRESULT hrStatus = bPhaseSucceeded ? NOERROR : SelectFailureStatus ();
  231. wprintf (L"\nThreadId 0x%04x - Received event - OnFreeze ()%s%s",
  232. GetCurrentThreadId (),
  233. bPhaseSucceeded ? L"" : L" - FAILED ",
  234. GetStringFromFailureType (hrStatus));
  235. // simulate a hung writer
  236. if (!bPhaseSucceeded && bHungWriter)
  237. {
  238. wprintf(L"Sleeping %ld seconds\n", dwHungWriterTimeout/1000);
  239. ::Sleep(dwHungWriterTimeout);
  240. wprintf(L"Wake up.\n");
  241. }
  242. if (!bPhaseSucceeded)
  243. {
  244. SetWriterFailure (hrStatus);
  245. }
  246. return (bPhaseSucceeded);
  247. }
  248. bool STDMETHODCALLTYPE CVssWriterFailSnap::OnThaw ()
  249. {
  250. bool bPhaseSucceeded = (PHASE_THAW != fpFailPhase);
  251. HRESULT hrStatus = bPhaseSucceeded ? NOERROR : SelectFailureStatus ();
  252. wprintf (L"\nThreadId 0x%04x - Received event - OnThaw ()%s%s",
  253. GetCurrentThreadId (),
  254. bPhaseSucceeded ? L"" : L" - FAILED ",
  255. GetStringFromFailureType (hrStatus));
  256. // simulate a hung writer
  257. if (!bPhaseSucceeded && bHungWriter)
  258. {
  259. wprintf(L"Sleeping %ld seconds\n", dwHungWriterTimeout/1000);
  260. ::Sleep(dwHungWriterTimeout);
  261. wprintf(L"Wake up.\n");
  262. }
  263. if (!bPhaseSucceeded)
  264. {
  265. SetWriterFailure (hrStatus);
  266. }
  267. return (bPhaseSucceeded);
  268. }
  269. bool STDMETHODCALLTYPE CVssWriterFailSnap::OnAbort ()
  270. {
  271. bool bPhaseSucceeded = (PHASE_ABORT != fpFailPhase);
  272. HRESULT hrStatus = bPhaseSucceeded ? NOERROR : SelectFailureStatus ();
  273. wprintf (L"\nThreadId 0x%04x - Received event - OnAbort ()%s%s",
  274. GetCurrentThreadId (),
  275. bPhaseSucceeded ? L"" : L" - FAILED ",
  276. GetStringFromFailureType (hrStatus));
  277. // simulate a hung writer
  278. if (!bPhaseSucceeded && bHungWriter)
  279. {
  280. wprintf(L"Sleeping %ld seconds\n", dwHungWriterTimeout/1000);
  281. ::Sleep(dwHungWriterTimeout);
  282. wprintf(L"Wake up.\n");
  283. }
  284. if (!bPhaseSucceeded)
  285. {
  286. SetWriterFailure (hrStatus);
  287. }
  288. return (bPhaseSucceeded);
  289. }
  290. bool STDMETHODCALLTYPE CVssWriterFailSnap::OnBackupComplete (IVssWriterComponents *pIVssWriterComponents)
  291. {
  292. bool bPhaseSucceeded = (PHASE_BACKUP_COMPLETE != fpFailPhase);
  293. HRESULT hrStatus = bPhaseSucceeded ? NOERROR : SelectFailureStatus ();
  294. wprintf (L"\nThreadId 0x%04x - Received event - OnBackupComplete ()%s%s",
  295. GetCurrentThreadId (),
  296. bPhaseSucceeded ? L"" : L" - FAILED ",
  297. GetStringFromFailureType (hrStatus));
  298. // simulate a hung writer
  299. if (!bPhaseSucceeded && bHungWriter)
  300. {
  301. wprintf(L"Sleeping %ld seconds\n", dwHungWriterTimeout/1000);
  302. ::Sleep(dwHungWriterTimeout);
  303. wprintf(L"Wake up.\n");
  304. }
  305. if (!bPhaseSucceeded)
  306. {
  307. SetWriterFailure (hrStatus);
  308. }
  309. return (bPhaseSucceeded);
  310. }
  311. bool STDMETHODCALLTYPE CVssWriterFailSnap::OnPostRestore (IVssWriterComponents *pIVssWriterComponents)
  312. {
  313. bool bPhaseSucceeded = (PHASE_RESTORE != fpFailPhase);
  314. HRESULT hrStatus = bPhaseSucceeded ? NOERROR : SelectFailureStatus ();
  315. wprintf (L"\nThreadId 0x%04x - Received event - OnPostRestore ()%s%s",
  316. GetCurrentThreadId (),
  317. bPhaseSucceeded ? L"" : L" - FAILED ",
  318. GetStringFromFailureType (hrStatus));
  319. // simulate a hung writer
  320. if (!bPhaseSucceeded && bHungWriter)
  321. {
  322. wprintf(L"Sleeping %ld seconds\n", dwHungWriterTimeout/1000);
  323. ::Sleep(dwHungWriterTimeout);
  324. wprintf(L"Wake up.\n");
  325. }
  326. if (!bPhaseSucceeded)
  327. {
  328. SetWriterFailure (hrStatus);
  329. }
  330. return (bPhaseSucceeded);
  331. }
  332. static BOOL AssertPrivilege (LPCWSTR privName)
  333. {
  334. HANDLE tokenHandle;
  335. BOOL stat = FALSE;
  336. if (OpenProcessToken (GetCurrentProcess (), TOKEN_ADJUST_PRIVILEGES, &tokenHandle))
  337. {
  338. LUID value;
  339. if (LookupPrivilegeValue (NULL, privName, &value))
  340. {
  341. TOKEN_PRIVILEGES newState;
  342. DWORD error;
  343. newState.PrivilegeCount = 1;
  344. newState.Privileges[0].Luid = value;
  345. newState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  346. /*
  347. ** We will always call GetLastError below, so clear
  348. ** any prior error values on this thread.
  349. */
  350. SetLastError (ERROR_SUCCESS);
  351. stat = AdjustTokenPrivileges (tokenHandle,
  352. FALSE,
  353. &newState,
  354. (DWORD)0,
  355. NULL,
  356. NULL);
  357. /*
  358. ** Supposedly, AdjustTokenPriveleges always returns TRUE
  359. ** (even when it fails). So, call GetLastError to be
  360. ** extra sure everything's cool.
  361. */
  362. if ((error = GetLastError()) != ERROR_SUCCESS)
  363. {
  364. stat = FALSE;
  365. }
  366. if (!stat)
  367. {
  368. wprintf (L"AdjustTokenPrivileges for %s failed with 0x%08X",
  369. privName,
  370. error);
  371. }
  372. }
  373. CloseHandle (tokenHandle);
  374. }
  375. return stat;
  376. }
  377. BOOL WINAPI CtrlC_HandlerRoutine (IN DWORD /* dwType */)
  378. {
  379. bContinue = FALSE;
  380. // Mark that the break was handled.
  381. return TRUE;
  382. }
  383. extern "C" int __cdecl wmain (int argc, WCHAR *argv[])
  384. {
  385. HRESULT hrStatus = NOERROR;
  386. CVssWriterFailSnap *pCVssWriterFailSnap = NULL;
  387. BOOL bSucceeded = FALSE;
  388. BOOL bComInitialized = FALSE;
  389. BOOL bSubscribed = FALSE;
  390. VSS_USAGE_TYPE wtWriterType = VSS_UT_USERDATA;
  391. const GUID guidIdWriter = {0xd335a99e,
  392. 0x57fb,
  393. 0x4b80,
  394. {0x85, 0xb1, 0x15, 0xda, 0xa7, 0xc7, 0x4e, 0x14}};
  395. srand ((unsigned)time (NULL));
  396. SetConsoleCtrlHandler(CtrlC_HandlerRoutine, TRUE);
  397. // Get the "hung writer" flag
  398. if ((argc >= 3) && (_wcsicmp(argv[1], L"/h") == 0))
  399. {
  400. bHungWriter = TRUE;
  401. swscanf(argv[2], L"%ld", &dwHungWriterTimeout);
  402. dwHungWriterTimeout *= 1000;
  403. argc-=2;
  404. argv+=2;
  405. }
  406. if ((argc >= 2) && (wcslen (argv[1]) > 0))
  407. {
  408. switch (*argv[1])
  409. {
  410. case L'I': case L'i': fpFailPhase = PHASE_IDENTIFY; break;
  411. case L'B': case L'b': fpFailPhase = PHASE_PREPARE_FOR_BACKUP; break;
  412. case L'S': case L's': fpFailPhase = PHASE_PREPARE_FOR_SNAPSHOT; break;
  413. case L'F': case L'f': fpFailPhase = PHASE_FREEZE; break;
  414. case L'T': case L't': fpFailPhase = PHASE_THAW; break;
  415. case L'A': case L'a': fpFailPhase = PHASE_ABORT; break;
  416. case L'C': case L'c': fpFailPhase = PHASE_BACKUP_COMPLETE; break;
  417. case L'R': case L'r': fpFailPhase = PHASE_RESTORE; break;
  418. default:
  419. wprintf (L"\nFAILSNAP [/h seconds] [phase] [writer type]"
  420. L"\n\n\tFailPhases"
  421. L"\n\t\ti - Identify"
  422. L"\n\t\tb - PrepareForBackup"
  423. L"\n\t\ts - PrepareForSnapshot"
  424. L"\n\t\tf - Freeze (default)"
  425. L"\n\t\tt - Thaw"
  426. L"\n\t\ta - Abort"
  427. L"\n\t\tc - BackupComplete"
  428. L"\n\t\tr - PostRestore"
  429. L"\n\n\tWriterTypes"
  430. L"\n\t\tb - BootableState writer"
  431. L"\n\t\ts - ServiceState writer"
  432. L"\n\t\tu - UserData writer (default)"
  433. L"\n\t\to - Other writer"
  434. L"\n"
  435. L"\n\t/h - Additionally, hung in the failed state for the specified time."
  436. L"\n");
  437. bContinue = FALSE;
  438. break;
  439. }
  440. }
  441. if ((argc >= 3) && (wcslen (argv[2]) > 0))
  442. {
  443. switch (*argv[2])
  444. {
  445. case L'B': case L'b': wtWriterType = VSS_UT_BOOTABLESYSTEMSTATE; break;
  446. case L'S': case L's': wtWriterType = VSS_UT_SYSTEMSERVICE; break;
  447. case L'U': case L'u': wtWriterType = VSS_UT_USERDATA; break;
  448. case L'O': case L'o': wtWriterType = VSS_UT_OTHER; break;
  449. default:
  450. bContinue = FALSE;
  451. break;
  452. }
  453. }
  454. if (bContinue)
  455. {
  456. wprintf (L"\nSetting up %s writer to fail %s requests (ProcessId 0x%04x)",
  457. GetStringFromWriterType (wtWriterType),
  458. GetStringFromFailPhase (fpFailPhase),
  459. GetCurrentProcessId ());
  460. /*
  461. wprintf (L"\nChecking privileges");
  462. bSubscribed = AssertPrivilege (SE_BACKUP_NAME);
  463. hrStatus = GET_STATUS_FROM_BOOL (bSucceeded);
  464. if (FAILED (hrStatus))
  465. {
  466. wprintf (L"\nAssertPrivilege returned error 0x%08X", hrStatus);
  467. }
  468. */
  469. }
  470. if (bContinue && SUCCEEDED (hrStatus))
  471. {
  472. wprintf (L"\nInitializing COM");
  473. hrStatus = CoInitializeEx (NULL, COINIT_MULTITHREADED);
  474. if (FAILED (hrStatus))
  475. {
  476. wprintf (L"\nCoInitialize() returned error 0x%08X", hrStatus);
  477. }
  478. else
  479. {
  480. bComInitialized = TRUE;
  481. }
  482. }
  483. if (bContinue && SUCCEEDED (hrStatus))
  484. {
  485. wprintf (L"\nInitializing COM security");
  486. // Initialize COM security
  487. hrStatus = CoInitializeSecurity
  488. (
  489. NULL, // IN PSECURITY_DESCRIPTOR pSecDesc,
  490. -1, // IN LONG cAuthSvc,
  491. NULL, // IN SOLE_AUTHENTICATION_SERVICE *asAuthSvc,
  492. NULL, // IN void *pReserved1,
  493. RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // IN DWORD dwAuthnLevel,
  494. RPC_C_IMP_LEVEL_IDENTIFY, // IN DWORD dwImpLevel,
  495. NULL, // IN void *pAuthList,
  496. EOAC_NONE, // IN DWORD dwCapabilities,
  497. NULL // IN void *pReserved3
  498. );
  499. if (FAILED (hrStatus))
  500. {
  501. wprintf (L"\nCoInitialize() returned error 0x%08X", hrStatus);
  502. }
  503. }
  504. if (bContinue && SUCCEEDED (hrStatus))
  505. {
  506. wprintf (L"\nConstructing Writer");
  507. pCVssWriterFailSnap = new CVssWriterFailSnap;
  508. if (NULL == pCVssWriterFailSnap)
  509. {
  510. hrStatus = HRESULT_FROM_WIN32 (ERROR_NOT_ENOUGH_MEMORY);
  511. wprintf (L"\nFailed to allocate CVssWriterFailSnap : 0x%08X", hrStatus);
  512. }
  513. }
  514. if (bContinue && SUCCEEDED (hrStatus))
  515. {
  516. WCHAR awchWriterName [256];
  517. wprintf (L"\nInitialising the writer");
  518. _snwprintf (awchWriterName,
  519. SIZEOF_ARRAY (awchWriterName),
  520. L"Microsoft Test Writer - FailSnap (%s/%s/0x%04x)",
  521. GetStringFromWriterType (wtWriterType),
  522. GetStringFromFailPhase (fpFailPhase),
  523. GetCurrentProcessId ());
  524. hrStatus = pCVssWriterFailSnap->Initialize (guidIdWriter,
  525. awchWriterName,
  526. wtWriterType,
  527. VSS_ST_OTHER);
  528. if (FAILED (hrStatus))
  529. {
  530. wprintf (L"\nFailed to initialize the writer : 0x%08X", hrStatus);
  531. }
  532. }
  533. if (bContinue && SUCCEEDED (hrStatus))
  534. {
  535. wprintf (L"\nSubscribing to snapshot events");
  536. hrStatus = pCVssWriterFailSnap->Subscribe ();
  537. if (FAILED (hrStatus))
  538. {
  539. wprintf (L"\nFailed to subscribe to snapshot events : 0x%08X", hrStatus);
  540. }
  541. else
  542. {
  543. bSubscribed = TRUE;
  544. }
  545. }
  546. if (bContinue && SUCCEEDED (hrStatus))
  547. {
  548. wprintf (L"\nWaiting for snapshot events (or Ctrl-C)");
  549. while (bContinue)
  550. {
  551. Sleep (100);
  552. }
  553. }
  554. if (bSubscribed)
  555. {
  556. wprintf (L"\nUn-Subscribing from snapshot events");
  557. pCVssWriterFailSnap->Unsubscribe ();
  558. }
  559. if (NULL != pCVssWriterFailSnap)
  560. {
  561. wprintf (L"\nDeconstructing Writer");
  562. delete pCVssWriterFailSnap;
  563. }
  564. if (bComInitialized)
  565. {
  566. wprintf (L"\nUnInitialising COM");
  567. CoUninitialize();
  568. }
  569. return (hrStatus);
  570. }