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.

1390 lines
34 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. backup.cpp
  5. Abstract:
  6. main module of backup test exe
  7. Brian Berkowitz [brianb] 05/23/2000
  8. TBD:
  9. Revision History:
  10. Name Date Comments
  11. brianb 05/23/2000 Created
  12. brianb 06/16/2000 Added comments
  13. --*/
  14. #include <stdafx.h>
  15. #include <vststmsgclient.hxx>
  16. #include <tstiniconfig.hxx>
  17. #include <vststprocess.hxx>
  18. #include <vss.h>
  19. #include <vswriter.h>
  20. #include <vsbackup.h>
  21. #include <vststparser.hxx>
  22. #include <vststutil.hxx>
  23. #include <vststvolinfo.hxx>
  24. #include <backup.h>
  25. void LogUnexpectedFailure(LPCWSTR wsz, ...);
  26. // selection of volumes
  27. static LPCWSTR x_wszVolumeBackup = L"VolumeBackup";
  28. static LPCWSTR x_wszSome = L"Some";
  29. static LPCWSTR x_wszOne = L"One";
  30. static LPCWSTR x_wszAll = L"All";
  31. // selection of file system type
  32. static LPCWSTR x_wszFileSystemBackup = L"FileSystemBackup";
  33. static LPCWSTR x_wszNTFS = L"NTFS";
  34. static LPCWSTR x_wszFAT32 = L"FAT32";
  35. static LPCWSTR x_wszFAT16 = L"FAT16";
  36. static LPCWSTR x_wszRAW = L"RAW";
  37. // what to backup
  38. static LPCWSTR x_wszBackingUp = L"BackingUp";
  39. static LPCWSTR x_wszSerialVolumes = L"Serial";
  40. static LPCWSTR x_wszVolumes = L"Volumes";
  41. static LPCWSTR x_wszComponents = L"Components";
  42. // cancelling async operations
  43. static LPCWSTR x_wszCancelPrepareBackup = L"CancelPrepareBackup";
  44. static LPCWSTR x_wszCancelDoSnapshotSet = L"CancelDoSnapshotSet";
  45. static LPCWSTR x_wszCancelBackupComplete = L"CancelBackupComplete";
  46. // wait time interval
  47. static LPCWSTR x_wszWaitInterval = L"WaitInterval";
  48. // volumes to exclude
  49. static LPCWSTR x_wszExcludeVolumes = L"ExcludeVolumes";
  50. // volumes to include
  51. static LPCWSTR x_wszVolumeList = L"VolumeList";
  52. // volumes to fill with data
  53. static LPCWSTR x_wszFillVolumes = L"FillVolumes";
  54. static LPCWSTR x_wszFillVolumesOptRandom = L"Random";
  55. static LPCWSTR x_wszFillVolumesOptSelected = L"Selected";
  56. static LPCWSTR x_wszFillVolumesOptNone = L"None";
  57. // whether volumes filled with data should be fragmented
  58. static LPCWSTR x_wszFillVolumesOptFragment = L"Fragment";
  59. // which volumes to fill
  60. static LPCWSTR x_wszFillVolumesList = L"FillVolumesList";
  61. // constructor
  62. CVsBackupTest::CVsBackupTest() :
  63. m_bTerminateTest(false),
  64. m_bBackupNTFS(false),
  65. m_bBackupFAT32(false),
  66. m_bBackupFAT16(false),
  67. m_bBackupRAW(false),
  68. m_bSerialBackup(false),
  69. m_bVolumeBackup(false),
  70. m_bComponentBackup(false),
  71. m_cyclesCancelPrepareBackup(0),
  72. m_cyclesCancelDoSnapshotSet(0),
  73. m_cyclesCancelBackupComplete(0),
  74. m_cVolumes(0),
  75. m_cVolumesLeft(0),
  76. m_cSnapshotSets(0),
  77. m_cExcludedVolumes(0),
  78. m_rgwszExcludedVolumes(NULL),
  79. m_cIncludedVolumes(0),
  80. m_rgwszIncludedVolumes(NULL),
  81. m_bRandomFills(false),
  82. m_bFragmentWhenFilling(false),
  83. m_rgwszFillVolumes(NULL),
  84. m_cFillVolumes(0)
  85. {
  86. }
  87. // delete an array of strings
  88. void CVsBackupTest::DeleteVolumeList(LPWSTR *rgwsz, UINT cwsz)
  89. {
  90. if (rgwsz)
  91. {
  92. for(UINT iwsz = 0; iwsz < cwsz; iwsz++)
  93. delete rgwsz[iwsz];
  94. }
  95. delete rgwsz;
  96. }
  97. // destructor
  98. CVsBackupTest::~CVsBackupTest()
  99. {
  100. // delete any snapshot sets that are cached
  101. if (m_cSnapshotSets)
  102. DeleteCachedSnapshotSets();
  103. delete m_wszVolumesSnapshot;
  104. // delete various lists of volumes (string arrays)
  105. DeleteVolumeList(m_rgwszExcludedVolumes, m_cExcludedVolumes);
  106. DeleteVolumeList(m_rgwszIncludedVolumes, m_cIncludedVolumes);
  107. DeleteVolumeList(m_rgwszFillVolumes, m_cFillVolumes);
  108. }
  109. // enable a privilege
  110. BOOL CVsBackupTest::AssertPrivilege(LPCWSTR privName)
  111. {
  112. HANDLE tokenHandle;
  113. BOOL stat = FALSE;
  114. if (OpenProcessToken
  115. (
  116. GetCurrentProcess(),
  117. TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
  118. &tokenHandle
  119. ))
  120. {
  121. LUID value;
  122. // obtain privilige value
  123. if (LookupPrivilegeValue( NULL, privName, &value ))
  124. {
  125. TOKEN_PRIVILEGES newState;
  126. DWORD error;
  127. newState.PrivilegeCount = 1;
  128. newState.Privileges[0].Luid = value;
  129. newState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
  130. /*
  131. * We will always call GetLastError below, so clear
  132. * any prior error values on this thread.
  133. */
  134. SetLastError( ERROR_SUCCESS );
  135. stat = AdjustTokenPrivileges
  136. (
  137. tokenHandle,
  138. FALSE,
  139. &newState,
  140. (DWORD)0,
  141. NULL,
  142. NULL
  143. );
  144. /*
  145. * Supposedly, AdjustTokenPriveleges always returns TRUE
  146. * (even when it fails). So, call GetLastError to be
  147. * extra sure everything's cool.
  148. */
  149. if ((error = GetLastError()) != ERROR_SUCCESS)
  150. stat = FALSE;
  151. if (!stat)
  152. {
  153. char buf[128];
  154. sprintf
  155. (
  156. buf,
  157. "AdjustTokenPrivileges for %s failed with %d",
  158. privName,
  159. error
  160. );
  161. LogFailure(buf);
  162. }
  163. }
  164. CloseHandle(tokenHandle);
  165. }
  166. return stat;
  167. }
  168. // build a list of volumes
  169. void CVsBackupTest::BuildVolumeList
  170. (
  171. LPCWSTR wszOption,
  172. UINT *pcVolumes,
  173. LPWSTR **prgwszVolumes
  174. )
  175. {
  176. // delete existing volume list
  177. DeleteVolumeList(*prgwszVolumes, *pcVolumes);
  178. *prgwszVolumes = NULL;
  179. *pcVolumes = 0;
  180. // get option value
  181. CBsString bssVolumes;
  182. m_pConfig->GetOptionValue(wszOption, &bssVolumes);
  183. // split into seperate strings for each volume
  184. LPCWSTR wszEnd = CVsTstParser::SplitOptions(bssVolumes);
  185. LPCWSTR wszStart = bssVolumes;
  186. UINT cVolumes = 0;
  187. // count number of volumes in exclude list
  188. while(wszStart < wszEnd)
  189. {
  190. cVolumes++;
  191. wszStart += wcslen(wszStart) + 1;
  192. }
  193. // allocate array for strings
  194. *prgwszVolumes = new LPWSTR[cVolumes];
  195. if (*prgwszVolumes == NULL)
  196. {
  197. LogUnexpectedFailure(L"Out of Memory");
  198. throw E_OUTOFMEMORY;
  199. }
  200. wszStart = bssVolumes;
  201. for (UINT iVolume = 0; iVolume < cVolumes; iVolume++)
  202. {
  203. // extract a string value
  204. LPWSTR wszNew = new WCHAR[wcslen(wszStart) + 2];
  205. if (wszNew == NULL)
  206. {
  207. LogUnexpectedFailure(L"Out of Memory");
  208. throw E_OUTOFMEMORY;
  209. }
  210. UINT cwc = (UINT) wcslen(wszStart);
  211. memcpy(wszNew, wszStart, cwc * sizeof(WCHAR));
  212. wszStart += cwc + 1;
  213. // add trailing backslash if not there in order to convert
  214. // into a path to the root directory on the voloume
  215. if (wszNew[cwc-1] != L'\\')
  216. wszNew[cwc++] = L'\\';
  217. wszNew[cwc] = L'\0';
  218. WCHAR wsz[MAX_PATH];
  219. // get unique volume name
  220. if (!GetVolumeNameForVolumeMountPoint(wszNew, wsz, MAX_PATH))
  221. {
  222. delete wszNew;
  223. LogUnexpectedFailure
  224. (
  225. L"Cannot find unique volume name for volume volume %s due to error %d.",
  226. wszStart,
  227. GetLastError()
  228. );
  229. }
  230. else
  231. {
  232. delete wszNew;
  233. // allocate new string for unique volume name
  234. (*prgwszVolumes)[*pcVolumes] = new WCHAR[wcslen(wsz) + 1];
  235. if ((*prgwszVolumes)[*pcVolumes] == NULL)
  236. {
  237. LogUnexpectedFailure(L"Out of Memory");
  238. throw E_OUTOFMEMORY;
  239. }
  240. wcscpy((*prgwszVolumes)[*pcVolumes], wsz);
  241. // incrmement count of volumes
  242. *pcVolumes += 1;
  243. }
  244. }
  245. }
  246. // callback to run the test
  247. HRESULT CVsBackupTest::RunTest
  248. (
  249. CVsTstINIConfig *pConfig, // configuration file (selected section)
  250. CVsTstClientMsg *pClient, // message pipe
  251. CVsTstParams *pParams // command line parameters
  252. )
  253. {
  254. // save supplied parameters
  255. m_pConfig = pConfig;
  256. m_pParams = pParams;
  257. SetClientMsg(pClient);
  258. try
  259. {
  260. // make sure that backup privileges are enabled
  261. if (!AssertPrivilege(SE_BACKUP_NAME))
  262. {
  263. LogFailure("Unable to assert backup privilege");
  264. throw E_UNEXPECTED;
  265. }
  266. // determine what we are backing up
  267. CBsString bssBackingUp;
  268. m_pConfig->GetOptionValue(x_wszBackingUp, &bssBackingUp);
  269. // determe the type of volume backup being performed
  270. CBsString bssVolumeBackup;
  271. m_pConfig->GetOptionValue(x_wszVolumeBackup, &bssVolumeBackup);
  272. // determine which volumes are being backed up
  273. CBsString bssFilesystemBackup;
  274. m_pConfig->GetOptionValue(x_wszFileSystemBackup, &bssFilesystemBackup);
  275. // get value of FillVolumes option
  276. CBsString bssFillVolumes;
  277. m_pConfig->GetOptionValue(x_wszFillVolumes, &bssFillVolumes);
  278. // get cancel test options
  279. m_pConfig->GetOptionValue(x_wszCancelPrepareBackup, &m_llCancelPrepareBackupLow, &m_llCancelPrepareBackupHigh);
  280. m_pConfig->GetOptionValue(x_wszCancelDoSnapshotSet, &m_llCancelDoSnapshotSetLow, &m_llCancelDoSnapshotSetHigh);
  281. m_pConfig->GetOptionValue(x_wszCancelBackupComplete, &m_llCancelBackupCompleteLow, &m_llCancelBackupCompleteHigh);
  282. // get wait time interval
  283. LONGLONG llWaitTimeLow, llWaitTimeHigh;
  284. m_pConfig->GetOptionValue(x_wszWaitInterval, &llWaitTimeLow, &llWaitTimeHigh);
  285. m_waitTime = (UINT) llWaitTimeLow;
  286. // determine type of backup
  287. if (_wcsicmp(bssBackingUp, x_wszComponents) == 0)
  288. m_bComponentBackup = true;
  289. else if (_wcsicmp(bssBackingUp, x_wszVolumes) == 0)
  290. m_bVolumeBackup = true;
  291. else if (_wcsicmp(bssBackingUp, x_wszSerialVolumes) == 0)
  292. m_bSerialBackup = true;
  293. // determine how many volumes are snapshot
  294. if (_wcsicmp(bssVolumeBackup, x_wszAll) == 0)
  295. m_backupVolumes = VSTST_BV_ALL;
  296. else if (_wcsicmp(bssVolumeBackup, x_wszSome) == 0)
  297. m_backupVolumes = VSTST_BV_SOME;
  298. else if (_wcsicmp(bssVolumeBackup, x_wszOne) == 0)
  299. m_backupVolumes = VSTST_BV_ONE;
  300. // determine which file systems are backed up
  301. LPCWSTR wszEnd = CVsTstParser::SplitOptions(bssFilesystemBackup);
  302. LPCWSTR wszStart = bssFilesystemBackup;
  303. while(wszStart < wszEnd)
  304. {
  305. if (_wcsicmp(wszStart, x_wszAll) == 0)
  306. {
  307. m_bBackupNTFS = true;
  308. m_bBackupFAT16 = true;
  309. m_bBackupFAT32 = true;
  310. m_bBackupRAW = true;
  311. break;
  312. }
  313. else if (_wcsicmp(wszStart, x_wszNTFS) == 0)
  314. m_bBackupNTFS = true;
  315. else if (_wcsicmp(wszStart, x_wszFAT32) == 0)
  316. m_bBackupFAT32 = true;
  317. else if (_wcsicmp(wszStart, x_wszFAT16) == 0)
  318. m_bBackupFAT16 = true;
  319. else if (_wcsicmp(wszStart, x_wszRAW) == 0)
  320. m_bBackupRAW = true;
  321. wszStart += wcslen(wszStart) + 1;
  322. }
  323. // build list of excluded volumes
  324. BuildVolumeList
  325. (
  326. x_wszExcludeVolumes,
  327. &m_cExcludedVolumes,
  328. &m_rgwszExcludedVolumes
  329. );
  330. // build list of included volumes
  331. BuildVolumeList
  332. (
  333. x_wszVolumeList,
  334. &m_cIncludedVolumes,
  335. &m_rgwszIncludedVolumes
  336. );
  337. // build list of volumes to fill
  338. BuildVolumeList
  339. (
  340. x_wszFillVolumesList,
  341. &m_cFillVolumes,
  342. &m_rgwszFillVolumes
  343. );
  344. // log information about the test
  345. LogMessage("Starting Backup test.\n");
  346. if (m_bVolumeBackup || m_bSerialBackup)
  347. {
  348. LogMessage("Performing volume backup\n");
  349. if (m_bSerialBackup)
  350. LogMessage("Serially backing up volumes\n");
  351. if (m_bBackupNTFS && m_bBackupFAT32 &&
  352. m_bBackupRAW && m_bBackupFAT16)
  353. LogMessage("Backing up all file systems\n");
  354. else
  355. {
  356. if (m_bBackupNTFS)
  357. LogMessage("Backing up NTFS volumes.\n");
  358. if (m_bBackupFAT32)
  359. LogMessage("Backing up FAT32 volumes.\n");
  360. if (m_bBackupFAT16)
  361. LogMessage("Backing up FAT16 volumes.\n");
  362. if (m_bBackupRAW)
  363. LogMessage("Backing up RAW volumes.\n");
  364. }
  365. if (m_backupVolumes == VSTST_BV_ONE)
  366. LogMessage("Backing up one volume at a time");
  367. else if (m_backupVolumes == VSTST_BV_SOME)
  368. LogMessage("Backing up multiple volumes at a time");
  369. else if (m_backupVolumes == VSTST_BV_ALL)
  370. LogMessage("Backing up all volumes at once");
  371. }
  372. else
  373. LogMessage("Performing component backup.\n");
  374. if (m_llCancelPrepareBackupHigh > 0i64)
  375. LogMessage("Cancel during PrepareBackup.\n");
  376. if (m_llCancelDoSnapshotSetHigh > 0i64)
  377. LogMessage("Cancel during DoSnapshotSet.\n");
  378. if (m_llCancelBackupCompleteHigh > 0i64)
  379. LogMessage("Cancel during BackupComplete.\n");
  380. // run the test until told to terminate the test
  381. while(!m_bTerminateTest)
  382. RunBackupTest();
  383. LogMessage("Ending backup test.\n");
  384. }
  385. catch(...)
  386. {
  387. return E_FAIL;
  388. }
  389. return S_OK;
  390. }
  391. // routine to handle waiting for an asynchronous operation to compelte
  392. HRESULT CVsBackupTest::WaitLoop
  393. (
  394. IVssBackupComponents *pvbc,
  395. IVssAsync *pAsync,
  396. UINT cycles,
  397. VSS_WRITER_STATE state1,
  398. VSS_WRITER_STATE state2,
  399. VSS_WRITER_STATE state3,
  400. VSS_WRITER_STATE state4,
  401. VSS_WRITER_STATE state5,
  402. VSS_WRITER_STATE state6,
  403. VSS_WRITER_STATE state7
  404. )
  405. {
  406. HRESULT hr;
  407. INT nPercentDone;
  408. HRESULT hrResult;
  409. while(TRUE)
  410. {
  411. if (cycles == 0)
  412. {
  413. hr = pAsync->Cancel();
  414. ValidateResult(hr, "IVssAsync::Cancel");
  415. GetAndValidateWriterState
  416. (
  417. pvbc,
  418. state1,
  419. state2,
  420. state3,
  421. state4,
  422. state5,
  423. state6,
  424. state7
  425. );
  426. while(TRUE)
  427. {
  428. hr = pAsync->QueryStatus(&hrResult, &nPercentDone);
  429. ValidateResult(hr, "IVssAsync::QueryStatus");
  430. if (hrResult != STG_S_ASYNC_PENDING)
  431. return hrResult;
  432. Sleep(m_waitTime);
  433. }
  434. }
  435. cycles--;
  436. hr = pAsync->QueryStatus(&hrResult, &nPercentDone);
  437. ValidateResult(hr, "IVssAsync::QueryStatus");
  438. if (hrResult == STG_S_ASYNC_FINISHED)
  439. break;
  440. else if (hrResult != STG_S_ASYNC_PENDING)
  441. return hrResult;
  442. Sleep(m_waitTime);
  443. }
  444. return S_OK;
  445. }
  446. void CVsBackupTest::RunBackupTest()
  447. {
  448. if (m_wszVolumesSnapshot == NULL)
  449. {
  450. m_wszVolumesSnapshot = new WCHAR[1024];
  451. if (m_wszVolumesSnapshot == NULL)
  452. {
  453. LogFailure("Out of memory");
  454. throw E_OUTOFMEMORY;
  455. }
  456. m_cwcVolumesSnapshot = 1024;
  457. }
  458. m_wszVolumesSnapshot[0] = L'\0';
  459. CComPtr<IVssBackupComponents> pvbc;
  460. HRESULT hr;
  461. bool bAbortNeeded = false;
  462. bool bDeleteNeeded = false;
  463. VSS_ID id = GUID_NULL;
  464. try
  465. {
  466. hr = CreateVssBackupComponents(&pvbc);
  467. ValidateResult(hr, "CreateVssBackupComponents");
  468. hr = pvbc->InitializeForBackup();
  469. ValidateResult(hr, "IVssBackupComponents::InitializeForBackup");
  470. hr = pvbc->SetBackupState(true, false, VSS_BT_FULL);
  471. ValidateResult(hr, "IVssBackupComponents::SetBackupState");
  472. hr = pvbc->StartSnapshotSet(&id);
  473. bAbortNeeded = true;
  474. ValidateResult(hr, "IVssBackupComponents::StartSnapshotSet");
  475. GetMetadataAndSetupComponents(pvbc);
  476. if(m_bVolumeBackup || m_bSerialBackup)
  477. {
  478. if (m_cVolumes == 0)
  479. {
  480. m_volumeList.RefreshVolumeList();
  481. m_cVolumes = m_volumeList.GetVolumeCount();
  482. if (m_cVolumes > MAX_VOLUME_COUNT)
  483. m_cVolumes = MAX_VOLUME_COUNT;
  484. m_cVolumesLeft = m_cVolumes;
  485. memset(m_rgbAssignedVolumes, 0, m_cVolumes * sizeof(bool));
  486. RemoveNonCandidateVolumes();
  487. if (m_cVolumesLeft == 0)
  488. LogFailure("No Volumes to snapshot.");
  489. }
  490. if (m_backupVolumes == VSTST_BV_ONE)
  491. ChooseVolumeToBackup(pvbc);
  492. else if (m_backupVolumes == VSTST_BV_ALL)
  493. {
  494. // backup all volumes
  495. while(m_cVolumesLeft > 0)
  496. ChooseVolumeToBackup(pvbc);
  497. }
  498. else
  499. {
  500. // choose some subset of volumes to backup
  501. UINT cVolumesToBackup = CVsTstRandom::RandomChoice(1, m_cVolumes);
  502. while(cVolumesToBackup-- > 0)
  503. ChooseVolumeToBackup(pvbc);
  504. }
  505. }
  506. {
  507. CComPtr<IVssAsync> pAsync;
  508. hr = pvbc->PrepareForBackup(&pAsync);
  509. ValidateResult(hr, "IVssBackupComponents::PrepareForBackup");
  510. if (m_llCancelPrepareBackupHigh > 0i64)
  511. {
  512. if (m_cyclesCancelPrepareBackup < (UINT) m_llCancelPrepareBackupLow)
  513. m_cyclesCancelPrepareBackup = (UINT) m_llCancelPrepareBackupLow;
  514. }
  515. else
  516. m_cyclesCancelPrepareBackup = 0xffffffff;
  517. hr = WaitLoop
  518. (
  519. pvbc,
  520. pAsync,
  521. m_cyclesCancelPrepareBackup,
  522. VSS_WS_FAILED_AT_PREPARE_BACKUP,
  523. VSS_WS_STABLE
  524. );
  525. if (m_cyclesCancelPrepareBackup != 0xffffffff)
  526. m_cyclesCancelPrepareBackup++;
  527. if (m_cyclesCancelPrepareBackup > (UINT) m_llCancelPrepareBackupHigh)
  528. m_cyclesCancelPrepareBackup = 0xffffffff;
  529. }
  530. if (FAILED(hr))
  531. {
  532. char buf[128];
  533. sprintf(buf, "PrepareForBackup failed. hr = 0x%08lx", hr);
  534. LogFailure(buf);
  535. throw hr;
  536. }
  537. if (hr == STG_S_ASYNC_CANCELLED)
  538. throw S_OK;
  539. LogMessage("PrepareForBackup Succeeded.\n");
  540. if (!GetAndValidateWriterState(pvbc, VSS_WS_STABLE))
  541. throw E_FAIL;
  542. LogMessage("Starting snapshot");
  543. {
  544. CComPtr<IVssAsync> pAsync;
  545. hr = pvbc->DoSnapshotSet(0, &pAsync);
  546. if (m_llCancelDoSnapshotSetHigh > 0i64)
  547. {
  548. if (m_cyclesCancelDoSnapshotSet < (UINT) m_llCancelDoSnapshotSetLow)
  549. m_cyclesCancelDoSnapshotSet = (UINT) m_llCancelDoSnapshotSetLow;
  550. }
  551. else
  552. m_cyclesCancelDoSnapshotSet = 0xffffffff;
  553. hr = WaitLoop
  554. (
  555. pvbc,
  556. pAsync,
  557. m_cyclesCancelDoSnapshotSet,
  558. VSS_WS_FAILED_AT_PREPARE_SYNC,
  559. VSS_WS_FAILED_AT_FREEZE,
  560. VSS_WS_FAILED_AT_THAW,
  561. VSS_WS_WAITING_FOR_COMPLETION,
  562. VSS_WS_WAITING_FOR_FREEZE,
  563. VSS_WS_WAITING_FOR_THAW,
  564. VSS_WS_STABLE
  565. );
  566. if (m_cyclesCancelDoSnapshotSet != 0xffffffff)
  567. m_cyclesCancelDoSnapshotSet++;
  568. if (m_cyclesCancelDoSnapshotSet > (UINT) m_llCancelDoSnapshotSetHigh)
  569. m_cyclesCancelDoSnapshotSet = 0xffffffff;
  570. }
  571. if (FAILED(hr))
  572. {
  573. char buf[128];
  574. sprintf(buf, "DoSnapshotSet failed. hr = 0x%08lx", hr);
  575. LogFailure(buf);
  576. throw hr;
  577. }
  578. if (hr == STG_S_ASYNC_CANCELLED)
  579. throw S_OK;
  580. bDeleteNeeded = true;
  581. LogMessage("DoSnapshotSet Succeeded.\n");
  582. bAbortNeeded = false;
  583. if (!GetAndValidateWriterState(pvbc, VSS_WS_WAITING_FOR_COMPLETION, VSS_WS_STABLE))
  584. throw E_FAIL;
  585. SetComponentsSuccessfullyBackedUp(pvbc);
  586. {
  587. CComPtr<IVssAsync> pAsync;
  588. hr = pvbc->BackupComplete(&pAsync);
  589. ValidateResult(hr, "IVssBackupComponents::BackupComplete");
  590. if (m_llCancelBackupCompleteHigh > 0i64)
  591. {
  592. if (m_cyclesCancelBackupComplete < (UINT) m_llCancelBackupCompleteLow)
  593. m_cyclesCancelBackupComplete = (UINT) m_llCancelBackupCompleteLow;
  594. }
  595. else
  596. m_cyclesCancelBackupComplete = 0xffffffff;
  597. hr = WaitLoop
  598. (
  599. pvbc,
  600. pAsync,
  601. m_cyclesCancelBackupComplete,
  602. VSS_WS_WAITING_FOR_COMPLETION,
  603. VSS_WS_STABLE
  604. );
  605. if (m_cyclesCancelBackupComplete != 0xffffffff)
  606. m_cyclesCancelBackupComplete++;
  607. if (m_cyclesCancelBackupComplete > (UINT) m_llCancelDoSnapshotSetHigh)
  608. m_cyclesCancelBackupComplete = 0xffffffff;
  609. }
  610. if (FAILED(hr))
  611. {
  612. char buf[128];
  613. sprintf(buf, "BackupComplete failed. hr = 0x%08lx", hr);
  614. LogFailure(buf);
  615. throw hr;
  616. }
  617. if (hr == STG_S_ASYNC_CANCELLED)
  618. throw S_OK;
  619. LogMessage("BackupComplete Succeeded.\n");
  620. if (!GetAndValidateWriterState(pvbc, VSS_WS_STABLE, VSS_WS_WAITING_FOR_COMPLETION))
  621. throw E_FAIL;
  622. m_cyclesCancelPrepareBackup = 0;
  623. m_cyclesCancelDoSnapshotSet = 0;
  624. m_cyclesCancelBackupComplete = 0;
  625. }
  626. catch(...)
  627. {
  628. }
  629. char buf[128];
  630. if (bAbortNeeded)
  631. {
  632. hr = pvbc->AbortBackup();
  633. if (FAILED(hr))
  634. {
  635. sprintf(buf, "IVssBackupComponents::AbortBackup failed. hr = 0x%08lx", hr);
  636. LogFailure(buf);
  637. }
  638. }
  639. if (bDeleteNeeded)
  640. {
  641. if (m_bSerialBackup)
  642. {
  643. m_rgSnapshotSetIds[m_cSnapshotSets] = id;
  644. m_rgvbc[m_cSnapshotSets] = pvbc.Detach();
  645. m_cSnapshotSets++;
  646. }
  647. else
  648. DoDeleteSnapshotSet(pvbc, id);
  649. }
  650. if (!m_bSerialBackup)
  651. {
  652. // reset for a new snapshot by causing volume list to be refreshed
  653. m_cVolumes = 0;
  654. m_cVolumesLeft = 0;
  655. }
  656. else if (m_cVolumesLeft == 0 ||
  657. m_cSnapshotSets == MAX_SNAPSHOT_SET_COUNT ||
  658. !bDeleteNeeded)
  659. {
  660. // delete existing snapshot sets if there was a failure or
  661. // if there are no more volumes to add or
  662. // if we can't create a new snapshot set.
  663. DeleteCachedSnapshotSets();
  664. m_cVolumes = 0;
  665. m_cVolumesLeft = 0;
  666. m_cSnapshotSets = 0;
  667. }
  668. }
  669. // delete all snapshot sets that are cached
  670. void CVsBackupTest::DeleteCachedSnapshotSets()
  671. {
  672. for(UINT iSnapshotSet = 0; iSnapshotSet < m_cSnapshotSets; iSnapshotSet++)
  673. {
  674. CComPtr<IVssBackupComponents> pvbc;
  675. pvbc.Attach(m_rgvbc[iSnapshotSet]);
  676. DoDeleteSnapshotSet(pvbc, m_rgSnapshotSetIds[iSnapshotSet]);
  677. }
  678. }
  679. void CVsBackupTest::DoDeleteSnapshotSet(IVssBackupComponents *pvbc, VSS_ID id)
  680. {
  681. try
  682. {
  683. LONG lSnapshotsNotDeleted;
  684. VSS_ID rgSnapshotsNotDeleted[10];
  685. HRESULT hr = pvbc->DeleteSnapshots
  686. (
  687. id,
  688. VSS_OBJECT_SNAPSHOT_SET,
  689. false,
  690. &lSnapshotsNotDeleted,
  691. rgSnapshotsNotDeleted
  692. );
  693. ValidateResult(hr, "IVssBackupComponents::DeleteSnapshots");
  694. }
  695. catch(HRESULT)
  696. {
  697. }
  698. catch(...)
  699. {
  700. LogUnexpectedException("CVsBackupTest::DoDeleteSnapshotSet");
  701. }
  702. }
  703. bool CVsBackupTest::GetAndValidateWriterState
  704. (
  705. IVssBackupComponents *pvbc,
  706. VSS_WRITER_STATE ws1,
  707. VSS_WRITER_STATE ws2,
  708. VSS_WRITER_STATE ws3,
  709. VSS_WRITER_STATE ws4,
  710. VSS_WRITER_STATE ws5,
  711. VSS_WRITER_STATE ws6,
  712. VSS_WRITER_STATE ws7
  713. )
  714. {
  715. unsigned cWriters;
  716. HRESULT hr = pvbc->GatherWriterStatus(&cWriters);
  717. ValidateResult(hr, "IVssBackupComponents::GatherWriterStatus");
  718. for(unsigned iWriter = 0; iWriter < cWriters; iWriter++)
  719. {
  720. VSS_ID idInstance;
  721. VSS_ID idWriter;
  722. VSS_WRITER_STATE status;
  723. CComBSTR bstrWriter;
  724. HRESULT hrWriterFailure;
  725. hr = pvbc->GetWriterStatus
  726. (
  727. iWriter,
  728. &idInstance,
  729. &idWriter,
  730. &bstrWriter,
  731. &status,
  732. &hrWriterFailure
  733. );
  734. ValidateResult(hr, "IVssBackupComponents::GetWriterStatus");
  735. if (status == VSS_WS_UNKNOWN ||
  736. (status != ws1 &&
  737. status != ws2 &&
  738. status != ws3 &&
  739. status != ws4 &&
  740. status != ws5 &&
  741. status != ws6 &&
  742. status != ws7))
  743. {
  744. char buf[128];
  745. sprintf(buf, "Writer is in inappropriate state %d.", status);
  746. LogFailure(buf);
  747. return false;
  748. }
  749. }
  750. hr = pvbc->FreeWriterStatus();
  751. ValidateResult(hr, "IVssBackupComponents::FreeWriterStatus");
  752. return true;
  753. }
  754. void CVsBackupTest::SetComponentsSuccessfullyBackedUp
  755. (
  756. IVssBackupComponents *pvbc
  757. )
  758. {
  759. unsigned cWriterComponents;
  760. HRESULT hr = pvbc->GetWriterComponentsCount(&cWriterComponents);
  761. ValidateResult(hr, "IVssBackupComponents::GetWriterComponentsCount");
  762. for(UINT iWriter = 0; iWriter < cWriterComponents; iWriter++)
  763. {
  764. CComPtr<IVssWriterComponentsExt> pWriter;
  765. hr = pvbc->GetWriterComponents(iWriter, &pWriter);
  766. ValidateResult(hr, "IVssBackupComponents::GetWriterComponents");
  767. unsigned cComponents;
  768. hr = pWriter->GetComponentCount(&cComponents);
  769. ValidateResult(hr, "IVssWriterComponents::GetComponentCount");
  770. VSS_ID idWriter, idInstance;
  771. hr = pWriter->GetWriterInfo(&idInstance, &idWriter);
  772. ValidateResult(hr, "IVssWriterComponents::GetWriterInfo");
  773. for(unsigned iComponent = 0; iComponent < cComponents; iComponent++)
  774. {
  775. CComPtr<IVssComponent> pComponent;
  776. hr = pWriter->GetComponent(iComponent, &pComponent);
  777. ValidateResult(hr, "IVssWriterComponents::GetComponent");
  778. VSS_COMPONENT_TYPE ct;
  779. CComBSTR bstrLogicalPath;
  780. CComBSTR bstrComponentName;
  781. hr = pComponent->GetLogicalPath(&bstrLogicalPath);
  782. ValidateResult(hr, "IVssComponent::GetLogicalPath");
  783. hr = pComponent->GetComponentType(&ct);
  784. ValidateResult(hr, "IVssComponent::GetComponentType");
  785. hr = pComponent->GetComponentName(&bstrComponentName);
  786. ValidateResult(hr, "IVssComponent::GetComponentName");
  787. hr = pvbc->SetBackupSucceeded
  788. (
  789. idInstance,
  790. idWriter,
  791. ct,
  792. bstrLogicalPath,
  793. bstrComponentName,
  794. true
  795. );
  796. ValidateResult(hr, "IVssComponent::SetBackupSucceeded");
  797. }
  798. }
  799. }
  800. void CVsBackupTest::GetMetadataAndSetupComponents
  801. (
  802. IVssBackupComponents *pvbc
  803. )
  804. {
  805. unsigned cWriters;
  806. HRESULT hr = pvbc->GatherWriterMetadata(&cWriters);
  807. ValidateResult(hr, "IVssBackupComponents::GatherWriterMetadata");
  808. for(unsigned iWriter = 0; iWriter < cWriters; iWriter++)
  809. {
  810. CComPtr<IVssExamineWriterMetadata> pMetadata;
  811. VSS_ID idInstance;
  812. hr = pvbc->GetWriterMetadata(iWriter, &idInstance, &pMetadata);
  813. ValidateResult(hr, "IVssBackupComponents::GetWriterMetadata");
  814. VSS_ID idInstanceT;
  815. VSS_ID idWriter;
  816. CComBSTR bstrWriterName;
  817. VSS_USAGE_TYPE usage;
  818. VSS_SOURCE_TYPE source;
  819. hr = pMetadata->GetIdentity
  820. (
  821. &idInstanceT,
  822. &idWriter,
  823. &bstrWriterName,
  824. &usage,
  825. &source
  826. );
  827. ValidateResult(hr, "IVssExamineWriterMetadata::GetIdentity");
  828. if (memcmp(&idInstance, &idInstanceT, sizeof(VSS_ID)) != 0)
  829. LogFailure("Id Instance mismatch");
  830. unsigned cIncludeFiles, cExcludeFiles, cComponents;
  831. hr = pMetadata->GetFileCounts(&cIncludeFiles, &cExcludeFiles, &cComponents);
  832. ValidateResult(hr, "IVssExamineWriterMetadata::GetFileCounts");
  833. CComBSTR bstrPath;
  834. CComBSTR bstrFilespec;
  835. CComBSTR bstrAlternate;
  836. CComBSTR bstrDestination;
  837. for(unsigned i = 0; i < cIncludeFiles; i++)
  838. {
  839. CComPtr<IVssWMFiledesc> pFiledesc;
  840. hr = pMetadata->GetIncludeFile(i, &pFiledesc);
  841. ValidateResult(hr, "IVssExamineWriterMetadata::GetIncludeFile");
  842. ValidateFiledesc(pFiledesc);
  843. }
  844. for(i = 0; i < cExcludeFiles; i++)
  845. {
  846. CComPtr<IVssWMFiledesc> pFiledesc;
  847. hr = pMetadata->GetExcludeFile(i, &pFiledesc);
  848. ValidateResult(hr, "IVssExamineWriterMetadata::GetExcludeFile");
  849. ValidateFiledesc(pFiledesc);
  850. }
  851. for(unsigned iComponent = 0; iComponent < cComponents; iComponent++)
  852. {
  853. CComPtr<IVssWMComponent> pComponent;
  854. PVSSCOMPONENTINFO pInfo;
  855. hr = pMetadata->GetComponent(iComponent, &pComponent);
  856. ValidateResult(hr, "IVssExamineWriterMetadata::GetComponent");
  857. hr = pComponent->GetComponentInfo(&pInfo);
  858. ValidateResult(hr, "IVssWMComponent::GetComponentInfo");
  859. if (m_bComponentBackup)
  860. {
  861. hr = pvbc->AddComponent
  862. (
  863. idInstance,
  864. idWriter,
  865. pInfo->type,
  866. pInfo->bstrLogicalPath,
  867. pInfo->bstrComponentName
  868. );
  869. ValidateResult(hr, "IVssBackupComponents::AddComponent");
  870. }
  871. if (pInfo->cFileCount > 0)
  872. {
  873. for(i = 0; i < pInfo->cFileCount; i++)
  874. {
  875. CComPtr<IVssWMFiledesc> pFiledesc;
  876. hr = pComponent->GetFile(i, &pFiledesc);
  877. ValidateResult(hr, "IVssWMComponent::GetFile");
  878. CComBSTR bstrPath;
  879. hr = pFiledesc->GetPath(&bstrPath);
  880. ValidateResult(hr, "IVssWMFiledesc::GetPath");
  881. if (m_bComponentBackup)
  882. DoAddToSnapshotSet(pvbc, bstrPath);
  883. ValidateFiledesc(pFiledesc);
  884. }
  885. }
  886. if (pInfo->cDatabases > 0)
  887. {
  888. for(i = 0; i < pInfo->cDatabases; i++)
  889. {
  890. CComPtr<IVssWMFiledesc> pFiledesc;
  891. hr = pComponent->GetDatabaseFile(i, &pFiledesc);
  892. ValidateResult(hr, "IVssWMComponent::GetDatabaseFile");
  893. CComBSTR bstrPath;
  894. hr = pFiledesc->GetPath(&bstrPath);
  895. ValidateResult(hr, "IVssWMFiledesc::GetPath");
  896. if (m_bComponentBackup)
  897. DoAddToSnapshotSet(pvbc, bstrPath);
  898. ValidateFiledesc(pFiledesc);
  899. }
  900. }
  901. if (pInfo->cLogFiles > 0)
  902. {
  903. for(i = 0; i < pInfo->cLogFiles; i++)
  904. {
  905. CComPtr<IVssWMFiledesc> pFiledesc;
  906. hr = pComponent->GetDatabaseLogFile(i, &pFiledesc);
  907. ValidateResult(hr, "IVssWMComponent::GetDatabaseLogFile");
  908. CComBSTR bstrPath;
  909. hr = pFiledesc->GetPath(&bstrPath);
  910. ValidateResult(hr, "IVssWMFiledesc::GetPath");
  911. if (m_bComponentBackup)
  912. DoAddToSnapshotSet(pvbc, bstrPath);
  913. ValidateFiledesc(pFiledesc);
  914. }
  915. }
  916. hr = pComponent->FreeComponentInfo(pInfo);
  917. ValidateResult(hr, "IVssWMComponent::FreeComponentInfo");
  918. }
  919. VSS_RESTOREMETHOD_ENUM method;
  920. CComBSTR bstrUserProcedure;
  921. CComBSTR bstrService;
  922. VSS_WRITERRESTORE_ENUM writerRestore;
  923. unsigned cMappings;
  924. bool bRebootRequired;
  925. hr = pMetadata->GetRestoreMethod
  926. (
  927. &method,
  928. &bstrService,
  929. &bstrUserProcedure,
  930. &writerRestore,
  931. &bRebootRequired,
  932. &cMappings
  933. );
  934. ValidateResult(hr, "IVssExamineWriterMetadata::GetRestoreMethod");
  935. for(i = 0; i < cMappings; i++)
  936. {
  937. CComPtr<IVssWMFiledesc> pFiledesc;
  938. hr = pMetadata->GetAlternateLocationMapping(i, &pFiledesc);
  939. ValidateResult(hr, "IVssExamineWriterMetadata::GetAlternateLocationMapping");
  940. ValidateFiledesc(pFiledesc);
  941. }
  942. }
  943. hr = pvbc->FreeWriterMetadata();
  944. ValidateResult(hr, "IVssBackupComponents::FreeWriterMetadata");
  945. }
  946. void CVsBackupTest::ValidateFiledesc(IVssWMFiledesc *pFiledesc)
  947. {
  948. CComBSTR bstrPath;
  949. CComBSTR bstrFilespec;
  950. CComBSTR bstrAlternate;
  951. CComBSTR bstrDestination;
  952. bool bRecursive;
  953. HRESULT hr = pFiledesc->GetPath(&bstrPath);
  954. ValidateResult(hr, "IVssWMFiledesc::GetPath");
  955. hr = pFiledesc->GetFilespec(&bstrFilespec);
  956. ValidateResult(hr, "IVssWMFiledesc::GetFilespec");
  957. hr = pFiledesc->GetRecursive(&bRecursive);
  958. ValidateResult(hr, "IVssWMFiledesc::GetRecursive");
  959. hr = pFiledesc->GetAlternateLocation(&bstrAlternate);
  960. ValidateResult(hr, "IVssWMFiledesc::GetAlternateLocation");
  961. }
  962. // add a component file to the snapshot set by determining which volume
  963. // contains the file and then adding the file to the snapshot set if it
  964. // is not already included.
  965. void CVsBackupTest::DoAddToSnapshotSet
  966. (
  967. IN IVssBackupComponents *pvbc,
  968. IN LPCWSTR wszPath
  969. )
  970. {
  971. WCHAR wszVolume[MAX_PATH];
  972. UINT cwc = (UINT) wcslen(wszPath) + 1;
  973. WCHAR *wszVolumeMountPoint = new WCHAR[cwc];
  974. if (wszVolumeMountPoint == NULL)
  975. {
  976. LogFailure("Out of memory");
  977. throw E_OUTOFMEMORY;
  978. }
  979. if (!GetVolumePathName(wszPath, wszVolumeMountPoint, cwc))
  980. ValidateResult(HRESULT_FROM_WIN32(GetLastError()), "GetVolumePathName");
  981. if (!GetVolumeNameForVolumeMountPointW
  982. (
  983. wszVolumeMountPoint,
  984. wszVolume,
  985. MAX_PATH
  986. ))
  987. ValidateResult(HRESULT_FROM_WIN32(GetLastError()), "GetVolumeNameForVolumeMountPointW");
  988. WCHAR *pwc = m_wszVolumesSnapshot;
  989. while(*pwc != '\0')
  990. {
  991. if (wcsncmp(pwc, wszVolume, wcslen(wszVolume)) == 0)
  992. return;
  993. pwc = wcschr(pwc, L';');
  994. if (pwc == NULL)
  995. break;
  996. pwc++;
  997. }
  998. HRESULT hr = pvbc->AddToSnapshotSet
  999. (
  1000. wszVolume,
  1001. GUID_NULL,
  1002. L"",
  1003. 0,
  1004. 0,
  1005. NULL,
  1006. NULL
  1007. );
  1008. ValidateResult(hr, "IVssBackupComponents::AddToSnaphsotSet");
  1009. if (pwc - m_wszVolumesSnapshot + wcslen(wszVolume) + 1 > m_cwcVolumesSnapshot)
  1010. {
  1011. WCHAR *wszVolumesNew = new WCHAR[m_cwcVolumesSnapshot + 1024];
  1012. if(wszVolumesNew == NULL)
  1013. {
  1014. LogFailure("Out of memory");
  1015. throw E_OUTOFMEMORY;
  1016. }
  1017. wcscpy(wszVolumesNew, m_wszVolumesSnapshot);
  1018. delete m_wszVolumesSnapshot;
  1019. m_wszVolumesSnapshot = wszVolumesNew;
  1020. m_cwcVolumesSnapshot += 1024;
  1021. pwc = m_wszVolumesSnapshot + wcslen(m_wszVolumesSnapshot);
  1022. }
  1023. *pwc++ = L';';
  1024. wcscpy(pwc, wszVolume);
  1025. }
  1026. // remove volumes for possible set of volume we can choose to backup based
  1027. // on configuration information
  1028. void CVsBackupTest::RemoveNonCandidateVolumes()
  1029. {
  1030. for(UINT iVolume = 0; iVolume < m_cVolumes; iVolume++)
  1031. {
  1032. // get volume information
  1033. const CVsTstVolumeInfo *pVolume = m_volumeList.GetVolumeInfo(iVolume);
  1034. bool bCandidate = false;
  1035. // validate that file system is one we will backup
  1036. if (pVolume->IsNtfs())
  1037. bCandidate = m_bBackupNTFS;
  1038. else if (pVolume->IsFat32())
  1039. bCandidate = m_bBackupFAT32;
  1040. else if (pVolume->IsFat())
  1041. bCandidate = m_bBackupFAT16;
  1042. else if (pVolume->IsRaw())
  1043. bCandidate = m_bBackupRAW;
  1044. // candidates must be in the included volumes list
  1045. if (m_cIncludedVolumes > 0)
  1046. {
  1047. LPCWSTR wszVolumeName = pVolume->GetVolumeName();
  1048. bool fFound = false;
  1049. for(UINT iIncluded = 0; iIncluded < m_cIncludedVolumes; iIncluded++)
  1050. {
  1051. if (wcscmp(wszVolumeName, m_rgwszIncludedVolumes[iIncluded]) == 0)
  1052. fFound = true;
  1053. }
  1054. if (!fFound)
  1055. bCandidate = false;
  1056. }
  1057. // candidates must not be in the excluded volumes list
  1058. if (m_cExcludedVolumes > 0)
  1059. {
  1060. LPCWSTR wszVolumeName = pVolume->GetVolumeName();
  1061. for(UINT iExcluded = 0; iExcluded < m_cExcludedVolumes; iExcluded++)
  1062. {
  1063. if (wcscmp(wszVolumeName, m_rgwszExcludedVolumes[iExcluded]) == 0)
  1064. bCandidate = false;
  1065. }
  1066. }
  1067. // if it is not a candidate, mark it is if it is already in use. This
  1068. // will prevent us from choosing the volume as part of a snapshot set
  1069. if (!bCandidate)
  1070. {
  1071. m_rgbAssignedVolumes[iVolume] = true;
  1072. m_cVolumesLeft--;
  1073. }
  1074. }
  1075. }
  1076. // pick a random volume to backup
  1077. void CVsBackupTest::ChooseVolumeToBackup(IVssBackupComponents *pvbc)
  1078. {
  1079. VSTST_ASSERT(m_cVolumesLeft > 0);
  1080. UINT iVolume;
  1081. while(TRUE)
  1082. {
  1083. // select a volume number
  1084. iVolume = CVsTstRandom::RandomChoice(0, m_cVolumes-1);
  1085. // check to see if volume is already assigned. If not, then
  1086. // break out of loop
  1087. if (!m_rgbAssignedVolumes[iVolume])
  1088. break;
  1089. }
  1090. // get volume information about volume
  1091. const CVsTstVolumeInfo *pVolume = m_volumeList.GetVolumeInfo(iVolume);
  1092. // add the volume to the snapshot set using the default provider
  1093. HRESULT hr = pvbc->AddToSnapshotSet
  1094. (
  1095. (VSS_PWSZ) pVolume->GetVolumeName(),
  1096. GUID_NULL,
  1097. L"",
  1098. 0,
  1099. 0,
  1100. NULL,
  1101. NULL
  1102. );
  1103. ValidateResult(hr, "IVssBackupComponents::AddToSnapshotSet");
  1104. // indicate that volume is assigned
  1105. m_rgbAssignedVolumes[iVolume] = true;
  1106. m_cVolumesLeft--;
  1107. }
  1108. // main driver routine
  1109. extern "C" __cdecl wmain(int argc, WCHAR **argv)
  1110. {
  1111. CVsBackupTest *pTest = NULL;
  1112. bool bCoInitializeSucceeded = false;
  1113. try
  1114. {
  1115. // setup to use OLE
  1116. HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  1117. if (FAILED(hr))
  1118. {
  1119. LogUnexpectedFailure(L"CoInitialize Failed hr = 0x%08lx", hr);
  1120. throw hr;
  1121. }
  1122. bCoInitializeSucceeded = true;
  1123. // create test object
  1124. pTest = new CVsBackupTest;
  1125. if (pTest == NULL)
  1126. {
  1127. LogUnexpectedFailure(L"Cannot create test object.");
  1128. throw(E_OUTOFMEMORY);
  1129. }
  1130. // run test using the test object
  1131. hr = CVsTstRunner::RunVsTest(argv, argc, pTest, true);
  1132. if (FAILED(hr))
  1133. LogUnexpectedFailure(L"CVsTstRunner::RunTest failed. hr = 0x%08lx", hr);
  1134. }
  1135. catch(HRESULT)
  1136. {
  1137. }
  1138. catch(...)
  1139. {
  1140. LogUnexpectedFailure(L"Unexpected exception in wmain");
  1141. }
  1142. // delete test object
  1143. delete pTest;
  1144. // uninitialize OLE
  1145. if (bCoInitializeSucceeded)
  1146. CoUninitialize();
  1147. return 0;
  1148. }
  1149. // log an unexpected failure from the test.
  1150. void LogUnexpectedFailure(LPCWSTR wsz, ...)
  1151. {
  1152. va_list args;
  1153. va_start(args, wsz);
  1154. VSTST_ASSERT(FALSE);
  1155. vwprintf(wsz, args);
  1156. }