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.

536 lines
17 KiB

  1. /*++
  2. Copyright (c) 1999-2001 Microsoft Corporation
  3. Abstract:
  4. @doc
  5. @module process.cpp | The processing functions for the VSS admin CLI
  6. @end
  7. Author:
  8. Adi Oltean [aoltean] 04/04/2000
  9. TBD:
  10. Add comments.
  11. Revision History:
  12. Name Date Comments
  13. aoltean 04/04/2000 Created
  14. ssteiner 10/20/2000 Changed List SnapshotSets to use more limited VSS queries.
  15. --*/
  16. /////////////////////////////////////////////////////////////////////////////
  17. // Includes
  18. // The rest of includes are specified here
  19. #include "vssadmin.h"
  20. #include "vswriter.h"
  21. #include "vsbackup.h"
  22. ////////////////////////////////////////////////////////////////////////
  23. // Standard foo for file name aliasing. This code block must be after
  24. // all includes of VSS header files.
  25. //
  26. #ifdef VSS_FILE_ALIAS
  27. #undef VSS_FILE_ALIAS
  28. #endif
  29. #define VSS_FILE_ALIAS "ADMPROCC"
  30. //
  31. ////////////////////////////////////////////////////////////////////////
  32. /////////////////////////////////////////////////////////////////////////////
  33. // Implementation
  34. class CVssAdmSnapshotSetEntry {
  35. public:
  36. // Constructor - Throws NOTHING
  37. CVssAdmSnapshotSetEntry(
  38. IN VSS_ID SnapshotSetId,
  39. IN INT nOriginalSnapshotsCount
  40. ) : m_SnapshotSetId( SnapshotSetId ),
  41. m_nOriginalSnapshotCount(nOriginalSnapshotsCount){ }
  42. ~CVssAdmSnapshotSetEntry()
  43. {
  44. // Have to delete all snapshots entries
  45. int iCount = GetSnapshotCount();
  46. for ( int i = 0; i < iCount; ++i )
  47. {
  48. VSS_SNAPSHOT_PROP *pSSProp;
  49. pSSProp = GetSnapshotAt( i );
  50. ::VssFreeSnapshotProperties(pSSProp);
  51. delete pSSProp;
  52. }
  53. }
  54. // Add new snapshot to the snapshot set
  55. HRESULT AddSnapshot(
  56. IN CVssFunctionTracer &ft,
  57. IN VSS_SNAPSHOT_PROP *pVssSnapshotProp )
  58. {
  59. HRESULT hr = S_OK;
  60. try
  61. {
  62. VSS_SNAPSHOT_PROP *pNewVssSnapshotProp = new VSS_SNAPSHOT_PROP;
  63. if ( pNewVssSnapshotProp == NULL )
  64. ft.Throw( VSSDBG_VSSADMIN, E_OUTOFMEMORY, L"Out of memory" );
  65. *pNewVssSnapshotProp = *pVssSnapshotProp;
  66. if ( !m_mapSnapshots.Add( pNewVssSnapshotProp->m_SnapshotId, pNewVssSnapshotProp ) )
  67. {
  68. delete pNewVssSnapshotProp;
  69. ft.Throw( VSSDBG_VSSADMIN, E_OUTOFMEMORY, L"Out of memory" );
  70. }
  71. }
  72. BS_STANDARD_CATCH();
  73. return hr;
  74. }
  75. INT GetSnapshotCount() { return m_mapSnapshots.GetSize(); }
  76. INT GetOriginalSnapshotCount() { return m_nOriginalSnapshotCount; }
  77. VSS_ID GetSnapshotSetId() { return m_SnapshotSetId; }
  78. VSS_SNAPSHOT_PROP *GetSnapshotAt(
  79. IN int nIndex )
  80. {
  81. BS_ASSERT( !(nIndex < 0 || nIndex >= GetSnapshotCount()) );
  82. return m_mapSnapshots.GetValueAt( nIndex );
  83. }
  84. private:
  85. VSS_ID m_SnapshotSetId;
  86. INT m_nOriginalSnapshotCount;
  87. CVssSimpleMap<VSS_ID, VSS_SNAPSHOT_PROP *> m_mapSnapshots;
  88. };
  89. // This class queries the list of all snapshots and assembles from the query
  90. // the list of snapshotsets and the volumes which are in the snapshotset.
  91. class CVssAdmSnapshotSets
  92. {
  93. public:
  94. // Constructor - Throws HRESULTS
  95. CVssAdmSnapshotSets(
  96. IN VSS_ID FilteredSnapshotSetId = GUID_NULL )
  97. {
  98. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdmSnapshotSets::CVssAdmSnapshotSets" );
  99. bool bFiltered = !( FilteredSnapshotSetId == GUID_NULL );
  100. // Create the coordinator object
  101. CComPtr<IVssCoordinator> pICoord;
  102. ft.LogVssStartupAttempt();
  103. ft.hr = pICoord.CoCreateInstance( CLSID_VSSCoordinator );
  104. if ( ft.HrFailed() )
  105. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"Connection failed with hr = 0x%08lx", ft.hr);
  106. // Get list all snapshots
  107. CComPtr<IVssEnumObject> pIEnumSnapshots;
  108. ft.hr = pICoord->Query( GUID_NULL,
  109. VSS_OBJECT_NONE,
  110. VSS_OBJECT_SNAPSHOT,
  111. &pIEnumSnapshots );
  112. if ( ft.HrFailed() )
  113. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"Query failed with hr = 0x%08lx", ft.hr);
  114. // For all snapshots do...
  115. VSS_OBJECT_PROP Prop;
  116. VSS_SNAPSHOT_PROP& Snap = Prop.Obj.Snap;
  117. for(;;) {
  118. // Get next element
  119. ULONG ulFetched;
  120. ft.hr = pIEnumSnapshots->Next( 1, &Prop, &ulFetched );
  121. if ( ft.HrFailed() )
  122. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"Next failed with hr = 0x%08lx", ft.hr);
  123. // Test if the cycle is finished
  124. if (ft.hr == S_FALSE) {
  125. BS_ASSERT( ulFetched == 0);
  126. break;
  127. }
  128. // If filtering, skip entry if snapshot is not in the specified snapshot set
  129. if ( bFiltered && !( Snap.m_SnapshotSetId == FilteredSnapshotSetId ) )
  130. continue;
  131. ft.Trace( VSSDBG_VSSADMIN, L"Snapshot: %s", Snap.m_pwszOriginalVolumeName );
  132. // Look up the snapshot set id in the list of snapshot sets
  133. CVssAdmSnapshotSetEntry *pcSSE;
  134. pcSSE = m_mapSnapshotSets.Lookup( Snap.m_SnapshotSetId );
  135. if ( pcSSE == NULL )
  136. {
  137. // Haven't seen this snapshot set before, add it to list
  138. pcSSE = new CVssAdmSnapshotSetEntry( Snap.m_SnapshotSetId,
  139. Snap.m_lSnapshotsCount );
  140. if ( pcSSE == NULL )
  141. ft.Throw( VSSDBG_VSSADMIN, E_OUTOFMEMORY, L"Out of memory" );
  142. if ( !m_mapSnapshotSets.Add( Snap.m_SnapshotSetId, pcSSE ) )
  143. {
  144. delete pcSSE;
  145. ft.Throw( VSSDBG_VSSADMIN, E_OUTOFMEMORY, L"Out of memory" );
  146. }
  147. }
  148. // Now add the snapshot to the snapshot set
  149. ft.hr = pcSSE->AddSnapshot( ft, &Snap );
  150. if ( ft.HrFailed() )
  151. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"AddSnapshot failed" );
  152. }
  153. }
  154. ~CVssAdmSnapshotSets()
  155. {
  156. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdmSnapshotSets::~CVssAdmSnapshotSets" );
  157. // Have to delete all
  158. int iCount;
  159. iCount = m_mapSnapshotSets.GetSize();
  160. for ( int i = 0; i < iCount; ++i )
  161. {
  162. delete m_mapSnapshotSets.GetValueAt( i );
  163. }
  164. }
  165. INT GetSnapshotSetCount() { return m_mapSnapshotSets.GetSize(); }
  166. CVssAdmSnapshotSetEntry *GetSnapshotSetAt(
  167. IN int nIndex )
  168. {
  169. BS_ASSERT( !(nIndex < 0 || nIndex >= GetSnapshotSetCount()) );
  170. return m_mapSnapshotSets.GetValueAt( nIndex );
  171. }
  172. private:
  173. CVssSimpleMap<VSS_ID, CVssAdmSnapshotSetEntry *> m_mapSnapshotSets;
  174. };
  175. /////////////////////////////////////////////////////////////////////////////
  176. // Implementation
  177. void CVssAdminCLI::PrintUsage(
  178. IN CVssFunctionTracer& ft
  179. ) throw(HRESULT)
  180. {
  181. // Usage:\n\n
  182. // vssadmin list snapshots [-set {snapshot set guid}]\n
  183. // \tWill list all snapshots in the system, grouped by snapshot set Id.\n\n
  184. // vssadmin list writers\n
  185. // \tWill list all writers in the system\n\n
  186. // vssadmin list providers\n
  187. // \tWill list all currently installed snapshot providers\n
  188. Output( ft, IDS_USAGE );
  189. Output( ft, IDS_USAGE_SNAPSHOTS,
  190. wszVssOptVssadmin, wszVssOptList, wszVssOptSnapshots, wszVssOptSet );
  191. Output( ft, IDS_USAGE_WRITERS,
  192. wszVssOptVssadmin, wszVssOptList, wszVssOptWriters );
  193. Output( ft, IDS_USAGE_PROVIDERS,
  194. wszVssOptVssadmin, wszVssOptList, wszVssOptProviders);
  195. }
  196. void CVssAdminCLI::ListSnapshots(
  197. IN CVssFunctionTracer& ft
  198. ) throw(HRESULT)
  199. {
  200. bool bNonEmptyResult = false;
  201. // Check the filter type
  202. switch ( m_eFilterObjectType ) {
  203. case VSS_OBJECT_SNAPSHOT_SET:
  204. case VSS_OBJECT_NONE:
  205. break;
  206. default:
  207. BS_ASSERT(false);
  208. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"Invalid object type %d", m_eFilterObjectType);
  209. }
  210. CVssAdmSnapshotSets cVssAdmSS( m_FilterSnapshotSetId );
  211. INT iSnapshotSetCount = cVssAdmSS.GetSnapshotSetCount();
  212. // If there are no present snapshots then display a message.
  213. if (iSnapshotSetCount == 0) {
  214. Output( ft,
  215. (m_eFilterObjectType == VSS_OBJECT_SNAPSHOT_SET)?
  216. IDS_NO_SNAPSHOTS_FOR_SET: IDS_NO_SNAPSHOTS );
  217. }
  218. // For all snapshot sets do...
  219. for ( INT iSSS = 0; iSSS < iSnapshotSetCount; ++iSSS )
  220. {
  221. CVssAdmSnapshotSetEntry *pcSSE;
  222. pcSSE = cVssAdmSS.GetSnapshotSetAt( iSSS );
  223. BS_ASSERT( pcSSE != NULL );
  224. // Print each snapshot set
  225. Output( ft, IDS_SNAPSHOT_SET_HEADER,
  226. GUID_PRINTF_ARG( pcSSE->GetSnapshotSetId() ),
  227. pcSSE->GetOriginalSnapshotCount(), pcSSE->GetSnapshotCount());
  228. // TBD: add creation time from the first snapshot.
  229. INT iSnapshotCount = pcSSE->GetSnapshotCount();
  230. VSS_SNAPSHOT_PROP *pSnap;
  231. for( INT iSS = 0; iSS < iSnapshotCount; ++iSS ) {
  232. pSnap = pcSSE->GetSnapshotAt( iSS );
  233. BS_ASSERT( pSnap != NULL );
  234. // Get the provider name
  235. LPCWSTR pwszProviderName =
  236. GetProviderName(ft, pSnap->m_ProviderId);
  237. // Print each snapshot
  238. Output( ft, IDS_SNAPSHOT_CONTENTS,
  239. pwszProviderName? pwszProviderName: L"",
  240. GUID_PRINTF_ARG(pSnap->m_SnapshotId),
  241. pSnap->m_pwszOriginalVolumeName
  242. );
  243. Output( ft, wszVssFmtNewline );
  244. bNonEmptyResult = true;
  245. }
  246. }
  247. m_nReturnValue = bNonEmptyResult? VSS_CMDRET_SUCCESS: VSS_CMDRET_EMPTY_RESULT;
  248. }
  249. void CVssAdminCLI::ListWriters(
  250. IN CVssFunctionTracer& ft
  251. ) throw(HRESULT)
  252. {
  253. bool bNonEmptyResult = false;
  254. // Get the backup components object
  255. CComPtr<IVssBackupComponents> pBackupComp;
  256. CComPtr<IVssAsync> pAsync;
  257. ft.hr = ::CreateVssBackupComponents(&pBackupComp);
  258. if (ft.HrFailed())
  259. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"CreateVssBackupComponents failed with hr = 0x%08lx", ft.hr);
  260. // BUGBUG Initialize for backup
  261. ft.hr = pBackupComp->InitializeForBackup();
  262. if (ft.HrFailed())
  263. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"InitializeForBackup failed with hr = 0x%08lx", ft.hr);
  264. UINT unWritersCount;
  265. // get metadata for all writers
  266. ft.hr = pBackupComp->GatherWriterMetadata(&pAsync);
  267. if (ft.HrFailed())
  268. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"GatherWriterMetadata failed with hr = 0x%08lx", ft.hr);
  269. // Using polling, try to obtain the list of writers as soon as possible
  270. HRESULT hrReturned = S_OK;
  271. for (int nRetries = 0; nRetries < MAX_RETRIES_COUNT; nRetries++ ) {
  272. // Wait a little
  273. ::Sleep(nPollingInterval);
  274. // Check if finished
  275. INT nReserved = 0;
  276. ft.hr = pAsync->QueryStatus(
  277. &hrReturned,
  278. &nReserved
  279. );
  280. if (ft.HrFailed())
  281. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED,
  282. L"IVssAsync::QueryStatus failed with hr = 0x%08lx", ft.hr);
  283. if (hrReturned == VSS_S_ASYNC_FINISHED)
  284. break;
  285. if (hrReturned == VSS_S_ASYNC_PENDING)
  286. continue;
  287. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED,
  288. L"IVssAsync::QueryStatus returned hr = 0x%08lx", hrReturned);
  289. }
  290. // If still not ready, then print the "waiting for responses" message and wait.
  291. if (hrReturned == VSS_S_ASYNC_PENDING) {
  292. Output( ft, IDS_WAITING_RESPONSES );
  293. ft.hr = pAsync->Wait();
  294. if (ft.HrFailed())
  295. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"IVssAsync::Wait failed with hr = 0x%08lx", ft.hr);
  296. }
  297. pAsync = NULL;
  298. // Gather the status of all writers
  299. ft.hr = pBackupComp->GatherWriterStatus(&pAsync);
  300. if (ft.HrFailed())
  301. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"GatherWriterMetadata failed with hr = 0x%08lx", ft.hr);
  302. ft.hr = pAsync->Wait();
  303. if (ft.HrFailed())
  304. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"IVssAsync::Wait failed with hr = 0x%08lx", ft.hr);
  305. pAsync = NULL;
  306. ft.hr = pBackupComp->GetWriterStatusCount(&unWritersCount);
  307. if (ft.HrFailed())
  308. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"GetWriterStatusCount failed with hr = 0x%08lx", ft.hr);
  309. // Print each writer status+supplementary info
  310. for(UINT unIndex = 0; unIndex < unWritersCount; unIndex++)
  311. {
  312. VSS_ID idInstance;
  313. VSS_ID idWriter;
  314. CComBSTR bstrWriter;
  315. VSS_WRITER_STATE eStatus;
  316. HRESULT hrWriterFailure;
  317. // Get the status for the (unIndex)-th writer
  318. ft.hr = pBackupComp->GetWriterStatus(unIndex, &idInstance, &idWriter, &bstrWriter, &eStatus, &hrWriterFailure);
  319. if (ft.HrFailed())
  320. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"GetWriterStatus failed with hr = 0x%08lx", ft.hr);
  321. // Get the status description strings
  322. LPCWSTR pwszStatusDescription;
  323. switch (eStatus) {
  324. case VSS_WS_STABLE:
  325. pwszStatusDescription = LoadString( ft, IDS_WRITER_STATUS_STABLE);
  326. break;
  327. case VSS_WS_WAITING_FOR_FREEZE:
  328. pwszStatusDescription = LoadString( ft, IDS_WRITER_STATUS_WAITING_FOR_FREEZE);
  329. break;
  330. case VSS_WS_WAITING_FOR_THAW:
  331. pwszStatusDescription = LoadString( ft, IDS_WRITER_STATUS_FROZEN);
  332. break;
  333. case VSS_WS_WAITING_FOR_BACKUP_COMPLETE:
  334. pwszStatusDescription = LoadString( ft, IDS_WRITER_STATUS_WAITING_FOR_COMPLETION);
  335. break;
  336. case VSS_WS_FAILED_AT_IDENTIFY:
  337. case VSS_WS_FAILED_AT_PREPARE_BACKUP:
  338. case VSS_WS_FAILED_AT_PREPARE_SNAPSHOT:
  339. case VSS_WS_FAILED_AT_FREEZE:
  340. case VSS_WS_FAILED_AT_THAW:
  341. pwszStatusDescription = LoadString( ft, IDS_WRITER_STATUS_FAILED);
  342. break;
  343. default:
  344. pwszStatusDescription = LoadString( ft, IDS_WRITER_STATUS_UNKNOWN);
  345. break;
  346. }
  347. BS_ASSERT(pwszStatusDescription);
  348. // Print status+info about each writer
  349. Output( ft, IDS_WRITER_CONTENTS,
  350. (LPWSTR)bstrWriter? (LPWSTR)bstrWriter: L"",
  351. GUID_PRINTF_ARG(idWriter),
  352. GUID_PRINTF_ARG(idInstance),
  353. (INT)eStatus,
  354. pwszStatusDescription
  355. );
  356. Output( ft, wszVssFmtNewline );
  357. bNonEmptyResult = true;
  358. }
  359. ft.hr = pBackupComp->FreeWriterStatus();
  360. if (ft.HrFailed())
  361. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"FreeWriterStatus failed with hr = 0x%08lx", ft.hr);
  362. m_nReturnValue = bNonEmptyResult? VSS_CMDRET_SUCCESS: VSS_CMDRET_EMPTY_RESULT;
  363. }
  364. void CVssAdminCLI::ListProviders(
  365. IN CVssFunctionTracer& ft
  366. ) throw(HRESULT)
  367. {
  368. bool bNonEmptyResult = false;
  369. // Check the filter type
  370. switch ( m_eFilterObjectType ) {
  371. case VSS_OBJECT_NONE:
  372. break;
  373. default:
  374. BS_ASSERT(false);
  375. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"Invalid object type %d", m_eFilterObjectType);
  376. }
  377. // Create the coordinator object
  378. CComPtr<IVssCoordinator> pICoord;
  379. ft.LogVssStartupAttempt();
  380. ft.hr = pICoord.CoCreateInstance( CLSID_VSSCoordinator );
  381. if ( ft.HrFailed() )
  382. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"Connection failed with hr = 0x%08lx", ft.hr);
  383. // Query all (filtered) snapshot sets
  384. CComPtr<IVssEnumObject> pIEnumProv;
  385. ft.hr = pICoord->Query( GUID_NULL,
  386. VSS_OBJECT_NONE,
  387. VSS_OBJECT_PROVIDER,
  388. &pIEnumProv );
  389. if ( ft.HrFailed() )
  390. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"Query failed with hr = 0x%08lx", ft.hr);
  391. // For all snapshot sets do...
  392. VSS_OBJECT_PROP Prop;
  393. VSS_PROVIDER_PROP& Prov = Prop.Obj.Prov;
  394. for(;;) {
  395. // Get next element
  396. ULONG ulFetched;
  397. ft.hr = pIEnumProv->Next( 1, &Prop, &ulFetched );
  398. if ( ft.HrFailed() )
  399. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"Next failed with hr = 0x%08lx", ft.hr);
  400. // Test if the cycle is ended
  401. if (ft.hr == S_FALSE) {
  402. BS_ASSERT( ulFetched == 0);
  403. break;
  404. }
  405. // Get the provider type strings
  406. LPCWSTR pwszProviderType;
  407. switch (Prov.m_eProviderType) {
  408. case VSS_PROV_SYSTEM:
  409. pwszProviderType = LoadString( ft, IDS_PROV_TYPE_SYSTEM);
  410. break;
  411. case VSS_PROV_SOFTWARE:
  412. pwszProviderType = LoadString( ft, IDS_PROV_TYPE_SOFTWARE);
  413. break;
  414. case VSS_PROV_HARDWARE:
  415. pwszProviderType = LoadString( ft, IDS_PROV_TYPE_HARDWARE);
  416. break;
  417. default:
  418. pwszProviderType = LoadString( ft, IDS_PROV_TYPE_UNKNOWN);
  419. break;
  420. }
  421. BS_ASSERT(pwszProviderType);
  422. // Print each snapshot set
  423. Output( ft, IDS_PROVIDER_CONTENTS,
  424. Prov.m_pwszProviderName? Prov.m_pwszProviderName: L"",
  425. pwszProviderType,
  426. GUID_PRINTF_ARG(Prov.m_ProviderId),
  427. Prov.m_pwszProviderVersion? Prov.m_pwszProviderVersion: L"");
  428. ::CoTaskMemFree(Prov.m_pwszProviderName);
  429. ::CoTaskMemFree(Prov.m_pwszProviderVersion);
  430. bNonEmptyResult = true;
  431. }
  432. m_nReturnValue = bNonEmptyResult? VSS_CMDRET_SUCCESS: VSS_CMDRET_EMPTY_RESULT;
  433. }