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.

481 lines
15 KiB

  1. #pragma warning(disable:4290)
  2. #include <stdlib.h>
  3. #include <time.h>
  4. #include <Nt.h>
  5. #include <ntrtl.h>
  6. #include <nturtl.h>
  7. #include <windows.h>
  8. #include <wchar.h>
  9. #include <stdio.h>
  10. #include <oleauto.h>
  11. #include <stddef.h>
  12. #include "vs_assert.hxx"
  13. #include <atlbase.h>
  14. #include "vs_idl.hxx"
  15. #include "vswriter.h"
  16. #include "vsbackup.h"
  17. #include "bsstring.hxx"
  18. enum {
  19. PrepareForBackup = 0,
  20. DoSnapshotSet = 1,
  21. BackupComplete = 2,
  22. PreRestore = 3,
  23. PostRestore = 4,
  24. GatherWriterMetadata = 5,
  25. GatherWriterStatus = 6,
  26. MaxOperations = 7
  27. };
  28. const wchar_t* operationCodes[MaxOperations] = { L"-pfb",
  29. L"-dss",
  30. L"-bc",
  31. L"-prer",
  32. L"-postr",
  33. L"-gwm",
  34. L"-gws" };
  35. const wchar_t* timeCode = L"-time";
  36. wchar_t* programName = L"canceltest.exe";
  37. void checker(HRESULT error, wchar_t* string);
  38. HRESULT cancelTest(IVssAsync* async, LONG cancelDelay);
  39. HRESULT waitTest(IVssAsync* async);
  40. void parse(int argc, wchar_t* argv[], bool* operations, long& waitTime);
  41. int findParam(wchar_t* findee);
  42. CComBSTR runBackupTest(bool* cancel, long cancelDelay);
  43. void runRestoreTest(bool* cancel, long cancelDelay, CComBSTR xmlData);
  44. const wchar_t* WszFromRestoreMethod(VSS_RESTOREMETHOD_ENUM method);
  45. const wchar_t* WszFromUsageType(VSS_USAGE_TYPE usage);
  46. const wchar_t* GetStringFromWriterStatus(VSS_WRITER_STATE eWriterStatus);
  47. void checkMetadata(IVssBackupComponents* components);
  48. void checkStatus(IVssBackupComponents* components);
  49. CBsString helpString();
  50. extern "C" INT __cdecl wmain(int argc, wchar_t* argv[])
  51. {
  52. try {
  53. bool operations[MaxOperations];
  54. long waitTime = 0;
  55. parse(argc, argv, operations, waitTime);
  56. checker(CoInitializeEx(NULL, COINIT_MULTITHREADED),
  57. L"CoInitializeEx");
  58. CComBSTR xmlData = runBackupTest(operations, waitTime);
  59. runRestoreTest(operations, waitTime, xmlData);
  60. } catch(CBsString thrown) {
  61. fwprintf(stderr, thrown);
  62. exit(1);
  63. }
  64. }
  65. void parse(int argc, wchar_t* argv[], bool* operations, long& waitTime)
  66. {
  67. memset(operations, 0, sizeof(bool) * MaxOperations);
  68. // parse each command-line argument
  69. for (int x = 1; x < argc; x++) {
  70. int index = findParam(argv[x]);
  71. if (index == -1) {
  72. if (wcscmp(argv[x], timeCode) != 0) {
  73. CBsString throwString = L"Invalid command line parameter\n\n"+ helpString();
  74. throw throwString;
  75. }
  76. if (x == argc - 1) {
  77. CBsString throwString = L"no value given for time parameter\n\n" + helpString();
  78. throw throwString;
  79. }
  80. waitTime = wcstol(argv[++x], NULL, 10);
  81. } else {
  82. operations[index] = true;
  83. }
  84. }
  85. }
  86. CBsString helpString()
  87. {
  88. CBsString help;
  89. help += L"Usage: ";
  90. help += programName;
  91. help += L" [<option-list>]\n\n";
  92. help += L"[<option-list>] is zero or more of the following options\n";
  93. help += timeCode;
  94. help += L" <milliseconds>\tspecify milliseconds to wait before cancelling\n";
  95. help += operationCodes[PrepareForBackup];
  96. help += L"\t\t\tcancel the asynchronous call to PrepareForBackup\n";
  97. help += operationCodes[DoSnapshotSet];
  98. help += L"\t\t\tcancel the asynchronous call to DoSnapshotSet\n";
  99. help += operationCodes[BackupComplete];
  100. help += L"\t\t\tcancel the asynchronous call to BackupComplete\n";
  101. help += operationCodes[PreRestore];
  102. help += L"\t\t\tcancel the asynchronous call to PreRestore\n";
  103. help += operationCodes[PostRestore];
  104. help += L"\t\t\tcancel the asynchronous call to PostRestore\n";
  105. help += operationCodes[GatherWriterMetadata];
  106. help += L"\t\t\tcancel the asynchronous calls to GatherWriterMetadata\n";
  107. help += operationCodes[GatherWriterStatus];
  108. help += L"\t\t\tcancel the asynchronous calls to GatherWriterStatus\n";
  109. return help;
  110. }
  111. int findParam(wchar_t* findee)
  112. {
  113. // find the parameter in the list of accepted parameters
  114. for (int x = 0; x < MaxOperations; x++) {
  115. if (wcscmp(operationCodes[x], findee) == 0)
  116. return x;
  117. }
  118. return -1;
  119. }
  120. // run a backup test
  121. CComBSTR runBackupTest(bool cancel[MaxOperations], long cancelDelay)
  122. {
  123. CComPtr<IVssBackupComponents> components;
  124. checker(::CreateVssBackupComponents(&components), L"CreateVssBackupComponents");
  125. checker(components->InitializeForBackup(), L"InitializeForBackup");
  126. checker(components->SetBackupState(false, true, VSS_BT_FULL, false), L"SetBackupState");
  127. CComPtr<IVssAsync> async;
  128. checker(components->GatherWriterMetadata(&async), L"GatherWriterMetadata");
  129. checker(cancel[GatherWriterMetadata] ? cancelTest(async, cancelDelay) : waitTest(async),
  130. L"GatherWriterMetadata async");
  131. checkMetadata(components);
  132. async = NULL;
  133. VSS_ID setId = GUID_NULL;
  134. VSS_ID snapshotId = GUID_NULL;
  135. checker(components->StartSnapshotSet(&setId),
  136. L"StartSnapshotSet");
  137. fwprintf(stderr, L"\nWriter Status after SSS \n");
  138. checker(components->GatherWriterStatus(&async), L"GatherWriterStatus");
  139. checker(cancel[GatherWriterStatus] ? cancelTest(async, cancelDelay) : waitTest(async),
  140. L"GatherWriterStatus async");
  141. checkStatus(components);
  142. async = NULL;
  143. checker(components->AddToSnapshotSet(L"C:\\", GUID_NULL, &snapshotId),
  144. L"AddToSnapshotSet");
  145. checker(components->PrepareForBackup(&async), L"PrepareForBackup");
  146. checker(cancel[PrepareForBackup] ? cancelTest(async, cancelDelay) : waitTest(async),
  147. L"PrepareForBackup async");
  148. async = NULL;
  149. fwprintf(stderr, L"\nWriter Status after PrepareForBackup \n");
  150. checker(components->GatherWriterStatus(&async), L"GatherWriterStatus");
  151. checker(cancel[GatherWriterStatus] ? cancelTest(async, cancelDelay) : waitTest(async),
  152. L"GatherWriterStatus async");
  153. checkStatus(components);
  154. async = NULL;
  155. checker(components->DoSnapshotSet(&async), L"DoSnapshotSet");
  156. checker(cancel[DoSnapshotSet] ? cancelTest(async, cancelDelay) : waitTest(async),
  157. L"DoSnapshotSet async");
  158. async = NULL;
  159. fwprintf(stderr, L"\nWriter Status after DoSnapshotSet\n");
  160. checker(components->GatherWriterStatus(&async), L"GatherWriterStatus");
  161. checker(cancel[GatherWriterStatus] ? cancelTest(async, cancelDelay) : waitTest(async),
  162. L"GatherWriterStatus async");
  163. checkStatus(components);
  164. async = NULL;
  165. checker(components->BackupComplete(&async), L"BackupComplete");
  166. checker(cancel[BackupComplete] ? cancelTest(async, cancelDelay) : waitTest(async),
  167. L"BackupComplete async");
  168. async = NULL;
  169. fwprintf(stderr, L"\nWriter Status after BackupComplete\n");
  170. checker(components->GatherWriterStatus(&async), L"GatherWriterStatus");
  171. checker(cancel[GatherWriterStatus] ? cancelTest(async, cancelDelay) : waitTest(async),
  172. L"GatherWriterStatus async");
  173. checkStatus(components);
  174. CComBSTR xmlData;
  175. checker(components->SaveAsXML(&xmlData), L"SaveAsXML");
  176. return xmlData;
  177. }
  178. // run a restore test
  179. void runRestoreTest(bool cancel[MaxOperations], long cancelDelay, CComBSTR xmlData)
  180. {
  181. CComPtr<IVssBackupComponents> components;
  182. checker(::CreateVssBackupComponents(&components), L"CreateVssBackupComponents");
  183. checker(components->InitializeForRestore(xmlData), L"InitializeForRestore");
  184. CComPtr<IVssAsync> async;
  185. checker(components->GatherWriterMetadata(&async), L"GatherWriterMetadata");
  186. checker(cancel[GatherWriterMetadata] ? cancelTest(async, cancelDelay) : waitTest(async),
  187. L"GatherWriterMetadata async");
  188. // select all writer components
  189. UINT numComponents = 0;
  190. checker(components->GetWriterComponentsCount(&numComponents), L"numComponents");
  191. for (UINT x = 0; x < numComponents; x++) {
  192. CComPtr<IVssWriterComponentsExt> writerComponents;
  193. checker(components->GetWriterComponents(x, &writerComponents), L"GetWriterComponents");
  194. VSS_ID idWriter, idInstance;
  195. UINT cComponents;
  196. checker(writerComponents->GetComponentCount(&cComponents), L"GetComponentCount");
  197. checker(writerComponents->GetWriterInfo(&idInstance, &idWriter), L"GetWriterInfo");
  198. for (UINT y = 0; y < cComponents; y++) {
  199. CComPtr<IVssComponent> writerComponent;
  200. checker(writerComponents->GetComponent(y, &writerComponent), L"GetComponent");
  201. CComBSTR logicalPath, name;
  202. VSS_COMPONENT_TYPE ct;
  203. checker(writerComponent->GetLogicalPath(&logicalPath), L"GetLogicalPath");
  204. checker(writerComponent->GetComponentName(&name), L"GetComponentName");
  205. checker(writerComponent->GetComponentType(&ct), L"GetComponentType");
  206. checker(components->SetSelectedForRestore(idWriter, ct, logicalPath, name, true),
  207. L"SetSelectedForRestore");
  208. }
  209. }
  210. async = NULL;
  211. checker(components->PreRestore(&async), L"GatherWriterMetadata");
  212. checker(cancel[PreRestore] ? cancelTest(async, cancelDelay) : waitTest(async),
  213. L"GatherWriterMetadata async");
  214. async = NULL;
  215. fwprintf(stderr, L"\nWriter Status after PreRestore\n");
  216. checker(components->GatherWriterStatus(&async), L"GatherWriterStatus");
  217. checker(cancel[GatherWriterStatus] ? cancelTest(async, cancelDelay) : waitTest(async),
  218. L"GatherWriterStatus async");
  219. async = NULL;
  220. checkStatus(components);
  221. checker(components->PostRestore(&async), L"GatherWriterMetadata");
  222. checker(cancel[PostRestore] ? cancelTest(async, cancelDelay) : waitTest(async),
  223. L"GatherWriterMetadata async");
  224. async = NULL;
  225. fwprintf(stderr, L"\nWriter Status after PostRestore\n");
  226. checker(components->GatherWriterStatus(&async), L"GatherWriterStatus");
  227. checker(cancel[GatherWriterStatus] ? cancelTest(async, cancelDelay) : waitTest(async),
  228. L"GatherWriterStatus async");
  229. checkStatus(components);
  230. }
  231. // check a return code and throw upon failure
  232. inline void checker(HRESULT error, wchar_t* string)
  233. {
  234. if (FAILED(error)) {
  235. CBsString error;
  236. error.Format(L"%s failed with error 0x%08lx", string, error);
  237. throw error;
  238. }
  239. }
  240. // wait on an async object
  241. inline HRESULT waitTest(IVssAsync* async)
  242. {
  243. checker(async->Wait(), L"IVssAsync::Wait");
  244. HRESULT hr;
  245. async->QueryStatus(&hr, NULL);
  246. // convert non-failure state codes to S_OK
  247. return FAILED(hr) ? hr : S_OK;
  248. }
  249. // cancel an async object
  250. inline HRESULT cancelTest(IVssAsync* async, long cancelDelay)
  251. {
  252. // put an upper limit on random delays
  253. const int MaxRandDelay = 1000;
  254. // wait for the requisite amount of time
  255. if (cancelDelay != 0)
  256. ::Sleep((cancelDelay > 0) ? cancelDelay : rand() % MaxRandDelay);
  257. async->Cancel();
  258. HRESULT hr;
  259. async->QueryStatus(&hr, NULL);
  260. // convert non-failure state codes to S_OK
  261. return FAILED(hr) ? hr : S_OK;
  262. }
  263. void checkMetadata(IVssBackupComponents* components)
  264. {
  265. UINT numWriters = 0;
  266. checker(components->GetWriterMetadataCount(&numWriters),
  267. L"GetWriterMetadataCount");
  268. for (UINT x = 0; x < numWriters; x++) {
  269. VSS_ID instance = GUID_NULL;
  270. CComPtr<IVssExamineWriterMetadata> examineData;
  271. checker(components->GetWriterMetadata(x, &instance, &examineData),
  272. L"GetWriterMetadata");
  273. VSS_ID outInstance = GUID_NULL, outClass = GUID_NULL;
  274. BSTR outName;
  275. VSS_USAGE_TYPE outUsage;
  276. VSS_SOURCE_TYPE outSource;
  277. checker(examineData->GetIdentity(&outInstance, &outClass, &outName, &outUsage, &outSource),
  278. L"GetIdentity");
  279. BS_ASSERT(outInstance == instance);
  280. fwprintf (stderr, L"\nWriter name %s\n", outName);
  281. fwprintf (stderr, L"usage type %s\n", WszFromUsageType(outUsage));
  282. VSS_RESTOREMETHOD_ENUM restoreMethod;
  283. BSTR service, userProc;
  284. VSS_WRITERRESTORE_ENUM writerRestore;
  285. bool reboot;
  286. UINT mappings;
  287. checker(examineData->GetRestoreMethod(&restoreMethod, &service, &userProc, &writerRestore, &reboot, &mappings),
  288. L"GetIdentity");
  289. fwprintf(stderr, L"restore method %s\n", WszFromRestoreMethod(restoreMethod));
  290. fwprintf(stderr, L"reboot required %s\n", reboot ? L"true" : L"false");
  291. UINT includes = 0, excludes = 0, components = 0;
  292. checker(examineData->GetFileCounts(&includes, &excludes, &components),
  293. L"GetFileCounts");
  294. fwprintf(stderr, L"%d include files\n%d exclude files \n%d components\n", includes, excludes, components);
  295. }
  296. }
  297. void checkStatus(IVssBackupComponents* components)
  298. {
  299. UINT numWriters = 0;
  300. checker(components->GetWriterMetadataCount(&numWriters),
  301. L"GetWriterMetadataCount");
  302. UINT numStatus = 0;
  303. checker(components->GetWriterStatusCount(&numStatus),
  304. L"GetWriterMetadataCount");
  305. BS_ASSERT(numStatus == numWriters);
  306. for (UINT x = 0; x < numStatus; x++) {
  307. VSS_ID instance, classWriter;
  308. BSTR writerName;
  309. VSS_WRITER_STATE state;
  310. HRESULT failure = S_OK;
  311. checker(components->GetWriterStatus(x, &instance, &classWriter, &writerName, &state, &failure),
  312. L"GetWriterStatus");
  313. fwprintf(stderr, L"\n writer name %s\n", writerName);
  314. fwprintf(stderr, L"writer status %s\n", GetStringFromWriterStatus(state));
  315. fwprintf(stderr, L"writer failure 0x%08lx\n", failure);
  316. }
  317. }
  318. const wchar_t* WszFromUsageType(VSS_USAGE_TYPE usage)
  319. {
  320. switch(usage) {
  321. default:
  322. throw L"UNKOWN";
  323. case VSS_UT_OTHER:
  324. return L"OTHER";
  325. case VSS_UT_BOOTABLESYSTEMSTATE:
  326. return L"BOOTABLE_SYSTEM_STATE";
  327. case VSS_UT_SYSTEMSERVICE:
  328. return L"SYSTEM_SERVICE";
  329. case VSS_UT_USERDATA:
  330. return L"USER_DATA";
  331. }
  332. }
  333. // convert from restore method to string
  334. const wchar_t* WszFromRestoreMethod(VSS_RESTOREMETHOD_ENUM method)
  335. {
  336. switch(method) {
  337. default:
  338. return L"UNKNOWN";
  339. case VSS_RME_RESTORE_IF_NOT_THERE:
  340. return L"RESTORE_IF_NONE_THERE";
  341. case VSS_RME_RESTORE_IF_CAN_REPLACE:
  342. return L"RESTORE_IF_CAN_BE_REPLACED";
  343. case VSS_RME_STOP_RESTORE_START:
  344. return L"STOP_RESTART_SERVICE";
  345. case VSS_RME_RESTORE_TO_ALTERNATE_LOCATION:
  346. return L"RESTORE_TO_ALTERNATE_LOCATION";
  347. case VSS_RME_RESTORE_AT_REBOOT:
  348. return L"REPLACE_AT_REBOOT";
  349. case VSS_RME_CUSTOM:
  350. return L"CUSTOM";
  351. }
  352. }
  353. const wchar_t* GetStringFromWriterStatus(VSS_WRITER_STATE eWriterStatus)
  354. {
  355. const wchar_t* pwszRetString = L"UNDEFINED";
  356. switch (eWriterStatus)
  357. {
  358. case VSS_WS_STABLE: pwszRetString = L"STABLE"; break;
  359. case VSS_WS_WAITING_FOR_FREEZE: pwszRetString = L"WAITING_FOR_FREEZE"; break;
  360. case VSS_WS_WAITING_FOR_THAW: pwszRetString = L"WAITING_FOR_THAW"; break;
  361. case VSS_WS_WAITING_FOR_POST_SNAPSHOT: pwszRetString = L"WAITING_FOR_POST_SNAPSHOT"; break;
  362. case VSS_WS_WAITING_FOR_BACKUP_COMPLETE: pwszRetString = L"WAITING_FOR_BACKUP_COMPLETION"; break;
  363. case VSS_WS_FAILED_AT_IDENTIFY: pwszRetString = L"FAILED_AT_IDENTIFY"; break;
  364. case VSS_WS_FAILED_AT_PREPARE_BACKUP: pwszRetString = L"FAILED_AT_PREPARE_BACKUP";break;
  365. case VSS_WS_FAILED_AT_PREPARE_SNAPSHOT: pwszRetString = L"FAILED_AT_PREPARE_SNAPSHOT"; break;
  366. case VSS_WS_FAILED_AT_FREEZE: pwszRetString = L"FAILED_AT_FREEZE"; break;
  367. case VSS_WS_FAILED_AT_THAW: pwszRetString = L"FAILED_AT_THAW"; break;
  368. case VSS_WS_FAILED_AT_POST_SNAPSHOT: pwszRetString = L"FAILED_AT_POST_SNAPSHOT"; break;
  369. case VSS_WS_FAILED_AT_BACKUP_COMPLETE: pwszRetString = L"FAILED_AT_BACKUP_COMPLETE"; break;
  370. case VSS_WS_FAILED_AT_PRE_RESTORE: pwszRetString = L"FAILED_AT_PRE_RESTORE"; break;
  371. case VSS_WS_FAILED_AT_POST_RESTORE: pwszRetString = L"FAILED_AT_POST_RESTORE"; break;
  372. default:
  373. break;
  374. }
  375. return (pwszRetString);
  376. }