Leaked source code of windows server 2003

451 lines
17 KiB

  1. /*
  2. **++
  3. **
  4. ** Copyright (c) 2000-2001 Microsoft Corporation
  5. **
  6. **
  7. ** Module Name:
  8. **
  9. ** util.cpp
  10. **
  11. **
  12. ** Abstract:
  13. **
  14. ** Sample program to
  15. ** - obtain and display the Writer metadata.
  16. ** - create a snapshot set
  17. **
  18. ** Author:
  19. **
  20. ** Adi Oltean [aoltean] 05-Dec-2000
  21. **
  22. ** The sample is based on the Metasnap test program written by Michael C. Johnson.
  23. **
  24. **
  25. ** Revision History:
  26. **
  27. **--
  28. */
  29. ///////////////////////////////////////////////////////////////////////////////
  30. // Includes
  31. #include "vsreq.h"
  32. ///////////////////////////////////////////////////////////////////////////////
  33. // Print usage
  34. void CVssSampleRequestor::PrintUsage()
  35. {
  36. wprintf(
  37. L"\nUsage:\n"
  38. L" vsreq [-b] [-s] [-x <file.xml>] [<volumes>]\n"
  39. L"\nOptions:\n"
  40. L" -b Backup includes bootable & system state.\n"
  41. L" -s Enable component selection.\n"
  42. L" -x <file.xml> Generate an XML file containing the backup metadata\n"
  43. L" <volumes> Specifies the volumes to be part of the snapshot set\n"
  44. L" The volumes in the list must be distinct and \n"
  45. L" must be separated by space. A volume must be \n"
  46. L" terminated with a trailing backslask (for example C:\\).\n"
  47. L"\n"
  48. L"\nExample:\n"
  49. L" The following command will create a snapshot set\n"
  50. L" on the volumes mounted under c:\\ and d:\\\n"
  51. L"\n"
  52. L" vsreq c:\\ d:\\ \n"
  53. L"\n"
  54. L" The following command will create a snapshot set on the volumes \n"
  55. L" that contain selected components and also the volume c:\\\n"
  56. L" Also, the backup will contain bootable and system state.\n"
  57. L" The XML results will be stored in file.xml\n"
  58. L"\n"
  59. L" vsreq -b -s -x file.xml c:\\ \n"
  60. );
  61. throw(2);
  62. }
  63. void CVssSampleRequestor::ParseCommandLine(
  64. IN INT nArgsCount,
  65. IN WCHAR ** ppwszArgsArray
  66. )
  67. {
  68. if (nArgsCount == 0)
  69. PrintUsage();
  70. // For each argument in the command line
  71. bool bParsingVolumes = false;
  72. INT nCurrentArg = nArgsCount;
  73. WCHAR ** ppwszCurrentArg = ppwszArgsArray;
  74. for(; nCurrentArg--; ppwszCurrentArg++)
  75. {
  76. if (!bParsingVolumes) {
  77. // Check for Bootable & system state option
  78. if (!m_bBootableSystemState && !wcscmp(*ppwszCurrentArg, L"-b")) {
  79. m_bBootableSystemState = true;
  80. continue;
  81. }
  82. // Check for Selected components option
  83. if (!m_bComponentSelectionEnabled && !wcscmp(*ppwszCurrentArg, L"-s")) {
  84. m_bComponentSelectionEnabled = true;
  85. continue;
  86. }
  87. // Check for Xml file option
  88. if (!m_pwszXmlFile && !wcscmp(*ppwszCurrentArg, L"-x")) {
  89. if (nCurrentArg-- == 0)
  90. return PrintUsage();
  91. ppwszCurrentArg++;
  92. m_pwszXmlFile = *ppwszCurrentArg;
  93. continue;
  94. }
  95. }
  96. // We suppose that the next arguments are the volumes
  97. bParsingVolumes = true;
  98. // Add the volume to the list of snapshotting volumes
  99. // Make sure that the volume name is valid
  100. bool bAdded = false;
  101. if (!AddVolume(*ppwszCurrentArg, bAdded)) {
  102. wprintf(L"\nError while parsing the command line:\n"
  103. L"\t%s is not a valid option or a mount point [0x%08lx]\n\n",
  104. *ppwszCurrentArg, GetLastError() );
  105. PrintUsage();
  106. }
  107. // Check if the same volume is added twice
  108. if (!bAdded) {
  109. wprintf(L"\nError while parsing the command line:\n"
  110. L"\tThe volume %s is specified twice\n\n", *ppwszCurrentArg );
  111. PrintUsage();
  112. }
  113. }
  114. // Check if we added at least one volume
  115. if ((m_nVolumesCount == 0) && !m_bComponentSelectionEnabled) {
  116. wprintf(L"\nError while parsing the command line:\n"
  117. L"\t- You should specify at least one volume or enable component selection\n\n");
  118. PrintUsage();
  119. }
  120. }
  121. // Add the given volume by the contained path
  122. void CVssSampleRequestor::AddVolumeForComponent(
  123. IN IVssWMFiledesc* pFileDesc
  124. )
  125. {
  126. // Get the component path
  127. CComBSTR bstrPath;
  128. CHECK_SUCCESS(pFileDesc->GetPath(&bstrPath));
  129. // Trying to find the volume that will contain the path.
  130. WCHAR wszExpandedPath[MAX_TEXT_BUFFER];
  131. if (!ExpandEnvironmentStringsW(bstrPath, wszExpandedPath, MAX_TEXT_BUFFER))
  132. Error( 1, L"\nExpandEnvironmentStringsW(%s, wszExpandedPath, MAX_TEXT_BUFFER) failed with [0x%08lx]\n",
  133. bstrPath, GetLastError());
  134. // Eliminate one by one the terminating folder names, until we reach an existing path.
  135. // Then get the volume name for that path
  136. WCHAR wszMountPoint[MAX_TEXT_BUFFER];
  137. while(true) {
  138. if (GetVolumePathNameW(wszExpandedPath, wszMountPoint, MAX_TEXT_BUFFER))
  139. break;
  140. if (GetLastError() != ERROR_FILE_NOT_FOUND)
  141. Error( 1, L"\nGetVolumePathNameW(%s, wszMountPoint, MAX_TEXT_BUFFER) failed with [0x%08lx]\n",
  142. wszExpandedPath, GetLastError());
  143. WCHAR* pwszLastBackslashIndex = wcsrchr(wszExpandedPath, L'\\');
  144. if (!pwszLastBackslashIndex)
  145. Error( 1, L"\nCannot find anymore a backslash in path %s. \n"
  146. L"The original path %s seems invalid.\n", wszExpandedPath, bstrPath);
  147. // Eliminate the last folder name
  148. pwszLastBackslashIndex[0] = L'\0';
  149. }
  150. // Add the volume, if possible
  151. bool bAdded = false;
  152. if (!AddVolume( wszMountPoint, bAdded ))
  153. Error( 1, L"\nUnexpected error: cannot add volume %s to the snapshot set.\n", wszMountPoint);
  154. wprintf (L" [Volume %s (that contains the file) %s marked as a candidate for snapshot]\n",
  155. wszMountPoint, bAdded? L"is": L"is already");
  156. }
  157. // Add the given volume in the list of potential candidates for snapshots
  158. // - Returns "false" if the volume does not correspond to a real mount point
  159. // (and GetLastError() will contain the correct Win32 error code)
  160. // - Sets "true" in the bAdded parameter if the volume is actually added
  161. bool CVssSampleRequestor::AddVolume(
  162. IN WCHAR* pwszVolume,
  163. OUT bool & bAdded
  164. )
  165. {
  166. // Initialize [out] parameters
  167. bAdded = false;
  168. // Check if the volume represents a real mount point
  169. WCHAR wszVolumeName[MAX_TEXT_BUFFER];
  170. if (!GetVolumeNameForVolumeMountPoint(pwszVolume, wszVolumeName, MAX_TEXT_BUFFER))
  171. return false; // Invalid volume
  172. // Check if the volume is already added.
  173. for (INT nIndex = 0; nIndex < m_nVolumesCount; nIndex++)
  174. if (!wcscmp(wszVolumeName, m_ppwszVolumeNamesList[nIndex]))
  175. return true; // Volume already added. Stop here.
  176. // Check if we exceeded the maximum number of volumes
  177. if (m_nVolumesCount == MAX_VOLUMES)
  178. Error( 1, L"Maximum number of volumes exceeded");
  179. // Create a copy of the volume
  180. WCHAR* pwszNewVolume = _wcsdup(pwszVolume);
  181. if (pwszNewVolume == NULL)
  182. Error( 1, L"Memory allocation error");
  183. // Create a copy of the volume name
  184. WCHAR* pwszNewVolumeName = _wcsdup(wszVolumeName);
  185. if (pwszNewVolumeName == NULL) {
  186. free(pwszNewVolume);
  187. Error( 1, L"Memory allocation error");
  188. }
  189. // Add the volume in our internal list of snapshotted volumes
  190. m_ppwszVolumesList[m_nVolumesCount] = pwszNewVolume;
  191. m_ppwszVolumeNamesList[m_nVolumesCount] = pwszNewVolumeName;
  192. m_nVolumesCount++;
  193. bAdded = true;
  194. return true;
  195. }
  196. // This function displays the formatted message at the console and throws
  197. // The passed return code will be returned by vsreq.exe
  198. void CVssSampleRequestor::Error(
  199. IN INT nReturnCode,
  200. IN const WCHAR* pwszMsgFormat,
  201. IN ...
  202. )
  203. {
  204. va_list marker;
  205. va_start( marker, pwszMsgFormat );
  206. vwprintf( pwszMsgFormat, marker );
  207. va_end( marker );
  208. // throw that return code.
  209. throw(nReturnCode);
  210. }
  211. ///////////////////////////////////////////////////////////////////////////////
  212. // Utility functions
  213. // Print a file description object
  214. void CVssSampleRequestor::PrintFiledesc (IVssWMFiledesc *pFiledesc, LPCWSTR wszDescription)
  215. {
  216. CComBSTR bstrPath;
  217. CComBSTR bstrFilespec;
  218. CComBSTR bstrAlternate;
  219. bool bRecursive;
  220. CHECK_SUCCESS(pFiledesc->GetPath(&bstrPath));
  221. CHECK_SUCCESS(pFiledesc->GetFilespec (&bstrFilespec));
  222. CHECK_NOFAIL(pFiledesc->GetRecursive(&bRecursive));
  223. CHECK_NOFAIL(pFiledesc->GetAlternateLocation(&bstrAlternate));
  224. wprintf (L"%s\n"
  225. L" Path = %s\n"
  226. L" Filespec = %s\n"
  227. L" Recursive = %s\n",
  228. wszDescription,
  229. bstrPath,
  230. bstrFilespec,
  231. bRecursive ? L"yes" : L"no");
  232. if (bstrAlternate && wcslen (bstrAlternate) > 0)
  233. wprintf(L" Alternate Location = %s\n", bstrAlternate);
  234. }
  235. // Convert a usage type into a string
  236. LPCWSTR CVssSampleRequestor::GetStringFromUsageType (VSS_USAGE_TYPE eUsageType)
  237. {
  238. LPCWSTR pwszRetString = L"UNDEFINED";
  239. switch (eUsageType)
  240. {
  241. case VSS_UT_BOOTABLESYSTEMSTATE: pwszRetString = L"BootableSystemState"; break;
  242. case VSS_UT_SYSTEMSERVICE: pwszRetString = L"SystemService"; break;
  243. case VSS_UT_USERDATA: pwszRetString = L"UserData"; break;
  244. case VSS_UT_OTHER: pwszRetString = L"Other"; break;
  245. default:
  246. break;
  247. }
  248. return (pwszRetString);
  249. }
  250. // Convert a source type into a string
  251. LPCWSTR CVssSampleRequestor::GetStringFromSourceType (VSS_SOURCE_TYPE eSourceType)
  252. {
  253. LPCWSTR pwszRetString = L"UNDEFINED";
  254. switch (eSourceType)
  255. {
  256. case VSS_ST_TRANSACTEDDB: pwszRetString = L"TransactionDb"; break;
  257. case VSS_ST_NONTRANSACTEDDB: pwszRetString = L"NonTransactionDb"; break;
  258. case VSS_ST_OTHER: pwszRetString = L"Other"; break;
  259. default:
  260. break;
  261. }
  262. return (pwszRetString);
  263. }
  264. // Convert a restore method into a string
  265. LPCWSTR CVssSampleRequestor::GetStringFromRestoreMethod (VSS_RESTOREMETHOD_ENUM eRestoreMethod)
  266. {
  267. LPCWSTR pwszRetString = L"UNDEFINED";
  268. switch (eRestoreMethod)
  269. {
  270. case VSS_RME_RESTORE_IF_NOT_THERE: pwszRetString = L"RestoreIfNotThere"; break;
  271. case VSS_RME_RESTORE_IF_CAN_REPLACE: pwszRetString = L"RestoreIfCanReplace"; break;
  272. case VSS_RME_STOP_RESTORE_START: pwszRetString = L"StopRestoreStart"; break;
  273. case VSS_RME_RESTORE_TO_ALTERNATE_LOCATION: pwszRetString = L"RestoreToAlternateLocation"; break;
  274. case VSS_RME_RESTORE_AT_REBOOT: pwszRetString = L"RestoreAtReboot"; break;
  275. case VSS_RME_CUSTOM: pwszRetString = L"Custom"; break;
  276. default:
  277. break;
  278. }
  279. return (pwszRetString);
  280. }
  281. // Convert a writer restore method into a string
  282. LPCWSTR CVssSampleRequestor::GetStringFromWriterRestoreMethod (VSS_WRITERRESTORE_ENUM eWriterRestoreMethod)
  283. {
  284. LPCWSTR pwszRetString = L"UNDEFINED";
  285. switch (eWriterRestoreMethod)
  286. {
  287. case VSS_WRE_NEVER: pwszRetString = L"RestoreNever"; break;
  288. case VSS_WRE_IF_REPLACE_FAILS: pwszRetString = L"RestoreIfReplaceFailsI"; break;
  289. case VSS_WRE_ALWAYS: pwszRetString = L"RestoreAlways"; break;
  290. default:
  291. break;
  292. }
  293. return (pwszRetString);
  294. }
  295. // Convert a component type into a string
  296. LPCWSTR CVssSampleRequestor::GetStringFromComponentType (VSS_COMPONENT_TYPE eComponentType)
  297. {
  298. LPCWSTR pwszRetString = L"UNDEFINED";
  299. switch (eComponentType)
  300. {
  301. case VSS_CT_DATABASE: pwszRetString = L"Database"; break;
  302. case VSS_CT_FILEGROUP: pwszRetString = L"FileGroup"; break;
  303. default:
  304. break;
  305. }
  306. return (pwszRetString);
  307. }
  308. // Convert a failure type into a string
  309. LPCWSTR CVssSampleRequestor::GetStringFromFailureType(HRESULT hrStatus)
  310. {
  311. LPCWSTR pwszFailureType = L"";
  312. switch (hrStatus)
  313. {
  314. case VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT: pwszFailureType = L"VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT"; break;
  315. case VSS_E_WRITERERROR_OUTOFRESOURCES: pwszFailureType = L"VSS_E_WRITERERROR_OUTOFRESOURCES"; break;
  316. case VSS_E_WRITERERROR_TIMEOUT: pwszFailureType = L"VSS_E_WRITERERROR_TIMEOUT"; break;
  317. case VSS_E_WRITERERROR_NONRETRYABLE: pwszFailureType = L"VSS_E_WRITERERROR_NONRETRYABLE"; break;
  318. case VSS_E_WRITERERROR_RETRYABLE: pwszFailureType = L"VSS_E_WRITERERROR_RETRYABLE"; break;
  319. case VSS_E_BAD_STATE: pwszFailureType = L"VSS_E_BAD_STATE"; break;
  320. case VSS_E_PROVIDER_ALREADY_REGISTERED: pwszFailureType = L"VSS_E_PROVIDER_ALREADY_REGISTERED"; break;
  321. case VSS_E_PROVIDER_NOT_REGISTERED: pwszFailureType = L"VSS_E_PROVIDER_NOT_REGISTERED"; break;
  322. case VSS_E_PROVIDER_VETO: pwszFailureType = L"VSS_E_PROVIDER_VETO"; break;
  323. case VSS_E_PROVIDER_IN_USE: pwszFailureType = L"VSS_E_PROVIDER_IN_USE"; break;
  324. case VSS_E_OBJECT_NOT_FOUND: pwszFailureType = L"VSS_E_OBJECT_NOT_FOUND"; break;
  325. case VSS_S_ASYNC_PENDING: pwszFailureType = L"VSS_S_ASYNC_PENDING"; break;
  326. case VSS_S_ASYNC_FINISHED: pwszFailureType = L"VSS_S_ASYNC_FINISHED"; break;
  327. case VSS_S_ASYNC_CANCELLED: pwszFailureType = L"VSS_S_ASYNC_CANCELLED"; break;
  328. case VSS_E_VOLUME_NOT_SUPPORTED: pwszFailureType = L"VSS_E_VOLUME_NOT_SUPPORTED"; break;
  329. case VSS_E_VOLUME_NOT_SUPPORTED_BY_PROVIDER: pwszFailureType = L"VSS_E_VOLUME_NOT_SUPPORTED_BY_PROVIDER"; break;
  330. case VSS_E_OBJECT_ALREADY_EXISTS: pwszFailureType = L"VSS_E_OBJECT_ALREADY_EXISTS"; break;
  331. case VSS_E_UNEXPECTED_PROVIDER_ERROR: pwszFailureType = L"VSS_E_UNEXPECTED_PROVIDER_ERROR"; break;
  332. case VSS_E_CORRUPT_XML_DOCUMENT: pwszFailureType = L"VSS_E_CORRUPT_XML_DOCUMENT"; break;
  333. case VSS_E_INVALID_XML_DOCUMENT: pwszFailureType = L"VSS_E_INVALID_XML_DOCUMENT"; break;
  334. case VSS_E_MAXIMUM_NUMBER_OF_VOLUMES_REACHED: pwszFailureType = L"VSS_E_MAXIMUM_NUMBER_OF_VOLUMES_REACHED"; break;
  335. case VSS_E_FLUSH_WRITES_TIMEOUT: pwszFailureType = L"VSS_E_FLUSH_WRITES_TIMEOUT"; break;
  336. case VSS_E_HOLD_WRITES_TIMEOUT: pwszFailureType = L"VSS_E_HOLD_WRITES_TIMEOUT"; break;
  337. case VSS_E_UNEXPECTED_WRITER_ERROR: pwszFailureType = L"VSS_E_UNEXPECTED_WRITER_ERROR"; break;
  338. case VSS_E_SNAPSHOT_SET_IN_PROGRESS: pwszFailureType = L"VSS_E_SNAPSHOT_SET_IN_PROGRESS"; break;
  339. case VSS_E_MAXIMUM_NUMBER_OF_SNAPSHOTS_REACHED: pwszFailureType = L"VSS_E_MAXIMUM_NUMBER_OF_SNAPSHOTS_REACHED"; break;
  340. case VSS_E_WRITER_INFRASTRUCTURE: pwszFailureType = L"VSS_E_WRITER_INFRASTRUCTURE"; break;
  341. case VSS_E_WRITER_NOT_RESPONDING: pwszFailureType = L"VSS_E_WRITER_NOT_RESPONDING"; break;
  342. case VSS_E_WRITER_ALREADY_SUBSCRIBED: pwszFailureType = L"VSS_E_WRITER_ALREADY_SUBSCRIBED"; break;
  343. case NOERROR:
  344. default:
  345. break;
  346. }
  347. return (pwszFailureType);
  348. }
  349. // Convert a writer status into a string
  350. LPCWSTR CVssSampleRequestor::GetStringFromWriterStatus(VSS_WRITER_STATE eWriterStatus)
  351. {
  352. LPCWSTR pwszRetString = L"UNDEFINED";
  353. switch (eWriterStatus)
  354. {
  355. case VSS_WS_STABLE: pwszRetString = L"STABLE"; break;
  356. case VSS_WS_WAITING_FOR_FREEZE: pwszRetString = L"WAITING_FOR_FREEZE"; break;
  357. case VSS_WS_WAITING_FOR_THAW: pwszRetString = L"WAITING_FOR_THAW"; break;
  358. case VSS_WS_WAITING_FOR_BACKUP_COMPLETE:pwszRetString = L"VSS_WS_WAITING_FOR_BACKUP_COMPLETE"; break;
  359. case VSS_WS_FAILED_AT_IDENTIFY: pwszRetString = L"FAILED_AT_IDENTIFY"; break;
  360. case VSS_WS_FAILED_AT_PREPARE_BACKUP: pwszRetString = L"FAILED_AT_PREPARE_BACKUP";break;
  361. case VSS_WS_FAILED_AT_PREPARE_SNAPSHOT: pwszRetString = L"VSS_WS_FAILED_AT_PREPARE_SNAPSHOT"; break;
  362. case VSS_WS_FAILED_AT_FREEZE: pwszRetString = L"FAILED_AT_FREEZE"; break;
  363. case VSS_WS_FAILED_AT_THAW: pwszRetString = L"FAILED_AT_THAW"; break;
  364. default:
  365. break;
  366. }
  367. return (pwszRetString);
  368. }