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.

1962 lines
68 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 "commandverifier.h"
  21. #include "versionspecific.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. #define VSSADM_INFINITE_DIFFAREA 0xFFFFFFFFFFFFFFFF
  33. #define VSS_CTX_ATTRIB_MASK 0x01F
  34. /////////////////////////////////////////////////////////////////////////////
  35. // Implementation
  36. class CVssAdmSnapshotSetEntry {
  37. public:
  38. // Constructor - Throws NOTHING
  39. CVssAdmSnapshotSetEntry(
  40. IN VSS_ID SnapshotSetId,
  41. IN INT nOriginalSnapshotsCount
  42. ) : m_SnapshotSetId( SnapshotSetId ),
  43. m_nOriginalSnapshotCount(nOriginalSnapshotsCount)
  44. { }
  45. ~CVssAdmSnapshotSetEntry()
  46. {
  47. // Have to delete all snapshots entries
  48. int iCount = GetSnapshotCount();
  49. for ( int i = 0; i < iCount; ++i )
  50. {
  51. VSS_SNAPSHOT_PROP *pSSProp;
  52. pSSProp = GetSnapshotAt( i );
  53. ::VssFreeSnapshotProperties(pSSProp);
  54. delete pSSProp;
  55. }
  56. }
  57. // Add new snapshot to the snapshot set
  58. HRESULT AddSnapshot(
  59. IN VSS_SNAPSHOT_PROP *pVssSnapshotProp )
  60. {
  61. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdmSnapshotSetEntry::AddSnapshot" );
  62. HRESULT hr = S_OK;
  63. try
  64. {
  65. VSS_SNAPSHOT_PROP *pNewVssSnapshotProp = new VSS_SNAPSHOT_PROP;
  66. if ( pNewVssSnapshotProp == NULL )
  67. ft.Throw( VSSDBG_VSSADMIN, E_OUTOFMEMORY, L"Out of memory" );
  68. *pNewVssSnapshotProp = *pVssSnapshotProp;
  69. //
  70. // Transfer of pointer ownership
  71. //
  72. if ( !m_mapSnapshots.Add( pNewVssSnapshotProp->m_SnapshotId, pNewVssSnapshotProp ) )
  73. {
  74. delete pNewVssSnapshotProp;
  75. ft.Throw( VSSDBG_VSSADMIN, E_OUTOFMEMORY, L"Out of memory" );
  76. }
  77. }
  78. BS_STANDARD_CATCH();
  79. return hr;
  80. }
  81. INT GetSnapshotCount() { return m_mapSnapshots.GetSize(); }
  82. INT GetOriginalSnapshotCount() { return m_nOriginalSnapshotCount; }
  83. VSS_ID GetSnapshotSetId() { return m_SnapshotSetId; }
  84. VSS_SNAPSHOT_PROP *GetSnapshotAt(
  85. IN int nIndex )
  86. {
  87. BS_ASSERT( !(nIndex < 0 || nIndex >= GetSnapshotCount()) );
  88. return m_mapSnapshots.GetValueAt( nIndex );
  89. }
  90. private:
  91. VSS_ID m_SnapshotSetId;
  92. INT m_nOriginalSnapshotCount;
  93. CVssSimpleMap<VSS_ID, VSS_SNAPSHOT_PROP *> m_mapSnapshots;
  94. };
  95. // This class queries the list of all snapshots and assembles from the query
  96. // the list of snapshotsets and the volumes which are in the snapshotset.
  97. class CVssAdmSnapshotSets
  98. {
  99. public:
  100. // Constructor
  101. CVssAdmSnapshotSets() { };
  102. void Initialize(
  103. IN LONG lSnapshotContext,
  104. IN VSS_ID FilteredSnapshotSetId,
  105. IN VSS_ID FilteredSnapshotId,
  106. IN VSS_ID FilteredProviderId,
  107. IN LPCWSTR pwszFilteredForVolume
  108. )
  109. {
  110. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdmSnapshotSets::CVssAdmSnapshotSets" );
  111. // Create the coordinator object
  112. CComPtr<IVssCoordinator> pICoord;
  113. ft.CoCreateInstanceWithLog(
  114. VSSDBG_VSSADMIN,
  115. CLSID_VSSCoordinator,
  116. L"Coordinator",
  117. CLSCTX_ALL,
  118. IID_IVssCoordinator,
  119. (IUnknown**)&(pICoord));
  120. if ( ft.HrFailed() )
  121. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
  122. // Set the context
  123. ft.hr = pICoord->SetContext( lSnapshotContext );
  124. //
  125. // If access denied, don't stop, it probably is a backup operator making this
  126. // call. Continue. Also continue if E_NOTIMPL. The coordinator will use the backup context.
  127. //
  128. if ( ft.HrFailed() && ft.hr != E_ACCESSDENIED && ft.hr != E_NOTIMPL )
  129. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"SetContext failed with hr = 0x%08lx", ft.hr);
  130. // Get list all snapshots
  131. CComPtr<IVssEnumObject> pIEnumSnapshots;
  132. ft.hr = pICoord->Query( GUID_NULL,
  133. VSS_OBJECT_NONE,
  134. VSS_OBJECT_SNAPSHOT,
  135. &pIEnumSnapshots );
  136. if ( ft.HrFailed() )
  137. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Query failed with hr = 0x%08lx", ft.hr);
  138. // For all snapshots do...
  139. VSS_OBJECT_PROP Prop;
  140. for(;;) {
  141. // Get next element
  142. ULONG ulFetched;
  143. ft.hr = pIEnumSnapshots->Next( 1, &Prop, &ulFetched );
  144. if ( ft.HrFailed() )
  145. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Next failed with hr = 0x%08lx", ft.hr);
  146. // Test if the cycle is finished
  147. if (ft.hr == S_FALSE) {
  148. BS_ASSERT( ulFetched == 0);
  149. break;
  150. }
  151. // Use auto delete class to manage the snapshot properties
  152. CVssAutoSnapshotProperties cSnap( Prop );
  153. // If filtering, skip entry if snapshot set id is not in the specified snapshot set
  154. if ( ( FilteredSnapshotSetId != GUID_NULL ) &&
  155. !( cSnap->m_SnapshotSetId == FilteredSnapshotSetId ) )
  156. {
  157. continue;
  158. }
  159. // If filtering, skip entry if snapshot id is not in the specified snapshot set
  160. if ( ( FilteredSnapshotId != GUID_NULL ) &&
  161. !( cSnap->m_SnapshotId == FilteredSnapshotId ) )
  162. {
  163. continue;
  164. }
  165. // If filtering, skip entry if provider ID is not in the specified snapshot
  166. if ( ( FilteredProviderId != GUID_NULL ) &&
  167. !( cSnap->m_ProviderId == FilteredProviderId ) )
  168. {
  169. continue;
  170. }
  171. // If filtering, skip entry if FOR volume is not in the specified snapshot
  172. if ( ( pwszFilteredForVolume != NULL ) && ( pwszFilteredForVolume[0] != '\0' ) &&
  173. ( ::_wcsicmp( pwszFilteredForVolume, cSnap->m_pwszOriginalVolumeName ) != 0 ) )
  174. {
  175. continue;
  176. }
  177. ft.Trace( VSSDBG_VSSADMIN, L"Snapshot: %s", cSnap->m_pwszOriginalVolumeName );
  178. // Look up the snapshot set id in the list of snapshot sets
  179. CVssAdmSnapshotSetEntry *pcSSE;
  180. pcSSE = m_mapSnapshotSets.Lookup( cSnap->m_SnapshotSetId );
  181. if ( pcSSE == NULL )
  182. {
  183. // Haven't seen this snapshot set before, add it to list
  184. pcSSE = new CVssAdmSnapshotSetEntry( cSnap->m_SnapshotSetId,
  185. cSnap->m_lSnapshotsCount );
  186. if ( pcSSE == NULL )
  187. ft.Throw( VSSDBG_VSSADMIN, E_OUTOFMEMORY, L"Out of memory" );
  188. if ( !m_mapSnapshotSets.Add( cSnap->m_SnapshotSetId, pcSSE ) )
  189. {
  190. delete pcSSE;
  191. ft.Throw( VSSDBG_VSSADMIN, E_OUTOFMEMORY, L"Out of memory" );
  192. }
  193. }
  194. // Now add the snapshot to the snapshot set. Transfer of pointer
  195. // ownership of &Snap.
  196. ft.hr = pcSSE->AddSnapshot( cSnap.GetPtr() );
  197. if ( ft.HrFailed() )
  198. {
  199. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"AddSnapshot failed" );
  200. }
  201. cSnap.Transferred();
  202. }
  203. }
  204. ~CVssAdmSnapshotSets()
  205. {
  206. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdmSnapshotSets::~CVssAdmSnapshotSets" );
  207. // Have to delete all
  208. int iCount;
  209. iCount = m_mapSnapshotSets.GetSize();
  210. for ( int i = 0; i < iCount; ++i )
  211. {
  212. delete m_mapSnapshotSets.GetValueAt( i );
  213. }
  214. }
  215. INT GetSnapshotSetCount() { return m_mapSnapshotSets.GetSize(); }
  216. CVssAdmSnapshotSetEntry *GetSnapshotSetAt(
  217. IN int nIndex )
  218. {
  219. BS_ASSERT( !(nIndex < 0 || nIndex >= GetSnapshotSetCount()) );
  220. return m_mapSnapshotSets.GetValueAt( nIndex );
  221. }
  222. private:
  223. CVssSimpleMap<VSS_ID, CVssAdmSnapshotSetEntry *> m_mapSnapshotSets;
  224. };
  225. void CVssAdminCLI::GetDifferentialSoftwareSnapshotMgmtInterface(
  226. IN VSS_ID ProviderId,
  227. IN IVssSnapshotMgmt *pIMgmt,
  228. OUT IUnknown** ppItf
  229. )
  230. {
  231. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"GetDifferentialSoftwareSnapshotMgmtInterface" );
  232. BS_ASSERT( pIMgmt != NULL );
  233. ft.hr = pIMgmt->GetProviderMgmtInterface( ProviderId, IID_IVssDifferentialSoftwareSnapshotMgmt, ppItf );
  234. if ( ft.HrFailed() )
  235. {
  236. if ( ft.hr == E_NOINTERFACE )
  237. {
  238. // The provider doesn't support this interface
  239. OutputErrorMsg( MSG_ERROR_PROVIDER_DOESNT_SUPPORT_DIFFAREAS, GetOptionValueStr( VSSADM_O_PROVIDER ) );
  240. ft.Throw( VSSDBG_VSSADMIN, S_OK, L"Provider doesn't support diff aras");
  241. }
  242. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"GetProviderMgmtInterface failed with hr = 0x%08lx", ft.hr);
  243. }
  244. }
  245. /////////////////////////////////////////////////////////////////////////////
  246. // Implementation
  247. void CVssAdminCLI::PrintUsage(
  248. ) throw(HRESULT)
  249. {
  250. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::PrintUsage" );
  251. //
  252. // Based on parsed command line type, print detailed command usage if
  253. // eAdmCmd is valid, else print general vssadmin usage
  254. //
  255. if ( m_sParsedCommand.eAdmCmd != VSSADM_C_INVALID )
  256. {
  257. OutputMsg( g_asAdmCommands[m_sParsedCommand.eAdmCmd].lMsgDetail,
  258. g_asAdmCommands[m_sParsedCommand.eAdmCmd].pwszMajorOption,
  259. g_asAdmCommands[m_sParsedCommand.eAdmCmd].pwszMinorOption);
  260. if ( g_asAdmCommands[m_sParsedCommand.eAdmCmd].bShowSSTypes )
  261. DumpSnapshotTypes();
  262. return;
  263. }
  264. //
  265. // Print out header
  266. //
  267. OutputMsg( MSG_USAGE );
  268. //
  269. // Figure out the maximum command length to help with formatting
  270. //
  271. INT idx;
  272. INT iMaxLen = 0;
  273. for ( idx = VSSADM_C_FIRST; idx < VSSADM_C_NUM_COMMANDS; ++idx )
  274. {
  275. if ( dCurrentSKU & g_asAdmCommands[idx].dwSKUs )
  276. {
  277. size_t cCmd;
  278. cCmd = ::wcslen( g_asAdmCommands[idx].pwszMajorOption ) +
  279. ::wcslen( g_asAdmCommands[idx].pwszMinorOption ) + 2;
  280. if ( iMaxLen < (INT)cCmd )
  281. iMaxLen = (INT)cCmd;
  282. }
  283. }
  284. //
  285. // Get a string to hold the string
  286. //
  287. CVssAutoPWSZ awszCommand;
  288. awszCommand.Allocate( iMaxLen );
  289. LPWSTR pwszCommand = awszCommand; // will be automatically deleted
  290. //
  291. // Go through the list of commands and print the general information
  292. // about each.
  293. //
  294. for ( idx = VSSADM_C_FIRST; idx < VSSADM_C_NUM_COMMANDS; ++idx )
  295. {
  296. if ( dCurrentSKU & g_asAdmCommands[idx].dwSKUs )
  297. {
  298. // stick both parts of the command together
  299. ::wcscpy( pwszCommand, g_asAdmCommands[idx].pwszMajorOption );
  300. ::wcscat( pwszCommand, L" " );
  301. ::wcscat( pwszCommand, g_asAdmCommands[idx].pwszMinorOption );
  302. // pad with spaces at the end
  303. for ( INT i = (INT) ::wcslen( pwszCommand); i < iMaxLen; ++i )
  304. pwszCommand[i] = L' ';
  305. pwszCommand[iMaxLen] = L'\0';
  306. OutputMsg( g_asAdmCommands[idx].lMsgGen, pwszCommand );
  307. }
  308. }
  309. m_nReturnValue = VSS_CMDRET_SUCCESS;
  310. }
  311. void CVssAdminCLI::AddDiffArea(
  312. ) throw(HRESULT)
  313. {
  314. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::AddDiffArea" );
  315. // grab all of the options
  316. VSS_ID ProviderId = GUID_NULL;
  317. GetProviderId( &ProviderId );
  318. LPWSTR forVolume = GetOptionValueStr( VSSADM_O_FOR );
  319. LPWSTR onVolume = GetOptionValueStr( VSSADM_O_ON );
  320. LONGLONG llMaxSize;
  321. if (!GetOptionValueNum( VSSADM_O_MAXSIZE, &llMaxSize ) )
  322. llMaxSize = VSSADM_INFINITE_DIFFAREA;
  323. // Verify the passed-in parameters
  324. m_pVerifier->AddDiffArea (ProviderId, forVolume, onVolume, llMaxSize, ft);
  325. // Create a Coordinator interface
  326. CComPtr<IVssSnapshotMgmt> pIMgmt;
  327. ft.CoCreateInstanceWithLog(
  328. VSSDBG_VSSADMIN,
  329. CLSID_VssSnapshotMgmt,
  330. L"VssSnapshotMgmt",
  331. CLSCTX_ALL,
  332. IID_IVssSnapshotMgmt,
  333. (IUnknown**)&(pIMgmt));
  334. if ( ft.HrFailed() )
  335. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
  336. // Get the management object
  337. CComPtr<IVssDifferentialSoftwareSnapshotMgmt> pIDiffSnapMgmt;
  338. GetDifferentialSoftwareSnapshotMgmtInterface( ProviderId, pIMgmt, (IUnknown**)&pIDiffSnapMgmt );
  339. // Now add the assocation
  340. ft.hr = pIDiffSnapMgmt->AddDiffArea(forVolume, onVolume, llMaxSize );
  341. if ( ft.HrFailed() )
  342. {
  343. switch( ft.hr )
  344. {
  345. case VSS_E_OBJECT_ALREADY_EXISTS:
  346. OutputErrorMsg( MSG_ERROR_ASSOCIATION_ALREADY_EXISTS );
  347. break;
  348. default:
  349. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"AddDiffArea failed with hr = 0x%08lx", ft.hr);
  350. break;
  351. }
  352. return;
  353. }
  354. //
  355. // Print results, if needed
  356. //
  357. OutputMsg( MSG_INFO_ADDED_DIFFAREA );
  358. m_nReturnValue = VSS_CMDRET_SUCCESS;
  359. }
  360. void CVssAdminCLI::CreateSnapshot(
  361. ) throw(HRESULT)
  362. {
  363. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::CreateSnapshot" );
  364. // Grab all parameters to the function
  365. LONG lSnapshotContext = (dCurrentSKU & SKU_INT) ?
  366. DetermineSnapshotType( GetOptionValueStr( VSSADM_O_SNAPTYPE ) ) :
  367. VSS_CTX_CLIENT_ACCESSIBLE;
  368. BS_ASSERT( lSnapshotContext | VSS_VOLSNAP_ATTR_NO_WRITERS );
  369. LPWSTR forVolume = GetOptionValueStr( VSSADM_O_FOR );
  370. VSS_ID ProviderId = GUID_NULL;
  371. GetProviderId( &ProviderId );
  372. LONGLONG llTimeout = 0;
  373. GetOptionValueNum (VSSADM_O_AUTORETRY, &llTimeout, false);
  374. // Verify the passed-in parameters
  375. m_pVerifier->CreateSnapshot (lSnapshotContext, forVolume, ProviderId, llTimeout, ft);
  376. // Create the coordinator object
  377. CComPtr<IVssCoordinator> pICoord;
  378. ft.CoCreateInstanceWithLog(
  379. VSSDBG_VSSADMIN,
  380. CLSID_VSSCoordinator,
  381. L"Coordinator",
  382. CLSCTX_ALL,
  383. IID_IVssCoordinator,
  384. (IUnknown**)&(pICoord));
  385. if ( ft.HrFailed() )
  386. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
  387. ft.hr = pICoord->SetContext(lSnapshotContext);
  388. if ( ft.HrFailed() )
  389. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Error from SetContext(0x%x) hr = 0x%08lx", lSnapshotContext, ft.hr);
  390. CComPtr<IVssAsync> pAsync;
  391. VSS_ID SnapshotSetId = GUID_NULL;
  392. // Starting a new snapshot set. Note, if another process is creating snapshots, then
  393. // this will fail. If AutoRetry was specified, then retry the start snapshot set for
  394. // that the specified number of minutes.
  395. if (llTimeout > 0)
  396. {
  397. LARGE_INTEGER liPerfCount;
  398. (void)QueryPerformanceCounter( &liPerfCount );
  399. ::srand( liPerfCount.LowPart );
  400. DWORD dwTickcountStart = ::GetTickCount();
  401. do
  402. {
  403. ft.hr = pICoord->StartSnapshotSet(&SnapshotSetId);
  404. if ( ft.HrFailed() )
  405. {
  406. if ( ft.hr == VSS_E_SNAPSHOT_SET_IN_PROGRESS &&
  407. ( (LONGLONG)( ::GetTickCount() - dwTickcountStart ) < ( llTimeout * 1000 * 60 ) ) )
  408. {
  409. static dwMSec = 250; // Starting retry time
  410. if ( dwMSec < 10000 )
  411. {
  412. dwMSec += ::rand() % 750;
  413. }
  414. ft.Trace( VSSDBG_VSSADMIN, L"Snapshot already in progress, retrying in %u millisecs", dwMSec );
  415. Sleep( dwMSec );
  416. }
  417. else
  418. {
  419. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Error from StartSnapshotSet hr = 0x%08lx", ft.hr);
  420. }
  421. }
  422. } while ( ft.HrFailed() );
  423. }
  424. else
  425. {
  426. //
  427. // Error right away with out a timeout when there is another snapshot in progress.
  428. //
  429. ft.hr = pICoord->StartSnapshotSet(&SnapshotSetId);
  430. if ( ft.HrFailed() )
  431. {
  432. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Error from StartSnapshotSet hr = 0x%08lx", ft.hr);
  433. }
  434. }
  435. // Add the volume to the snapshot set
  436. VSS_ID SnapshotId = GUID_NULL;
  437. ft.hr = pICoord->AddToSnapshotSet(
  438. forVolume,
  439. ProviderId,
  440. &SnapshotId);
  441. if ( ft.HrFailed() )
  442. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Error from AddToSnapshotSet hr = 0x%08lx", ft.hr);
  443. ft.hr = S_OK;
  444. pAsync = NULL;
  445. ft.hr = pICoord->DoSnapshotSet(NULL, &pAsync);
  446. if ( ft.HrFailed() )
  447. ft.Throw( VSSDBG_VSSADMIN, ft.hr,
  448. L"Error from DoSnapshotSet hr = 0x%08lx", ft.hr);
  449. ft.hr = pAsync->Wait();
  450. if ( ft.HrFailed() )
  451. ft.Throw( VSSDBG_VSSADMIN, ft.hr,
  452. L"Error from Wait hr = 0x%08lx", ft.hr);
  453. HRESULT hrStatus;
  454. ft.hr = pAsync->QueryStatus(&hrStatus, NULL);
  455. if ( ft.HrFailed() )
  456. ft.Throw( VSSDBG_VSSADMIN, ft.hr,
  457. L"Error from QueryStatus hr = 0x%08lx", ft.hr);
  458. //
  459. // If VSS failed to create the snapshot, it's result code is in hrStatus. Process
  460. // it.
  461. //
  462. ft.hr = hrStatus;
  463. if ( ft.HrFailed() )
  464. ft.Throw( VSSDBG_VSSADMIN, ft.hr,
  465. L"QueryStatus hrStatus parameter returned error, hr = 0x%08lx", ft.hr);
  466. //
  467. // Print results
  468. //
  469. VSS_SNAPSHOT_PROP sSSProp;
  470. ft.hr = pICoord->GetSnapshotProperties( SnapshotId, &sSSProp );
  471. if ( ft.HrFailed() )
  472. ft.Throw( VSSDBG_VSSADMIN, ft.hr,
  473. L"Error from GetId hr = 0x%08lx", ft.hr);
  474. CVssAutoPWSZ awszSnapshotId( ::GuidToString( SnapshotId ) );
  475. OutputMsg( MSG_INFO_SNAPSHOT_CREATED, forVolume,
  476. (LPWSTR)awszSnapshotId, sSSProp.m_pwszSnapshotDeviceObject );
  477. ::VssFreeSnapshotProperties(&sSSProp);
  478. m_nReturnValue = VSS_CMDRET_SUCCESS;
  479. }
  480. void CVssAdminCLI::DisplayDiffAreasPrivate(
  481. IVssEnumMgmtObject *pIEnumMgmt
  482. ) throw(HRESULT)
  483. {
  484. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::DisplayDiffAreasPrivate" );
  485. // For all diffareas do...
  486. VSS_MGMT_OBJECT_PROP Prop;
  487. VSS_DIFF_AREA_PROP& DiffArea = Prop.Obj.DiffArea;
  488. for(;;)
  489. {
  490. // Get next element
  491. ULONG ulFetched;
  492. ft.hr = pIEnumMgmt->Next( 1, &Prop, &ulFetched );
  493. if ( ft.HrFailed() )
  494. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Next failed with hr = 0x%08lx", ft.hr);
  495. // Test if the cycle is finished
  496. if (ft.hr == S_FALSE) {
  497. BS_ASSERT( ulFetched == 0);
  498. break;
  499. }
  500. CVssAutoPWSZ awszVolumeName( DiffArea.m_pwszVolumeName );
  501. CVssAutoPWSZ awszDiffAreaVolumeName( DiffArea.m_pwszDiffAreaVolumeName );
  502. CVssAutoPWSZ awszUsedSpace( FormatNumber( DiffArea.m_llUsedDiffSpace ) );
  503. CVssAutoPWSZ awszAllocatedSpace( FormatNumber( DiffArea.m_llAllocatedDiffSpace ) );
  504. CVssAutoPWSZ awszMaxSpace( FormatNumber( DiffArea.m_llMaximumDiffSpace ) );
  505. LPCWSTR pwszVolumeDisplayName = GetVolumeDisplayName( awszVolumeName );
  506. LPCWSTR pwszDiffAreaVolumeDisplayName = GetVolumeDisplayName( awszDiffAreaVolumeName );
  507. OutputMsg( MSG_INFO_SNAPSHOT_STORAGE_CONTENTS,
  508. pwszVolumeDisplayName,
  509. (LPWSTR)awszVolumeName,
  510. pwszDiffAreaVolumeDisplayName,
  511. (LPWSTR)awszDiffAreaVolumeName,
  512. (LPWSTR)awszUsedSpace,
  513. (LPWSTR)awszAllocatedSpace,
  514. (LPWSTR)awszMaxSpace
  515. );
  516. }
  517. }
  518. void CVssAdminCLI::ListDiffAreas(
  519. ) throw(HRESULT)
  520. {
  521. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::ListDiffAreas" );
  522. // Grab all parameters
  523. VSS_ID ProviderId = GUID_NULL;
  524. GetProviderId( &ProviderId );
  525. LPWSTR forVolume = GetOptionValueStr (VSSADM_O_FOR);
  526. LPWSTR onVolume = GetOptionValueStr (VSSADM_O_ON);
  527. // Verify all parameters
  528. m_pVerifier->ListDiffAreas (ProviderId, forVolume, onVolume, ft);
  529. // Create a Coordinator interface
  530. CComPtr<IVssSnapshotMgmt> pIMgmt;
  531. ft.CoCreateInstanceWithLog(
  532. VSSDBG_VSSADMIN,
  533. CLSID_VssSnapshotMgmt,
  534. L"VssSnapshotMgmt",
  535. CLSCTX_ALL,
  536. IID_IVssSnapshotMgmt,
  537. (IUnknown**)&(pIMgmt));
  538. if ( ft.HrFailed() )
  539. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
  540. // Get the management object
  541. CComPtr<IVssDifferentialSoftwareSnapshotMgmt> pIDiffSnapMgmt;
  542. GetDifferentialSoftwareSnapshotMgmtInterface( ProviderId, pIMgmt, (IUnknown**)&pIDiffSnapMgmt );
  543. // See if query by for volume
  544. if (forVolume != NULL )
  545. {
  546. // Query by For volume
  547. CComPtr<IVssEnumMgmtObject> pIEnumMgmt;
  548. ft.hr = pIDiffSnapMgmt->QueryDiffAreasForVolume(
  549. forVolume,
  550. &pIEnumMgmt );
  551. if ( ft.HrFailed() )
  552. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"QueryDiffAreasForVolume failed, hr = 0x%08lx", ft.hr);
  553. if ( ft.hr == S_FALSE )
  554. // empty query
  555. ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_NO_ITEMS_IN_QUERY,
  556. L"CVssAdminCLI::ListDiffareas: No diffareas found that satisfy the query" );
  557. DisplayDiffAreasPrivate( pIEnumMgmt );
  558. }
  559. else if (onVolume != NULL )
  560. {
  561. // Query by On volume
  562. CComPtr<IVssEnumMgmtObject> pIEnumMgmt;
  563. ft.hr = pIDiffSnapMgmt->QueryDiffAreasOnVolume(
  564. onVolume,
  565. &pIEnumMgmt );
  566. if ( ft.HrFailed() )
  567. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"QueryDiffAreasOnVolume failed, hr = 0x%08lx", ft.hr);
  568. if ( ft.hr == S_FALSE )
  569. // empty query
  570. ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_NO_ITEMS_IN_QUERY,
  571. L"CVssAdminCLI::ListDiffareas: No diffareas found that satisfy the query" );
  572. DisplayDiffAreasPrivate( pIEnumMgmt );
  573. }
  574. else
  575. {
  576. // Query all diff areas
  577. BOOL bEmptyQuery = TRUE;
  578. //
  579. // Get the list of all volumes
  580. //
  581. CComPtr<IVssEnumMgmtObject> pIEnumMgmt;
  582. ft.hr = pIMgmt->QueryVolumesSupportedForSnapshots(
  583. ProviderId,
  584. VSS_CTX_ALL,
  585. &pIEnumMgmt );
  586. if ( ft.HrFailed() )
  587. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"QueryVolumesSupportedForSnapshots failed, hr = 0x%08lx", ft.hr);
  588. if ( ft.hr == S_FALSE )
  589. // empty query
  590. ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_NO_ITEMS_IN_QUERY,
  591. L"CVssAdminCLI::ListDiffareas: No diffareas found that satisfy the query" );
  592. //
  593. // Query each volume to see if diff areas exist.
  594. //
  595. VSS_MGMT_OBJECT_PROP Prop;
  596. VSS_VOLUME_PROP& VolProp = Prop.Obj.Vol;
  597. for(;;)
  598. {
  599. // Get next element
  600. ULONG ulFetched;
  601. ft.hr = pIEnumMgmt->Next( 1, &Prop, &ulFetched );
  602. if ( ft.HrFailed() )
  603. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Next failed with hr = 0x%08lx", ft.hr);
  604. // Test if the cycle is finished
  605. if (ft.hr == S_FALSE) {
  606. BS_ASSERT( ulFetched == 0);
  607. break;
  608. }
  609. CVssAutoPWSZ awszVolumeName( VolProp.m_pwszVolumeName );
  610. CVssAutoPWSZ awszVolumeDisplayName( VolProp.m_pwszVolumeDisplayName );
  611. // For all volumes do...
  612. CComPtr<IVssEnumMgmtObject> pIEnumMgmtDiffArea;
  613. ft.hr = pIDiffSnapMgmt->QueryDiffAreasForVolume(
  614. awszVolumeName,
  615. &pIEnumMgmtDiffArea );
  616. if ( ft.HrFailed() )
  617. {
  618. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"QueryDiffAreasForVolume failed, hr = 0x%08lx", ft.hr);
  619. }
  620. if ( ft.hr == S_FALSE )
  621. {
  622. // empty query
  623. continue;
  624. }
  625. DisplayDiffAreasPrivate( pIEnumMgmtDiffArea );
  626. bEmptyQuery = FALSE;
  627. }
  628. if ( bEmptyQuery )
  629. // empty query
  630. ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_NO_ITEMS_IN_QUERY,
  631. L"CVssAdminCLI::ListDiffareas: No diffareas found that satisfy the query" );
  632. }
  633. m_nReturnValue = VSS_CMDRET_SUCCESS;
  634. }
  635. void CVssAdminCLI::ListSnapshots(
  636. ) throw(HRESULT)
  637. {
  638. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::ListSnapshots" );
  639. // gather parameters
  640. LONG lSnapshotContext = (dCurrentSKU & SKU_INT) ?
  641. DetermineSnapshotType( GetOptionValueStr( VSSADM_O_SNAPTYPE ) ) :
  642. VSS_CTX_ALL;
  643. VSS_ID ProviderId = GUID_NULL;
  644. GetProviderId( &ProviderId );
  645. LPCWSTR forVolume = GetOptionValueStr( VSSADM_O_FOR );
  646. bool bNonEmptyResult = false;
  647. // --- get the set id
  648. VSS_ID guidSSID = GUID_NULL;
  649. if ( GetOptionValueStr( VSSADM_O_SET ) != NULL &&
  650. !ScanGuid( GetOptionValueStr( VSSADM_O_SET ), guidSSID ))
  651. {
  652. ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_INVALID_OPTION_VALUE,
  653. L"CVssAdminCLI::ListSnapshots: invalid snapshot set ID: %s",
  654. GetOptionValueStr( VSSADM_O_SET ) );
  655. }
  656. // --- get the snapshot id
  657. VSS_ID guidSnapID = GUID_NULL;
  658. if ( GetOptionValueStr( VSSADM_O_SNAPSHOT ) != NULL &&
  659. !ScanGuid( GetOptionValueStr( VSSADM_O_SNAPSHOT ), guidSnapID ))
  660. {
  661. ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_INVALID_OPTION_VALUE,
  662. L"CVssAdminCLI::ListSnapshots: invalid snapshot ID: %s",
  663. GetOptionValueStr( VSSADM_O_SNAPSHOT ) );
  664. }
  665. // verify the parameters
  666. m_pVerifier->ListSnapshots (lSnapshotContext, ProviderId, forVolume, guidSnapID, guidSSID, ft);
  667. // See if we have to filter by volume name
  668. WCHAR wszVolumeNameInternal[x_nLengthOfVolMgmtVolumeName + 1] = L"";
  669. if (forVolume != NULL )
  670. {
  671. // Calculate the unique volume name, just to make sure that we have the right path
  672. // If FOR volume name starts with the '\', assume it is already in the correct volume name format.
  673. // This is important for transported volumes since GetVolumeNameForVolumeMountPointW() won't work.
  674. if ( forVolume[0] != L'\\' )
  675. {
  676. if (!::GetVolumeNameForVolumeMountPointW(forVolume,
  677. wszVolumeNameInternal, ARRAY_LEN(wszVolumeNameInternal)))
  678. ft.Throw( VSSDBG_COORD, VSS_E_OBJECT_NOT_FOUND,
  679. L"GetVolumeNameForVolumeMountPoint(%s,...) "
  680. L"failed with error code 0x%08lx", forVolume, ::GetLastError());
  681. }
  682. else
  683. {
  684. ::wcsncpy( wszVolumeNameInternal, forVolume, STRING_LEN(wszVolumeNameInternal) );
  685. wszVolumeNameInternal[x_nLengthOfVolMgmtVolumeName] = L'\0';
  686. }
  687. }
  688. //
  689. // See if we have to filter by provider
  690. //
  691. // Query the snapshots
  692. CVssAdmSnapshotSets cVssAdmSS;
  693. cVssAdmSS.Initialize( lSnapshotContext, guidSSID, guidSnapID, ProviderId, wszVolumeNameInternal );
  694. INT iSnapshotSetCount = cVssAdmSS.GetSnapshotSetCount();
  695. // If there are no present snapshots then display a message.
  696. if (iSnapshotSetCount == 0) {
  697. ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_NO_ITEMS_IN_QUERY,
  698. L"CVssAdminCLI::ListSnapshots: No snapshots found that satisfy the query");
  699. }
  700. // For all snapshot sets do...
  701. for ( INT iSSS = 0; iSSS < iSnapshotSetCount; ++iSSS )
  702. {
  703. CVssAdmSnapshotSetEntry *pcSSE;
  704. pcSSE = cVssAdmSS.GetSnapshotSetAt( iSSS );
  705. BS_ASSERT( pcSSE != NULL );
  706. CVssAutoPWSZ awszGuid( ::GuidToString( pcSSE->GetSnapshotSetId() ) ) ;
  707. CVssAutoPWSZ awszDateTime( ::DateTimeToString( &( pcSSE->GetSnapshotAt( 0 )->m_tsCreationTimestamp ) ) );
  708. // Print each snapshot set
  709. OutputMsg(
  710. MSG_INFO_SNAPSHOT_SET_HEADER,
  711. (LPWSTR)awszGuid,
  712. pcSSE->GetOriginalSnapshotCount(),
  713. (LPWSTR)awszDateTime );
  714. INT iSnapshotCount = pcSSE->GetSnapshotCount();
  715. VSS_SNAPSHOT_PROP *pSnap;
  716. for( INT iSS = 0; iSS < iSnapshotCount; ++iSS ) {
  717. pSnap = pcSSE->GetSnapshotAt( iSS );
  718. BS_ASSERT( pSnap != NULL );
  719. // Get the provider name
  720. LPCWSTR pwszProviderName = GetProviderName( pSnap->m_ProviderId );
  721. CVssAutoPWSZ awszAttributeStr( BuildSnapshotAttributeDisplayString( pSnap->m_lSnapshotAttributes ) );
  722. CVssAutoPWSZ awszSnapshotType( DetermineSnapshotType( pSnap->m_lSnapshotAttributes ) );
  723. // Print each snapshot
  724. CVssAutoPWSZ awszSnapGuid( ::GuidToString( pSnap->m_SnapshotId ) );
  725. LPCWSTR pwszVolumeDisplayName = GetVolumeDisplayName( pSnap->m_pwszOriginalVolumeName );
  726. OutputMsg(
  727. MSG_INFO_SNAPSHOT_CONTENTS,
  728. (LPWSTR)awszSnapGuid,
  729. pwszVolumeDisplayName ? pwszVolumeDisplayName : L"?",
  730. pSnap->m_pwszOriginalVolumeName,
  731. pSnap->m_pwszSnapshotDeviceObject,
  732. pSnap->m_pwszOriginatingMachine ? pSnap->m_pwszOriginatingMachine : L"",
  733. pSnap->m_pwszServiceMachine ? pSnap->m_pwszServiceMachine : L"", // fix this when the idl file changes
  734. pwszProviderName ? pwszProviderName : L"?",
  735. (LPWSTR)awszSnapshotType,
  736. (LPWSTR)awszAttributeStr
  737. );
  738. bNonEmptyResult = true;
  739. }
  740. }
  741. m_nReturnValue = bNonEmptyResult? VSS_CMDRET_SUCCESS: VSS_CMDRET_EMPTY_RESULT;
  742. }
  743. void CVssAdminCLI::DumpSnapshotTypes(
  744. ) throw(HRESULT)
  745. {
  746. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::DumpSnapshotTypes" );
  747. //
  748. // Dump list of snapshot types based on SKU
  749. //
  750. INT idx;
  751. // Determine type of snapshot
  752. for ( idx = 0; g_asAdmTypeNames[idx].pwszName != NULL; ++idx )
  753. {
  754. if ( dCurrentSKU & g_asAdmTypeNames[idx].dwSKUs )
  755. {
  756. OutputMsg (g_asAdmTypeNames[idx].pwszDescription,
  757. g_asAdmTypeNames[idx].pwszName);
  758. }
  759. }
  760. }
  761. void CVssAdminCLI::ListWriters(
  762. ) throw(HRESULT)
  763. {
  764. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::ListWriters" );
  765. // verify the parameters
  766. m_pVerifier->ListWriters (ft);
  767. bool bNonEmptyResult = false;
  768. // Get the backup components object
  769. CComPtr<IVssBackupComponents> pBackupComp;
  770. CComPtr<IVssAsync> pAsync;
  771. ft.hr = ::CreateVssBackupComponents(&pBackupComp);
  772. if (ft.HrFailed())
  773. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"CreateVssBackupComponents failed with hr = 0x%08lx", ft.hr);
  774. ft.hr = pBackupComp->InitializeForBackup();
  775. if (ft.HrFailed())
  776. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"InitializeForBackup failed with hr = 0x%08lx", ft.hr);
  777. UINT unWritersCount;
  778. // get metadata for all writers
  779. ft.hr = pBackupComp->GatherWriterMetadata(&pAsync);
  780. if (ft.HrFailed())
  781. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"GatherWriterMetadata failed with hr = 0x%08lx", ft.hr);
  782. // Using polling, try to obtain the list of writers as soon as possible
  783. HRESULT hrReturned = S_OK;
  784. for (int nRetries = 0; nRetries < x_nMaxRetriesCount; nRetries++ ) {
  785. // Wait a little
  786. ::Sleep(x_nPollingInterval);
  787. // Check if finished
  788. INT nReserved = 0;
  789. ft.hr = pAsync->QueryStatus(
  790. &hrReturned,
  791. &nReserved
  792. );
  793. if (ft.HrFailed())
  794. ft.Throw( VSSDBG_VSSADMIN, ft.hr,
  795. L"IVssAsync::QueryStatus failed with hr = 0x%08lx", ft.hr);
  796. if (hrReturned == VSS_S_ASYNC_FINISHED)
  797. break;
  798. if (hrReturned == VSS_S_ASYNC_PENDING)
  799. continue;
  800. ft.Throw( VSSDBG_VSSADMIN, ft.hr,
  801. L"IVssAsync::QueryStatus returned hr = 0x%08lx", hrReturned);
  802. }
  803. // If still not ready, then print the "waiting for responses" message and wait.
  804. if (hrReturned == VSS_S_ASYNC_PENDING) {
  805. OutputMsg( MSG_INFO_WAITING_RESPONSES );
  806. ft.hr = pAsync->Wait();
  807. if (ft.HrFailed())
  808. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"IVssAsync::Wait failed with hr = 0x%08lx", ft.hr);
  809. }
  810. pAsync = NULL;
  811. // Free the writer metadata
  812. ft.hr = pBackupComp->FreeWriterMetadata();
  813. if (ft.HrFailed())
  814. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"FreeWriterMetadata failed with hr = 0x%08lx", ft.hr);
  815. // Gather the status of all writers
  816. ft.hr = pBackupComp->GatherWriterStatus(&pAsync);
  817. if (ft.HrFailed())
  818. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"GatherWriterStatus failed with hr = 0x%08lx", ft.hr);
  819. ft.hr = pAsync->Wait();
  820. if (ft.HrFailed())
  821. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"IVssAsync::Wait failed with hr = 0x%08lx", ft.hr);
  822. pAsync = NULL;
  823. ft.hr = pBackupComp->GetWriterStatusCount(&unWritersCount);
  824. if (ft.HrFailed())
  825. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"GetWriterStatusCount failed with hr = 0x%08lx", ft.hr);
  826. // Print each writer status+supplementary info
  827. for(UINT unIndex = 0; unIndex < unWritersCount; unIndex++)
  828. {
  829. VSS_ID idInstance = GUID_NULL;
  830. VSS_ID idWriter = GUID_NULL;
  831. CComBSTR bstrWriter;
  832. VSS_WRITER_STATE eStatus;
  833. HRESULT hrWriterFailure;
  834. // Get the status for the (unIndex)-th writer
  835. ft.hr = pBackupComp->GetWriterStatus(unIndex, &idInstance, &idWriter, &bstrWriter, &eStatus, &hrWriterFailure);
  836. if (ft.HrFailed())
  837. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"GetWriterStatus failed with hr = 0x%08lx", ft.hr);
  838. // Get the status description strings
  839. LPCWSTR pwszStatusDescription;
  840. switch (eStatus)
  841. {
  842. case VSS_WS_STABLE:
  843. pwszStatusDescription = LoadString( IDS_WRITER_STATUS_STABLE);
  844. break;
  845. case VSS_WS_WAITING_FOR_FREEZE:
  846. pwszStatusDescription = LoadString( IDS_WRITER_STATUS_WAITING_FOR_FREEZE);
  847. break;
  848. case VSS_WS_WAITING_FOR_THAW:
  849. pwszStatusDescription = LoadString( IDS_WRITER_STATUS_FROZEN);
  850. break;
  851. case VSS_WS_WAITING_FOR_POST_SNAPSHOT:
  852. pwszStatusDescription = LoadString( IDS_WRITER_STATUS_WAITING_FOR_POST_SNAPSHOT);
  853. break;
  854. case VSS_WS_WAITING_FOR_BACKUP_COMPLETE:
  855. pwszStatusDescription = LoadString( IDS_WRITER_STATUS_WAITING_FOR_COMPLETION);
  856. break;
  857. case VSS_WS_FAILED_AT_IDENTIFY:
  858. case VSS_WS_FAILED_AT_PREPARE_BACKUP:
  859. case VSS_WS_FAILED_AT_PREPARE_SNAPSHOT:
  860. case VSS_WS_FAILED_AT_FREEZE:
  861. case VSS_WS_FAILED_AT_THAW:
  862. case VSS_WS_FAILED_AT_POST_SNAPSHOT:
  863. case VSS_WS_FAILED_AT_BACKUP_COMPLETE:
  864. case VSS_WS_FAILED_AT_PRE_RESTORE:
  865. case VSS_WS_FAILED_AT_POST_RESTORE:
  866. pwszStatusDescription = LoadString( IDS_WRITER_STATUS_FAILED);
  867. break;
  868. default:
  869. pwszStatusDescription = LoadString( IDS_WRITER_STATUS_UNKNOWN);
  870. break;
  871. }
  872. BS_ASSERT(pwszStatusDescription);
  873. LPCWSTR pwszWriterError;
  874. switch ( hrWriterFailure )
  875. {
  876. case S_OK:
  877. pwszWriterError = LoadString ( IDS_WRITER_ERROR_SUCCESS );
  878. break;
  879. case VSS_E_WRITER_NOT_RESPONDING:
  880. pwszWriterError = LoadString( IDS_WRITER_ERROR_NOT_RESPONDING );
  881. break;
  882. case VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT:
  883. pwszWriterError = LoadString( IDS_WRITER_ERROR_INCONSISTENTSNAPSHOT);
  884. break;
  885. case VSS_E_WRITERERROR_OUTOFRESOURCES:
  886. pwszWriterError = LoadString( IDS_WRITER_ERROR_OUTOFRESOURCES);
  887. break;
  888. case VSS_E_WRITERERROR_TIMEOUT:
  889. pwszWriterError = LoadString( IDS_WRITER_ERROR_TIMEOUT);
  890. break;
  891. case VSS_E_WRITERERROR_RETRYABLE:
  892. pwszWriterError = LoadString( IDS_WRITER_ERROR_RETRYABLE);
  893. break;
  894. case VSS_E_WRITERERROR_NONRETRYABLE:
  895. pwszWriterError = LoadString( IDS_WRITER_ERROR_NONRETRYABLE);
  896. break;
  897. default:
  898. pwszWriterError = LoadString( IDS_WRITER_ERROR_UNEXPECTED);
  899. ft.Trace( VSSDBG_VSSADMIN, L"Unexpected writer error failure: 0x%08x", hrWriterFailure );
  900. break;
  901. }
  902. CVssAutoPWSZ awszWriterId( ::GuidToString( idWriter ) );
  903. CVssAutoPWSZ awszInstanceId( ::GuidToString( idInstance ) );
  904. OutputMsg( MSG_INFO_WRITER_CONTENTS,
  905. (LPWSTR)bstrWriter ? (LPWSTR)bstrWriter : L"",
  906. (LPWSTR)awszWriterId,
  907. (LPWSTR)awszInstanceId,
  908. (INT)eStatus,
  909. pwszStatusDescription,
  910. pwszWriterError
  911. );
  912. bNonEmptyResult = true;
  913. }
  914. ft.hr = pBackupComp->FreeWriterStatus();
  915. if (ft.HrFailed())
  916. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"FreeWriterStatus failed with hr = 0x%08lx", ft.hr);
  917. m_nReturnValue = bNonEmptyResult? VSS_CMDRET_SUCCESS: VSS_CMDRET_EMPTY_RESULT;
  918. }
  919. void CVssAdminCLI::ListProviders(
  920. ) throw(HRESULT)
  921. {
  922. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::ListProviders" );
  923. // verify the parameters
  924. m_pVerifier->ListProviders (ft);
  925. bool bNonEmptyResult = false;
  926. // Create the coordinator object
  927. CComPtr<IVssCoordinator> pICoord;
  928. ft.CoCreateInstanceWithLog(
  929. VSSDBG_VSSADMIN,
  930. CLSID_VSSCoordinator,
  931. L"Coordinator",
  932. CLSCTX_ALL,
  933. IID_IVssCoordinator,
  934. (IUnknown**)&(pICoord));
  935. if ( ft.HrFailed() )
  936. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
  937. // Query all (filtered) snapshot sets
  938. CComPtr<IVssEnumObject> pIEnumProv;
  939. ft.hr = pICoord->Query( GUID_NULL,
  940. VSS_OBJECT_NONE,
  941. VSS_OBJECT_PROVIDER,
  942. &pIEnumProv );
  943. if ( ft.HrFailed() )
  944. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Query failed with hr = 0x%08lx", ft.hr);
  945. // For all snapshot sets do...
  946. VSS_OBJECT_PROP Prop;
  947. VSS_PROVIDER_PROP& Prov = Prop.Obj.Prov;
  948. for(;;) {
  949. // Get next element
  950. ULONG ulFetched;
  951. ft.hr = pIEnumProv->Next( 1, &Prop, &ulFetched );
  952. if ( ft.HrFailed() )
  953. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Next failed with hr = 0x%08lx", ft.hr);
  954. // Test if the cycle is ended
  955. if (ft.hr == S_FALSE) {
  956. BS_ASSERT( ulFetched == 0);
  957. break;
  958. }
  959. // Get the provider type strings
  960. LPCWSTR pwszProviderType;
  961. switch (Prov.m_eProviderType) {
  962. case VSS_PROV_SYSTEM:
  963. pwszProviderType = LoadString( IDS_PROV_TYPE_SYSTEM);
  964. break;
  965. case VSS_PROV_SOFTWARE:
  966. pwszProviderType = LoadString( IDS_PROV_TYPE_SOFTWARE);
  967. break;
  968. case VSS_PROV_HARDWARE:
  969. pwszProviderType = LoadString( IDS_PROV_TYPE_HARDWARE);
  970. break;
  971. default:
  972. pwszProviderType = LoadString( IDS_PROV_TYPE_UNKNOWN);
  973. break;
  974. }
  975. BS_ASSERT(pwszProviderType);
  976. // Print each snapshot set
  977. CVssAutoPWSZ awszProviderId( ::GuidToString( Prov.m_ProviderId ) );
  978. CVssAutoPWSZ awszProviderName( Prov.m_pwszProviderName );
  979. CVssAutoPWSZ awszProviderVersion( Prov.m_pwszProviderVersion );
  980. OutputMsg( MSG_INFO_PROVIDER_CONTENTS,
  981. (LPWSTR)awszProviderName ? (LPWSTR)awszProviderName: L"",
  982. pwszProviderType,
  983. (LPWSTR)awszProviderId,
  984. (LPWSTR)awszProviderVersion ? (LPWSTR)awszProviderVersion: L"");
  985. bNonEmptyResult = true;
  986. }
  987. m_nReturnValue = bNonEmptyResult? VSS_CMDRET_SUCCESS: VSS_CMDRET_EMPTY_RESULT;
  988. }
  989. void CVssAdminCLI::ListVolumes(
  990. ) throw(HRESULT)
  991. {
  992. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::ListVolumes" );
  993. // gather the parameters
  994. LONG lContext = (dCurrentSKU & SKU_INT) ?
  995. DetermineSnapshotType( GetOptionValueStr( VSSADM_O_SNAPTYPE ) ) :
  996. VSS_CTX_CLIENT_ACCESSIBLE;
  997. VSS_ID ProviderId = GUID_NULL;
  998. GetProviderId( &ProviderId );
  999. // verify the parameters
  1000. m_pVerifier->ListVolumes (ProviderId, lContext, ft);
  1001. // Create a Coordinator interface
  1002. CComPtr<IVssSnapshotMgmt> pIMgmt;
  1003. ft.CoCreateInstanceWithLog(
  1004. VSSDBG_VSSADMIN,
  1005. CLSID_VssSnapshotMgmt,
  1006. L"VssSnapshotMgmt",
  1007. CLSCTX_ALL,
  1008. IID_IVssSnapshotMgmt,
  1009. (IUnknown**)&(pIMgmt));
  1010. if ( ft.HrFailed() )
  1011. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
  1012. //
  1013. // Get the list of all volumes
  1014. //
  1015. CComPtr<IVssEnumMgmtObject> pIEnumMgmt;
  1016. ft.hr = pIMgmt->QueryVolumesSupportedForSnapshots(
  1017. ProviderId,
  1018. lContext,
  1019. &pIEnumMgmt );
  1020. if ( ft.HrFailed() )
  1021. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"QueryVolumesSupportedForSnapshots failed, hr = 0x%08lx", ft.hr);
  1022. if ( ft.hr == S_FALSE )
  1023. // empty query
  1024. ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_NO_ITEMS_IN_QUERY,
  1025. L"CVssAdminCLI::ListVolumes: No volumes found that satisfy the query" );
  1026. //
  1027. // Query each volume to see if diff areas exist.
  1028. //
  1029. VSS_MGMT_OBJECT_PROP Prop;
  1030. VSS_VOLUME_PROP& VolProp = Prop.Obj.Vol;
  1031. for(;;)
  1032. {
  1033. // Get next element
  1034. ULONG ulFetched;
  1035. ft.hr = pIEnumMgmt->Next( 1, &Prop, &ulFetched );
  1036. if ( ft.HrFailed() )
  1037. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Next failed with hr = 0x%08lx", ft.hr);
  1038. // Test if the cycle is finished
  1039. if (ft.hr == S_FALSE) {
  1040. BS_ASSERT( ulFetched == 0);
  1041. break;
  1042. }
  1043. CVssAutoPWSZ awszVolumeName( VolProp.m_pwszVolumeName );
  1044. CVssAutoPWSZ awszVolumeDisplayName( VolProp.m_pwszVolumeDisplayName );
  1045. OutputMsg( MSG_INFO_VOLUME_CONTENTS, (LPWSTR)awszVolumeDisplayName, (LPWSTR)awszVolumeName );
  1046. }
  1047. m_nReturnValue = VSS_CMDRET_SUCCESS;
  1048. }
  1049. void CVssAdminCLI::ResizeDiffArea(
  1050. ) throw(HRESULT)
  1051. {
  1052. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::ResizeDiffArea" );
  1053. // gather the parameters
  1054. VSS_ID ProviderId = GUID_NULL;
  1055. GetProviderId( &ProviderId );
  1056. LPWSTR forVolume = GetOptionValueStr( VSSADM_O_FOR );
  1057. LPWSTR onVolume = GetOptionValueStr( VSSADM_O_ON );
  1058. LONGLONG llMaxSize = 0;
  1059. if (!GetOptionValueNum( VSSADM_O_MAXSIZE, &llMaxSize ))
  1060. {
  1061. llMaxSize = VSSADM_INFINITE_DIFFAREA;
  1062. }
  1063. // verify the parameters
  1064. m_pVerifier->ResizeDiffArea (ProviderId, forVolume, onVolume, llMaxSize, ft);
  1065. // Create a Coordinator interface
  1066. CComPtr<IVssSnapshotMgmt> pIMgmt;
  1067. ft.CoCreateInstanceWithLog(
  1068. VSSDBG_VSSADMIN,
  1069. CLSID_VssSnapshotMgmt,
  1070. L"VssSnapshotMgmt",
  1071. CLSCTX_ALL,
  1072. IID_IVssSnapshotMgmt,
  1073. (IUnknown**)&(pIMgmt));
  1074. if ( ft.HrFailed() )
  1075. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
  1076. // Get the management object
  1077. CComPtr<IVssDifferentialSoftwareSnapshotMgmt> pIDiffSnapMgmt;
  1078. GetDifferentialSoftwareSnapshotMgmtInterface( ProviderId, pIMgmt, (IUnknown**)&pIDiffSnapMgmt );
  1079. // Now add the assocation
  1080. ft.hr = pIDiffSnapMgmt->ChangeDiffAreaMaximumSize(forVolume, onVolume, llMaxSize );
  1081. if ( ft.HrFailed() )
  1082. {
  1083. if ( ft.hr == VSS_E_OBJECT_NOT_FOUND ) // should be VSS_E_MAXIMUM_DIFFAREA_ASSOCIATIONS
  1084. {
  1085. // The associations was not found
  1086. OutputErrorMsg( MSG_ERROR_ASSOCIATION_NOT_FOUND );
  1087. return;
  1088. }
  1089. else
  1090. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"ResizeDiffArea failed with hr = 0x%08lx", ft.hr);
  1091. }
  1092. //
  1093. // Print results, if needed
  1094. //
  1095. OutputMsg( MSG_INFO_RESIZED_DIFFAREA );
  1096. m_nReturnValue = VSS_CMDRET_SUCCESS;
  1097. }
  1098. void CVssAdminCLI::DeleteDiffAreas(
  1099. ) throw(HRESULT)
  1100. {
  1101. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::DeleteDiffAreas" );
  1102. // gather the parameters
  1103. VSS_ID ProviderId = GUID_NULL;
  1104. GetProviderId( &ProviderId );
  1105. LPWSTR forVolume = GetOptionValueStr( VSSADM_O_FOR );
  1106. LPWSTR onVolume = GetOptionValueStr( VSSADM_O_ON );
  1107. // verify the parameters
  1108. m_pVerifier->DeleteDiffAreas (ProviderId, forVolume, onVolume, IsQuiet() == TRUE, ft);
  1109. // Create a Coordinator interface
  1110. CComPtr<IVssSnapshotMgmt> pIMgmt;
  1111. ft.CoCreateInstanceWithLog(
  1112. VSSDBG_VSSADMIN,
  1113. CLSID_VssSnapshotMgmt,
  1114. L"VssSnapshotMgmt",
  1115. CLSCTX_ALL,
  1116. IID_IVssSnapshotMgmt,
  1117. (IUnknown**)&(pIMgmt));
  1118. if ( ft.HrFailed() )
  1119. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
  1120. // Get the management object
  1121. CComPtr<IVssDifferentialSoftwareSnapshotMgmt> pIDiffSnapMgmt;
  1122. GetDifferentialSoftwareSnapshotMgmtInterface( ProviderId, pIMgmt, (IUnknown**)&pIDiffSnapMgmt );
  1123. //
  1124. // See if the on option was provided. If not, determine what the on value is:
  1125. //
  1126. CVssAutoPWSZ awszOnVol;
  1127. if (onVolume == NULL )
  1128. {
  1129. // Need to query the association to get the on value...
  1130. CComPtr<IVssEnumMgmtObject> pIEnumMgmt;
  1131. ft.hr = pIDiffSnapMgmt->QueryDiffAreasForVolume(
  1132. forVolume,
  1133. &pIEnumMgmt );
  1134. if ( ft.HrFailed() )
  1135. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"QueryDiffAreasForVolume failed, hr = 0x%08lx", ft.hr);
  1136. if ( ft.hr == S_FALSE )
  1137. {
  1138. // empty query
  1139. OutputErrorMsg( MSG_ERROR_ASSOCIATION_NOT_FOUND );
  1140. return;
  1141. }
  1142. VSS_MGMT_OBJECT_PROP Prop;
  1143. VSS_DIFF_AREA_PROP& DiffArea = Prop.Obj.DiffArea;
  1144. // Get next element
  1145. ULONG ulFetched;
  1146. ft.hr = pIEnumMgmt->Next( 1, &Prop, &ulFetched );
  1147. if ( ft.HrFailed() )
  1148. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Next failed with hr = 0x%08lx", ft.hr);
  1149. // Test if the cycle is finished
  1150. if (ft.hr == S_FALSE)
  1151. {
  1152. OutputErrorMsg( MSG_ERROR_ASSOCIATION_NOT_FOUND );
  1153. return;
  1154. }
  1155. ::VssFreeString( DiffArea.m_pwszVolumeName );
  1156. CVssAutoPWSZ awszDiffAreaVolumeName( DiffArea.m_pwszDiffAreaVolumeName );
  1157. // Save it away in the auto delete object.
  1158. awszOnVol.CopyFrom( awszDiffAreaVolumeName );
  1159. onVolume = awszOnVol;
  1160. }
  1161. // Now delete the assocation by changing the size to zero
  1162. ft.hr = pIDiffSnapMgmt->ChangeDiffAreaMaximumSize(
  1163. forVolume,
  1164. onVolume,
  1165. 0 );
  1166. if ( ft.HrFailed() )
  1167. {
  1168. if ( ft.hr == VSS_E_OBJECT_NOT_FOUND ) // should be VSS_E_MAXIMUM_DIFFAREA_ASSOCIATIONS
  1169. {
  1170. // The associations was not found
  1171. OutputErrorMsg( MSG_ERROR_ASSOCIATION_NOT_FOUND );
  1172. return;
  1173. }
  1174. else if ( ft.hr == VSS_E_VOLUME_IN_USE )
  1175. {
  1176. // Can't delete associations that are in use
  1177. OutputErrorMsg( MSG_ERROR_ASSOCIATION_IS_IN_USE );
  1178. return;
  1179. }
  1180. else
  1181. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"ResizeDiffArea to 0 failed with hr = 0x%08lx", ft.hr);
  1182. }
  1183. //
  1184. // Print results, if needed
  1185. //
  1186. if ( !IsQuiet() )
  1187. {
  1188. OutputMsg( MSG_INFO_DELETED_DIFFAREAS );
  1189. }
  1190. m_nReturnValue = VSS_CMDRET_SUCCESS;
  1191. }
  1192. void CVssAdminCLI::DeleteSnapshots(
  1193. ) throw(HRESULT)
  1194. {
  1195. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::DeleteSnapshots" );
  1196. // gather the parameters
  1197. LONG lContext = (dCurrentSKU & SKU_INT) ?
  1198. DetermineSnapshotType( GetOptionValueStr( VSSADM_O_SNAPTYPE ) ) :
  1199. VSS_CTX_CLIENT_ACCESSIBLE;
  1200. LPCWSTR forVolume = GetOptionValueStr( VSSADM_O_FOR );
  1201. BOOL oldest = GetOptionValueBool( VSSADM_O_OLDEST );
  1202. BOOL all = GetOptionValueBool(VSSADM_O_ALL);
  1203. VSS_ID SnapshotId = GUID_NULL;
  1204. if (GetOptionValueStr (VSSADM_O_SNAPSHOT) &&
  1205. !ScanGuid (GetOptionValueStr (VSSADM_O_SNAPSHOT), SnapshotId))
  1206. {
  1207. ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_INVALID_OPTION_VALUE,
  1208. L"CVssAdminCLI::DeleteSnapshots: Invalid snapshot id" );
  1209. }
  1210. // verify the parameters
  1211. m_pVerifier->DeleteSnapshots (lContext, forVolume, all == TRUE, oldest==TRUE, SnapshotId, IsQuiet()==TRUE, ft);
  1212. LONG lNumDeleted = 0;
  1213. if ( GetOptionValueStr( VSSADM_O_SNAPSHOT ) )
  1214. {
  1215. //
  1216. // Let's try to delete the snapshot
  1217. //
  1218. if ( PromptUserForConfirmation( MSG_INFO_PROMPT_USER_FOR_DELETE_SNAPSHOTS, 1 ) )
  1219. {
  1220. // Create the coordinator object
  1221. CComPtr<IVssCoordinator> pICoord;
  1222. ft.CoCreateInstanceWithLog(
  1223. VSSDBG_VSSADMIN,
  1224. CLSID_VSSCoordinator,
  1225. L"Coordinator",
  1226. CLSCTX_ALL,
  1227. IID_IVssCoordinator,
  1228. (IUnknown**)&(pICoord));
  1229. if ( ft.HrFailed() )
  1230. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
  1231. // Set all context
  1232. ft.hr = pICoord->SetContext( lContext );
  1233. if ( ft.HrFailed() )
  1234. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"SetContext failed with hr = 0x%08lx", ft.hr);
  1235. VSS_ID NondeletedSnapshotId = GUID_NULL;
  1236. ft.hr = pICoord->DeleteSnapshots(
  1237. SnapshotId,
  1238. VSS_OBJECT_SNAPSHOT,
  1239. TRUE,
  1240. &lNumDeleted,
  1241. &NondeletedSnapshotId );
  1242. if ( ft.hr == VSS_E_OBJECT_NOT_FOUND )
  1243. {
  1244. OutputErrorMsg( MSG_ERROR_SNAPSHOT_NOT_FOUND, GetOptionValueStr( VSSADM_O_SNAPSHOT ) );
  1245. }
  1246. else if ( ft.HrFailed() )
  1247. {
  1248. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"DeleteSnapshots failed with hr = 0x%08lx", ft.hr);
  1249. }
  1250. }
  1251. }
  1252. else
  1253. {
  1254. BS_ASSERT (GetOptionValueStr(VSSADM_O_SNAPSHOT) == NULL);
  1255. // Calculate the unique volume name, just to make sure that we have the right path
  1256. WCHAR wszVolumeNameInternal[x_nLengthOfVolMgmtVolumeName + 1];
  1257. memset (wszVolumeNameInternal, 0, sizeof(wszVolumeNameInternal));
  1258. // If FOR volume name starts with the '\', assume it is already in the correct volume name format.
  1259. // This is important for transported volumes since GetVolumeNameForVolumeMountPointW() won't work.
  1260. if (forVolume != NULL && forVolume[0] != L'\\' )
  1261. {
  1262. if (!::GetVolumeNameForVolumeMountPointW( forVolume,
  1263. wszVolumeNameInternal, ARRAY_LEN(wszVolumeNameInternal)))
  1264. ft.Throw( VSSDBG_COORD, VSS_E_OBJECT_NOT_FOUND,
  1265. L"GetVolumeNameForVolumeMountPoint(%s,...) "
  1266. L"failed with error code 0x%08lx", GetOptionValueStr( VSSADM_O_FOR ), ::GetLastError());
  1267. }
  1268. else if (forVolume != NULL)
  1269. {
  1270. ::wcsncpy( wszVolumeNameInternal, forVolume, STRING_LEN(wszVolumeNameInternal) );
  1271. wszVolumeNameInternal[x_nLengthOfVolMgmtVolumeName] = L'\0';
  1272. }
  1273. // Create the coordinator object
  1274. CComPtr<IVssCoordinator> pICoord;
  1275. ft.CoCreateInstanceWithLog(
  1276. VSSDBG_VSSADMIN,
  1277. CLSID_VSSCoordinator,
  1278. L"Coordinator",
  1279. CLSCTX_ALL,
  1280. IID_IVssCoordinator,
  1281. (IUnknown**)&(pICoord));
  1282. if ( ft.HrFailed() )
  1283. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
  1284. // Set the context
  1285. ft.hr = pICoord->SetContext( lContext);
  1286. if ( ft.HrFailed() )
  1287. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"SetContext failed with hr = 0x%08lx", ft.hr);
  1288. // Get list all snapshots
  1289. CComPtr<IVssEnumObject> pIEnumSnapshots;
  1290. ft.hr = pICoord->Query( GUID_NULL,
  1291. VSS_OBJECT_NONE,
  1292. VSS_OBJECT_SNAPSHOT,
  1293. &pIEnumSnapshots );
  1294. if ( ft.HrFailed() )
  1295. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Query failed with hr = 0x%08lx", ft.hr);
  1296. // For all snapshots do...
  1297. VSS_ID OldestSnapshotId = GUID_NULL; // used if Oldest option is specified
  1298. VSS_TIMESTAMP OldestSnapshotTimestamp = 0x7FFFFFFFFFFFFFFF; // Used if Oldest option is specified
  1299. VSS_OBJECT_PROP Prop;
  1300. //
  1301. // If not asking to delete the oldest snapshot, this could possibly delete multiple snapshots
  1302. // Let's determine how many snapshots will be deleted. If one or more, ask the user if we
  1303. // should continue. If in quiet mode, don't bother the user and skip this step.
  1304. //
  1305. if ( !oldest && !IsQuiet() )
  1306. {
  1307. ULONG ulNumToBeDeleted = 0;
  1308. for (;;)
  1309. {
  1310. ULONG ulFetched;
  1311. ft.hr = pIEnumSnapshots->Next( 1, &Prop, &ulFetched );
  1312. if ( ft.HrFailed() )
  1313. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Next failed with hr = 0x%08lx", ft.hr);
  1314. // Test if the cycle is finished
  1315. if (ft.hr == S_FALSE) {
  1316. BS_ASSERT( ulFetched == 0);
  1317. break;
  1318. }
  1319. // Use auto delete class to manage the snapshot properties
  1320. CVssAutoSnapshotProperties cSnap( Prop );
  1321. if (::_wcsicmp( cSnap->m_pwszOriginalVolumeName, wszVolumeNameInternal ) == 0 ||
  1322. (forVolume == NULL && all))
  1323. ++ulNumToBeDeleted;
  1324. }
  1325. if ( ulNumToBeDeleted == 0 )
  1326. ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_NO_ITEMS_IN_QUERY,
  1327. L"CVssAdminCLI::DeleteSnapshots: No snapshots found that satisfy the query");
  1328. if ( !PromptUserForConfirmation( MSG_INFO_PROMPT_USER_FOR_DELETE_SNAPSHOTS, ulNumToBeDeleted ) )
  1329. return;
  1330. // Reset the enumerator to the beginning.
  1331. ft.hr = pIEnumSnapshots->Reset();
  1332. if ( ft.HrFailed() )
  1333. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Reset failed with hr = 0x%08lx", ft.hr);
  1334. }
  1335. //
  1336. // Now iterate through the list of snapshots looking for matches and delete them.
  1337. //
  1338. for(;;)
  1339. {
  1340. // Get next element
  1341. ULONG ulFetched;
  1342. ft.hr = pIEnumSnapshots->Next( 1, &Prop, &ulFetched );
  1343. if ( ft.HrFailed() )
  1344. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Next failed with hr = 0x%08lx", ft.hr);
  1345. // Test if the cycle is finished
  1346. if (ft.hr == S_FALSE) {
  1347. BS_ASSERT( ulFetched == 0);
  1348. break;
  1349. }
  1350. // Use auto delete class to manage the snapshot properties
  1351. CVssAutoSnapshotProperties cSnap( Prop );
  1352. if (::_wcsicmp( cSnap->m_pwszOriginalVolumeName, wszVolumeNameInternal ) == 0 ||
  1353. (forVolume == NULL && all))
  1354. {
  1355. // We have a volume name match
  1356. if (oldest)
  1357. {
  1358. // Stow away snapshot info if this is the oldest one so far
  1359. if ( OldestSnapshotTimestamp > cSnap->m_tsCreationTimestamp )
  1360. {
  1361. OldestSnapshotId = cSnap->m_SnapshotId;
  1362. OldestSnapshotTimestamp = cSnap->m_tsCreationTimestamp;
  1363. }
  1364. }
  1365. else
  1366. {
  1367. // Delete the snapshot
  1368. VSS_ID NondeletedSnapshotId = GUID_NULL;
  1369. LONG lNumDeletedPrivate;
  1370. ft.hr = pICoord->DeleteSnapshots(
  1371. cSnap->m_SnapshotId,
  1372. VSS_OBJECT_SNAPSHOT,
  1373. TRUE,
  1374. &lNumDeletedPrivate,
  1375. &NondeletedSnapshotId );
  1376. if ( ft.HrFailed() )
  1377. {
  1378. // If it is object not found, the snapshot must have gotten deleted by someone else
  1379. if ( ft.hr != VSS_E_OBJECT_NOT_FOUND )
  1380. {
  1381. // Print out an error message but keep going
  1382. CVssAutoPWSZ awszSnapshotId( ::GuidToString( cSnap->m_SnapshotId ) );
  1383. OutputErrorMsg( MSG_ERROR_UNABLE_TO_DELETE_SNAPSHOT, ft.hr, (LPWSTR)awszSnapshotId );
  1384. }
  1385. }
  1386. else
  1387. {
  1388. lNumDeleted += lNumDeletedPrivate;
  1389. }
  1390. }
  1391. }
  1392. }
  1393. // If in delete oldest mode, do the delete
  1394. if (oldest && OldestSnapshotId != GUID_NULL )
  1395. {
  1396. if ( PromptUserForConfirmation( MSG_INFO_PROMPT_USER_FOR_DELETE_SNAPSHOTS, 1 ) )
  1397. {
  1398. // Delete the snapshot
  1399. VSS_ID NondeletedSnapshotId = GUID_NULL;
  1400. ft.hr = pICoord->DeleteSnapshots(
  1401. OldestSnapshotId,
  1402. VSS_OBJECT_SNAPSHOT,
  1403. TRUE,
  1404. &lNumDeleted,
  1405. &NondeletedSnapshotId );
  1406. if ( ft.HrFailed() )
  1407. {
  1408. CVssAutoPWSZ awszSnapshotId( ::GuidToString( OldestSnapshotId ) );
  1409. // If it is object not found, the snapshot must have gotten deleted by someone else
  1410. if ( ft.hr == VSS_E_OBJECT_NOT_FOUND )
  1411. {
  1412. OutputErrorMsg( MSG_ERROR_SNAPSHOT_NOT_FOUND, awszSnapshotId );
  1413. }
  1414. else
  1415. {
  1416. OutputErrorMsg( MSG_ERROR_UNABLE_TO_DELETE_SNAPSHOT, ft.hr, awszSnapshotId );
  1417. }
  1418. }
  1419. }
  1420. else
  1421. return;
  1422. }
  1423. if ( lNumDeleted == 0 )
  1424. ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_NO_ITEMS_IN_QUERY,
  1425. L"CVssAdminCLI::DeleteSnapshots: No snapshots found that satisfy the query");
  1426. }
  1427. if ( !IsQuiet() && lNumDeleted > 0 )
  1428. OutputMsg( MSG_INFO_SNAPSHOTS_DELETED_SUCCESSFULLY, lNumDeleted );
  1429. m_nReturnValue = VSS_CMDRET_SUCCESS;
  1430. }
  1431. void CVssAdminCLI::ExposeSnapshot(
  1432. ) throw(HRESULT)
  1433. {
  1434. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::ExposeSnapshot" );
  1435. // gather the parameters
  1436. BOOL bExposeLocally = FALSE;
  1437. LPWSTR pwszExposeUsing = GetOptionValueStr( VSSADM_O_EXPOSE_USING );
  1438. LPWSTR pwszPathFromRoot = GetOptionValueStr( VSSADM_O_SHAREPATH );
  1439. if ( pwszExposeUsing != NULL && ::wcslen( pwszExposeUsing ) >= 2 && pwszExposeUsing[1] == L':' )
  1440. {
  1441. // User specified a mountpoint or a drive letter.
  1442. bExposeLocally = TRUE;
  1443. }
  1444. BS_ASSERT (GetOptionValueStr (VSSADM_O_SNAPSHOT) != NULL);
  1445. VSS_ID SnapshotId = GUID_NULL;
  1446. if (!ScanGuid (GetOptionValueStr (VSSADM_O_SNAPSHOT), SnapshotId))
  1447. {
  1448. ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_INVALID_OPTION_VALUE,
  1449. L"CVssAdminCLI::ExposeSnapshot: Invalid snapshot id" );
  1450. }
  1451. // verify the parameters
  1452. m_pVerifier->ExposeSnapshot (SnapshotId, pwszExposeUsing, pwszPathFromRoot, bExposeLocally==TRUE, ft);
  1453. LONG lAttributes;
  1454. if ( bExposeLocally )
  1455. lAttributes = VSS_VOLSNAP_ATTR_EXPOSED_LOCALLY;
  1456. else
  1457. lAttributes = VSS_VOLSNAP_ATTR_EXPOSED_REMOTELY;
  1458. // Create the coordinator object
  1459. CComPtr<IVssCoordinator> pICoord;
  1460. ft.CoCreateInstanceWithLog(
  1461. VSSDBG_VSSADMIN,
  1462. CLSID_VSSCoordinator,
  1463. L"Coordinator",
  1464. CLSCTX_ALL,
  1465. IID_IVssCoordinator,
  1466. (IUnknown**)&(pICoord));
  1467. if ( ft.HrFailed() )
  1468. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Connection failed with hr = 0x%08lx", ft.hr);
  1469. // Set the context to all so that we don't have to specify a specific context which would require either
  1470. // the user to specify it on the command-line or for us to first query the snapshot to determine its
  1471. // context.
  1472. ft.hr = pICoord->SetContext( VSS_CTX_ALL );
  1473. if ( ft.HrFailed() )
  1474. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Error returned from IVssCoordinator::SetContext( CTX_ALL) hr = 0x%08x", ft.hr);
  1475. LPWSTR wszExposedAs = NULL;
  1476. // Now try to expose
  1477. ft.hr = pICoord->ExposeSnapshot( SnapshotId,
  1478. pwszPathFromRoot,
  1479. lAttributes,
  1480. pwszExposeUsing,
  1481. &wszExposedAs );
  1482. if ( ft.HrFailed() )
  1483. {
  1484. switch (ft.hr) {
  1485. case E_INVALIDARG:
  1486. OutputErrorMsg( MSG_ERROR_EXPOSE_INVALID_ARG);
  1487. return;
  1488. case VSS_E_OBJECT_ALREADY_EXISTS:
  1489. OutputErrorMsg(MSG_ERROR_EXPOSE_OBJECT_EXISTS);
  1490. return;
  1491. case VSS_E_OBJECT_NOT_FOUND:
  1492. OutputErrorMsg( MSG_ERROR_SNAPSHOT_NOT_FOUND, GetOptionValueStr( VSSADM_O_SNAPSHOT ) );
  1493. return;
  1494. default:
  1495. ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"Error returned from ExposeSnapshot: hr = 0x%08x", ft.hr);
  1496. }
  1497. }
  1498. CVssAutoPWSZ awszExposedAs( wszExposedAs );
  1499. // The snapshot is exposed, print the results to the user
  1500. OutputMsg( MSG_INFO_EXPOSE_SNAPSHOT_SUCCESSFUL, awszExposedAs );
  1501. m_nReturnValue = VSS_CMDRET_SUCCESS;
  1502. }
  1503. LPWSTR CVssAdminCLI::BuildSnapshotAttributeDisplayString(
  1504. IN DWORD Attr
  1505. ) throw(HRESULT)
  1506. {
  1507. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::BuildSnapshotAttributeDisplayString" );
  1508. WCHAR pwszDisplayString[1024] = L"";
  1509. WORD wBit = 0;
  1510. // Go through the bits of the attribute
  1511. for ( ; wBit < (sizeof ( Attr ) * 8) ; ++wBit )
  1512. {
  1513. switch ( Attr & ( 1 << wBit ) )
  1514. {
  1515. case 0:
  1516. break;
  1517. case VSS_VOLSNAP_ATTR_PERSISTENT:
  1518. AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
  1519. MSG_INFO_SNAPSHOT_ATTR_PERSISTENT, 0, L", " );
  1520. break;
  1521. case VSS_VOLSNAP_ATTR_CLIENT_ACCESSIBLE:
  1522. AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
  1523. MSG_INFO_SNAPSHOT_ATTR_CLIENT_ACCESSIBLE, 0, L", " );
  1524. break;
  1525. case VSS_VOLSNAP_ATTR_NO_AUTO_RELEASE:
  1526. AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
  1527. MSG_INFO_SNAPSHOT_ATTR_NO_AUTO_RELEASE, 0, L", " );
  1528. break;
  1529. case VSS_VOLSNAP_ATTR_NO_WRITERS:
  1530. AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
  1531. MSG_INFO_SNAPSHOT_ATTR_NO_WRITERS, 0, L", " );
  1532. break;
  1533. case VSS_VOLSNAP_ATTR_TRANSPORTABLE:
  1534. AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
  1535. MSG_INFO_SNAPSHOT_ATTR_TRANSPORTABLE, 0, L", " );
  1536. break;
  1537. case VSS_VOLSNAP_ATTR_NOT_SURFACED:
  1538. AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
  1539. MSG_INFO_SNAPSHOT_ATTR_NOT_SURFACED, 0, L", " );
  1540. break;
  1541. case VSS_VOLSNAP_ATTR_HARDWARE_ASSISTED:
  1542. AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
  1543. MSG_INFO_SNAPSHOT_ATTR_HARDWARE_ASSISTED, 0, L", " );
  1544. break;
  1545. case VSS_VOLSNAP_ATTR_DIFFERENTIAL:
  1546. AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
  1547. MSG_INFO_SNAPSHOT_ATTR_DIFFERENTIAL, 0, L", " );
  1548. break;
  1549. case VSS_VOLSNAP_ATTR_PLEX:
  1550. AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
  1551. MSG_INFO_SNAPSHOT_ATTR_PLEX, 0, L", " );
  1552. break;
  1553. case VSS_VOLSNAP_ATTR_IMPORTED:
  1554. AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
  1555. MSG_INFO_SNAPSHOT_ATTR_IMPORTED, 0, L", " );
  1556. break;
  1557. case VSS_VOLSNAP_ATTR_EXPOSED_LOCALLY:
  1558. AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
  1559. MSG_INFO_SNAPSHOT_ATTR_EXPOSED_LOCALLY, 0, L", " );
  1560. break;
  1561. case VSS_VOLSNAP_ATTR_EXPOSED_REMOTELY:
  1562. AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
  1563. MSG_INFO_SNAPSHOT_ATTR_EXPOSED_REMOTELY, 0, L", " );
  1564. break;
  1565. default:
  1566. AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
  1567. 0, Attr & ( 1 << wBit ), L", " );
  1568. break;
  1569. }
  1570. }
  1571. // If this is a backup snapshot, most like there will not be any attributes
  1572. if ( pwszDisplayString[0] == L'\0' )
  1573. {
  1574. AppendMessageToStr( pwszDisplayString, STRING_LEN( pwszDisplayString ),
  1575. MSG_INFO_SNAPSHOT_ATTR_NONE, 0, L", " );
  1576. }
  1577. LPWSTR pwszRetString = NULL;
  1578. ::VssSafeDuplicateStr( ft, pwszRetString, pwszDisplayString );
  1579. return pwszRetString;
  1580. }
  1581. LONG CVssAdminCLI::DetermineSnapshotType(
  1582. IN LPCWSTR pwszType
  1583. ) throw(HRESULT)
  1584. {
  1585. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::DetermineSnapshotType" );
  1586. // Determine the snapshot type based on the entered snapshot type string.
  1587. // See if the snapshot type was specified, if not, return all context
  1588. if ( pwszType == NULL || pwszType[0] == L'\0' )
  1589. {
  1590. return VSS_CTX_ALL;
  1591. }
  1592. INT idx;
  1593. // Determine type of snapshot
  1594. for ( idx = 0; g_asAdmTypeNames[idx].pwszName != NULL; ++idx )
  1595. {
  1596. if ( ( dCurrentSKU & g_asAdmTypeNames[idx].dwSKUs ) &&
  1597. ( ::_wcsicmp( pwszType, g_asAdmTypeNames[idx].pwszName ) == 0 ) )
  1598. {
  1599. break;
  1600. }
  1601. }
  1602. if ( g_asAdmTypeNames[idx].pwszName == NULL )
  1603. {
  1604. ft.Throw( VSSDBG_VSSADMIN, VSSADM_E_INVALID_OPTION_VALUE,
  1605. L"DetermineSnapshotType: Invalid type specified: %s",
  1606. pwszType );
  1607. }
  1608. //
  1609. // Now return the context
  1610. //
  1611. return( g_asAdmTypeNames[idx].lSnapshotContext );
  1612. }
  1613. LPWSTR CVssAdminCLI::DetermineSnapshotType(
  1614. IN LONG lSnapshotAttributes
  1615. ) throw(HRESULT)
  1616. {
  1617. CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdminCLI::DetermineSnapshotType" );
  1618. // Determine the snapshot type string based on the snapshot attributes
  1619. LPWSTR pwszType = NULL;
  1620. INT idx;
  1621. // Determine type of snapshot
  1622. for ( idx = 0; g_asAdmTypeNames[idx].pwszName != NULL; ++idx )
  1623. {
  1624. if ( g_asAdmTypeNames[idx].lSnapshotContext == ( lSnapshotAttributes & VSS_CTX_ATTRIB_MASK ) )
  1625. break;
  1626. }
  1627. if ( g_asAdmTypeNames[idx].pwszName == NULL )
  1628. {
  1629. ft.Trace( VSSDBG_VSSADMIN, L"DetermineSnapshotType: Invalid context in lSnapshotAttributes: 0x%08x",
  1630. lSnapshotAttributes );
  1631. LPWSTR pwszMsg = GetMsg( FALSE, MSG_UNKNOWN );
  1632. if ( pwszMsg == NULL )
  1633. {
  1634. ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED,
  1635. L"Error on loading the message string id %d. 0x%08lx",
  1636. MSG_UNKNOWN, ::GetLastError() );
  1637. }
  1638. return pwszMsg;
  1639. }
  1640. //
  1641. // Now return the context
  1642. //
  1643. ::VssSafeDuplicateStr( ft, pwszType, g_asAdmTypeNames[idx].pwszName );
  1644. return pwszType;
  1645. }