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.

1809 lines
63 KiB

  1. /*
  2. **++
  3. **
  4. ** Copyright (c) 2000-2001 Microsoft Corporation
  5. **
  6. **
  7. ** Module Name:
  8. **
  9. ** ml.cpp
  10. **
  11. **
  12. ** Abstract:
  13. **
  14. ** Test program to exercise backup and multilayer snapshots
  15. **
  16. ** Author:
  17. **
  18. ** Adi Oltean [aoltean] 02/22/2001
  19. **
  20. **
  21. ** Revision History:
  22. **
  23. **--
  24. */
  25. ///////////////////////////////////////////////////////////////////////////////
  26. // Includes
  27. #include "ml.h"
  28. #include "vsbackup.h"
  29. #include "ntddsnap.h"
  30. #include "vss.h"
  31. #include "vscoordint.h"
  32. #include "vsprov.h"
  33. #include <initguid.h>
  34. #include "ichannel.hxx"
  35. #include "vs_inc.hxx"
  36. #include "vs_sec.hxx"
  37. #include "vs_reg.hxx"
  38. #include <sddl.h>
  39. // Small structure to keep an event pair
  40. struct CVssWriterEventPair
  41. {
  42. CVssWriterEventPair(LPWSTR wszWriterName, INT dwEventID):
  43. m_wszWriterName(wszWriterName), m_dwEventID(dwEventID) {};
  44. // Data members
  45. LPWSTR m_wszWriterName;
  46. INT m_dwEventID;
  47. };
  48. // The map of event pairs
  49. typedef CVssSimpleMap<CVssWriterEventPair, CVssDiagData*> CVssEventPairMap;
  50. int __cdecl compare_DiagData( const void *arg1, const void *arg2 )
  51. {
  52. CVssDiagData* pData1 = *((CVssDiagData**)arg1);
  53. CVssDiagData* pData2 = *((CVssDiagData**)arg2);
  54. if (pData1->m_llTimestamp < pData2->m_llTimestamp)
  55. return (-1);
  56. else if (pData1->m_llTimestamp == pData2->m_llTimestamp)
  57. return (0);
  58. else
  59. return (1);
  60. }
  61. // Needed in order to define correctly the CVssEventPairMap map
  62. inline BOOL VssHashAreKeysEqual( const CVssWriterEventPair& lhK, const CVssWriterEventPair& rhK )
  63. {
  64. return ((::wcscmp(lhK.m_wszWriterName, rhK.m_wszWriterName) == 0) && (lhK.m_dwEventID == rhK.m_dwEventID));
  65. }
  66. ///////////////////////////////////////////////////////////////////////////////
  67. // Processing functions
  68. void CVssMultilayerTest::Initialize()
  69. {
  70. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::Initialize");
  71. wprintf (L"\n----------------- Initializing ---------------------\n");
  72. // Initialize the random starting point.
  73. srand(m_uSeed);
  74. // Initialize COM library
  75. CHECK_NOFAIL(CoInitializeEx (NULL, COINIT_MULTITHREADED));
  76. m_bCoInitializeSucceeded = true;
  77. wprintf (L"COM library initialized.\n");
  78. // Initialize COM security
  79. CHECK_SUCCESS
  80. (
  81. CoInitializeSecurity
  82. (
  83. NULL, // IN PSECURITY_DESCRIPTOR pSecDesc,
  84. -1, // IN LONG cAuthSvc,
  85. NULL, // IN SOLE_AUTHENTICATION_SERVICE *asAuthSvc,
  86. NULL, // IN void *pReserved1,
  87. RPC_C_AUTHN_LEVEL_CONNECT, // IN DWORD dwAuthnLevel,
  88. RPC_C_IMP_LEVEL_IMPERSONATE, // IN DWORD dwImpLevel,
  89. NULL, // IN void *pAuthList,
  90. EOAC_NONE, // IN DWORD dwCapabilities,
  91. NULL // IN void *pReserved3
  92. )
  93. );
  94. wprintf (L"COM security initialized.\n");
  95. // Disable SEH exceptions treatment in COM threads
  96. ft.ComDisableSEH(VSSDBG_VSSTEST);
  97. wprintf (L"COM SEH disabled.\n");
  98. }
  99. // Run the tests
  100. void CVssMultilayerTest::Run()
  101. {
  102. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::Run");
  103. BS_ASSERT(!m_bAttachYourDebuggerNow);
  104. switch(m_eTest)
  105. {
  106. case VSS_TEST_NONE:
  107. break;
  108. case VSS_TEST_QUERY_VOLUMES:
  109. QuerySupportedVolumes();
  110. break;
  111. case VSS_TEST_QUERY_SNAPSHOTS:
  112. QuerySnapshots();
  113. break;
  114. case VSS_TEST_VOLSNAP_QUERY:
  115. QueryVolsnap();
  116. break;
  117. case VSS_TEST_DELETE_BY_SNAPSHOT_ID:
  118. DeleteBySnapshotId();
  119. break;
  120. case VSS_TEST_DELETE_BY_SNAPSHOT_SET_ID:
  121. DeleteBySnapshotSetId();
  122. break;
  123. case VSS_TEST_QUERY_SNAPSHOTS_ON_VOLUME:
  124. QuerySnapshotsByVolume();
  125. break;
  126. case VSS_TEST_CREATE:
  127. // Preload the list of existing snapshots
  128. PreloadExistingSnapshots();
  129. if (m_lContext)
  130. CreateTimewarpSnapshotSet();
  131. else
  132. CreateBackupSnapshotSet();
  133. break;
  134. case VSS_TEST_ADD_DIFF_AREA:
  135. AddDiffArea();
  136. break;
  137. case VSS_TEST_REMOVE_DIFF_AREA:
  138. RemoveDiffArea();
  139. break;
  140. case VSS_TEST_CHANGE_DIFF_AREA_MAX_SIZE:
  141. ChangeDiffAreaMaximumSize();
  142. break;
  143. case VSS_TEST_QUERY_SUPPORTED_VOLUMES_FOR_DIFF_AREA:
  144. QueryVolumesSupportedForDiffAreas();
  145. break;
  146. case VSS_TEST_QUERY_DIFF_AREAS_FOR_VOLUME:
  147. QueryDiffAreasForVolume();
  148. break;
  149. case VSS_TEST_QUERY_DIFF_AREAS_ON_VOLUME:
  150. QueryDiffAreasOnVolume();
  151. break;
  152. case VSS_TEST_QUERY_DIFF_AREAS_FOR_SNAPSHOT:
  153. QueryDiffAreasForSnapshot();
  154. break;
  155. case VSS_TEST_IS_VOLUME_SNAPSHOTTED_C:
  156. IsVolumeSnapshotted_C();
  157. break;
  158. case VSS_TEST_SET_SNAPSHOT_PROPERTIES:
  159. SetSnapshotProperties();
  160. break;
  161. case VSS_TEST_ACCESS_CONTROL_SD:
  162. TestAccessControlSD();
  163. break;
  164. case VSS_TEST_DIAG_WRITERS:
  165. case VSS_TEST_DIAG_WRITERS_LOG:
  166. case VSS_TEST_DIAG_WRITERS_CSV:
  167. case VSS_TEST_DIAG_WRITERS_ON:
  168. case VSS_TEST_DIAG_WRITERS_OFF:
  169. DiagnoseWriters(m_eTest);
  170. break;
  171. case VSS_TEST_LIST_WRITERS:
  172. TestListWriters();
  173. break;
  174. default:
  175. BS_ASSERT(false);
  176. }
  177. }
  178. // Querying supported volumes
  179. void CVssMultilayerTest::QuerySupportedVolumes()
  180. {
  181. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::QuerySupportedVolumes");
  182. wprintf (L"\n---------- Querying supported volumes ----------------\n");
  183. // Create a Coordinator interface
  184. CComPtr<IVssSnapshotMgmt> pMgmt;
  185. CHECK_SUCCESS(pMgmt.CoCreateInstance( CLSID_VssSnapshotMgmt ));
  186. wprintf (L"Management object created.\n");
  187. // Get list all snapshots
  188. CComPtr<IVssEnumMgmtObject> pIEnum;
  189. CHECK_NOFAIL( pMgmt->QueryVolumesSupportedForSnapshots( m_ProviderId, m_lContext, &pIEnum ) )
  190. if (ft.hr == S_FALSE) {
  191. wprintf(L"Query: Empty result...\n");
  192. return;
  193. }
  194. wprintf(L"\n%-50s %-15s\n", L"Volume Name", L"Display name");
  195. wprintf(L"--------------------------------------------------------------------------------\n");
  196. // For all volumes do...
  197. VSS_MGMT_OBJECT_PROP Prop;
  198. VSS_VOLUME_PROP& Vol = Prop.Obj.Vol;
  199. for(;;) {
  200. // Get next element
  201. ULONG ulFetched;
  202. CHECK_NOFAIL( pIEnum->Next( 1, &Prop, &ulFetched ) );
  203. // Test if the cycle is finished
  204. if (ft.hr == S_FALSE) {
  205. BS_ASSERT( ulFetched == 0);
  206. break;
  207. }
  208. wprintf(L"%-50s %-15s\n",
  209. Vol.m_pwszVolumeName,
  210. Vol.m_pwszVolumeDisplayName
  211. );
  212. ::CoTaskMemFree(Vol.m_pwszVolumeName);
  213. ::CoTaskMemFree(Vol.m_pwszVolumeDisplayName);
  214. }
  215. wprintf(L"--------------------------------------------------------------------------------\n");
  216. }
  217. // Querying snapshots
  218. void CVssMultilayerTest::QuerySnapshotsByVolume()
  219. {
  220. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::QuerySnapshotsByVolume");
  221. wprintf (L"\n---------- Querying snapshots on volume ----------------\n");
  222. // Create a Coordinator interface
  223. CComPtr<IVssSnapshotMgmt> pMgmt;
  224. CHECK_NOFAIL(pMgmt.CoCreateInstance( CLSID_VssSnapshotMgmt ));
  225. wprintf (L"Management object created.\n");
  226. // Get list all snapshots
  227. CComPtr<IVssEnumObject> pIEnumSnapshots;
  228. CHECK_NOFAIL( pMgmt->QuerySnapshotsByVolume( m_pwszVolume, m_ProviderId, &pIEnumSnapshots ) );
  229. if (ft.hr == S_FALSE) {
  230. wprintf(L"Query: Empty result...\n");
  231. return;
  232. }
  233. wprintf(L"\n%-8s %-38s %-50s %-50s %-50s %-50s %-50s %-50s\n",
  234. L"Attrib.", L"Snapshot ID", L"Original Volume Name", L"Snapshot device name", L"Originating machine", L"Service machine", L"Exposed name", L"Exposed path");
  235. wprintf(L"--------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
  236. // For all snapshots do...
  237. VSS_OBJECT_PROP Prop;
  238. VSS_SNAPSHOT_PROP& Snap = Prop.Obj.Snap;
  239. for(;;) {
  240. // Get next element
  241. ULONG ulFetched;
  242. CHECK_NOFAIL( pIEnumSnapshots->Next( 1, &Prop, &ulFetched ));
  243. // Test if the cycle is finished
  244. if (ft.hr == S_FALSE) {
  245. BS_ASSERT( ulFetched == 0);
  246. break;
  247. }
  248. wprintf(L"%08lx " WSTR_GUID_FMT L" %-50s %-50s %-50s %-50s %-50s\n",
  249. Snap.m_lSnapshotAttributes,
  250. GUID_PRINTF_ARG(Snap.m_SnapshotId),
  251. Snap.m_pwszOriginalVolumeName,
  252. Snap.m_pwszSnapshotDeviceObject,
  253. Snap.m_pwszOriginatingMachine,
  254. Snap.m_pwszServiceMachine,
  255. Snap.m_pwszExposedName,
  256. Snap.m_pwszExposedPath
  257. );
  258. ::CoTaskMemFree(Snap.m_pwszOriginalVolumeName);
  259. ::CoTaskMemFree(Snap.m_pwszSnapshotDeviceObject);
  260. ::CoTaskMemFree(Snap.m_pwszOriginatingMachine);
  261. ::CoTaskMemFree(Snap.m_pwszServiceMachine);
  262. ::CoTaskMemFree(Snap.m_pwszExposedName);
  263. ::CoTaskMemFree(Snap.m_pwszExposedPath);
  264. }
  265. wprintf(L"--------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
  266. }
  267. // Querying snapshots
  268. void CVssMultilayerTest::QuerySnapshots()
  269. {
  270. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::QuerySnapshots");
  271. wprintf (L"\n---------- Querying existing snapshots ----------------\n");
  272. // Create a Coordinator interface
  273. CComPtr<IVssCoordinator> pCoord;
  274. CHECK_NOFAIL(pCoord.CoCreateInstance( CLSID_VSSCoordinator ));
  275. if (m_lContext)
  276. CHECK_NOFAIL(pCoord->SetContext(m_lContext));
  277. wprintf (L"Coordinator object created with context 0x%08lx.\n", m_lContext);
  278. // Get list all snapshots
  279. CComPtr<IVssEnumObject> pIEnumSnapshots;
  280. CHECK_NOFAIL( pCoord->Query( GUID_NULL, VSS_OBJECT_NONE, VSS_OBJECT_SNAPSHOT, &pIEnumSnapshots ) );
  281. if (ft.hr == S_FALSE) {
  282. wprintf(L"Query: Empty result...\n");
  283. return;
  284. }
  285. wprintf(L"\n%-8s %-38s %-50s %-50s %-50s %-50s %-50s %-50s\n",
  286. L"Attrib.", L"Snapshot ID", L"Original Volume Name", L"Snapshot device name", L"Originating machine", L"Service machine", L"Exposed name", L"Exposed path");
  287. wprintf(L"--------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
  288. // For all snapshots do...
  289. VSS_OBJECT_PROP Prop;
  290. VSS_SNAPSHOT_PROP& Snap = Prop.Obj.Snap;
  291. for(;;) {
  292. // Get next element
  293. ULONG ulFetched;
  294. CHECK_NOFAIL( pIEnumSnapshots->Next( 1, &Prop, &ulFetched ));
  295. // Test if the cycle is finished
  296. if (ft.hr == S_FALSE) {
  297. BS_ASSERT( ulFetched == 0);
  298. break;
  299. }
  300. wprintf(L"%08lx " WSTR_GUID_FMT L" %-50s %-50s %-50s %-50s %-50s\n",
  301. Snap.m_lSnapshotAttributes,
  302. GUID_PRINTF_ARG(Snap.m_SnapshotId),
  303. Snap.m_pwszOriginalVolumeName,
  304. Snap.m_pwszSnapshotDeviceObject,
  305. Snap.m_pwszOriginatingMachine,
  306. Snap.m_pwszServiceMachine,
  307. Snap.m_pwszExposedName,
  308. Snap.m_pwszExposedPath
  309. );
  310. ::CoTaskMemFree(Snap.m_pwszOriginalVolumeName);
  311. ::CoTaskMemFree(Snap.m_pwszSnapshotDeviceObject);
  312. ::CoTaskMemFree(Snap.m_pwszOriginatingMachine);
  313. ::CoTaskMemFree(Snap.m_pwszServiceMachine);
  314. ::CoTaskMemFree(Snap.m_pwszExposedName);
  315. ::CoTaskMemFree(Snap.m_pwszExposedPath);
  316. }
  317. wprintf(L"--------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
  318. }
  319. // Delete by snapshot Id
  320. void CVssMultilayerTest::DeleteBySnapshotId()
  321. {
  322. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::DeleteBySnapshotId");
  323. // Create a Timewarp Coordinator interface
  324. CHECK_NOFAIL(m_pTimewarpCoord.CoCreateInstance( CLSID_VSSCoordinator ));
  325. CHECK_NOFAIL(m_pTimewarpCoord->SetContext(m_lContext));
  326. wprintf (L"Timewarp Coordinator object created.\n");
  327. wprintf (L"\n---------- Deleting TIMEWARP snapshot ----------------\n");
  328. LONG lDeletedSnapshots = 0;
  329. VSS_ID ProblemSnapshotId = GUID_NULL;
  330. ft.hr = m_pTimewarpCoord->DeleteSnapshots(m_SnapshotId,
  331. VSS_OBJECT_SNAPSHOT,
  332. TRUE,
  333. &lDeletedSnapshots,
  334. &ProblemSnapshotId
  335. );
  336. if (ft.hr == VSS_E_OBJECT_NOT_FOUND)
  337. wprintf( L"Snapshot with ID " WSTR_GUID_FMT L" not found in any provider\n", GUID_PRINTF_ARG(m_SnapshotId));
  338. else if (ft.hr == S_OK)
  339. wprintf( L"Snapshot with ID " WSTR_GUID_FMT L" successfully deleted\n", GUID_PRINTF_ARG(m_SnapshotId));
  340. else
  341. wprintf( L"Error deleting Snapshot with ID " WSTR_GUID_FMT L" 0x%08lx\n"
  342. L"Deleted Snapshots %ld\n",
  343. L"Snapshot with problem: " WSTR_GUID_FMT L"\n",
  344. GUID_PRINTF_ARG(m_SnapshotId),
  345. lDeletedSnapshots,
  346. GUID_PRINTF_ARG(ProblemSnapshotId)
  347. );
  348. wprintf (L"\n------------------------------------------------------\n");
  349. }
  350. // Delete by snapshot set Id
  351. void CVssMultilayerTest::DeleteBySnapshotSetId()
  352. {
  353. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::DeleteBySnapshotSetId");
  354. // Create a Timewarp Coordinator interface
  355. CHECK_NOFAIL(m_pTimewarpCoord.CoCreateInstance( CLSID_VSSCoordinator ));
  356. CHECK_NOFAIL(m_pTimewarpCoord->SetContext(m_lContext));
  357. wprintf (L"Timewarp Coordinator object created.\n");
  358. wprintf (L"\n---------- Deleting TIMEWARP snapshot set ------------\n");
  359. LONG lDeletedSnapshots = 0;
  360. VSS_ID ProblemSnapshotId = GUID_NULL;
  361. ft.hr = m_pTimewarpCoord->DeleteSnapshots(m_SnapshotSetId,
  362. VSS_OBJECT_SNAPSHOT_SET,
  363. TRUE,
  364. &lDeletedSnapshots,
  365. &ProblemSnapshotId
  366. );
  367. if (ft.hr == VSS_E_OBJECT_NOT_FOUND)
  368. wprintf( L"Snapshot set with ID " WSTR_GUID_FMT L" not found\n", GUID_PRINTF_ARG(m_SnapshotSetId));
  369. else if (ft.hr == S_OK)
  370. wprintf( L"Snapshot set with ID " WSTR_GUID_FMT L" successfully deleted\n", GUID_PRINTF_ARG(m_SnapshotSetId));
  371. else
  372. wprintf( L"Error deleting Snapshot set with ID " WSTR_GUID_FMT L" 0x%08lx\n"
  373. L"Deleted Snapshots %ld\n",
  374. L"Snapshot with problem: " WSTR_GUID_FMT L"\n",
  375. GUID_PRINTF_ARG(m_SnapshotSetId),
  376. lDeletedSnapshots,
  377. GUID_PRINTF_ARG(ProblemSnapshotId)
  378. );
  379. wprintf (L"\n------------------------------------------------------\n");
  380. }
  381. // Querying snapshots using the IOCTL
  382. void CVssMultilayerTest::QueryVolsnap()
  383. {
  384. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::QueryVolsnap");
  385. /*
  386. // The GUID that corresponds to the format used to store the
  387. // Backup Snapshot Application Info in Server SKU
  388. // {BAE53126-BC65-41d6-86CC-3D56A5CEE693}
  389. const GUID VOLSNAP_APPINFO_GUID_BACKUP_SERVER_SKU =
  390. { 0xbae53126, 0xbc65, 0x41d6, { 0x86, 0xcc, 0x3d, 0x56, 0xa5, 0xce, 0xe6, 0x93 } };
  391. */
  392. wprintf (L"\n---------- Querying existing snapshots ----------------\n");
  393. // Check if the volume represents a real mount point
  394. WCHAR wszVolumeName[MAX_TEXT_BUFFER];
  395. if (!GetVolumeNameForVolumeMountPoint(m_pwszVolume, wszVolumeName, MAX_TEXT_BUFFER))
  396. CHECK_NOFAIL(HRESULT_FROM_WIN32(GetLastError()));
  397. wprintf(L"Querying snapshots on volume %s\n[From oldest to newest]\n\n", wszVolumeName);
  398. // Check if the snapshot is belonging to that volume
  399. // Open a IOCTL channel on that volume
  400. // Eliminate the last backslash in order to open the volume
  401. CVssIOCTLChannel volumeIChannel;
  402. CHECK_NOFAIL(volumeIChannel.Open(ft, wszVolumeName, true, false, VSS_ICHANNEL_LOG_NONE, 0));
  403. // Get the list of snapshots
  404. // If IOCTL_VOLSNAP_QUERY_NAMES_OF_SNAPSHOTS not
  405. // supported then try with the next volume.
  406. CHECK_NOFAIL(volumeIChannel.Call(ft, IOCTL_VOLSNAP_QUERY_NAMES_OF_SNAPSHOTS, false, VSS_ICHANNEL_LOG_NONE));
  407. // Get the length of snapshot names multistring
  408. ULONG ulMultiszLen;
  409. volumeIChannel.Unpack(ft, &ulMultiszLen);
  410. // Try to find the snapshot with the corresponding Id
  411. DWORD dwInitialOffset = volumeIChannel.GetCurrentOutputOffset();
  412. CVssAutoPWSZ pwszSnapshotName;
  413. while(volumeIChannel.UnpackZeroString(ft, pwszSnapshotName.GetRef())) {
  414. // Compose the snapshot name in a user-mode style
  415. WCHAR wszUserModeSnapshotName[MAX_PATH];
  416. ::VssConcatenate( ft, wszUserModeSnapshotName, MAX_PATH - 1,
  417. x_wszGlobalRootPrefix, pwszSnapshotName );
  418. // Open that snapshot
  419. // Do not eliminate the trailing backslash
  420. // Do not throw on error
  421. CVssIOCTLChannel snapshotIChannel;
  422. CHECK_NOFAIL(snapshotIChannel.Open(ft, wszUserModeSnapshotName, false, false, VSS_ICHANNEL_LOG_NONE, 0));
  423. // Send the IOCTL to get the application buffer
  424. CHECK_NOFAIL(snapshotIChannel.Call(ft, IOCTL_VOLSNAP_QUERY_APPLICATION_INFO, false, VSS_ICHANNEL_LOG_NONE));
  425. // Unpack the length of the application buffer
  426. ULONG ulLen;
  427. snapshotIChannel.Unpack(ft, &ulLen);
  428. if (ulLen == 0) {
  429. wprintf(L"Zero-size snapshot detected: %s\n", pwszSnapshotName);
  430. continue;
  431. }
  432. // Get the application Id
  433. VSS_ID AppinfoId;
  434. snapshotIChannel.Unpack(ft, &AppinfoId);
  435. // Get the snapshot Id
  436. VSS_ID CurrentSnapshotId;
  437. snapshotIChannel.Unpack(ft, &CurrentSnapshotId);
  438. // Get the snapshot set Id
  439. VSS_ID CurrentSnapshotSetId;
  440. snapshotIChannel.Unpack(ft, &CurrentSnapshotSetId);
  441. if (AppinfoId == VOLSNAP_APPINFO_GUID_BACKUP_CLIENT_SKU)
  442. {
  443. // Get the snapshot counts
  444. LONG lSnapshotsCount;
  445. snapshotIChannel.Unpack(ft, &lSnapshotsCount);
  446. // Reset the ichannel
  447. snapshotIChannel.ResetOffsets();
  448. // Get the original volume name
  449. CHECK_NOFAIL(snapshotIChannel.Call(ft, IOCTL_VOLSNAP_QUERY_ORIGINAL_VOLUME_NAME, false, VSS_ICHANNEL_LOG_NONE));
  450. // Load the Original volume name
  451. VSS_PWSZ pwszOriginalVolumeName = NULL;
  452. snapshotIChannel.UnpackSmallString(ft, pwszOriginalVolumeName);
  453. // Reset the ichannel
  454. snapshotIChannel.ResetOffsets();
  455. // Get the timestamp
  456. CHECK_NOFAIL(snapshotIChannel.Call(ft, IOCTL_VOLSNAP_QUERY_CONFIG_INFO, false, VSS_ICHANNEL_LOG_NONE));
  457. // Load the Original volume name
  458. VOLSNAP_CONFIG_INFO configStruct;
  459. snapshotIChannel.Unpack(ft, &configStruct);
  460. // Print the snapshot
  461. wprintf(
  462. L" * Client Snapshot with name %s:\n"
  463. L" Application Info: " WSTR_GUID_FMT L"\n"
  464. L" SnapshotID: " WSTR_GUID_FMT L"\n"
  465. L" SnapshotSetID: " WSTR_GUID_FMT L"\n"
  466. L" Snapshot count: %d\n"
  467. L" Original volume: %s\n"
  468. L" Attributes: 0x%08lx\n"
  469. L" Internal attributes: 0x%08lx\n"
  470. L" Reserved config info: 0x%08lx\n"
  471. L" Timestamp: %I64x\n"
  472. L" Structure length: %lu\n"
  473. ,
  474. pwszSnapshotName.GetRef(),
  475. GUID_PRINTF_ARG(AppinfoId),
  476. GUID_PRINTF_ARG(CurrentSnapshotId),
  477. GUID_PRINTF_ARG(CurrentSnapshotSetId),
  478. lSnapshotsCount,
  479. pwszOriginalVolumeName,
  480. configStruct.Attributes,
  481. configStruct.Reserved,
  482. configStruct.SnapshotCreationTime,
  483. ulLen
  484. );
  485. ::VssFreeString(pwszOriginalVolumeName);
  486. }
  487. else
  488. {
  489. // Get the snapshot context
  490. LONG lStructureContext = -1;
  491. snapshotIChannel.Unpack(ft, &lStructureContext);
  492. // Get the snapshot counts
  493. LONG lSnapshotsCount;
  494. snapshotIChannel.Unpack(ft, &lSnapshotsCount);
  495. // Get the snapshot attributes
  496. LONG lSnapshotAttributes;
  497. snapshotIChannel.Unpack(ft, &lSnapshotAttributes);
  498. // Get the exposed name
  499. LPCWSTR pwszExposedName = NULL;
  500. snapshotIChannel.UnpackSmallString(ft, pwszExposedName);
  501. // Get the exposed path
  502. LPCWSTR pwszExposedPath = NULL;
  503. snapshotIChannel.UnpackSmallString(ft, pwszExposedPath);
  504. // Get the originating machine
  505. LPCWSTR pwszOriginatingMachine = NULL;
  506. snapshotIChannel.UnpackSmallString(ft, pwszOriginatingMachine);
  507. // Get the service machine
  508. LPCWSTR pwszServiceMachine = NULL;
  509. snapshotIChannel.UnpackSmallString(ft, pwszServiceMachine);
  510. // Reset the ichannel
  511. snapshotIChannel.ResetOffsets();
  512. // Get the original volume name
  513. CHECK_NOFAIL(snapshotIChannel.Call(ft, IOCTL_VOLSNAP_QUERY_ORIGINAL_VOLUME_NAME, false, VSS_ICHANNEL_LOG_NONE));
  514. // Load the Original volume name
  515. VSS_PWSZ pwszOriginalVolumeName = NULL;
  516. snapshotIChannel.UnpackSmallString(ft, pwszOriginalVolumeName);
  517. // Reset the ichannel
  518. snapshotIChannel.ResetOffsets();
  519. // Get the timestamp
  520. CHECK_NOFAIL(snapshotIChannel.Call(ft, IOCTL_VOLSNAP_QUERY_CONFIG_INFO, false, VSS_ICHANNEL_LOG_NONE));
  521. // Load the Original volume name
  522. VOLSNAP_CONFIG_INFO configStruct;
  523. snapshotIChannel.Unpack(ft, &configStruct);
  524. // Print the snapshot
  525. wprintf(
  526. L" * Server Snapshot with name %s:\n"
  527. L" Application Info: " WSTR_GUID_FMT L"\n"
  528. L" SnapshotID: " WSTR_GUID_FMT L"\n"
  529. L" SnapshotSetID: " WSTR_GUID_FMT L"\n"
  530. L" Context: 0x%08lx\n"
  531. L" Snapshot count: %d\n"
  532. L" Original volume: %s\n"
  533. L" Attributes: 0x%08lx\n"
  534. L" Internal attributes: 0x%08lx\n"
  535. L" Reserved config info: 0x%08lx\n"
  536. L" Timestamp: %I64x\n"
  537. L" Exposed name: %s\n"
  538. L" Exposed path: %s\n"
  539. L" Originating machine: %s\n"
  540. L" Service machine: %s\n"
  541. L" Structure length: %lu\n"
  542. ,
  543. pwszSnapshotName.GetRef(),
  544. GUID_PRINTF_ARG(AppinfoId),
  545. GUID_PRINTF_ARG(CurrentSnapshotId),
  546. GUID_PRINTF_ARG(CurrentSnapshotSetId),
  547. lStructureContext,
  548. lSnapshotsCount,
  549. pwszOriginalVolumeName,
  550. lSnapshotAttributes,
  551. configStruct.Attributes,
  552. configStruct.Reserved,
  553. configStruct.SnapshotCreationTime,
  554. pwszExposedName,
  555. pwszExposedPath,
  556. pwszOriginatingMachine,
  557. pwszServiceMachine,
  558. ulLen
  559. );
  560. ::VssFreeString(pwszOriginalVolumeName);
  561. ::VssFreeString(pwszExposedName);
  562. ::VssFreeString(pwszExposedPath);
  563. ::VssFreeString(pwszOriginatingMachine);
  564. ::VssFreeString(pwszServiceMachine);
  565. }
  566. }
  567. // Check if all strings were browsed correctly
  568. DWORD dwFinalOffset = volumeIChannel.GetCurrentOutputOffset();
  569. BS_VERIFY( (dwFinalOffset - dwInitialOffset == ulMultiszLen));
  570. wprintf(L"----------------------------------------------------------\n");
  571. }
  572. // Delete by snapshot set Id
  573. void CVssMultilayerTest::SetSnapshotProperties()
  574. {
  575. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::SetSnapshotProperties");
  576. // Create a Babbage provider interface
  577. CComPtr<IVssSoftwareSnapshotProvider> ptrSnapshotProvider;
  578. CHECK_NOFAIL(ptrSnapshotProvider.CoCreateInstance( CLSID_VSSoftwareProvider ));
  579. CHECK_NOFAIL(ptrSnapshotProvider->SetContext(m_lContext));
  580. wprintf (L"Babbage object created.\n");
  581. wprintf (L"\n---------- Setting the property ------------\n");
  582. CHECK_NOFAIL(ptrSnapshotProvider->SetSnapshotProperty(m_SnapshotId,
  583. (VSS_SNAPSHOT_PROPERTY_ID)m_uPropertyId,
  584. m_value));
  585. wprintf (L"\n------------------------------------------------------\n");
  586. }
  587. // Checks if hte volume is snapshotted using the C API
  588. void CVssMultilayerTest::IsVolumeSnapshotted_C()
  589. {
  590. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::IsVolumeSnapshotted_C");
  591. wprintf (L"\n---------- Querying IsVolumeSnapshotted ---------------\n");
  592. BOOL bSnapshotsPresent = FALSE;
  593. LONG lSnapshotCompatibility = 0;
  594. CHECK_NOFAIL(IsVolumeSnapshotted(m_pwszVolume, &bSnapshotsPresent, &lSnapshotCompatibility));
  595. wprintf(L"\n IsVolumeSnapshotted(%s) returned:\n\tSnapshots present = %s\n\tCompatibility flags = 0x%08lx\n\n",
  596. m_pwszVolume, bSnapshotsPresent? L"True": L"False", lSnapshotCompatibility);
  597. wprintf(L"----------------------------------------------------------\n");
  598. }
  599. // Preloading snapshots
  600. void CVssMultilayerTest::PreloadExistingSnapshots()
  601. {
  602. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::PreloadExistingSnapshots");
  603. wprintf (L"\n---------- Preloading existing snapshots ----------------\n");
  604. // Create a Timewarp Coordinator interface
  605. CHECK_NOFAIL(m_pAllCoord.CoCreateInstance( CLSID_VSSCoordinator ));
  606. CHECK_NOFAIL(m_pAllCoord->SetContext(VSS_CTX_ALL));
  607. wprintf (L"Timewarp Coordinator object created.\n");
  608. // Get list all snapshots
  609. CComPtr<IVssEnumObject> pIEnumSnapshots;
  610. CHECK_NOFAIL( m_pAllCoord->Query( GUID_NULL,
  611. VSS_OBJECT_NONE,
  612. VSS_OBJECT_SNAPSHOT,
  613. &pIEnumSnapshots ) );
  614. wprintf(L"\n%-8s %-38s %-50s %-50s\n", L"Attrib.", L"Snapshot ID", L"Original Volume Name", L"Snapshot device name");
  615. wprintf(L"--------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
  616. // For all snapshots do...
  617. VSS_OBJECT_PROP Prop;
  618. VSS_SNAPSHOT_PROP& Snap = Prop.Obj.Snap;
  619. for(;;) {
  620. // Get next element
  621. ULONG ulFetched;
  622. CHECK_NOFAIL( pIEnumSnapshots->Next( 1, &Prop, &ulFetched ));
  623. // Test if the cycle is finished
  624. if (ft.hr == S_FALSE) {
  625. BS_ASSERT( ulFetched == 0);
  626. break;
  627. }
  628. wprintf(L"%08lx " WSTR_GUID_FMT L" %-50s %-50s\n",
  629. Snap.m_lSnapshotAttributes,
  630. GUID_PRINTF_ARG(Snap.m_SnapshotId),
  631. Snap.m_pwszOriginalVolumeName,
  632. Snap.m_pwszSnapshotDeviceObject
  633. );
  634. //
  635. // Adding the snapshot to the internal list
  636. //
  637. // Create the new snapshot set object, if not exists
  638. CVssSnapshotSetInfo* pSet = m_pSnapshotSetCollection.Lookup(Snap.m_SnapshotSetId);
  639. bool bSetNew = false;
  640. if (pSet == NULL) {
  641. pSet = new CVssSnapshotSetInfo(Snap.m_SnapshotSetId);
  642. if (pSet == NULL)
  643. {
  644. ::CoTaskMemFree(Snap.m_pwszOriginalVolumeName);
  645. ::CoTaskMemFree(Snap.m_pwszSnapshotDeviceObject);
  646. ft.Err( VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allocation error");
  647. }
  648. bSetNew = true;
  649. }
  650. // Create the snapshot info object
  651. CVssSnapshotInfo* pSnap = new CVssSnapshotInfo(
  652. true, Snap.m_lSnapshotAttributes,
  653. Snap.m_SnapshotSetId,
  654. Snap.m_pwszSnapshotDeviceObject,
  655. Snap.m_pwszOriginalVolumeName,
  656. NULL);
  657. if (pSnap == NULL)
  658. {
  659. ::CoTaskMemFree(Snap.m_pwszOriginalVolumeName);
  660. ::CoTaskMemFree(Snap.m_pwszSnapshotDeviceObject);
  661. if (bSetNew)
  662. delete pSet;
  663. ft.Err( VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allocation error");
  664. }
  665. ::CoTaskMemFree(Snap.m_pwszSnapshotDeviceObject);
  666. // Add the snapshot to the snapshot set's internal list
  667. if (!pSet->Add(Snap.m_pwszOriginalVolumeName, pSnap))
  668. {
  669. ::CoTaskMemFree(Snap.m_pwszOriginalVolumeName);
  670. delete pSnap;
  671. if (bSetNew)
  672. delete pSet;
  673. ft.Err( VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allocation error");
  674. }
  675. ::CoTaskMemFree(Snap.m_pwszOriginalVolumeName);
  676. // Add the snapshot set info to the global list, if needed
  677. if (bSetNew)
  678. if (!m_pSnapshotSetCollection.Add(Snap.m_SnapshotSetId, pSet))
  679. ft.Err( VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allocation error");
  680. }
  681. wprintf(L"--------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
  682. }
  683. // Creating a backup snapshot
  684. void CVssMultilayerTest::CreateTimewarpSnapshotSet()
  685. {
  686. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::CreateTimewarpSnapshotSet");
  687. // Create a Timewarp Coordinator interface
  688. CHECK_NOFAIL(m_pTimewarpCoord.CoCreateInstance( CLSID_VSSCoordinator ));
  689. CHECK_NOFAIL(m_pTimewarpCoord->SetContext(m_lContext));
  690. wprintf (L"Timewarp Coordinator object created.\n");
  691. wprintf (L"\n---------- Starting TIMEWARP snapshot ----------------\n");
  692. CVssVolumeMapNoRemove mapVolumes;
  693. if (m_uSeed != VSS_SEED)
  694. {
  695. // Select one volume. Make sure that we have enough iterations
  696. for(INT nIterations = 0; nIterations < MAX_VOL_ITERATIONS; nIterations++)
  697. {
  698. // If we succeeded to select some volumes then continue;
  699. if (mapVolumes.GetSize())
  700. break;
  701. // Try to select some volumes for backup
  702. for (INT nIndex = 0; nIndex < m_mapVolumes.GetSize(); nIndex++)
  703. {
  704. // Arbitrarily skip volumes
  705. if (RndDecision())
  706. continue;
  707. CVssVolumeInfo* pVol = m_mapVolumes.GetValueAt(nIndex);
  708. BS_ASSERT(pVol);
  709. // WARNING: the test assumes that VSS can have multiple backup snapshots at once.
  710. if (!mapVolumes.Add(pVol->GetVolumeDisplayName(), pVol))
  711. ft.Err(VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allcation error");
  712. // Add only one volume!
  713. break;
  714. }
  715. }
  716. if (nIterations >= MAX_VOL_ITERATIONS)
  717. {
  718. wprintf (L"Warning: a backup snapshot cannot be created. Insufficient volumes?\n");
  719. wprintf (L"\n---------- Ending TIMEWARP snapshot ----------------\n");
  720. return;
  721. }
  722. }
  723. else
  724. {
  725. // Select all volumes
  726. for (INT nIndex = 0; nIndex < m_mapVolumes.GetSize(); nIndex++)
  727. {
  728. CVssVolumeInfo* pVol = m_mapVolumes.GetValueAt(nIndex);
  729. BS_ASSERT(pVol);
  730. // WARNING: the test assumes that VSS can have multiple backup snapshots at once.
  731. if (!mapVolumes.Add(pVol->GetVolumeDisplayName(), pVol))
  732. ft.Err(VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allcation error");
  733. }
  734. }
  735. wprintf(L"\tCurrent volume set:\n");
  736. for (INT nIndex = 0; nIndex < mapVolumes.GetSize(); nIndex++)
  737. {
  738. CVssVolumeInfo* pVol = mapVolumes.GetValueAt(nIndex);
  739. BS_ASSERT(pVol);
  740. // Get the volume containing the path
  741. wprintf(L"\t- Volume %s mounted on %s\n", pVol->GetVolumeName(), pVol->GetVolumeDisplayName() );
  742. }
  743. wprintf (L"\n---------- starting the snapshot set ---------------\n");
  744. CComPtr<IVssAsync> pAsync;
  745. CSimpleArray<VSS_ID > pSnapshotIDsArray;
  746. VSS_ID SnapshotSetId = GUID_NULL;
  747. // Starting a new snapshot set
  748. wprintf(L"Starting a new Snapshot Set\n");
  749. CHECK_SUCCESS(m_pTimewarpCoord->StartSnapshotSet(&SnapshotSetId));
  750. wprintf(L"Snapshot Set created with ID = " WSTR_GUID_FMT L"\n", GUID_PRINTF_ARG(SnapshotSetId));
  751. // Add volumes to the snapshot set
  752. wprintf(L"Adding volumes to the Snapshot Set: \n");
  753. for (INT nIndex = 0; nIndex < mapVolumes.GetSize(); nIndex++)
  754. {
  755. CVssVolumeInfo* pVol = mapVolumes.GetValueAt(nIndex);
  756. BS_ASSERT(pVol);
  757. // Get the volume containing the path
  758. wprintf(L"\t- Adding volume %s ... ", pVol->GetVolumeDisplayName() );
  759. // Add the volume to the snapshot set
  760. VSS_ID SnapshotId;
  761. CHECK_SUCCESS(m_pTimewarpCoord->AddToSnapshotSet(pVol->GetVolumeName(),
  762. GUID_NULL, &SnapshotId));
  763. // Add the snapshot to the array
  764. pSnapshotIDsArray.Add(SnapshotId);
  765. BS_ASSERT(nIndex + 1 == pSnapshotIDsArray.GetSize());
  766. wprintf( L"OK\n");
  767. }
  768. wprintf (L"\n------------ Creating the snapshot -----------------\n");
  769. // Create the snapshot
  770. wprintf(L"\nStarting asynchronous DoSnapshotSet. Please wait...\n");
  771. ft.hr = S_OK;
  772. pAsync = NULL;
  773. CHECK_SUCCESS(m_pTimewarpCoord->DoSnapshotSet(NULL, &pAsync));
  774. CHECK_SUCCESS(pAsync->Wait());
  775. HRESULT hrReturned = S_OK;
  776. CHECK_SUCCESS(pAsync->QueryStatus(&hrReturned, NULL));
  777. CHECK_NOFAIL(hrReturned);
  778. wprintf(L"Asynchronous DoSnapshotSet finished.\n");
  779. wprintf(L"Snapshot set created\n");
  780. // Create the new snapshot set object
  781. CVssSnapshotSetInfo* pSet = new CVssSnapshotSetInfo(SnapshotSetId);
  782. if (pSet == NULL)
  783. ft.Err( VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allocation error");
  784. for (INT nIndex = 0; nIndex < mapVolumes.GetSize(); nIndex++)
  785. {
  786. CVssVolumeInfo* pVol = mapVolumes.GetValueAt(nIndex);
  787. BS_ASSERT(pVol);
  788. if (pSnapshotIDsArray[nIndex] == GUID_NULL)
  789. continue;
  790. VSS_SNAPSHOT_PROP prop;
  791. CHECK_SUCCESS(m_pTimewarpCoord->GetSnapshotProperties(pSnapshotIDsArray[nIndex], &prop));
  792. wprintf(L"\t- The snapshot on volume %s resides at %s\n",
  793. pVol->GetVolumeDisplayName(), prop.m_pwszSnapshotDeviceObject);
  794. // Create the snapshot info object
  795. CVssSnapshotInfo* pSnap = new CVssSnapshotInfo(
  796. true, VSS_CTX_CLIENT_ACCESSIBLE, SnapshotSetId, prop.m_pwszSnapshotDeviceObject, pVol->GetVolumeName(), pVol);
  797. if (pSnap == NULL)
  798. {
  799. ::VssFreeSnapshotProperties(&prop);
  800. delete pSet;
  801. ft.Err( VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allocation error");
  802. }
  803. ::VssFreeSnapshotProperties(&prop);
  804. // Add the snapshot to the snapshot set's internal list
  805. if (!pSet->Add(pVol->GetVolumeName(), pSnap))
  806. {
  807. delete pSnap;
  808. delete pSet;
  809. ft.Err( VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allocation error");
  810. }
  811. }
  812. // Add the snapshot set info to the global list
  813. if (!m_pSnapshotSetCollection.Add(SnapshotSetId, pSet))
  814. {
  815. delete pSet;
  816. ft.Err( VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allocation error");
  817. }
  818. wprintf (L"\n---------- TIMEWARP snapshot created -----------------\n");
  819. // Wait for user input
  820. wprintf(L"\nPress <Enter> to continue...\n");
  821. getwchar();
  822. }
  823. // Creating a backup snapshot
  824. void CVssMultilayerTest::CreateBackupSnapshotSet()
  825. {
  826. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::CreateBackupSnapshotSet");
  827. // Create the Backup components object and initialize for backup
  828. CHECK_NOFAIL(CreateVssBackupComponents(&m_pBackupComponents));
  829. CHECK_NOFAIL(m_pBackupComponents->InitializeForBackup());
  830. CHECK_SUCCESS(m_pBackupComponents->SetBackupState( false, true, VSS_BT_FULL, false));
  831. wprintf (L"Backup components object created.\n");
  832. DisplayCurrentTime();
  833. // Gather writer metadata
  834. GatherWriterMetadata();
  835. GatherWriterStatus(L"after GatherWriterMetadata", VSS_QWS_DISPLAY_WRITER_STATUS);
  836. wprintf (L"\n---------- Starting BACKUP snapshot ----------------\n");
  837. DisplayCurrentTime();
  838. // Compute a set of volumes.
  839. // Select at least one volume. Make sure that we have enough iterations
  840. CVssVolumeMapNoRemove mapVolumes;
  841. if (m_uSeed != VSS_SEED)
  842. {
  843. for(INT nIterations = 0; nIterations < MAX_VOL_ITERATIONS; nIterations++)
  844. {
  845. // If we succeeded to select some volumes then continue;
  846. if (mapVolumes.GetSize())
  847. break;
  848. // Try to select some volumes for backup
  849. for (INT nIndex = 0; nIndex < m_mapVolumes.GetSize(); nIndex++)
  850. {
  851. // Arbitrarily skip volumes
  852. if (RndDecision())
  853. continue;
  854. CVssVolumeInfo* pVol = m_mapVolumes.GetValueAt(nIndex);
  855. BS_ASSERT(pVol);
  856. // WARNING: the test assumes that VSS can have multiple backup snapshots at once.
  857. if (!mapVolumes.Add(pVol->GetVolumeDisplayName(), pVol))
  858. ft.Err(VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allcation error");
  859. }
  860. }
  861. if (nIterations >= MAX_VOL_ITERATIONS)
  862. {
  863. wprintf (L"Warning: a backup snapshot cannot be created. Insufficient volumes?\n");
  864. wprintf (L"\n---------- Ending BACKUP snapshot ----------------\n");
  865. return;
  866. }
  867. }
  868. else
  869. {
  870. // Select all volumes
  871. for (INT nIndex = 0; nIndex < m_mapVolumes.GetSize(); nIndex++)
  872. {
  873. CVssVolumeInfo* pVol = m_mapVolumes.GetValueAt(nIndex);
  874. BS_ASSERT(pVol);
  875. // WARNING: the test assumes that VSS can have multiple backup snapshots at once.
  876. if (!mapVolumes.Add(pVol->GetVolumeDisplayName(), pVol))
  877. ft.Err(VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allcation error");
  878. }
  879. }
  880. wprintf(L"\tCurrent volume set:\n");
  881. for (INT nIndex = 0; nIndex < mapVolumes.GetSize(); nIndex++)
  882. {
  883. CVssVolumeInfo* pVol = mapVolumes.GetValueAt(nIndex);
  884. BS_ASSERT(pVol);
  885. // Get the volume containing the path
  886. wprintf(L"\t- Volume %s mounted on %s\n", pVol->GetVolumeName(), pVol->GetVolumeDisplayName() );
  887. }
  888. wprintf (L"\n---------- starting the snapshot set ---------------\n");
  889. CComPtr<IVssAsync> pAsync;
  890. CSimpleArray<VSS_ID > pSnapshotIDsArray;
  891. VSS_ID SnapshotSetId = GUID_NULL;
  892. // Starting a new snapshot set
  893. wprintf(L"Starting a new Snapshot Set\n");
  894. CHECK_SUCCESS(m_pBackupComponents->StartSnapshotSet(&SnapshotSetId));
  895. wprintf(L"Snapshot Set created with ID = " WSTR_GUID_FMT L"\n", GUID_PRINTF_ARG(SnapshotSetId));
  896. // Add volumes to the snapshot set
  897. wprintf(L"Adding volumes to the Snapshot Set: \n");
  898. for (INT nIndex = 0; nIndex < mapVolumes.GetSize(); nIndex++)
  899. {
  900. CVssVolumeInfo* pVol = mapVolumes.GetValueAt(nIndex);
  901. BS_ASSERT(pVol);
  902. // Get the volume containing the path
  903. wprintf(L"\t- Adding volume %s ... ", pVol->GetVolumeDisplayName() );
  904. // Add the volume to the snapshot set
  905. VSS_ID SnapshotId;
  906. CHECK_SUCCESS(m_pBackupComponents->AddToSnapshotSet(pVol->GetVolumeName(),
  907. GUID_NULL, &SnapshotId));
  908. // Add the snapshot to the array
  909. pSnapshotIDsArray.Add(SnapshotId);
  910. BS_ASSERT(nIndex + 1 == pSnapshotIDsArray.GetSize());
  911. wprintf( L"OK\n");
  912. }
  913. wprintf (L"\n------------ Creating the snapshot -----------------\n");
  914. DisplayCurrentTime();
  915. // Prepare for backup
  916. wprintf(L"Starting asynchronous PrepareForBackup. Please wait...\n");
  917. ft.hr = S_OK;
  918. CHECK_SUCCESS(m_pBackupComponents->PrepareForBackup(&pAsync));
  919. CHECK_SUCCESS(pAsync->Wait());
  920. HRESULT hrReturned = S_OK;
  921. CHECK_SUCCESS(pAsync->QueryStatus(&hrReturned, NULL));
  922. CHECK_NOFAIL(hrReturned);
  923. wprintf(L"Asynchronous PrepareForBackup finished.\n");
  924. GatherWriterStatus(L"after PrepareForBackup");
  925. DisplayCurrentTime();
  926. // Create the snapshot
  927. wprintf(L"\nStarting asynchronous DoSnapshotSet. Please wait...\n");
  928. ft.hr = S_OK;
  929. pAsync = NULL;
  930. CHECK_SUCCESS(m_pBackupComponents->DoSnapshotSet(&pAsync));
  931. CHECK_SUCCESS(pAsync->Wait());
  932. CHECK_SUCCESS(pAsync->QueryStatus(&hrReturned, NULL));
  933. CHECK_NOFAIL(hrReturned);
  934. wprintf(L"Asynchronous DoSnapshotSet finished.\n");
  935. wprintf(L"Snapshot set created\n");
  936. DisplayCurrentTime();
  937. GatherWriterStatus(L"after DoSnapshotSet");
  938. // Create the new snapshot set object
  939. CVssSnapshotSetInfo* pSet = new CVssSnapshotSetInfo(SnapshotSetId);
  940. if (pSet == NULL)
  941. ft.Err( VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allocation error");
  942. for (INT nIndex = 0; nIndex < mapVolumes.GetSize(); nIndex++)
  943. {
  944. CVssVolumeInfo* pVol = mapVolumes.GetValueAt(nIndex);
  945. BS_ASSERT(pVol);
  946. if (pSnapshotIDsArray[nIndex] == GUID_NULL)
  947. continue;
  948. VSS_SNAPSHOT_PROP prop;
  949. CHECK_SUCCESS(m_pBackupComponents->GetSnapshotProperties(pSnapshotIDsArray[nIndex], &prop));
  950. wprintf(L"\t- The snapshot on volume %s resides at %s\n",
  951. pVol->GetVolumeDisplayName(), prop.m_pwszSnapshotDeviceObject);
  952. // Create the snapshot info object
  953. CVssSnapshotInfo* pSnap = new CVssSnapshotInfo(
  954. true, VSS_CTX_BACKUP, SnapshotSetId, prop.m_pwszSnapshotDeviceObject, pVol->GetVolumeName(), pVol);
  955. if (pSnap == NULL)
  956. {
  957. ::VssFreeSnapshotProperties(&prop);
  958. delete pSet;
  959. ft.Err( VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allocation error");
  960. }
  961. ::VssFreeSnapshotProperties(&prop);
  962. // Add the snapshot to the snapshot set's internal list
  963. if (!pSet->Add(pVol->GetVolumeName(), pSnap))
  964. {
  965. delete pSnap;
  966. delete pSet;
  967. ft.Err( VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allocation error");
  968. }
  969. }
  970. // Add the snapshot set info to the global list
  971. if (!m_pSnapshotSetCollection.Add(SnapshotSetId, pSet))
  972. {
  973. delete pSet;
  974. ft.Err( VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allocation error");
  975. }
  976. wprintf (L"\n---------- BACKUP snapshot created -----------------\n");
  977. // Wait for user input
  978. wprintf(L"\nPress <Enter> to continue...\n");
  979. getwchar();
  980. DisplayCurrentTime();
  981. // Complete the backup
  982. BackupComplete();
  983. GatherWriterStatus(L"after BackupComplete");
  984. DisplayCurrentTime();
  985. }
  986. void CVssMultilayerTest::BackupComplete()
  987. {
  988. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::BackupComplete");
  989. CComPtr<IVssAsync> pAsync;
  990. wprintf (L"\n------------ Completing backup phase ---------------\n");
  991. // Send the BackupComplete event
  992. wprintf(L"\nStarting asynchronous BackupComplete. Please wait...\n");
  993. ft.hr = S_OK;
  994. CHECK_SUCCESS(m_pBackupComponents->BackupComplete(&pAsync));
  995. CHECK_SUCCESS(pAsync->Wait());
  996. HRESULT hrReturned = S_OK;
  997. CHECK_SUCCESS(pAsync->QueryStatus(&hrReturned, NULL));
  998. CHECK_NOFAIL(hrReturned);
  999. wprintf(L"Asynchronous BackupComplete finished.\n");
  1000. }
  1001. // Gather writera metadata and select components for backup, if needed
  1002. void CVssMultilayerTest::GatherWriterMetadata()
  1003. {
  1004. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::GatherWriterMetadata");
  1005. unsigned cWriters;
  1006. CComPtr<IVssAsync> pAsync;
  1007. wprintf (L"\n---------- Gathering writer metadata ---------------\n");
  1008. wprintf(L"Starting asynchronous GatherWriterMetadata. Please wait...\n");
  1009. ft.hr = S_OK;
  1010. CHECK_SUCCESS(m_pBackupComponents->GatherWriterMetadata(&pAsync));
  1011. CHECK_SUCCESS(pAsync->Wait());
  1012. HRESULT hrReturned = S_OK;
  1013. CHECK_SUCCESS(pAsync->QueryStatus(&hrReturned, NULL));
  1014. CHECK_NOFAIL(hrReturned);
  1015. wprintf(L"Asynchronous GatherWriterMetadata finished.\n");
  1016. CHECK_NOFAIL (m_pBackupComponents->GetWriterMetadataCount (&cWriters));
  1017. wprintf(L"Number of writers that responded: %u\n", cWriters);
  1018. CHECK_SUCCESS (m_pBackupComponents->FreeWriterMetadata());
  1019. }
  1020. void CVssMultilayerTest::GatherWriterStatus(
  1021. IN LPCWSTR wszWhen,
  1022. DWORD dwQWSFlags /* = VSS_QWS_THROW_ON_WRITER_FAILURE */
  1023. )
  1024. {
  1025. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::GatherWriterMetadata");
  1026. unsigned cWriters;
  1027. CComPtr<IVssAsync> pAsync;
  1028. wprintf (L"\nGathering writer status %s... ", wszWhen);
  1029. ft.hr = S_OK;
  1030. CHECK_SUCCESS(m_pBackupComponents->GatherWriterStatus(&pAsync));
  1031. CHECK_SUCCESS(pAsync->Wait());
  1032. HRESULT hrReturned = S_OK;
  1033. CHECK_SUCCESS(pAsync->QueryStatus(&hrReturned, NULL));
  1034. CHECK_NOFAIL(hrReturned);
  1035. CHECK_NOFAIL(m_pBackupComponents->GetWriterStatusCount(&cWriters));
  1036. wprintf (L"%d writers responded OK\n", cWriters);
  1037. if (dwQWSFlags & VSS_QWS_DISPLAY_WRITER_STATUS)
  1038. {
  1039. wprintf(L"\n\nStatus %s (%d writers)\n\n", wszWhen, cWriters);
  1040. // Print the writers state
  1041. for(unsigned iWriter = 0; iWriter < cWriters; iWriter++)
  1042. {
  1043. VSS_ID idInstance;
  1044. VSS_ID idWriter;
  1045. VSS_WRITER_STATE status;
  1046. CComBSTR bstrWriter;
  1047. HRESULT hrWriterFailure;
  1048. CHECK_SUCCESS(m_pBackupComponents->GetWriterStatus (iWriter,
  1049. &idInstance,
  1050. &idWriter,
  1051. &bstrWriter,
  1052. &status,
  1053. &hrWriterFailure));
  1054. wprintf (L"Status for writer %s: %s(0x%08lx%s%s)\n",
  1055. bstrWriter,
  1056. GetStringFromWriterState(status),
  1057. hrWriterFailure,
  1058. SUCCEEDED (hrWriterFailure) ? L"" : L" - ",
  1059. GetStringFromFailureType (hrWriterFailure));
  1060. }
  1061. wprintf (L"\n");
  1062. }
  1063. if (dwQWSFlags & VSS_QWS_THROW_ON_WRITER_FAILURE)
  1064. {
  1065. // Double-check that all writers are in stable state
  1066. for(unsigned iWriter = 0; iWriter < cWriters; iWriter++)
  1067. {
  1068. VSS_ID idInstance;
  1069. VSS_ID idWriter;
  1070. VSS_WRITER_STATE status;
  1071. CComBSTR bstrWriter;
  1072. HRESULT hrWriterFailure;
  1073. CHECK_SUCCESS(m_pBackupComponents->GetWriterStatus (iWriter,
  1074. &idInstance,
  1075. &idWriter,
  1076. &bstrWriter,
  1077. &status,
  1078. &hrWriterFailure));
  1079. switch(status)
  1080. {
  1081. case VSS_WS_STABLE:
  1082. case VSS_WS_WAITING_FOR_FREEZE:
  1083. case VSS_WS_WAITING_FOR_THAW:
  1084. case VSS_WS_WAITING_FOR_POST_SNAPSHOT:
  1085. case VSS_WS_WAITING_FOR_BACKUP_COMPLETE:
  1086. break;
  1087. default:
  1088. wprintf(
  1089. L"\n\nError: \n\t- Writer %s is not stable: %s(0x%08lx%s%s). \n",
  1090. bstrWriter,
  1091. GetStringFromWriterState(status),
  1092. hrWriterFailure,
  1093. SUCCEEDED (hrWriterFailure) ? L"" : L" - ",
  1094. GetStringFromFailureType (hrWriterFailure)
  1095. );
  1096. throw(E_UNEXPECTED);
  1097. }
  1098. }
  1099. }
  1100. m_pBackupComponents->FreeWriterStatus();
  1101. wprintf (L"\n");
  1102. }
  1103. CVssMultilayerTest::CVssMultilayerTest(
  1104. IN INT nArgsCount,
  1105. IN WCHAR ** ppwszArgsArray
  1106. )
  1107. {
  1108. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::CVssMultilayerTest");
  1109. // Initialize data members
  1110. m_bCoInitializeSucceeded = false;
  1111. m_bAttachYourDebuggerNow = false;
  1112. // Command line options
  1113. m_eTest = VSS_TEST_UNKNOWN;
  1114. m_uSeed = VSS_SEED;
  1115. m_lContext = VSS_CTX_BACKUP;
  1116. m_pwszVolume = NULL;
  1117. m_pwszDiffAreaVolume = NULL;
  1118. m_ProviderId = VSS_SWPRV_ProviderId;
  1119. m_llMaxDiffArea = VSS_ASSOC_NO_MAX_SPACE;
  1120. m_SnapshotId = GUID_NULL;
  1121. m_SnapshotSetId = GUID_NULL;
  1122. m_uPropertyId = 0;
  1123. // Command line arguments
  1124. m_nCurrentArgsCount = nArgsCount;
  1125. m_ppwszCurrentArgsArray = ppwszArgsArray;
  1126. // Print display header
  1127. wprintf(L"\nVSS Multilayer Test application, version 1.0\n");
  1128. }
  1129. CVssMultilayerTest::~CVssMultilayerTest()
  1130. {
  1131. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::~CVssMultilayerTest");
  1132. VssFreeString(m_pwszVolume);
  1133. VssFreeString(m_pwszDiffAreaVolume);
  1134. m_pTimewarpCoord = NULL;
  1135. m_pAllCoord = NULL;
  1136. m_pBackupComponents = NULL;
  1137. // Unloading the COM library
  1138. if (m_bCoInitializeSucceeded)
  1139. CoUninitialize();
  1140. }
  1141. void CVssMultilayerTest::TestAccessControlSD()
  1142. {
  1143. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::TestAccessControlSD");
  1144. wprintf (L"\n----------------- TestAccessControlSD ---------------------\n\n");
  1145. CVssSidCollection sidCollection;
  1146. // Read keys from registry
  1147. sidCollection.Initialize();
  1148. // Print contents of the list
  1149. for (INT nIndex = 0; nIndex < sidCollection.GetSidCount(); nIndex++)
  1150. {
  1151. CVssAutoLocalString sid;
  1152. CHECK_WIN32( ConvertSidToStringSid(
  1153. sidCollection.GetSid(nIndex), sid.ResetAndGetAddress()), ;);
  1154. wprintf(L"\n* entry[%d]: '%s' '%s' %s\n", nIndex,
  1155. sidCollection.GetPrincipal(nIndex), sid.Get(),
  1156. sidCollection.IsSidAllowed(nIndex)? L"Allowed": L"Denied" );
  1157. }
  1158. wprintf (L"\n----------------------------------------------------------\n");
  1159. }
  1160. // Print out diagnostic information for writers
  1161. void CVssMultilayerTest::DiagnoseWriters(
  1162. IN EVssTestType eType
  1163. )
  1164. {
  1165. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::DiagnoseWriters");
  1166. wprintf (L"\n----------------- DiagnoseWriters ---------------------\n\n");
  1167. if (eType == VSS_TEST_DIAG_WRITERS_ON)
  1168. {
  1169. // Turn on diag
  1170. CVssRegistryKey keyDiag;
  1171. if (!keyDiag.Open(HKEY_LOCAL_MACHINE, x_wszVssDiagPath ))
  1172. keyDiag.Create(HKEY_LOCAL_MACHINE, x_wszVssDiagPath );
  1173. CVssSecurityDescriptor objSD;
  1174. // Build the securityd descriptor
  1175. ft.hr = objSD.InitializeFromThreadToken();
  1176. if (ft.HrFailed())
  1177. ft.TranslateGenericError( VSSDBG_GEN, ft.hr, L"objSD.InitializeFromThreadToken()");
  1178. // Make sure the SACL is NULL (not supported by COM)
  1179. if (objSD.m_pSACL) {
  1180. free(objSD.m_pSACL);
  1181. objSD.m_pSACL= NULL;
  1182. }
  1183. CVssSidCollection sidCollection;
  1184. sidCollection.Initialize();
  1185. // Add principals to the DACL
  1186. for (INT nIndex = 0; nIndex < sidCollection.GetSidCount(); nIndex++)
  1187. {
  1188. if (sidCollection.IsSidAllowed(nIndex))
  1189. {
  1190. ft.hr = objSD.Allow(sidCollection.GetSid(nIndex),
  1191. KEY_ALL_ACCESS, // Registry access rights (for Diag)
  1192. CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
  1193. );
  1194. if (ft.HrFailed())
  1195. ft.TranslateGenericError( VSSDBG_GEN, ft.hr,
  1196. L"objSD.Allow(%s, COM_RIGHTS_EXECUTE);",
  1197. sidCollection.GetPrincipal(nIndex));
  1198. }
  1199. else
  1200. {
  1201. ft.hr = objSD.Deny(sidCollection.GetSid(nIndex),
  1202. KEY_ALL_ACCESS, // Registry access rights (for Diag)
  1203. CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
  1204. );
  1205. if (ft.HrFailed())
  1206. ft.TranslateGenericError( VSSDBG_GEN, ft.hr,
  1207. L"objSD.Deny(%s, COM_RIGHTS_EXECUTE);",
  1208. sidCollection.GetPrincipal(nIndex));
  1209. }
  1210. }
  1211. // Set the correct security on the Diag key (so that third-party writers will be diagnosed correctly)
  1212. SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;
  1213. DWORD dwRes = ::RegSetKeySecurity( keyDiag.GetHandle(), secInfo, objSD );
  1214. if (dwRes != ERROR_SUCCESS)
  1215. ft.TranslateGenericError( VSSDBG_COORD, HRESULT_FROM_WIN32(dwRes),
  1216. L"::RegSetKeySecurity( keyDiag.GetHandle(), secInfo, objSD )");
  1217. // Enable the diag in the registry
  1218. keyDiag.SetValue(L"", x_wszVssDiagEnabledValue);
  1219. wprintf (L"Diagnose writers is now turned on.\n");
  1220. wprintf (L"\n-----------------------------------------------\n\n");
  1221. return;
  1222. }
  1223. if (eType == VSS_TEST_DIAG_WRITERS_OFF)
  1224. {
  1225. // Disable the diag in the registry
  1226. CVssRegistryKey keyDiag;
  1227. if (keyDiag.Open(HKEY_LOCAL_MACHINE, x_wszVssDiagPath )) {
  1228. keyDiag.SetValue(L"", L"");
  1229. keyDiag.Close();
  1230. }
  1231. // Turn off diag
  1232. CVssRegistryKey keyVSS;
  1233. if (keyVSS.Open(HKEY_LOCAL_MACHINE, x_wszVSSKey ))
  1234. keyVSS.DeleteSubkey( L"Diag" );
  1235. wprintf (L"Diagnose writers is now turned off.\n");
  1236. wprintf (L"\n-----------------------------------------------\n\n");
  1237. return;
  1238. }
  1239. CVssSimpleMap<INT,CVssDiagData*> arrEvents;
  1240. // Enumerate all keys under diag
  1241. CVssRegistryKey keyDiag;
  1242. if (!keyDiag.Open(HKEY_LOCAL_MACHINE, x_wszVssDiagPath)){
  1243. wprintf (L"\nDiagnose disabled...\n\n");
  1244. wprintf (L"\n----------------------------------------------------------\n");
  1245. return;
  1246. }
  1247. CVssRegistryKeyIterator keyIterator;
  1248. keyIterator.Attach(keyDiag);
  1249. INT nIndex = 0;
  1250. for( ;!keyIterator.IsEOF(); keyIterator.MoveNext())
  1251. {
  1252. CVssRegistryKey keyWriter(KEY_QUERY_VALUE);
  1253. if (!keyWriter.Open(keyDiag.GetHandle(), keyIterator.GetCurrentKeyName()))
  1254. ft.Throw (VSSDBG_VSSTEST, E_UNEXPECTED,
  1255. L"Failed to open registry entry for key %s", keyIterator.GetCurrentKeyName());
  1256. CVssRegistryValueIterator valIterator;
  1257. valIterator.Attach(keyWriter);
  1258. // for each value take the value name as the user name (in the "domain\user" format)
  1259. for(;!valIterator.IsEOF();valIterator.MoveNext())
  1260. {
  1261. // Check to see ifthe value is of the right type
  1262. if (valIterator.GetCurrentValueType() != REG_BINARY) {
  1263. ft.Trace( VSSDBG_VSSTEST,
  1264. L"Invalid data for value %s on key %s",
  1265. valIterator.GetCurrentValueName(),
  1266. keyIterator.GetCurrentKeyName());
  1267. continue;
  1268. }
  1269. // Get the allow/deny flag
  1270. CVssAutoCppPtr<PBYTE> awszBuffer;
  1271. DWORD cbSize = 0;
  1272. valIterator.GetCurrentValueContent(*(awszBuffer.ResetAndGetAddress()), cbSize);
  1273. // Copy the value into a local CVssDiagData buffer
  1274. if (cbSize != sizeof(CVssDiagData)) {
  1275. ft.Trace( VSSDBG_VSSTEST,
  1276. L"Invalid data for value %s on key %s [%ld, %ld]",
  1277. valIterator.GetCurrentValueName(),
  1278. keyIterator.GetCurrentKeyName(),
  1279. cbSize, sizeof(CVssDiagData));
  1280. continue;
  1281. }
  1282. // We should allocate again (alignment problems)
  1283. CVssAutoCppPtr<CVssDiagData*> pDiag = new CVssDiagData;
  1284. if (!pDiag.IsValid())
  1285. ft.ThrowOutOfMemory(VSSDBG_VSSTEST);
  1286. CopyMemory((LPVOID)pDiag.Get(), (LPVOID)awszBuffer.Get(), sizeof(CVssDiagData));
  1287. // Get the writer name
  1288. CVssAutoLocalString strWriterName;
  1289. strWriterName.CopyFrom(keyIterator.GetCurrentKeyName());
  1290. pDiag.Get()->m_pReserved1 = (LPVOID)strWriterName.Detach();
  1291. // Get the event name
  1292. CVssAutoLocalString strEventName;
  1293. strEventName.CopyFrom(valIterator.GetCurrentValueName());
  1294. pDiag.Get()->m_pReserved2 = (LPVOID)strEventName.Detach();
  1295. // Add the buffer into the dynamic array
  1296. if (!arrEvents.Add(nIndex++, pDiag))
  1297. ft.ThrowOutOfMemory(VSSDBG_VSSTEST);
  1298. pDiag.Detach();
  1299. }
  1300. }
  1301. // Sort the array
  1302. CVssDiagData** pArrDiagData = arrEvents.m_aVal;
  1303. qsort( (void*)pArrDiagData, arrEvents.GetSize(), sizeof(CVssDiagData*), &compare_DiagData);
  1304. CVssEventPairMap arrEventPairs;
  1305. if (eType == VSS_TEST_DIAG_WRITERS_CSV)
  1306. wprintf(L"%s,%s,%s,%s,%s,%s,%s,%s,%s\n",
  1307. L"Date & Time", L"PID", L"TID",
  1308. L"Writer", L"Event",
  1309. L"Timestamp",
  1310. L"State", L"Last error code",
  1311. L"Snapshot Set ID");
  1312. // Print the result and deallocate array elements
  1313. for (nIndex = 0; nIndex < arrEvents.GetSize(); nIndex++)
  1314. {
  1315. CVssDiagData* pData = arrEvents.GetValueAt(nIndex);
  1316. // Convert the timestamp into a readable value
  1317. CVssAutoLocalString pwszDateTime;
  1318. pwszDateTime.Attach(DateTimeToString(pData->m_llTimestamp));
  1319. LPWSTR wszWriterName = (LPWSTR)pData->m_pReserved1;
  1320. LPWSTR wszEventName = (LPWSTR)pData->m_pReserved2;
  1321. if (eType == VSS_TEST_DIAG_WRITERS_LOG)
  1322. wprintf(L"* [%s - %ld.%ld] %s.%s\n (0x%016I64x, 0x%08lx, 0x%08lx, " WSTR_GUID_FMT L")\n\n",
  1323. pwszDateTime.Get(), pData->m_dwProcessID, pData->m_dwThreadID,
  1324. wszWriterName, wszEventName,
  1325. pData->m_llTimestamp,
  1326. pData->m_dwCurrentState, pData->m_hrLastErrorCode,
  1327. GUID_PRINTF_ARG(pData->m_guidSnapshotSetID));
  1328. if (eType == VSS_TEST_DIAG_WRITERS_CSV)
  1329. wprintf(L"%s,%ld,%ld,%s,%s,0x%016I64x,0x%08lx,0x%08lx," WSTR_GUID_FMT L"\n",
  1330. pwszDateTime.Get(), pData->m_dwProcessID, pData->m_dwThreadID,
  1331. wszWriterName, wszEventName,
  1332. pData->m_llTimestamp,
  1333. pData->m_dwCurrentState, pData->m_hrLastErrorCode,
  1334. GUID_PRINTF_ARG(pData->m_guidSnapshotSetID));
  1335. // Find events that have an Enter but not a Leave.
  1336. // Ignore one-time events (known to have an enter but no leave)
  1337. if ((pData->m_dwEventContext & CVssDiag::VSS_DIAG_IGNORE_LEAVE) == 0)
  1338. {
  1339. // If the element is an "Enter" then add it to the map
  1340. CVssDiagData* pPrevData = arrEventPairs.Lookup(
  1341. CVssWriterEventPair(wszWriterName, pData->m_dwEventID) );
  1342. if (pPrevData == NULL)
  1343. {
  1344. if (!arrEventPairs.Add(
  1345. CVssWriterEventPair(wszWriterName, pData->m_dwEventID), pData))
  1346. ft.ThrowOutOfMemory(VSSDBG_VSSTEST);
  1347. }
  1348. else
  1349. {
  1350. // If we have an old enter and a new leave, then remove the entry
  1351. if (!(pData->m_dwEventContext & CVssDiag::VSS_DIAG_ENTER_OPERATION) &&
  1352. (pPrevData->m_dwEventContext & CVssDiag::VSS_DIAG_ENTER_OPERATION) &&
  1353. (pData->m_llTimestamp >= pPrevData->m_llTimestamp))
  1354. {
  1355. arrEventPairs.Remove( CVssWriterEventPair(wszWriterName, pData->m_dwEventID) );
  1356. continue;
  1357. }
  1358. // If we have an enter leave of the same age, then remove the entry
  1359. if ((pData->m_dwEventContext & CVssDiag::VSS_DIAG_ENTER_OPERATION) &&
  1360. !(pPrevData->m_dwEventContext & CVssDiag::VSS_DIAG_ENTER_OPERATION) &&
  1361. (pData->m_llTimestamp == pPrevData->m_llTimestamp))
  1362. {
  1363. arrEventPairs.Remove( CVssWriterEventPair(wszWriterName, pData->m_dwEventID) );
  1364. continue;
  1365. }
  1366. // otherwise keep the most recent event
  1367. if (pData->m_llTimestamp > pPrevData->m_llTimestamp)
  1368. arrEventPairs.SetAt(
  1369. CVssWriterEventPair(wszWriterName, pData->m_dwEventID), pData);
  1370. }
  1371. }
  1372. }
  1373. // Display the list of pending operations
  1374. if (arrEventPairs.GetSize() != 0)
  1375. wprintf(L"\n\n --- Pending writers: --- \n\n");
  1376. else
  1377. wprintf(L"\n\n --- No pending writers --- \n\n");
  1378. if (eType == VSS_TEST_DIAG_WRITERS_CSV)
  1379. wprintf(L"%s,%s,%s,%s,%s,%s,%s,%s,%s\n",
  1380. L"Date & Time", L"PID", L"TID",
  1381. L"Writer", L"Event",
  1382. L"Timestamp",
  1383. L"State", L"Last error code",
  1384. L"Snapshot Set ID");
  1385. for (nIndex = 0; nIndex < arrEventPairs.GetSize(); nIndex++)
  1386. {
  1387. CVssDiagData* pData = arrEventPairs.GetValueAt(nIndex);
  1388. BS_ASSERT(pData);
  1389. // Convert the timestamp into a readable value
  1390. CVssAutoLocalString pwszDateTime;
  1391. pwszDateTime.Attach(DateTimeToString(pData->m_llTimestamp));
  1392. LPWSTR wszWriterName = (LPWSTR)pData->m_pReserved1;
  1393. LPWSTR wszEventName = (LPWSTR)pData->m_pReserved2;
  1394. if (eType == VSS_TEST_DIAG_WRITERS_CSV)
  1395. wprintf(L"%s,%ld.%ld,%s.%s,0x%08lx,0x%08lx," WSTR_GUID_FMT L"\n",
  1396. pwszDateTime.Get(), pData->m_dwProcessID, pData->m_dwThreadID,
  1397. wszWriterName, wszEventName,
  1398. pData->m_dwCurrentState, pData->m_hrLastErrorCode,
  1399. GUID_PRINTF_ARG(pData->m_guidSnapshotSetID));
  1400. else
  1401. wprintf(L"* [%s - %ld.%ld] %s.%s\n (0x%08lx, 0x%08lx, " WSTR_GUID_FMT L")\n\n",
  1402. pwszDateTime.Get(), pData->m_dwProcessID, pData->m_dwThreadID,
  1403. wszWriterName, wszEventName,
  1404. pData->m_dwCurrentState, pData->m_hrLastErrorCode,
  1405. GUID_PRINTF_ARG(pData->m_guidSnapshotSetID));
  1406. }
  1407. // Deallocate elements
  1408. for (nIndex = 0; nIndex < arrEvents.GetSize(); nIndex++)
  1409. {
  1410. CVssAutoCppPtr<CVssDiagData*> ptrData = arrEvents.GetValueAt(nIndex);
  1411. CVssDiagData* pData = ptrData.Get();
  1412. CVssAutoLocalString wszWriterName = (LPWSTR)pData->m_pReserved1;
  1413. CVssAutoLocalString wszEventName = (LPWSTR)pData->m_pReserved2;
  1414. }
  1415. wprintf (L"\n----------------------------------------------------------\n");
  1416. }
  1417. // Just list writers
  1418. void CVssMultilayerTest::TestListWriters()
  1419. {
  1420. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::TestListWriters");
  1421. // Create the Backup components object and initialize for backup
  1422. CHECK_NOFAIL(CreateVssBackupComponents(&m_pBackupComponents));
  1423. CHECK_NOFAIL(m_pBackupComponents->InitializeForBackup());
  1424. CHECK_SUCCESS(m_pBackupComponents->SetBackupState( false, true, VSS_BT_FULL, false));
  1425. wprintf (L"Backup components object created.\n");
  1426. DisplayCurrentTime();
  1427. // Gather writer metadata
  1428. GatherWriterMetadata();
  1429. GatherWriterStatus(L"after GatherWriterMetadata",
  1430. VSS_QWS_DISPLAY_WRITER_STATUS | VSS_QWS_THROW_ON_WRITER_FAILURE);
  1431. DisplayCurrentTime();
  1432. }
  1433. // Just display the current date and time
  1434. void CVssMultilayerTest::DisplayCurrentTime()
  1435. {
  1436. // Convert the timestamp into a readable value
  1437. CVsFileTime filetime;
  1438. CVssAutoLocalString awszDateTime;
  1439. awszDateTime.Attach(DateTimeToString(filetime));
  1440. wprintf (L"\n* Current time: [%s] - [0x%0I64x]\n", (LPWSTR)awszDateTime, (LONGLONG)filetime);
  1441. }