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.

914 lines
31 KiB

  1. /*
  2. **++
  3. **
  4. ** Copyright (c) 2000-2001 Microsoft Corporation
  5. **
  6. **
  7. ** Module Name:
  8. **
  9. ** mlutil.cpp
  10. **
  11. **
  12. ** Abstract:
  13. **
  14. ** Utility functions for the VSML test.
  15. **
  16. ** Author:
  17. **
  18. ** Adi Oltean [aoltean] 03/05/2001
  19. **
  20. ** The sample is based on the Metasnap test program written by Michael C. Johnson.
  21. **
  22. **
  23. ** Revision History:
  24. **
  25. **--
  26. */
  27. ///////////////////////////////////////////////////////////////////////////////
  28. // Includes
  29. #include "ml.h"
  30. #include "ntddsnap.h"
  31. #include "ntddvol.h"
  32. ///////////////////////////////////////////////////////////////////////////////
  33. // Command line parsing
  34. bool CVssMultilayerTest::PrintUsage(bool bThrow /* = true */)
  35. {
  36. wprintf(
  37. L"\nUsage:\n"
  38. L" 1) For snapshot creation:\n"
  39. L" vsml [-xt|-xa|-xp] [-s <seed_number>] <volumes>\n"
  40. L" 2) For query:\n"
  41. L" vsml [-xt|-xa|-xp|-xf] -qs [-P <ProviderID>]\n"
  42. L" vsml [-xt|-xa|-xp|-xf] -qsv <volume> [-P <ProviderID>]\n"
  43. L" vsml [-xt|-xa|-xp|-xf] -qv [-P <ProviderID>]\n"
  44. L" vsml -qi <volume>\n"
  45. L" vsml -is <volume>\n"
  46. L" vsml -lw\n"
  47. L" 3) For diff area:\n"
  48. L" vsml -da <vol> <diff vol> <max size> [-P <ProviderID>]\n"
  49. L" vsml -dr <vol> <diff vol> [-P <ProviderID>]\n"
  50. L" vsml -ds <vol> <diff vol> <max size> [-P <ProviderID>]\n"
  51. L" vsml -dqv [-v original_volume] [-P <ProviderID>]\n"
  52. L" vsml -dqf <volume> [-P <ProviderID>]\n"
  53. L" vsml -dqo <volume> [-P <ProviderID>]\n"
  54. L" vsml -dqs {SnapshotID} [-P <ProviderID>]\n"
  55. L" 4) For deleting snapshots:\n"
  56. L" vsml [-xt|-xa|-xp] -r {snapshot id}\n"
  57. L" vsml [-xt|-xa|-xp] -rs {snapshot set id}\n"
  58. L" 5) For various tests:\n"
  59. L" vsml [-xt|-xa|-xp] -sp {snapshot id} PropertyId string\n"
  60. L" vsml -test_sc\n"
  61. L" 6) For displaying various constants:\n"
  62. L" vsml -const\n"
  63. L" 7) For diagnosing writers:\n"
  64. L" vsml -diag\n"
  65. L" vsml -diag log\n"
  66. L" vsml -diag csv\n"
  67. L" vsml -diag on\n"
  68. L" vsml -diag off\n"
  69. L"\nOptions:\n"
  70. L" -s Specifies a seed for the random number generator\n"
  71. L" -xt Operates in the Timewarp context\n"
  72. L" -xa Operates in the 'ALL' context\n"
  73. L" -xp Operates in the 'Nas Rollback' context\n"
  74. L" -xr Operates in the 'App Rollback' context\n"
  75. L" -xf Operates in the File Share Backup context\n"
  76. L" -qs Queries the existing snapshots\n"
  77. L" -qi Queries the VOLSNAP snapshots (through ioctl)\n"
  78. L" -is Checks if the volume is snapshotted (through C API)\n"
  79. L" -qsv Queries the snapshots on the given volume\n"
  80. L" -qv Queries the supported volumes.\n"
  81. L" -P Specifies a provider Id\n"
  82. L" -da Adds a diff area association.\n"
  83. L" -dr Removes a diff area association.\n"
  84. L" -ds Change diff area max size.\n"
  85. L" -dqv Query the volumes supported for diff area.\n"
  86. L" -dqf Query the diff area associations for volume.\n"
  87. L" -dqo Query the diff area associations on volume.\n"
  88. L" -dqs Query the diff area associations for snapshot.\n"
  89. L" -r Remove the snapshot with that ID.\n"
  90. L" -rs Remove the snapshots from the set with that ID.\n"
  91. L" -sp Set snapshot properties.\n"
  92. L" -test_sc Test SID collection.\n"
  93. L" -const Prints out various constants.\n"
  94. L" -? Displays this help.\n"
  95. L" -D Pops up an assert for attaching a debugger.\n"
  96. L" -diag Diagnose all writers. Print all writers.\n"
  97. L" -diag log Diagnose all writers. Print only pending writers.\n"
  98. L" -diag csv Diagnose all writers. Print information in CSV format.\n"
  99. L" -diag on Turn on diagnose.\n"
  100. L" -diag off Turn off diagnose.\n"
  101. L" -lw List writers.\n"
  102. L"\n"
  103. L"\nExample:\n"
  104. L" The following command will create a backup snapshot set\n"
  105. L" on the volumes mounted under c:\\ and d:\\\n"
  106. L"\n"
  107. L" vsml c:\\ d:\\ \n"
  108. L"\n"
  109. );
  110. if (bThrow)
  111. throw(E_INVALIDARG);
  112. return false;
  113. }
  114. #define VSS_PRINT_VALUE(x) wprintf(L" 0x%08lx - %S\n", x, #x);
  115. #define VSS_PRINT_GUID(X) wprintf( L" {%.8x-%.4x-%.4x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x} - %S\n", \
  116. (X).Data1, \
  117. (X).Data2, \
  118. (X).Data3, \
  119. (X).Data4[0], (X).Data4[1], (X).Data4[2], (X).Data4[3], \
  120. (X).Data4[4], (X).Data4[5], (X).Data4[6], (X).Data4[7], \
  121. #X);
  122. bool CVssMultilayerTest::ParseCommandLine()
  123. {
  124. if (!TokensLeft() || Match(L"-?"))
  125. return PrintUsage(false);
  126. // Check for context options
  127. if (Match(L"-D"))
  128. m_bAttachYourDebuggerNow = true;
  129. // displays all ioctls
  130. if (Match(L"-const")) {
  131. m_eTest = VSS_TEST_NONE;
  132. wprintf (L"\nVolsnap ioctls:\n");
  133. VSS_PRINT_VALUE(IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES);
  134. VSS_PRINT_VALUE(IOCTL_VOLSNAP_RELEASE_WRITES);
  135. VSS_PRINT_VALUE(IOCTL_VOLSNAP_PREPARE_FOR_SNAPSHOT);
  136. VSS_PRINT_VALUE(IOCTL_VOLSNAP_ABORT_PREPARED_SNAPSHOT);
  137. VSS_PRINT_VALUE(IOCTL_VOLSNAP_COMMIT_SNAPSHOT);
  138. VSS_PRINT_VALUE(IOCTL_VOLSNAP_END_COMMIT_SNAPSHOT);
  139. VSS_PRINT_VALUE(IOCTL_VOLSNAP_QUERY_NAMES_OF_SNAPSHOTS);
  140. VSS_PRINT_VALUE(IOCTL_VOLSNAP_CLEAR_DIFF_AREA);
  141. VSS_PRINT_VALUE(IOCTL_VOLSNAP_ADD_VOLUME_TO_DIFF_AREA);
  142. VSS_PRINT_VALUE(IOCTL_VOLSNAP_QUERY_DIFF_AREA);
  143. VSS_PRINT_VALUE(IOCTL_VOLSNAP_SET_MAX_DIFF_AREA_SIZE);
  144. VSS_PRINT_VALUE(IOCTL_VOLSNAP_QUERY_DIFF_AREA_SIZES);
  145. VSS_PRINT_VALUE(IOCTL_VOLSNAP_DELETE_OLDEST_SNAPSHOT);
  146. VSS_PRINT_VALUE(IOCTL_VOLSNAP_AUTO_CLEANUP);
  147. VSS_PRINT_VALUE(IOCTL_VOLSNAP_DELETE_SNAPSHOT);
  148. VSS_PRINT_VALUE(IOCTL_VOLSNAP_QUERY_ORIGINAL_VOLUME_NAME);
  149. VSS_PRINT_VALUE(IOCTL_VOLSNAP_QUERY_CONFIG_INFO);
  150. VSS_PRINT_VALUE(IOCTL_VOLSNAP_SET_APPLICATION_INFO);
  151. VSS_PRINT_VALUE(IOCTL_VOLSNAP_QUERY_APPLICATION_INFO);
  152. VSS_PRINT_VALUE(FSCTL_DISMOUNT_VOLUME);
  153. VSS_PRINT_VALUE(IOCTL_VOLUME_OFFLINE);
  154. wprintf (L"\n\nVolsnap contexes:\n");
  155. VSS_PRINT_VALUE(VSS_CTX_BACKUP);
  156. VSS_PRINT_VALUE(VSS_CTX_FILE_SHARE_BACKUP);
  157. VSS_PRINT_VALUE(VSS_CTX_NAS_ROLLBACK);
  158. VSS_PRINT_VALUE(VSS_CTX_APP_ROLLBACK);
  159. VSS_PRINT_VALUE(VSS_CTX_CLIENT_ACCESSIBLE);
  160. VSS_PRINT_VALUE(VSS_CTX_ALL);
  161. wprintf (L"\n\nVolsnap guids:\n");
  162. VSS_PRINT_GUID(VOLSNAP_APPINFO_GUID_BACKUP_CLIENT_SKU);
  163. VSS_PRINT_GUID(VOLSNAP_APPINFO_GUID_BACKUP_SERVER_SKU);
  164. VSS_PRINT_GUID(VOLSNAP_APPINFO_GUID_SYSTEM_HIDDEN);
  165. VSS_PRINT_GUID(VOLSNAP_APPINFO_GUID_NAS_ROLLBACK);
  166. VSS_PRINT_GUID(VOLSNAP_APPINFO_GUID_APP_ROLLBACK);
  167. VSS_PRINT_GUID(VOLSNAP_APPINFO_GUID_FILE_SHARE_BACKUP);
  168. wprintf(L"\n\nValid attributes for SetContext:\n");
  169. wprintf(L" VSS_VOLSNAP_ATTR_EXPOSED_LOCALLY = %d\n", VSS_VOLSNAP_ATTR_EXPOSED_LOCALLY);
  170. wprintf(L" VSS_VOLSNAP_ATTR_EXPOSED_REMOTELY = %d\n", VSS_VOLSNAP_ATTR_EXPOSED_REMOTELY);
  171. wprintf(L" VSS_VOLSNAP_ATTR_EXPOSED_LOCALLY | VSS_..._REMOTELY = %d\n",
  172. VSS_VOLSNAP_ATTR_EXPOSED_LOCALLY | VSS_VOLSNAP_ATTR_EXPOSED_REMOTELY);
  173. wprintf(L"\n\nValid property IDs:\n");
  174. wprintf(L" VSS_SPROPID_SNAPSHOT_ATTRIBUTES = %d\n", VSS_SPROPID_SNAPSHOT_ATTRIBUTES);
  175. wprintf(L" VSS_SPROPID_EXPOSED_NAME = %d\n", VSS_SPROPID_EXPOSED_NAME);
  176. wprintf(L" VSS_SPROPID_EXPOSED_PATH = %d\n", VSS_SPROPID_EXPOSED_PATH);
  177. wprintf(L" VSS_SPROPID_SERVICE_MACHINE = %d\n", VSS_SPROPID_SERVICE_MACHINE);
  178. wprintf(L"\n");
  179. return TokensLeft()? PrintUsage(): true;
  180. }
  181. // Test CSidCollection
  182. if (Match(L"-test_sc")) {
  183. m_eTest = VSS_TEST_ACCESS_CONTROL_SD;
  184. return TokensLeft()? PrintUsage(): true;
  185. }
  186. // Diagnose writers
  187. if (Match(L"-diag")) {
  188. if (Match(L"on")) {
  189. m_eTest = VSS_TEST_DIAG_WRITERS_ON;
  190. return TokensLeft()? PrintUsage(): true;
  191. }
  192. if (Match(L"off")) {
  193. m_eTest = VSS_TEST_DIAG_WRITERS_OFF;
  194. return TokensLeft()? PrintUsage(): true;
  195. }
  196. if (Match(L"log")) {
  197. m_eTest = VSS_TEST_DIAG_WRITERS_LOG;
  198. return TokensLeft()? PrintUsage(): true;
  199. }
  200. if (Match(L"csv")) {
  201. m_eTest = VSS_TEST_DIAG_WRITERS_CSV;
  202. return TokensLeft()? PrintUsage(): true;
  203. }
  204. if (!TokensLeft()) {
  205. m_eTest = VSS_TEST_DIAG_WRITERS;
  206. return true;
  207. }
  208. return PrintUsage();
  209. }
  210. // Check for List Writers
  211. if (Match(L"-lw"))
  212. {
  213. m_eTest = VSS_TEST_LIST_WRITERS;
  214. return TokensLeft()? PrintUsage(): true;
  215. }
  216. // Query using the IOCTL
  217. if (Match(L"-qi")) {
  218. m_eTest = VSS_TEST_VOLSNAP_QUERY;
  219. // Get the original volume
  220. if (!Extract(m_pwszVolume) || !IsVolume(m_pwszVolume))
  221. return PrintUsage();
  222. return TokensLeft()? PrintUsage(): true;
  223. }
  224. // Query using the IOCTL
  225. if (Match(L"-is")) {
  226. m_eTest = VSS_TEST_IS_VOLUME_SNAPSHOTTED_C;
  227. // Get the original volume
  228. if (!Extract(m_pwszVolume) || !IsVolume(m_pwszVolume))
  229. return PrintUsage();
  230. return TokensLeft()? PrintUsage(): true;
  231. }
  232. // Check for context options
  233. if (Match(L"-xt"))
  234. m_lContext = VSS_CTX_CLIENT_ACCESSIBLE;
  235. if (Match(L"-xa"))
  236. m_lContext = VSS_CTX_ALL;
  237. if (Match(L"-xp"))
  238. m_lContext = VSS_CTX_NAS_ROLLBACK;
  239. if (Match(L"-xr"))
  240. m_lContext = VSS_CTX_APP_ROLLBACK;
  241. if (Match(L"-xf"))
  242. m_lContext = VSS_CTX_FILE_SHARE_BACKUP;
  243. // Set the snapshot property
  244. if (Match(L"-sp")) {
  245. m_eTest = VSS_TEST_SET_SNAPSHOT_PROPERTIES;
  246. // Extract the snapshot id
  247. if (!Extract(m_SnapshotId))
  248. return PrintUsage();
  249. // Extract the property ID
  250. Extract(m_uPropertyId);
  251. UINT uNewAttributes = 0;
  252. LPWSTR pwszString = NULL;
  253. switch(m_uPropertyId)
  254. {
  255. case VSS_SPROPID_SNAPSHOT_ATTRIBUTES:
  256. // Extract the snapshot attributes
  257. Extract(uNewAttributes);
  258. switch(uNewAttributes)
  259. {
  260. default:
  261. wprintf(L"\nInvalid attributes ID (%lu). Valid ones:\n", uNewAttributes);
  262. wprintf(L" VSS_VOLSNAP_ATTR_EXPOSED_LOCALLY = %d\n", VSS_VOLSNAP_ATTR_EXPOSED_LOCALLY);
  263. wprintf(L" VSS_VOLSNAP_ATTR_EXPOSED_REMOTELY = %d\n", VSS_VOLSNAP_ATTR_EXPOSED_REMOTELY);
  264. wprintf(L" VSS_VOLSNAP_ATTR_EXPOSED_LOCALLY | VSS_..._REMOTELY = %d\n",
  265. VSS_VOLSNAP_ATTR_EXPOSED_LOCALLY | VSS_VOLSNAP_ATTR_EXPOSED_REMOTELY);
  266. return false;
  267. case VSS_VOLSNAP_ATTR_EXPOSED_LOCALLY:
  268. case VSS_VOLSNAP_ATTR_EXPOSED_REMOTELY:
  269. case VSS_VOLSNAP_ATTR_EXPOSED_LOCALLY | VSS_VOLSNAP_ATTR_EXPOSED_REMOTELY:
  270. break;
  271. }
  272. m_value = (LONG)uNewAttributes;
  273. break;
  274. case VSS_SPROPID_EXPOSED_NAME:
  275. case VSS_SPROPID_EXPOSED_PATH:
  276. case VSS_SPROPID_SERVICE_MACHINE:
  277. // Extract the snapshot attributes
  278. if (Extract(pwszString))
  279. {
  280. m_value = pwszString;
  281. ::VssFreeString(pwszString);
  282. }
  283. else
  284. m_value = L"";
  285. break;
  286. default:
  287. wprintf(L"\nInvalid property ID (%ld). Valid ones:\n", m_uPropertyId);
  288. wprintf(L" VSS_SPROPID_SNAPSHOT_ATTRIBUTES = %d\n", VSS_SPROPID_SNAPSHOT_ATTRIBUTES);
  289. wprintf(L" VSS_SPROPID_EXPOSED_NAME = %d\n", VSS_SPROPID_EXPOSED_NAME);
  290. wprintf(L" VSS_SPROPID_EXPOSED_PATH = %d\n", VSS_SPROPID_EXPOSED_PATH);
  291. wprintf(L" VSS_SPROPID_SERVICE_MACHINE = %d\n", VSS_SPROPID_SERVICE_MACHINE);
  292. return false;
  293. }
  294. return TokensLeft()? PrintUsage(): true;
  295. }
  296. // Add the Diff Area
  297. if (Match(L"-da")) {
  298. m_eTest = VSS_TEST_ADD_DIFF_AREA;
  299. // Get the original volume
  300. if (!Extract(m_pwszVolume) || !IsVolume(m_pwszVolume))
  301. return PrintUsage();
  302. // Get the diff area volume
  303. if (!Extract(m_pwszDiffAreaVolume) || !IsVolume(m_pwszDiffAreaVolume))
  304. return PrintUsage();
  305. // Check to see if we specified a max diff area (i.e. -P is not present)
  306. if (!Peek(L"-P"))
  307. Extract(m_llMaxDiffArea);
  308. // Check to see if we specified a provider ID
  309. if (Match(L"-P")) {
  310. if (!Extract(m_ProviderId))
  311. return PrintUsage();
  312. Extract(m_llMaxDiffArea);
  313. }
  314. return TokensLeft()? PrintUsage(): true;
  315. }
  316. // Remove the Diff Area
  317. if (Match(L"-dr")) {
  318. m_eTest = VSS_TEST_REMOVE_DIFF_AREA;
  319. // Get the original volume
  320. if (!Extract(m_pwszVolume) || !IsVolume(m_pwszVolume))
  321. return PrintUsage();
  322. // Get the diff area volume
  323. if (!Extract(m_pwszDiffAreaVolume) || !IsVolume(m_pwszDiffAreaVolume))
  324. return PrintUsage();
  325. // Check to see if we specified a provider ID
  326. if (Match(L"-P"))
  327. if (!Extract(m_ProviderId))
  328. return PrintUsage();
  329. return TokensLeft()? PrintUsage(): true;
  330. }
  331. // Change Diff Area max size
  332. if (Match(L"-ds")) {
  333. m_eTest = VSS_TEST_CHANGE_DIFF_AREA_MAX_SIZE;
  334. // Get the original volume
  335. if (!Extract(m_pwszVolume) || !IsVolume(m_pwszVolume))
  336. return PrintUsage();
  337. // Get the diff area volume
  338. if (!Extract(m_pwszDiffAreaVolume) || !IsVolume(m_pwszDiffAreaVolume))
  339. return PrintUsage();
  340. // Check to see if we specified a max diff area (i.e. -P is not present)
  341. if (!Peek(L"-P"))
  342. Extract(m_llMaxDiffArea);
  343. // Check to see if we specified a provider ID
  344. if (Match(L"-P")) {
  345. if (!Extract(m_ProviderId))
  346. return PrintUsage();
  347. Extract(m_llMaxDiffArea);
  348. }
  349. return TokensLeft()? PrintUsage(): true;
  350. }
  351. // Query the volumes supported for Diff Area
  352. if (Match(L"-dqv")) {
  353. m_eTest = VSS_TEST_QUERY_SUPPORTED_VOLUMES_FOR_DIFF_AREA;
  354. // Check to see if we specified a max diff area (i.e. -P is not present)
  355. if (!Peek(L"-v"))
  356. if (!Extract(m_pwszVolume) || !IsVolume(m_pwszVolume))
  357. return PrintUsage();
  358. // Check to see if we specified a provider ID
  359. if (Match(L"-P"))
  360. if (!Extract(m_ProviderId))
  361. return PrintUsage();
  362. return TokensLeft()? PrintUsage(): true;
  363. }
  364. // Query the volumes supported for Diff Area
  365. if (Match(L"-dqf")) {
  366. m_eTest = VSS_TEST_QUERY_DIFF_AREAS_FOR_VOLUME;
  367. // Get the original volume
  368. if (!Extract(m_pwszVolume) || !IsVolume(m_pwszVolume))
  369. return PrintUsage();
  370. // Check to see if we specified a provider ID
  371. if (Match(L"-P"))
  372. if (!Extract(m_ProviderId))
  373. return PrintUsage();
  374. return TokensLeft()? PrintUsage(): true;
  375. }
  376. // Query the volumes supported for Diff Area
  377. if (Match(L"-dqo")) {
  378. m_eTest = VSS_TEST_QUERY_DIFF_AREAS_ON_VOLUME;
  379. // Get the original volume
  380. if (!Extract(m_pwszDiffAreaVolume) || !IsVolume(m_pwszDiffAreaVolume))
  381. return PrintUsage();
  382. // Check to see if we specified a provider ID
  383. if (Match(L"-P"))
  384. if (!Extract(m_ProviderId))
  385. return PrintUsage();
  386. return TokensLeft()? PrintUsage(): true;
  387. }
  388. // Query the volumes supported for Diff Area
  389. if (Match(L"-dqs")) {
  390. m_eTest = VSS_TEST_QUERY_DIFF_AREAS_FOR_SNAPSHOT;
  391. // Get the original volume
  392. if (!Extract(m_SnapshotId))
  393. return PrintUsage();
  394. // Check to see if we specified a provider ID
  395. if (Match(L"-P"))
  396. if (!Extract(m_ProviderId))
  397. return PrintUsage();
  398. return TokensLeft()? PrintUsage(): true;
  399. }
  400. // Check for Query
  401. if (Match(L"-qs")) {
  402. m_eTest = VSS_TEST_QUERY_SNAPSHOTS;
  403. // Check to see if we specified a provider ID
  404. if (Match(L"-P"))
  405. if (!Extract(m_ProviderId))
  406. return PrintUsage();
  407. return TokensLeft()? PrintUsage(): true;
  408. }
  409. // Check for Query
  410. if (Match(L"-qsv")) {
  411. m_eTest = VSS_TEST_QUERY_SNAPSHOTS_ON_VOLUME;
  412. // Extract the volume volume
  413. if (!Extract(m_pwszVolume) || !IsVolume(m_pwszVolume))
  414. return PrintUsage();
  415. // Check to see if we specified a provider ID
  416. if (Match(L"-P"))
  417. if (!Extract(m_ProviderId))
  418. return PrintUsage();
  419. return TokensLeft()? PrintUsage(): true;
  420. }
  421. // Check for Query Supported Volumes
  422. if (Match(L"-qv")) {
  423. m_eTest = VSS_TEST_QUERY_VOLUMES;
  424. // Check to see if we specified a provider ID
  425. if (Match(L"-P"))
  426. if (!Extract(m_ProviderId))
  427. return PrintUsage();
  428. return TokensLeft()? PrintUsage(): true;
  429. }
  430. // Check for Delete by snapshot Id
  431. if (Match(L"-r")) {
  432. m_eTest = VSS_TEST_DELETE_BY_SNAPSHOT_ID;
  433. // Extract the snapshot id
  434. if (!Extract(m_SnapshotId))
  435. return PrintUsage();
  436. return TokensLeft()? PrintUsage(): true;
  437. }
  438. // Check for Delete by snapshot set Id
  439. if (Match(L"-rs")) {
  440. m_eTest = VSS_TEST_DELETE_BY_SNAPSHOT_SET_ID;
  441. // Extract the snapshot id
  442. if (!Extract(m_SnapshotSetId))
  443. return PrintUsage();
  444. return TokensLeft()? PrintUsage(): true;
  445. }
  446. // Check for Seed option
  447. if (Match(L"-s"))
  448. if (!Extract(m_uSeed))
  449. return PrintUsage();
  450. // We are in snapshot creation mode
  451. if (!TokensLeft())
  452. return PrintUsage();
  453. bool bVolumeAdded = false;
  454. VSS_PWSZ pwszVolumeName = NULL;
  455. while (TokensLeft()) {
  456. Extract(pwszVolumeName);
  457. if (!AddVolume(pwszVolumeName, bVolumeAdded)) {
  458. wprintf(L"\nError while parsing the command line:\n"
  459. L"\t%s is not a valid option or a mount point [0x%08lx]\n\n",
  460. GetCurrentToken(), GetLastError() );
  461. return PrintUsage();
  462. }
  463. // Check if the same volume is added twice
  464. if (!bVolumeAdded) {
  465. wprintf(L"\nError while parsing the command line:\n"
  466. L"\tThe volume %s is specified twice\n\n", GetCurrentToken() );
  467. return PrintUsage();
  468. }
  469. ::VssFreeString(pwszVolumeName);
  470. }
  471. m_eTest = VSS_TEST_CREATE;
  472. return true;
  473. }
  474. // Check if there are tokens left
  475. bool CVssMultilayerTest::TokensLeft()
  476. {
  477. return (m_nCurrentArgsCount != 0);
  478. }
  479. // Returns the current token
  480. VSS_PWSZ CVssMultilayerTest::GetCurrentToken()
  481. {
  482. return (*m_ppwszCurrentArgsArray);
  483. }
  484. // Go to next token
  485. void CVssMultilayerTest::Shift()
  486. {
  487. BS_ASSERT(m_nCurrentArgsCount);
  488. m_nCurrentArgsCount--;
  489. m_ppwszCurrentArgsArray++;
  490. }
  491. // Check if the current command line token matches with the given pattern
  492. // Do not shift to the next token
  493. bool CVssMultilayerTest::Peek(
  494. IN VSS_PWSZ pwszPattern
  495. ) throw(HRESULT)
  496. {
  497. if (!TokensLeft())
  498. return false;
  499. // Try to find a match
  500. if (wcscmp(GetCurrentToken(), pwszPattern))
  501. return false;
  502. // Go to the next token
  503. return true;
  504. }
  505. // Match the current command line token with the given pattern
  506. // If succeeds, then switch to the next token
  507. bool CVssMultilayerTest::Match(
  508. IN VSS_PWSZ pwszPattern
  509. ) throw(HRESULT)
  510. {
  511. if (!Peek(pwszPattern))
  512. return false;
  513. // Go to the next token
  514. Shift();
  515. return true;
  516. }
  517. // Converts the current token to a guid
  518. // If succeeds, then switch to the next token
  519. bool CVssMultilayerTest::Extract(
  520. IN OUT VSS_ID& Guid
  521. ) throw(HRESULT)
  522. {
  523. if (!TokensLeft())
  524. return false;
  525. // Try to extract the guid
  526. if (!SUCCEEDED(::CLSIDFromString(W2OLE(const_cast<WCHAR*>(GetCurrentToken())), &Guid)))
  527. return false;
  528. // Go to the next token
  529. Shift();
  530. return true;
  531. }
  532. // Converts the current token to a string
  533. // If succeeds, then switch to the next token
  534. bool CVssMultilayerTest::Extract(
  535. IN OUT VSS_PWSZ& pwsz
  536. ) throw(HRESULT)
  537. {
  538. if (!TokensLeft())
  539. return false;
  540. // Extract the string
  541. ::VssDuplicateStr(pwsz, GetCurrentToken());
  542. if (!pwsz)
  543. throw(E_OUTOFMEMORY);
  544. // Go to the next token
  545. Shift();
  546. return true;
  547. }
  548. // Converts the current token to an UINT
  549. // If succeeds, then switch to the next token
  550. bool CVssMultilayerTest::Extract(
  551. IN OUT UINT& uint
  552. ) throw(HRESULT)
  553. {
  554. if (!TokensLeft())
  555. return false;
  556. // Extract the unsigned value
  557. uint = ::_wtoi(GetCurrentToken());
  558. // Go to the next token
  559. Shift();
  560. return true;
  561. }
  562. // Converts the current token to an UINT
  563. // If succeeds, then switch to the next token
  564. bool CVssMultilayerTest::Extract(
  565. IN OUT LONGLONG& llValue
  566. ) throw(HRESULT)
  567. {
  568. if (!TokensLeft())
  569. return false;
  570. // Extract the unsigned value
  571. llValue = ::_wtoi64(GetCurrentToken());
  572. // Go to the next token
  573. Shift();
  574. return true;
  575. }
  576. // Returns true if the given string is a volume
  577. bool CVssMultilayerTest::IsVolume(
  578. IN WCHAR* pwszVolumeDisplayName
  579. )
  580. {
  581. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::IsVolume");
  582. // Check if the volume represents a real mount point
  583. WCHAR wszVolumeName[MAX_TEXT_BUFFER];
  584. if (!GetVolumeNameForVolumeMountPoint(pwszVolumeDisplayName, wszVolumeName, MAX_TEXT_BUFFER))
  585. return false; // Invalid volume
  586. return true;
  587. }
  588. // Add the given volume in the list of potential candidates for snapshots
  589. // - Returns "false" if the volume does not correspond to a real mount point
  590. // (and GetLastError() will contain the correct Win32 error code)
  591. // - Sets "true" in the bAdded parameter if the volume is actually added
  592. bool CVssMultilayerTest::AddVolume(
  593. IN WCHAR* pwszVolumeDisplayName,
  594. OUT bool & bAdded
  595. )
  596. {
  597. CVssFunctionTracer ft(VSSDBG_VSSTEST, L"CVssMultilayerTest::AddVolume");
  598. // Initialize [out] parameters
  599. bAdded = false;
  600. // Check if the volume represents a real mount point
  601. WCHAR wszVolumeName[MAX_TEXT_BUFFER];
  602. if (!GetVolumeNameForVolumeMountPoint(pwszVolumeDisplayName, wszVolumeName, MAX_TEXT_BUFFER))
  603. return false; // Invalid volume
  604. // Check if the volume is already added.
  605. WCHAR* pwszVolumeNameToBeSearched = wszVolumeName;
  606. if (m_mapVolumes.FindKey(pwszVolumeNameToBeSearched) != -1)
  607. return true; // Volume already added. Stop here.
  608. // Create the volume info object
  609. CVssVolumeInfo* pVolInfo = new CVssVolumeInfo(wszVolumeName, pwszVolumeDisplayName);
  610. if (pVolInfo == NULL)
  611. ft.Err(VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allcation error");
  612. // Add the volume in our internal list of snapshotted volumes
  613. if (!m_mapVolumes.Add(pVolInfo->GetVolumeDisplayName(), pVolInfo)) {
  614. delete pVolInfo;
  615. ft.Err(VSSDBG_VSSTEST, E_OUTOFMEMORY, L"Memory allcation error");
  616. }
  617. bAdded = true;
  618. return true;
  619. }
  620. ///////////////////////////////////////////////////////////////////////////////
  621. // Utility functions
  622. // Convert a failure type into a string
  623. LPCWSTR CVssMultilayerTest::GetStringFromFailureType( IN HRESULT hrStatus )
  624. {
  625. static WCHAR wszBuffer[MAX_TEXT_BUFFER];
  626. switch (hrStatus)
  627. {
  628. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT)
  629. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_WRITERERROR_OUTOFRESOURCES)
  630. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_WRITERERROR_TIMEOUT)
  631. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_WRITERERROR_NONRETRYABLE)
  632. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_WRITERERROR_RETRYABLE)
  633. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_BAD_STATE)
  634. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_PROVIDER_ALREADY_REGISTERED)
  635. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_PROVIDER_NOT_REGISTERED)
  636. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_PROVIDER_VETO)
  637. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_PROVIDER_IN_USE)
  638. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_OBJECT_NOT_FOUND)
  639. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_S_ASYNC_PENDING)
  640. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_S_ASYNC_FINISHED)
  641. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_S_ASYNC_CANCELLED)
  642. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_VOLUME_NOT_SUPPORTED)
  643. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_VOLUME_NOT_SUPPORTED_BY_PROVIDER)
  644. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_OBJECT_ALREADY_EXISTS)
  645. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_UNEXPECTED_PROVIDER_ERROR)
  646. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_CORRUPT_XML_DOCUMENT)
  647. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_INVALID_XML_DOCUMENT)
  648. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_MAXIMUM_NUMBER_OF_VOLUMES_REACHED)
  649. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_FLUSH_WRITES_TIMEOUT)
  650. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_HOLD_WRITES_TIMEOUT)
  651. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_UNEXPECTED_WRITER_ERROR)
  652. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_SNAPSHOT_SET_IN_PROGRESS)
  653. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_MAXIMUM_NUMBER_OF_SNAPSHOTS_REACHED)
  654. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_WRITER_INFRASTRUCTURE)
  655. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_WRITER_NOT_RESPONDING)
  656. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_WRITER_ALREADY_SUBSCRIBED)
  657. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_UNSUPPORTED_CONTEXT)
  658. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_VOLUME_IN_USE)
  659. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_MAXIMUM_DIFFAREA_ASSOCIATIONS_REACHED)
  660. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_E_INSUFFICIENT_STORAGE)
  661. case NOERROR:
  662. break;
  663. default:
  664. ::FormatMessageW( FORMAT_MESSAGE_FROM_SYSTEM,
  665. NULL, hrStatus, 0, (LPWSTR)&wszBuffer, MAX_TEXT_BUFFER - 1, NULL);
  666. break;
  667. }
  668. return (wszBuffer);
  669. }
  670. // Convert a writer status into a string
  671. LPCWSTR CVssMultilayerTest::GetStringFromWriterState( IN VSS_WRITER_STATE state )
  672. {
  673. static WCHAR wszBuffer[MAX_TEXT_BUFFER];
  674. switch (state)
  675. {
  676. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_WS_UNKNOWN)
  677. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_WS_STABLE)
  678. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_WS_WAITING_FOR_FREEZE)
  679. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_WS_WAITING_FOR_THAW)
  680. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_WS_WAITING_FOR_POST_SNAPSHOT)
  681. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_WS_WAITING_FOR_BACKUP_COMPLETE)
  682. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_WS_FAILED_AT_PREPARE_BACKUP)
  683. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_WS_FAILED_AT_PREPARE_SNAPSHOT)
  684. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_WS_FAILED_AT_FREEZE)
  685. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_WS_FAILED_AT_THAW)
  686. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_WS_FAILED_AT_POST_SNAPSHOT)
  687. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_WS_FAILED_AT_BACKUP_COMPLETE)
  688. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_WS_FAILED_AT_PRE_RESTORE)
  689. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_WS_FAILED_AT_POST_RESTORE)
  690. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_WS_FAILED_AT_BACKUPSHUTDOWN)
  691. VSS_ERROR_CASE(wszBuffer, MAX_TEXT_BUFFER, VSS_WS_COUNT)
  692. default:
  693. swprintf(wszBuffer, L" Unknown state %d", state);
  694. break;
  695. }
  696. return (wszBuffer);
  697. }
  698. INT CVssMultilayerTest::RndDecision(
  699. IN INT nVariants /* = 2 */
  700. )
  701. {
  702. return (rand() % nVariants);
  703. }
  704. LPWSTR CVssMultilayerTest::DateTimeToString(
  705. IN LONGLONG llTimestamp
  706. )
  707. {
  708. CVssFunctionTracer ft( VSSDBG_VSSTEST, L"CVssMultilayerTest::DateTimeToString" );
  709. SYSTEMTIME stLocal;
  710. FILETIME ftLocal;
  711. WCHAR pwszDate[ 64 ];
  712. WCHAR pwszTime[ 64 ];
  713. BS_ASSERT(sizeof(FILETIME) == sizeof(LONGLONG));
  714. // Compensate for local TZ
  715. ::FileTimeToLocalFileTime( (FILETIME *) &llTimestamp, &ftLocal );
  716. // Finally convert it to system time
  717. ::FileTimeToSystemTime( &ftLocal, &stLocal );
  718. // Convert timestamp to a date string
  719. ::GetDateFormatW( GetThreadLocale( ),
  720. DATE_SHORTDATE,
  721. &stLocal,
  722. NULL,
  723. pwszDate,
  724. sizeof( pwszDate ) / sizeof( pwszDate[0] ));
  725. // Convert timestamp to a time string
  726. ::GetTimeFormatW( GetThreadLocale( ),
  727. 0,
  728. &stLocal,
  729. NULL,
  730. pwszTime,
  731. sizeof( pwszTime ) / sizeof( pwszTime[0] ));
  732. // Now combine the strings and return it
  733. CVssAutoLocalString pwszDateTime;
  734. pwszDateTime.Append(pwszDate);
  735. pwszDateTime.Append(L" ");
  736. pwszDateTime.Append(pwszTime);
  737. return pwszDateTime.Detach();
  738. }