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.

2697 lines
90 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2002-2004 Microsoft Corporation
  4. //
  5. // Module Name: VdsClasses.cpp
  6. //
  7. // Description:
  8. // Implementation of VDS WMI Provider classes
  9. //
  10. // Author: Jim Benton (jbenton) 15-Jan-2002
  11. //
  12. //////////////////////////////////////////////////////////////////////////////
  13. #include "Pch.h"
  14. #include <winioctl.h>
  15. #include <fmifs.h>
  16. #include "VdsClasses.h"
  17. #include "ichannel.hxx"
  18. #include <ntddvol.h>
  19. #define INITGUIDS
  20. #include <initguid.h>
  21. #include <dfrgifc.h>
  22. #include <dskquota.h>
  23. #include "volutil.h"
  24. #include "cmdproc.h"
  25. // Chkdsk and Format use callbacks which require us to track some data per thread
  26. // These help define the per thread data channel
  27. CRITICAL_SECTION g_csThreadData;
  28. typedef std::map < DWORD, void* > ThreadDataMap;
  29. static ThreadDataMap g_ThreadDataMap;
  30. typedef struct _CHKDSK_THREAD_DATA
  31. {
  32. BOOL fOkToRunAtBootup;
  33. DWORD rcStatus;
  34. } CHKDSK_THREAD_DATA, *PCHKDSK_THREAD_DATA;
  35. void
  36. LoadDefragAnalysis(
  37. IN DEFRAG_REPORT* pDefragReport,
  38. IN OUT IWbemClassObject* pObject);
  39. void
  40. TranslateDefragError(
  41. IN HRESULT hr,
  42. OUT DWORD* pdwError);
  43. void
  44. SetThreadData(
  45. IN DWORD dwThreadID,
  46. IN void* pThreadData)
  47. {
  48. EnterCriticalSection(&g_csThreadData);
  49. g_ThreadDataMap[dwThreadID] = pThreadData;
  50. LeaveCriticalSection(&g_csThreadData);
  51. }
  52. void*
  53. GetThreadData(
  54. IN DWORD dwThreadID)
  55. {
  56. void* pThreadData = 0;
  57. EnterCriticalSection(&g_csThreadData);
  58. pThreadData = g_ThreadDataMap[dwThreadID];
  59. LeaveCriticalSection(&g_csThreadData);
  60. return pThreadData;
  61. }
  62. void
  63. RemoveThreadData(
  64. IN DWORD dwThreadID)
  65. {
  66. EnterCriticalSection(&g_csThreadData);
  67. g_ThreadDataMap.erase(dwThreadID);
  68. LeaveCriticalSection(&g_csThreadData);
  69. }
  70. BOOLEAN ChkdskCallback(
  71. FMIFS_PACKET_TYPE PacketType,
  72. ULONG PacketLength,
  73. PVOID PacketData
  74. )
  75. {
  76. BOOL fFailed = FALSE;
  77. DWORD dwThreadID = GetCurrentThreadId();
  78. CHKDSK_THREAD_DATA* pThreadData = (CHKDSK_THREAD_DATA*) GetThreadData(dwThreadID);
  79. _ASSERTE(pThreadData);
  80. switch (PacketType)
  81. {
  82. case FmIfsTextMessage :
  83. FMIFS_TEXT_MESSAGE *MessageText;
  84. MessageText = (FMIFS_TEXT_MESSAGE*) PacketData;
  85. break;
  86. case FmIfsFinished:
  87. FMIFS_FINISHED_INFORMATION *Finish;
  88. Finish = (FMIFS_FINISHED_INFORMATION*) PacketData;
  89. if ( Finish->Success )
  90. {
  91. pThreadData->rcStatus = CHKDSK_RC_NO_ERROR;
  92. }
  93. else
  94. {
  95. if (pThreadData->rcStatus != CHKDSK_RC_VOLUME_LOCKED)
  96. {
  97. pThreadData->rcStatus = CHKDSK_RC_UNEXPECTED;
  98. }
  99. }
  100. break;
  101. case FmIfsCheckOnReboot:
  102. FMIFS_CHECKONREBOOT_INFORMATION *RebootResult;
  103. pThreadData->rcStatus = CHKDSK_RC_VOLUME_LOCKED;
  104. RebootResult = (FMIFS_CHECKONREBOOT_INFORMATION *) PacketData;
  105. if (pThreadData->fOkToRunAtBootup)
  106. RebootResult->QueryResult = 1;
  107. else
  108. RebootResult->QueryResult = 1;
  109. break;
  110. // although following are the additional message types, callback routine never gets these messages
  111. // hence the detailed code for each of these return type is not written.
  112. /*
  113. case FmIfsIncompatibleFileSystem:
  114. break;
  115. case FmIfsAccessDenied:
  116. break;
  117. case FmIfsBadLabel:
  118. break;
  119. case FmIfsHiddenStatus:
  120. break;
  121. case FmIfsClusterSizeTooSmall:
  122. break;
  123. case FmIfsClusterSizeTooBig:
  124. break;
  125. case FmIfsVolumeTooSmall:
  126. break;
  127. case FmIfsVolumeTooBig:
  128. break;
  129. case FmIfsNoMediaInDevice:
  130. break;
  131. case FmIfsClustersCountBeyond32bits:
  132. break;
  133. case FmIfsIoError:
  134. FMIFS_IO_ERROR_INFORMATION *IoErrorInfo;
  135. IoErrorInfo = ( FMIFS_IO_ERROR_INFORMATION * ) PacketData;
  136. break;
  137. case FmIfsMediaWriteProtected:
  138. break;
  139. case FmIfsIncompatibleMedia:
  140. break;
  141. case FmIfsInsertDisk:
  142. FMIFS_INSERT_DISK_INFORMATION *InsertDiskInfo;
  143. InsertDiskInfo = ( FMIFS_INSERT_DISK_INFORMATION *) PacketData;
  144. unRetVal = 1;
  145. break;
  146. */
  147. }
  148. return (BOOLEAN) (fFailed == FALSE);
  149. }
  150. //****************************************************************************
  151. //
  152. // CVolume
  153. //
  154. //****************************************************************************
  155. CVolume::CVolume(
  156. IN LPCWSTR pwszName,
  157. IN CWbemServices* pNamespace
  158. )
  159. : CProvBase(pwszName, pNamespace)
  160. {
  161. } //*** CVolume::CVolume()
  162. CProvBase *
  163. CVolume::S_CreateThis(
  164. IN LPCWSTR pwszName,
  165. IN CWbemServices* pNamespace
  166. )
  167. {
  168. HRESULT hr = WBEM_E_FAILED;
  169. CVolume * pObj = NULL;
  170. pObj = new CVolume(pwszName, pNamespace);
  171. if (pObj)
  172. {
  173. hr = pObj->Initialize();
  174. }
  175. else
  176. {
  177. hr = E_OUTOFMEMORY;
  178. }
  179. if (FAILED(hr))
  180. {
  181. delete pObj;
  182. pObj = NULL;
  183. }
  184. return pObj;
  185. } //*** CVolume::S_CreateThis()
  186. HRESULT
  187. CVolume::Initialize()
  188. {
  189. DWORD cchBufLen = MAX_COMPUTERNAME_LENGTH;
  190. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::Initialize");
  191. return ft.hr;
  192. }
  193. HRESULT
  194. CVolume::EnumInstance(
  195. IN long lFlags,
  196. IN IWbemContext* pCtx,
  197. IN IWbemObjectSink * pHandler
  198. )
  199. {
  200. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::EnumInstance");
  201. CVssAutoPWSZ awszVolume;
  202. try
  203. {
  204. awszVolume.Allocate(MAX_PATH);
  205. CVssVolumeIterator volumeIterator;
  206. while (true)
  207. {
  208. CComPtr<IWbemClassObject> spInstance;
  209. // Get the volume name
  210. if (!volumeIterator.SelectNewVolume(ft, awszVolume, MAX_PATH))
  211. break;
  212. if (VolumeIsValid(awszVolume))
  213. {
  214. ft.hr = m_pClass->SpawnInstance(0, &spInstance);
  215. if (ft.HrFailed())
  216. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SpawnInstance failed, hr<%#x>", ft.hr);
  217. LoadInstance(awszVolume, spInstance.p);
  218. ft.hr = pHandler->Indicate(1, &spInstance.p);
  219. }
  220. }
  221. }
  222. catch (HRESULT hrEx)
  223. {
  224. ft.hr = hrEx;
  225. }
  226. return ft.hr;
  227. } //*** CVolume::EnumInstance()
  228. HRESULT
  229. CVolume::GetObject(
  230. IN CObjPath& rObjPath,
  231. IN long lFlags,
  232. IN IWbemContext* pCtx,
  233. IN IWbemObjectSink* pHandler
  234. )
  235. {
  236. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::GetObject");
  237. try
  238. {
  239. CComPtr<IWbemClassObject> spInstance;
  240. _bstr_t bstrID;
  241. // Get the Volume GUID name
  242. bstrID = rObjPath.GetStringValueForProperty(PVDR_PROP_DEVICEID);
  243. IF_WSTR_NULL_THROW(bstrID, WBEM_E_INVALID_OBJECT_PATH, L"CVolume::GetObject: volume key property not found")
  244. ft.hr = m_pClass->SpawnInstance(0, &spInstance);
  245. if (ft.HrFailed())
  246. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SpawnInstance failed, hr<%#x>", ft.hr);
  247. if (VolumeIsValid((WCHAR*)bstrID))
  248. {
  249. LoadInstance((WCHAR*)bstrID, spInstance.p);
  250. ft.hr = pHandler->Indicate(1, &spInstance.p);
  251. }
  252. else
  253. {
  254. ft.hr = WBEM_E_NOT_SUPPORTED;
  255. ft.Trace(VSSDBG_VSSADMIN, L"Unsupported volume GUID, hr<%lS>", (WCHAR*)bstrID);
  256. }
  257. }
  258. catch (HRESULT hrEx)
  259. {
  260. ft.hr = hrEx;
  261. }
  262. return ft.hr;
  263. } //*** CVolume::GetObject()
  264. void
  265. CVolume:: LoadInstance(
  266. IN WCHAR* pwszVolume,
  267. IN OUT IWbemClassObject* pObject)
  268. {
  269. WCHAR wszDriveLetter[g_cchDriveName];
  270. DWORD cchBuf= MAX_COMPUTERNAME_LENGTH;
  271. WCHAR wszPath[MAX_PATH+1] ;
  272. CVssAutoPWSZ awszVolume;
  273. CVssAutoPWSZ awszComputerName;
  274. CComPtr<IDiskQuotaControl> spIDQC;
  275. IDiskQuotaControl* pIDQC = NULL;
  276. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::LoadInstance");
  277. _ASSERTE(pwszVolume != NULL);
  278. _ASSERTE(pObject != NULL);
  279. CWbemClassObject wcoInstance(pObject);
  280. awszVolume.Allocate(MAX_PATH);
  281. // Set the volume GUID name key property
  282. wcoInstance.SetProperty(pwszVolume, PVDR_PROP_DEVICEID);
  283. // Get the computer name
  284. awszComputerName.Allocate(MAX_COMPUTERNAME_LENGTH);
  285. if (!GetComputerName(awszComputerName, &cchBuf))
  286. {
  287. ft.Trace(VSSDBG_VSSADMIN, L"GetComputerName failed %#x", GetLastError());
  288. }
  289. else
  290. {
  291. wcoInstance.SetProperty(awszComputerName, PVDR_PROP_SYSTEMNAME);
  292. }
  293. VssGetVolumeDisplayName(
  294. pwszVolume,
  295. wszPath,
  296. MAX_PATH);
  297. wcoInstance.SetProperty(wszPath, PVDR_PROP_NAME);
  298. wcoInstance.SetProperty(wszPath, PVDR_PROP_CAPTION);
  299. // Don't populate the remaining properties if the volume is tagged no-automount
  300. if (!VolumeIsMountable(pwszVolume))
  301. {
  302. wcoInstance.SetProperty((DWORD)false, PVDR_PROP_MOUNTABLE);
  303. }
  304. else
  305. {
  306. DWORD dwSerialNumber = 0;
  307. DWORD cchMaxFileNameLen = 0;
  308. DWORD dwFileSystemFlags = 0;
  309. DWORD cSectorsPerCluster = 0;
  310. DWORD cBytesPerSector = 0;
  311. DWORD cDontCare = 0;
  312. ULARGE_INTEGER cbCapacity = {0, 0};
  313. ULARGE_INTEGER cbFreeSpace = {0, 0};
  314. ULARGE_INTEGER cbUserFreeSpace = {0, 0};
  315. DWORD dwAttributes = 0;
  316. WCHAR wszLabel[g_cchVolumeLabelMax+1];
  317. WCHAR wszFileSystem[g_cchFileSystemNameMax+1];
  318. wcoInstance.SetProperty((bool)true, PVDR_PROP_MOUNTABLE);
  319. // Set DriveType property
  320. wcoInstance.SetProperty(GetDriveType(pwszVolume), PVDR_PROP_DRIVETYPE);
  321. // Set DriveLetter property
  322. cchBuf = g_cchDriveName;
  323. if (GetVolumeDrive(
  324. pwszVolume,
  325. cchBuf,
  326. wszDriveLetter))
  327. {
  328. wszDriveLetter[wcslen(wszDriveLetter) - 1] = L'\0'; // Remove the trailing '\'
  329. wcoInstance.SetProperty(wszDriveLetter, PVDR_PROP_DRIVELETTER);
  330. }
  331. // Skip remaining properties for drives without media
  332. if (VolumeIsReady(pwszVolume))
  333. {
  334. BOOL fDirty = FALSE;
  335. if (VolumeIsDirty(pwszVolume, &fDirty) == ERROR_SUCCESS)
  336. wcoInstance.SetProperty(fDirty, PVDR_PROP_DIRTYBITSET);
  337. // Set BlockSize property
  338. if (!GetDiskFreeSpace(
  339. pwszVolume,
  340. &cSectorsPerCluster,
  341. &cBytesPerSector,
  342. &cDontCare, // total bytes
  343. &cDontCare)) // total free bytes
  344. {
  345. ft.Trace(VSSDBG_VSSADMIN, L"GetDiskFreeSpace failed for volume %lS, %#x", pwszVolume, GetLastError());
  346. }
  347. else
  348. {
  349. ULONGLONG cbBytesPerCluster = cBytesPerSector * cSectorsPerCluster;
  350. wcoInstance.SetPropertyI64(cbBytesPerCluster, PVDR_PROP_BLOCKSIZE);
  351. }
  352. // Set Label, FileSystem, SerialNumber, MaxFileNameLen,
  353. // SupportsCompression, Compressed, SupportsQuotas properties
  354. if (!GetVolumeInformation(
  355. pwszVolume,
  356. wszLabel,
  357. g_cchVolumeLabelMax,
  358. &dwSerialNumber,
  359. &cchMaxFileNameLen,
  360. &dwFileSystemFlags,
  361. wszFileSystem,
  362. g_cchFileSystemNameMax))
  363. {
  364. ft.Trace(VSSDBG_VSSADMIN, L"GetVolumeInformation failed for volume %lS, %#x", pwszVolume, GetLastError());
  365. }
  366. else
  367. {
  368. if (wszLabel[0] != L'\0')
  369. wcoInstance.SetProperty(wszLabel, PVDR_PROP_LABEL);
  370. wcoInstance.SetProperty(wszFileSystem, PVDR_PROP_FILESYSTEM);
  371. wcoInstance.SetProperty(dwSerialNumber, PVDR_PROP_SERIALNUMBER);
  372. wcoInstance.SetProperty(cchMaxFileNameLen, PVDR_PROP_MAXIMUMFILENAMELENGTH);
  373. wcoInstance.SetProperty(dwFileSystemFlags & FS_VOL_IS_COMPRESSED, PVDR_PROP_COMPRESSED);
  374. wcoInstance.SetProperty(dwFileSystemFlags & FILE_VOLUME_QUOTAS, PVDR_PROP_SUPPORTSDISKQUOTAS);
  375. wcoInstance.SetProperty(dwFileSystemFlags & FS_FILE_COMPRESSION, PVDR_PROP_SUPPORTSFILEBASEDCOMPRESSION);
  376. }
  377. if (!GetDiskFreeSpaceEx(
  378. pwszVolume,
  379. &cbUserFreeSpace,
  380. &cbCapacity,
  381. &cbFreeSpace))
  382. {
  383. ft.Trace(VSSDBG_VSSADMIN, L"GetDiskFreeSpace failed for volume, %lS", pwszVolume);
  384. }
  385. {
  386. ULONGLONG llTmp = 0;
  387. llTmp = cbCapacity.QuadPart;
  388. wcoInstance.SetPropertyI64(llTmp, PVDR_PROP_CAPACITY);
  389. llTmp = cbFreeSpace.QuadPart;
  390. wcoInstance.SetPropertyI64(llTmp, PVDR_PROP_FREESPACE);
  391. }
  392. if (_wcsicmp(wszFileSystem, L"NTFS") == 0)
  393. {
  394. dwAttributes = GetFileAttributes(pwszVolume);
  395. if (dwAttributes == INVALID_FILE_ATTRIBUTES)
  396. {
  397. ft.Trace(VSSDBG_VSSADMIN, L"GetFileAttributes failed for volume %lS, %#x", pwszVolume, GetLastError());
  398. }
  399. else
  400. {
  401. BOOL fIndexingEnabled = !(dwAttributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
  402. wcoInstance.SetProperty(fIndexingEnabled, PVDR_PROP_INDEXINGENABLED);
  403. }
  404. }
  405. ft.hr = CoCreateInstance(
  406. CLSID_DiskQuotaControl,
  407. NULL,
  408. CLSCTX_INPROC_SERVER,
  409. IID_IDiskQuotaControl,
  410. (void **)&pIDQC);
  411. if (ft.HrFailed())
  412. {
  413. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"unable to CoCreate IDiskQuotaControl");
  414. }
  415. spIDQC.Attach(pIDQC);
  416. ft.hr = spIDQC->Initialize(pwszVolume, FALSE /* read only */);
  417. if (ft.HrFailed())
  418. {
  419. ft.Trace(VSSDBG_VSSADMIN, L"IDiskQuotaControl::Initialize failed for volume %lS", pwszVolume);
  420. }
  421. else
  422. {
  423. DWORD dwState = 0;
  424. ft.hr = spIDQC->GetQuotaState(&dwState);
  425. if (ft.HrSucceeded())
  426. {
  427. wcoInstance.SetProperty(!(DISKQUOTA_IS_DISABLED(dwState)), PVDR_PROP_QUOTASENABLED);
  428. wcoInstance.SetProperty(DISKQUOTA_FILE_INCOMPLETE(dwState), PVDR_PROP_QUOTASINCOMPLETE);
  429. wcoInstance.SetProperty(DISKQUOTA_FILE_REBUILDING(dwState), PVDR_PROP_QUOTASREBUILDING);
  430. }
  431. }
  432. }
  433. }
  434. }
  435. HRESULT
  436. CVolume::PutInstance(
  437. IN CWbemClassObject& rInstToPut,
  438. IN long lFlag,
  439. IN IWbemContext* pCtx,
  440. IN IWbemObjectSink* pHandler
  441. )
  442. {
  443. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::PutInstance");
  444. try
  445. {
  446. _bstr_t bstrVolume;
  447. _bstr_t bstrDriveLetter;
  448. _bstr_t bstrLabel;
  449. BOOL fIndexingEnabled = FALSE;
  450. WCHAR* pwszVolume = NULL;
  451. if ( lFlag & WBEM_FLAG_CREATE_ONLY )
  452. {
  453. return WBEM_E_UNSUPPORTED_PARAMETER ;
  454. }
  455. // Retrieve key properties of the object to be saved.
  456. rInstToPut.GetProperty(bstrVolume, PVDR_PROP_DEVICEID);
  457. if ((WCHAR*)bstrVolume == NULL)
  458. {
  459. ft.hr = WBEM_E_INVALID_OBJECT;
  460. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"CVolume::PutInstance: NULL volume name");
  461. }
  462. pwszVolume = (wchar_t*)bstrVolume;
  463. if (VolumeIsValid(pwszVolume) && VolumeIsMountable(pwszVolume))
  464. {
  465. // Retrieve writeable properties of the object to be saved.
  466. rInstToPut.GetProperty(bstrDriveLetter, PVDR_PROP_DRIVELETTER);
  467. rInstToPut.GetProperty(bstrLabel, PVDR_PROP_LABEL);
  468. rInstToPut.GetProperty(&fIndexingEnabled, PVDR_PROP_INDEXINGENABLED);
  469. SetLabel(pwszVolume, bstrLabel);
  470. if (!rInstToPut.IsPropertyNull(PVDR_PROP_INDEXINGENABLED))
  471. SetContentIndexing(pwszVolume, fIndexingEnabled);
  472. SetDriveLetter(pwszVolume, bstrDriveLetter);
  473. }
  474. else
  475. {
  476. ft.hr = WBEM_E_NOT_SUPPORTED;
  477. ft.Trace(VSSDBG_VSSADMIN, L"Attempt to modify an unsupported or unmountedable volume, %lS", pwszVolume);
  478. }
  479. }
  480. catch (HRESULT hrEx)
  481. {
  482. ft.hr = hrEx;
  483. }
  484. return ft.hr;
  485. } //*** CStorage::PutInstance()
  486. void
  487. CVolume::SetDriveLetter(
  488. IN WCHAR* pwszVolume,
  489. IN WCHAR* pwszDrive
  490. )
  491. {
  492. WCHAR wszCurrentDrivePath[g_cchDriveName+1];
  493. BOOL fFoundDrive = FALSE;
  494. BOOL fDeleteDrive = FALSE;
  495. BOOL fAssignDrive = FALSE;
  496. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::SetDriveLetter");
  497. _ASSERTE(pwszVolume != NULL)
  498. // Validate drive letter
  499. if (pwszDrive != NULL)
  500. {
  501. ft.hr = WBEM_E_INVALID_PARAMETER;
  502. if (wcslen(pwszDrive) == 2)
  503. {
  504. WCHAR wc = towupper(pwszDrive[0]);
  505. if (wc >= L'A' && wc <= L'Z' && pwszDrive[1] == L':')
  506. ft.hr = S_OK;
  507. }
  508. if (ft.HrFailed())
  509. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SetDriveLetter: invalid drive letter, %lS", pwszDrive);
  510. }
  511. // Get the current drive letter if any
  512. fFoundDrive = GetVolumeDrive(
  513. pwszVolume,
  514. g_cchDriveName,
  515. wszCurrentDrivePath);
  516. if (fFoundDrive)
  517. {
  518. if (wszCurrentDrivePath[wcslen(wszCurrentDrivePath) - 1] != L'\\')
  519. {
  520. ft.hr = E_UNEXPECTED;
  521. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SetDriveLetter: unexpected drive letter format from GetVolumeDrivePath, %lS", wszCurrentDrivePath);
  522. }
  523. }
  524. if (pwszDrive == NULL && fFoundDrive == FALSE)
  525. {
  526. // Do nothing, drive letter already deleted
  527. }
  528. else if (pwszDrive == NULL && fFoundDrive == TRUE)
  529. {
  530. // Delete drive letter
  531. fDeleteDrive = TRUE;
  532. }
  533. else if (pwszDrive != NULL && fFoundDrive == FALSE)
  534. {
  535. // No drive letter currently assigned, assign drive letter
  536. fAssignDrive = TRUE;
  537. }
  538. else if (_wcsnicmp(pwszDrive, wszCurrentDrivePath, 2) != 0)
  539. {
  540. // Requested drive letter is different than currently assigned
  541. // Delete current drive letter
  542. fDeleteDrive = TRUE;
  543. // Assign new drive letter
  544. fAssignDrive = TRUE;
  545. }
  546. else
  547. {
  548. // Do nothing, drive letter not changing
  549. }
  550. if (fAssignDrive)
  551. {
  552. // Verify that the target drive letter is available
  553. // A race condition exists here since the drive letter may be stolen
  554. // after this verification and before the actual assignment
  555. if (!IsDriveLetterAvailable(pwszDrive))
  556. {
  557. if (IsDriveLetterSticky(pwszDrive))
  558. {
  559. ft.hr = VDSWMI_E_DRIVELETTER_IN_USE;
  560. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"drive letter is assigned to another volume");
  561. }
  562. else
  563. {
  564. ft.hr = VDSWMI_E_DRIVELETTER_UNAVAIL;
  565. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"drive letter is unavailable until reboot");
  566. }
  567. }
  568. }
  569. if (fDeleteDrive)
  570. {
  571. if (!IsBootDrive(wszCurrentDrivePath) &&
  572. !VolumeIsSystem(pwszVolume) &&
  573. !VolumeHoldsPagefile(pwszVolume))
  574. {
  575. // Try to lock the volume and delete the mountpoint.
  576. // If the volume can't be locked, remove the drive letter from the
  577. // volume mgr database only
  578. // Remove any network shares for this drive letter??
  579. DeleteVolumeDriveLetter(pwszVolume, wszCurrentDrivePath);
  580. }
  581. else
  582. {
  583. ft.hr = VDSWMI_E_DRIVELETTER_CANT_DELETE;
  584. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Drive letter deletion is blocked for this volume %lS", pwszVolume);
  585. }
  586. }
  587. if (fAssignDrive)
  588. {
  589. // No attempt will be made to roll back a previously deleted drive letter
  590. // if this assignment fails
  591. // SetVolumeMountPoint API requires trailing backslash
  592. WCHAR wszDrivePath[g_cchDriveName], *pwszDrivePath = wszDrivePath;
  593. ft.hr = StringCchPrintf(wszDrivePath, g_cchDriveName, L"%s\\", pwszDrive);
  594. if (ft.HrFailed())
  595. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"StringCchPrintf failed %#x", ft.hr);
  596. if (!SetVolumeMountPoint(wszDrivePath, pwszVolume))
  597. {
  598. ft.hr = HRESULT_FROM_WIN32(GetLastError());
  599. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SetVolumeMountPoint failed, volume<%lS> drivePath<%lS>", pwszVolume, wszDrivePath);
  600. }
  601. }
  602. }
  603. void
  604. CVolume::SetLabel(
  605. IN WCHAR* pwszVolume,
  606. IN WCHAR* pwszLabel
  607. )
  608. {
  609. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::SetLabel");
  610. _ASSERTE(pwszVolume != NULL);
  611. if (!SetVolumeLabel(pwszVolume, pwszLabel))
  612. {
  613. ft.hr = HRESULT_FROM_WIN32(GetLastError());
  614. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SetVolumeLabel failed, volume<%lS> label<%lS>", pwszVolume, pwszLabel);
  615. }
  616. }
  617. void
  618. CVolume::SetContentIndexing(
  619. IN WCHAR* pwszVolume,
  620. IN BOOL fIndexingEnabled
  621. )
  622. {
  623. DWORD dwAttributes;
  624. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::SetContentIndexing");
  625. // Get the file attributes which include the content indexing flag
  626. dwAttributes = GetFileAttributes(pwszVolume);
  627. if (dwAttributes == INVALID_FILE_ATTRIBUTES)
  628. {
  629. ft.hr = HRESULT_FROM_WIN32(GetLastError());
  630. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"GetFileAttributes failed, volume<%lS>", pwszVolume);
  631. }
  632. // Set the indexing flag
  633. if (fIndexingEnabled)
  634. {
  635. // Turn indexing on
  636. dwAttributes &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
  637. }
  638. else
  639. {
  640. // Turn indexing off
  641. dwAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
  642. }
  643. if (!SetFileAttributes(pwszVolume, dwAttributes))
  644. {
  645. ft.hr = HRESULT_FROM_WIN32(GetLastError());
  646. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SetFileAttributes failed, volume<%lS>", pwszVolume);
  647. }
  648. }
  649. HRESULT
  650. CVolume::ExecuteMethod(
  651. IN BSTR bstrObjPath,
  652. IN WCHAR* pwszMethodName,
  653. IN long lFlag,
  654. IN IWbemClassObject* pParams,
  655. IN IWbemObjectSink* pHandler
  656. )
  657. {
  658. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::ExecuteMethod");
  659. try
  660. {
  661. if (!_wcsicmp(pwszMethodName, PVDR_MTHD_ADDMOUNTPOINT))
  662. {
  663. ft.hr = ExecAddMountPoint(
  664. bstrObjPath,
  665. pwszMethodName,
  666. lFlag,
  667. pParams,
  668. pHandler);
  669. }
  670. else if (!_wcsicmp(pwszMethodName, PVDR_MTHD_MOUNT))
  671. {
  672. ft.hr = ExecMount(
  673. bstrObjPath,
  674. pwszMethodName,
  675. lFlag,
  676. pParams,
  677. pHandler);
  678. }
  679. else if (!_wcsicmp(pwszMethodName, PVDR_MTHD_DISMOUNT))
  680. {
  681. ft.hr = ExecDismount(
  682. bstrObjPath,
  683. pwszMethodName,
  684. lFlag,
  685. pParams,
  686. pHandler);
  687. }
  688. else if (!_wcsicmp(pwszMethodName, PVDR_MTHD_DEFRAG))
  689. {
  690. ft.hr = ExecDefrag(
  691. bstrObjPath,
  692. pwszMethodName,
  693. lFlag,
  694. pParams,
  695. pHandler);
  696. }
  697. else if (!_wcsicmp(pwszMethodName, PVDR_MTHD_DEFRAGANALYSIS))
  698. {
  699. ft.hr = ExecDefragAnalysis(
  700. bstrObjPath,
  701. pwszMethodName,
  702. lFlag,
  703. pParams,
  704. pHandler);
  705. }
  706. else if (!_wcsicmp(pwszMethodName, PVDR_MTHD_CHKDSK))
  707. {
  708. ft.hr = ExecChkdsk(
  709. bstrObjPath,
  710. pwszMethodName,
  711. lFlag,
  712. pParams,
  713. pHandler);
  714. }
  715. else if (!_wcsicmp(pwszMethodName, PVDR_MTHD_SCHEDULECHK))
  716. {
  717. ft.hr = ExecScheduleAutoChk(
  718. bstrObjPath,
  719. pwszMethodName,
  720. lFlag,
  721. pParams,
  722. pHandler);
  723. }
  724. else if (!_wcsicmp(pwszMethodName, PVDR_MTHD_EXCLUDECHK))
  725. {
  726. ft.hr = ExecExcludeAutoChk(
  727. bstrObjPath,
  728. pwszMethodName,
  729. lFlag,
  730. pParams,
  731. pHandler);
  732. }
  733. else if (!_wcsicmp(pwszMethodName, PVDR_MTHD_FORMAT))
  734. {
  735. ft.hr = ExecFormat(
  736. bstrObjPath,
  737. pwszMethodName,
  738. lFlag,
  739. pParams,
  740. pHandler);
  741. }
  742. else
  743. {
  744. ft.hr = WBEM_E_INVALID_METHOD;
  745. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Invalid method called, %lS, hr<%#x>", pwszMethodName, ft.hr);
  746. }
  747. }
  748. catch (HRESULT hrEx)
  749. {
  750. ft.hr = hrEx;
  751. }
  752. return ft.hr;
  753. }
  754. HRESULT
  755. CVolume::ExecAddMountPoint(
  756. IN BSTR bstrObjPath,
  757. IN WCHAR* pwszMethodName,
  758. IN long lFlag,
  759. IN IWbemClassObject* pParams,
  760. IN IWbemObjectSink* pHandler)
  761. {
  762. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::ExecAddMountPoint");
  763. CComPtr<IWbemClassObject> spOutParamClass;
  764. _bstr_t bstrDirectory;
  765. _bstr_t bstrVolume;
  766. CObjPath objPath;
  767. DWORD rcStatus = ERROR_SUCCESS;
  768. if (pParams == NULL)
  769. {
  770. ft.hr = WBEM_E_INVALID_METHOD_PARAMETERS;
  771. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Volume::AddMountPoint called with no parameters, hr<%#x>", ft.hr);
  772. }
  773. objPath.Init(bstrObjPath);
  774. bstrVolume = objPath.GetStringValueForProperty(PVDR_PROP_DEVICEID);
  775. IF_WSTR_NULL_THROW(bstrVolume, WBEM_E_INVALID_OBJECT_PATH, L"ExecAddMountPoint: volume key property not found")
  776. CWbemClassObject wcoInParam(pParams);
  777. CWbemClassObject wcoOutParam;
  778. if (wcoInParam.data() == NULL)
  779. {
  780. ft.hr = E_OUTOFMEMORY;
  781. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Volume::AddMountPoint: out of memory, hr<%#x>", ft.hr);
  782. }
  783. // Gets the Directory name - input param
  784. wcoInParam.GetProperty(bstrDirectory, PVDR_PROP_DIRECTORY);
  785. IF_WSTR_NULL_THROW(bstrDirectory, WBEM_E_INVALID_METHOD_PARAMETERS, L"ExecAddMountPoint: Directory param is NULL")
  786. WCHAR* pwszDirectory = bstrDirectory;
  787. if (pwszDirectory[wcslen(pwszDirectory) - 1] != L'\\')
  788. {
  789. ft.hr = WBEM_E_INVALID_METHOD_PARAMETERS;
  790. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Invalid mount point directory, %lS, hr<%#x>", pwszDirectory, ft.hr);
  791. }
  792. ft.hr = m_pClass->GetMethod(
  793. _bstr_t(PVDR_MTHD_ADDMOUNTPOINT),
  794. 0,
  795. NULL,
  796. &spOutParamClass
  797. );
  798. if (ft.HrFailed())
  799. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"AddMountPoint GetMethod failed, hr<%#x>", ft.hr);
  800. ft.hr = spOutParamClass->SpawnInstance(0, &wcoOutParam);
  801. if (ft.HrFailed())
  802. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SpawnInstance failed, hr<%#x>", ft.hr);
  803. rcStatus = AddMountPoint(bstrVolume, bstrDirectory);
  804. ft.hr = wcoOutParam.SetProperty(rcStatus, PVD_WBEM_PROP_RETURNVALUE);
  805. if (ft.HrFailed())
  806. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SetProperty failed, hr<%#x>", ft.hr);
  807. ft.hr = pHandler->Indicate( 1, wcoOutParam.dataPtr() );
  808. return ft.hr;
  809. }
  810. HRESULT
  811. CVolume::ExecMount(
  812. IN BSTR bstrObjPath,
  813. IN WCHAR* pwszMethodName,
  814. IN long lFlag,
  815. IN IWbemClassObject* pParams,
  816. IN IWbemObjectSink* pHandler)
  817. {
  818. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::ExecMount");
  819. CComPtr<IWbemClassObject> spOutParamClass;
  820. _bstr_t bstrVolume;
  821. CObjPath objPath;
  822. DWORD rcStatus = ERROR_SUCCESS;
  823. objPath.Init(bstrObjPath);
  824. bstrVolume = objPath.GetStringValueForProperty(PVDR_PROP_DEVICEID);
  825. IF_WSTR_NULL_THROW(bstrVolume, WBEM_E_INVALID_OBJECT_PATH, L"ExecMount: volume key property not found")
  826. CWbemClassObject wcoOutParam;
  827. ft.hr = m_pClass->GetMethod(
  828. _bstr_t(PVDR_MTHD_MOUNT),
  829. 0,
  830. NULL,
  831. &spOutParamClass
  832. );
  833. if (ft.HrFailed())
  834. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Mount GetMethod failed, hr<%#x>", ft.hr);
  835. ft.hr = spOutParamClass->SpawnInstance(0, &wcoOutParam);
  836. if (ft.HrFailed())
  837. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SpawnInstance failed, hr<%#x>", ft.hr);
  838. rcStatus = Mount(bstrVolume);
  839. ft.hr = wcoOutParam.SetProperty(rcStatus, PVD_WBEM_PROP_RETURNVALUE);
  840. if (ft.HrFailed())
  841. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SetProperty failed, hr<%#x>", ft.hr);
  842. ft.hr = pHandler->Indicate( 1, wcoOutParam.dataPtr() );
  843. return ft.hr;
  844. }
  845. HRESULT
  846. CVolume::ExecDismount(
  847. IN BSTR bstrObjPath,
  848. IN WCHAR* pwszMethodName,
  849. IN long lFlag,
  850. IN IWbemClassObject* pParams,
  851. IN IWbemObjectSink* pHandler)
  852. {
  853. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::ExecDismount");
  854. CComPtr<IWbemClassObject> spOutParamClass;
  855. _bstr_t bstrVolume;
  856. BOOL fForce = FALSE;
  857. BOOL fPermanent = FALSE;
  858. CObjPath objPath;
  859. DWORD rcStatus = ERROR_SUCCESS;
  860. if (pParams == NULL)
  861. {
  862. ft.hr = WBEM_E_INVALID_METHOD_PARAMETERS;
  863. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Volume::Dismount called with no parameters, hr<%#x>", ft.hr);
  864. }
  865. objPath.Init(bstrObjPath);
  866. bstrVolume = objPath.GetStringValueForProperty(PVDR_PROP_DEVICEID);
  867. IF_WSTR_NULL_THROW(bstrVolume, WBEM_E_INVALID_OBJECT_PATH, L"ExecDismount: volume key property not found")
  868. CWbemClassObject wcoInParam(pParams);
  869. CWbemClassObject wcoOutParam;
  870. if (wcoInParam.data() == NULL)
  871. {
  872. ft.hr = E_OUTOFMEMORY;
  873. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Volume::Dismount out of memory, hr<%#x>", ft.hr);
  874. }
  875. // Get the Force flag
  876. IF_PROP_NULL_THROW(wcoInParam, PVDR_PROP_FORCE, WBEM_E_INVALID_METHOD_PARAMETERS, L"ExecDismount: Force param is NULL")
  877. wcoInParam.GetProperty(&fForce, PVDR_PROP_FORCE);
  878. // Get the Permanent flag
  879. IF_PROP_NULL_THROW(wcoInParam, PVDR_PROP_PERMANENT, WBEM_E_INVALID_METHOD_PARAMETERS, L"ExecDismount: Permanent param is NULL")
  880. wcoInParam.GetProperty(&fPermanent, PVDR_PROP_PERMANENT);
  881. ft.hr = m_pClass->GetMethod(
  882. _bstr_t(PVDR_MTHD_DISMOUNT),
  883. 0,
  884. NULL,
  885. &spOutParamClass
  886. );
  887. if (ft.HrFailed())
  888. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Dismount GetMethod failed, hr<%#x>", ft.hr);
  889. ft.hr = spOutParamClass->SpawnInstance(0, &wcoOutParam);
  890. if (ft.HrFailed())
  891. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SpawnInstance failed, hr<%#x>", ft.hr);
  892. rcStatus = Dismount(bstrVolume, fForce, fPermanent);
  893. ft.hr = wcoOutParam.SetProperty(rcStatus, PVD_WBEM_PROP_RETURNVALUE);
  894. if (ft.HrFailed())
  895. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SetProperty failed, hr<%#x>", ft.hr);
  896. ft.hr = pHandler->Indicate( 1, wcoOutParam.dataPtr() );
  897. return ft.hr;
  898. }
  899. HRESULT
  900. CVolume::ExecDefrag(
  901. IN BSTR bstrObjPath,
  902. IN WCHAR* pwszMethodName,
  903. IN long lFlag,
  904. IN IWbemClassObject* pParams,
  905. IN IWbemObjectSink* pHandler)
  906. {
  907. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::ExecDefrag");
  908. CComPtr<IWbemClassObject> spOutParamClass;
  909. CComPtr<IWbemClassObject> spObjReport;
  910. _bstr_t bstrVolume;
  911. CObjPath objPath;
  912. DWORD rcStatus = ERROR_SUCCESS;
  913. BOOL fForce = FALSE;
  914. if (pParams == NULL)
  915. {
  916. ft.hr = WBEM_E_INVALID_METHOD_PARAMETERS;
  917. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Volume::Defrag called with no parameters, hr<%#x>", ft.hr);
  918. }
  919. objPath.Init(bstrObjPath);
  920. bstrVolume = objPath.GetStringValueForProperty(PVDR_PROP_DEVICEID);
  921. IF_WSTR_NULL_THROW(bstrVolume, WBEM_E_INVALID_OBJECT_PATH, L"ExecDefrag: volume key property not found")
  922. CWbemClassObject wcoInParam(pParams);
  923. CWbemClassObject wcoOutParam;
  924. // Get the force flag
  925. IF_PROP_NULL_THROW(wcoInParam, PVDR_PROP_FORCE, WBEM_E_INVALID_METHOD_PARAMETERS, L"ExecDefrag: Force param is NULL")
  926. wcoInParam.GetProperty(&fForce, PVDR_PROP_FORCE);
  927. ft.hr = m_pClass->GetMethod(
  928. _bstr_t(PVDR_MTHD_DEFRAG),
  929. 0,
  930. NULL,
  931. &spOutParamClass
  932. );
  933. if (ft.HrFailed())
  934. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Defrag GetMethod failed, hr<%#x>", ft.hr);
  935. // Create an out param object
  936. ft.hr = spOutParamClass->SpawnInstance(0, &wcoOutParam);
  937. if (ft.HrFailed())
  938. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SpawnInstance failed, hr<%#x>", ft.hr);
  939. // Create a defrag analysis report object
  940. ft.hr = m_pNamespace->GetObject(
  941. _bstr_t(PVDR_CLASS_DEFRAGANALYSIS),
  942. 0,
  943. 0,
  944. &spObjReport,
  945. NULL);
  946. if (ft.HrFailed())
  947. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"DefragAnalysis object creation failed, hr<%#x>", ft.hr);
  948. rcStatus = Defrag(bstrVolume, fForce, pHandler, spObjReport);
  949. ft.hr = wcoOutParam.SetProperty(spObjReport, PVDR_PROP_DEFRAGANALYSIS);
  950. if (ft.HrFailed())
  951. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SetProperty failed, hr<%#x>", ft.hr);
  952. ft.hr = wcoOutParam.SetProperty(rcStatus, PVD_WBEM_PROP_RETURNVALUE);
  953. if (ft.HrFailed())
  954. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SetProperty failed, hr<%#x>", ft.hr);
  955. ft.hr = pHandler->Indicate( 1, wcoOutParam.dataPtr() );
  956. return ft.hr;
  957. }
  958. HRESULT
  959. CVolume::ExecDefragAnalysis(
  960. IN BSTR bstrObjPath,
  961. IN WCHAR* pwszMethodName,
  962. IN long lFlag,
  963. IN IWbemClassObject* pParams,
  964. IN IWbemObjectSink* pHandler)
  965. {
  966. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::ExecDefragAnalysis");
  967. CComPtr<IWbemClassObject> spOutParamClass;
  968. CComPtr<IWbemClassObject> spObjReport;
  969. _bstr_t bstrVolume;
  970. CObjPath objPath;
  971. DWORD rcStatus = ERROR_SUCCESS;
  972. BOOL fDefragRecommended = FALSE;
  973. // The DefragAnalysis method has no input parameters
  974. objPath.Init(bstrObjPath);
  975. bstrVolume = objPath.GetStringValueForProperty(PVDR_PROP_DEVICEID);
  976. IF_WSTR_NULL_THROW(bstrVolume, WBEM_E_INVALID_OBJECT_PATH, L"ExecDefragAnalysis: volume key property not found")
  977. CWbemClassObject wcoOutParam;
  978. ft.hr = m_pClass->GetMethod(
  979. _bstr_t(PVDR_MTHD_DEFRAGANALYSIS),
  980. 0,
  981. NULL,
  982. &spOutParamClass
  983. );
  984. if (ft.HrFailed())
  985. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"DefragAnalysis GetMethod failed, hr<%#x>", ft.hr);
  986. // Create an out param object
  987. ft.hr = spOutParamClass->SpawnInstance(0, &wcoOutParam);
  988. if (ft.HrFailed())
  989. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SpawnInstance failed, hr<%#x>", ft.hr);
  990. // Create a defrag analysis report object
  991. ft.hr = m_pNamespace->GetObject(
  992. _bstr_t(PVDR_CLASS_DEFRAGANALYSIS),
  993. 0,
  994. 0,
  995. &spObjReport,
  996. NULL);
  997. if (ft.HrFailed())
  998. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"DefragAnalysis object creation failed, hr<%#x>", ft.hr);
  999. rcStatus = DefragAnalysis(bstrVolume, &fDefragRecommended, spObjReport);
  1000. ft.hr = wcoOutParam.SetProperty(fDefragRecommended, PVDR_PROP_DEFRAGRECOMMENDED);
  1001. if (ft.HrFailed())
  1002. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SetProperty failed, hr<%#x>", ft.hr);
  1003. ft.hr = wcoOutParam.SetProperty(spObjReport, PVDR_PROP_DEFRAGANALYSIS);
  1004. if (ft.HrFailed())
  1005. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SetProperty failed, hr<%#x>", ft.hr);
  1006. ft.hr = wcoOutParam.SetProperty(rcStatus, PVD_WBEM_PROP_RETURNVALUE);
  1007. if (ft.HrFailed())
  1008. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SetProperty failed, hr<%#x>", ft.hr);
  1009. ft.hr = pHandler->Indicate( 1, wcoOutParam.dataPtr() );
  1010. return ft.hr;
  1011. }
  1012. HRESULT
  1013. CVolume::ExecChkdsk(
  1014. IN BSTR bstrObjPath,
  1015. IN WCHAR* pwszMethodName,
  1016. IN long lFlag,
  1017. IN IWbemClassObject* pParams,
  1018. IN IWbemObjectSink* pHandler)
  1019. {
  1020. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::Chkdsk");
  1021. CComPtr<IWbemClassObject> spOutParamClass;
  1022. _bstr_t bstrVolume;
  1023. CObjPath objPath;
  1024. DWORD rcStatus = ERROR_SUCCESS;
  1025. BOOL fFixErrors = FALSE;
  1026. BOOL fVigorousIndexCheck = FALSE;
  1027. BOOL fSkipFolderCycle = FALSE;
  1028. BOOL fForceDismount = FALSE;
  1029. BOOL fRecoverBadSectors = FALSE;
  1030. BOOL fOkToRunAtBootup = FALSE;
  1031. if (pParams == NULL)
  1032. {
  1033. ft.hr = WBEM_E_INVALID_METHOD_PARAMETERS;
  1034. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Volume::Chkdsk called with no parameters, hr<%#x>", ft.hr);
  1035. }
  1036. objPath.Init(bstrObjPath);
  1037. bstrVolume = objPath.GetStringValueForProperty(PVDR_PROP_DEVICEID);
  1038. IF_WSTR_NULL_THROW(bstrVolume, WBEM_E_INVALID_OBJECT_PATH, L"ExecChkdsk: volume key property not found")
  1039. CWbemClassObject wcoInParam(pParams);
  1040. CWbemClassObject wcoOutParam;
  1041. // Check the params
  1042. IF_PROP_NULL_THROW(wcoInParam, PVDR_PROP_FIXERRORS, WBEM_E_INVALID_METHOD_PARAMETERS, L"ExecChkdsk: FixErrors param is NULL")
  1043. IF_PROP_NULL_THROW(wcoInParam, PVDR_PROP_VIGOROUSINDEXCHECK, WBEM_E_INVALID_METHOD_PARAMETERS, L"ExecChkdsk: VigorousCheck param is NULL")
  1044. IF_PROP_NULL_THROW(wcoInParam, PVDR_PROP_SKIPFOLDERCYCLE, WBEM_E_INVALID_METHOD_PARAMETERS, L"ExecChkdsk: SkipFolderCycle param is NULL")
  1045. IF_PROP_NULL_THROW(wcoInParam, PVDR_PROP_FORCEDISMOUNT, WBEM_E_INVALID_METHOD_PARAMETERS, L"ExecChkdsk: ForceDismount param is NULL")
  1046. IF_PROP_NULL_THROW(wcoInParam, PVDR_PROP_RECOVERBADSECTORS, WBEM_E_INVALID_METHOD_PARAMETERS, L"ExecChkdsk: RecoverBadSectors param is NULL")
  1047. IF_PROP_NULL_THROW(wcoInParam, PVDR_PROP_OKTORUNATBOOTUP, WBEM_E_INVALID_METHOD_PARAMETERS, L"ExecChkdsk: OkToRunAtBootUp param is NULL")
  1048. // Get the params
  1049. wcoInParam.GetProperty(&fFixErrors, PVDR_PROP_FIXERRORS);
  1050. wcoInParam.GetProperty(&fVigorousIndexCheck, PVDR_PROP_VIGOROUSINDEXCHECK);
  1051. wcoInParam.GetProperty(&fSkipFolderCycle, PVDR_PROP_SKIPFOLDERCYCLE);
  1052. wcoInParam.GetProperty(&fForceDismount, PVDR_PROP_FORCEDISMOUNT);
  1053. wcoInParam.GetProperty(&fRecoverBadSectors, PVDR_PROP_RECOVERBADSECTORS);
  1054. wcoInParam.GetProperty(&fOkToRunAtBootup, PVDR_PROP_OKTORUNATBOOTUP);
  1055. ft.hr = m_pClass->GetMethod(
  1056. _bstr_t(PVDR_MTHD_CHKDSK),
  1057. 0,
  1058. NULL,
  1059. &spOutParamClass
  1060. );
  1061. if (ft.HrFailed())
  1062. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Chkdsk GetMethod failed, hr<%#x>", ft.hr);
  1063. // Create an out param object
  1064. ft.hr = spOutParamClass->SpawnInstance(0, &wcoOutParam);
  1065. if (ft.HrFailed())
  1066. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SpawnInstance failed, hr<%#x>", ft.hr);
  1067. rcStatus = Chkdsk(
  1068. bstrVolume,
  1069. fFixErrors,
  1070. fVigorousIndexCheck,
  1071. fSkipFolderCycle,
  1072. fForceDismount,
  1073. fRecoverBadSectors,
  1074. fOkToRunAtBootup
  1075. );
  1076. ft.hr = wcoOutParam.SetProperty(rcStatus, PVD_WBEM_PROP_RETURNVALUE);
  1077. if (ft.HrFailed())
  1078. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SetProperty failed, hr<%#x>", ft.hr);
  1079. ft.hr = pHandler->Indicate( 1, wcoOutParam.dataPtr() );
  1080. return ft.hr;
  1081. }
  1082. // ScheduleAutoChk is a class static method.
  1083. HRESULT
  1084. CVolume::ExecScheduleAutoChk(
  1085. IN BSTR bstrObjPath, // no object path for static methods
  1086. IN WCHAR* pwszMethodName,
  1087. IN long lFlag,
  1088. IN IWbemClassObject* pParams,
  1089. IN IWbemObjectSink* pHandler)
  1090. {
  1091. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::ExecScheduleAutoChk");
  1092. DWORD rcStatus = ERROR_SUCCESS;
  1093. WCHAR* pmszVolumes = NULL;
  1094. try
  1095. {
  1096. DWORD cchVolumes = 0;
  1097. CComPtr<IWbemClassObject> spOutParamClass;
  1098. CObjPath objPath;
  1099. if (pParams == NULL)
  1100. {
  1101. ft.hr = WBEM_E_INVALID_METHOD_PARAMETERS;
  1102. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Volume::ExecScheduleAutoChk called with no parameters, hr<%#x>", ft.hr);
  1103. }
  1104. CWbemClassObject wcoInParam(pParams);
  1105. CWbemClassObject wcoOutParam;
  1106. if (wcoInParam.data() == NULL)
  1107. {
  1108. ft.hr = E_OUTOFMEMORY;
  1109. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Volume::ExecScheduleAutoChk: out of memory, hr<%#x>", ft.hr);
  1110. }
  1111. // Gets the Volumes
  1112. wcoInParam.GetPropertyMultiSz(&cchVolumes, &pmszVolumes, PVDR_PROP_VOLUME);
  1113. IF_WSTR_NULL_THROW(pmszVolumes, WBEM_E_INVALID_METHOD_PARAMETERS, L"ExecScheduleAutoChk: volume array param is NULL")
  1114. ft.hr = m_pClass->GetMethod(
  1115. _bstr_t(PVDR_MTHD_SCHEDULECHK),
  1116. 0,
  1117. NULL,
  1118. &spOutParamClass
  1119. );
  1120. if (ft.HrFailed())
  1121. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"ExecScheduleAutoChk GetMethod failed, hr<%#x>", ft.hr);
  1122. ft.hr = spOutParamClass->SpawnInstance(0, &wcoOutParam);
  1123. if (ft.HrFailed())
  1124. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SpawnInstance failed, hr<%#x>", ft.hr);
  1125. rcStatus = AutoChk(g_wszScheduleAutoChkCommand, pmszVolumes);
  1126. ft.hr = wcoOutParam.SetProperty(rcStatus, PVD_WBEM_PROP_RETURNVALUE);
  1127. if (ft.HrFailed())
  1128. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SetProperty failed, hr<%#x>", ft.hr);
  1129. ft.hr = pHandler->Indicate( 1, wcoOutParam.dataPtr() );
  1130. }
  1131. catch (...)
  1132. {
  1133. delete [] pmszVolumes;
  1134. throw;
  1135. }
  1136. delete [] pmszVolumes;
  1137. return ft.hr;
  1138. }
  1139. // ExcludeAutoChk is a class static method.
  1140. HRESULT
  1141. CVolume::ExecExcludeAutoChk(
  1142. IN BSTR bstrObjPath, // no object path for static methods
  1143. IN WCHAR* pwszMethodName,
  1144. IN long lFlag,
  1145. IN IWbemClassObject* pParams,
  1146. IN IWbemObjectSink* pHandler)
  1147. {
  1148. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::ExecExcludeAutoChk");
  1149. DWORD rcStatus = ERROR_SUCCESS;
  1150. WCHAR* pmszVolumes = NULL;
  1151. try
  1152. {
  1153. DWORD cchVolumes = 0;
  1154. CComPtr<IWbemClassObject> spOutParamClass;
  1155. CObjPath objPath;
  1156. if (pParams == NULL)
  1157. {
  1158. ft.hr = WBEM_E_INVALID_METHOD_PARAMETERS;
  1159. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Volume::ExecExcludeAutoChk called with no parameters, hr<%#x>", ft.hr);
  1160. }
  1161. CWbemClassObject wcoInParam(pParams);
  1162. CWbemClassObject wcoOutParam;
  1163. if (wcoInParam.data() == NULL)
  1164. {
  1165. ft.hr = E_OUTOFMEMORY;
  1166. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Volume::ExecExcludeAutoChk: out of memory, hr<%#x>", ft.hr);
  1167. }
  1168. // Gets the Volumes
  1169. wcoInParam.GetPropertyMultiSz(&cchVolumes, &pmszVolumes, PVDR_PROP_VOLUME);
  1170. IF_WSTR_NULL_THROW(pmszVolumes, WBEM_E_INVALID_METHOD_PARAMETERS, L"ExecExcludeAutoChk: volume array param is NULL")
  1171. ft.hr = m_pClass->GetMethod(
  1172. _bstr_t(PVDR_MTHD_EXCLUDECHK),
  1173. 0,
  1174. NULL,
  1175. &spOutParamClass
  1176. );
  1177. if (ft.HrFailed())
  1178. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"ExecExcludeAutoChk GetMethod failed, hr<%#x>", ft.hr);
  1179. ft.hr = spOutParamClass->SpawnInstance(0, &wcoOutParam);
  1180. if (ft.HrFailed())
  1181. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SpawnInstance failed, hr<%#x>", ft.hr);
  1182. rcStatus = AutoChk(g_wszExcludeAutoChkCommand, pmszVolumes);
  1183. ft.hr = wcoOutParam.SetProperty(rcStatus, PVD_WBEM_PROP_RETURNVALUE);
  1184. if (ft.HrFailed())
  1185. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SetProperty failed, hr<%#x>", ft.hr);
  1186. ft.hr = pHandler->Indicate( 1, wcoOutParam.dataPtr() );
  1187. }
  1188. catch (...)
  1189. {
  1190. delete [] pmszVolumes;
  1191. throw;
  1192. }
  1193. delete [] pmszVolumes;
  1194. return ft.hr;
  1195. }
  1196. HRESULT
  1197. CVolume::ExecFormat(
  1198. IN BSTR bstrObjPath,
  1199. IN WCHAR* pwszMethodName,
  1200. IN long lFlag,
  1201. IN IWbemClassObject* pParams,
  1202. IN IWbemObjectSink* pHandler)
  1203. {
  1204. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::ExecFormat");
  1205. CComPtr<IWbemClassObject> spOutParamClass;
  1206. _bstr_t bstrVolume;
  1207. CObjPath objPath;
  1208. DWORD rcStatus = ERROR_SUCCESS;
  1209. _bstr_t bstrFileSystem;
  1210. _bstr_t bstrLabel;
  1211. BOOL fQuickFormat = FALSE;
  1212. BOOL fEnableCompression = FALSE;
  1213. DWORD dwClusterSize = 0;
  1214. if (pParams == NULL)
  1215. {
  1216. ft.hr = WBEM_E_INVALID_METHOD_PARAMETERS;
  1217. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Volume::Format called with no parameters, hr<%#x>", ft.hr);
  1218. }
  1219. objPath.Init(bstrObjPath);
  1220. bstrVolume = objPath.GetStringValueForProperty(PVDR_PROP_DEVICEID);
  1221. IF_WSTR_NULL_THROW(bstrVolume, WBEM_E_INVALID_OBJECT_PATH, L"ExecFormat: volume key property not found")
  1222. CWbemClassObject wcoInParam(pParams);
  1223. CWbemClassObject wcoOutParam;
  1224. // Get the parameters
  1225. IF_PROP_NULL_THROW(wcoInParam, PVDR_PROP_QUICKFORMAT, WBEM_E_INVALID_METHOD_PARAMETERS, L"ExecFormat: FileSystem param is NULL")
  1226. IF_PROP_NULL_THROW(wcoInParam, PVDR_PROP_ENABLECOMPRESSION, WBEM_E_INVALID_METHOD_PARAMETERS, L"ExecFormat: FileSystem param is NULL")
  1227. IF_PROP_NULL_THROW(wcoInParam, PVDR_PROP_CLUSTERSIZE, WBEM_E_INVALID_METHOD_PARAMETERS, L"ExecFormat: FileSystem param is NULL")
  1228. wcoInParam.GetProperty(bstrFileSystem, PVDR_PROP_FILESYSTEM);
  1229. IF_WSTR_NULL_THROW(bstrFileSystem, WBEM_E_INVALID_METHOD_PARAMETERS, L"ExecFormat: FileSystem param is NULL")
  1230. wcoInParam.GetProperty(&fQuickFormat, PVDR_PROP_QUICKFORMAT);
  1231. wcoInParam.GetProperty(&fEnableCompression, PVDR_PROP_ENABLECOMPRESSION);
  1232. wcoInParam.GetProperty(&dwClusterSize, PVDR_PROP_CLUSTERSIZE);
  1233. wcoInParam.GetProperty(bstrLabel, PVDR_PROP_LABEL);
  1234. if ((WCHAR*)bstrLabel == NULL) // non-NULL zero length label is OK
  1235. {
  1236. ft.hr = WBEM_E_INVALID_METHOD_PARAMETERS;
  1237. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"ExecFormat: Label param is NULL");
  1238. }
  1239. ft.hr = m_pClass->GetMethod(
  1240. _bstr_t(PVDR_MTHD_FORMAT),
  1241. 0,
  1242. NULL,
  1243. &spOutParamClass
  1244. );
  1245. if (ft.HrFailed())
  1246. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Format GetMethod failed, hr<%#x>", ft.hr);
  1247. // Create an out param object
  1248. ft.hr = spOutParamClass->SpawnInstance(0, &wcoOutParam);
  1249. if (ft.HrFailed())
  1250. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SpawnInstance failed, hr<%#x>", ft.hr);
  1251. rcStatus = Format(
  1252. bstrVolume,
  1253. fQuickFormat,
  1254. fEnableCompression,
  1255. bstrFileSystem,
  1256. dwClusterSize,
  1257. bstrLabel,
  1258. pHandler
  1259. );
  1260. ft.hr = wcoOutParam.SetProperty(rcStatus, PVD_WBEM_PROP_RETURNVALUE);
  1261. if (ft.HrFailed())
  1262. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SetProperty failed, hr<%#x>", ft.hr);
  1263. ft.hr = pHandler->Indicate( 1, wcoOutParam.dataPtr() );
  1264. return ft.hr;
  1265. }
  1266. DWORD
  1267. CVolume::AddMountPoint(
  1268. IN WCHAR* pwszVolume,
  1269. IN WCHAR* pwszDirectory
  1270. )
  1271. {
  1272. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::AddMountPoint");
  1273. DWORD rcStatus = MOUNTPOINT_RC_NO_ERROR;
  1274. _ASSERTE(pwszVolume != NULL);
  1275. _ASSERTE(pwszDirectory != NULL);
  1276. if (!SetVolumeMountPoint(pwszDirectory, pwszVolume))
  1277. {
  1278. switch(GetLastError())
  1279. {
  1280. case ERROR_FILE_NOT_FOUND:
  1281. rcStatus = MOUNTPOINT_RC_FILE_NOT_FOUND;
  1282. break;
  1283. case ERROR_DIR_NOT_EMPTY:
  1284. rcStatus = MOUNTPOINT_RC_DIRECTORY_NOT_EMPTY;
  1285. break;
  1286. case ERROR_INVALID_PARAMETER:
  1287. case ERROR_INVALID_NAME:
  1288. rcStatus = MOUNTPOINT_RC_INVALID_ARG;
  1289. break;
  1290. case ERROR_ACCESS_DENIED:
  1291. rcStatus = MOUNTPOINT_RC_ACCESS_DENIED;
  1292. break;
  1293. case ERROR_INVALID_FUNCTION:
  1294. rcStatus = MOUNTPOINT_RC_NOT_SUPPORTED;
  1295. break;
  1296. default:
  1297. rcStatus = GetLastError();
  1298. ft.Trace(VSSDBG_VSSADMIN, L"CVolume::AddMountPoint: SetVolumeMountPoint failed %#x", rcStatus);
  1299. }
  1300. }
  1301. return rcStatus;
  1302. }
  1303. DWORD
  1304. CVolume::Mount(
  1305. IN WCHAR* pwszVolume
  1306. )
  1307. {
  1308. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::Mount");
  1309. DWORD rcStatus = MOUNT_RC_NO_ERROR;
  1310. _ASSERTE(pwszVolume != NULL);
  1311. // Issue mount only for offline volumes. System will automount others on next IO
  1312. if (!VolumeIsMountable(pwszVolume))
  1313. {
  1314. DWORD cch;
  1315. HANDLE hVol;
  1316. BOOL bOnline = FALSE;
  1317. DWORD bytes;
  1318. cch = wcslen(pwszVolume);
  1319. pwszVolume[cch - 1] = 0;
  1320. hVol = CreateFile(pwszVolume, GENERIC_READ | GENERIC_WRITE,
  1321. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  1322. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE);
  1323. pwszVolume[cch - 1] = '\\';
  1324. if (hVol != INVALID_HANDLE_VALUE)
  1325. {
  1326. bOnline = DeviceIoControl(hVol, IOCTL_VOLUME_ONLINE, NULL, 0, NULL, 0, &bytes,
  1327. NULL);
  1328. CloseHandle(hVol);
  1329. if (!bOnline)
  1330. rcStatus = MOUNT_RC_UNEXPECTED;
  1331. }
  1332. else
  1333. {
  1334. switch(GetLastError())
  1335. {
  1336. case ERROR_FILE_NOT_FOUND:
  1337. case ERROR_INVALID_PARAMETER:
  1338. case ERROR_INVALID_NAME:
  1339. ft.hr = WBEM_E_NOT_FOUND;
  1340. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"CVolume::Mount: CreateFile failed %#x", GetLastError());
  1341. break;
  1342. case ERROR_ACCESS_DENIED:
  1343. rcStatus = MOUNT_RC_ACCESS_DENIED;
  1344. break;
  1345. default:
  1346. rcStatus = GetLastError();
  1347. ft.Trace(VSSDBG_VSSADMIN, L"CVolume::Mount: CreateFile failed %#x", rcStatus);
  1348. }
  1349. }
  1350. }
  1351. return rcStatus;
  1352. }
  1353. DWORD
  1354. CVolume::Dismount(
  1355. IN WCHAR* pwszVolume,
  1356. IN BOOL fForce,
  1357. IN BOOL fPermanent
  1358. )
  1359. {
  1360. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::Dismount");
  1361. DWORD rcStatus = DISMOUNT_RC_NO_ERROR;
  1362. HANDLE hVol = INVALID_HANDLE_VALUE;
  1363. _ASSERTE(pwszVolume != NULL);
  1364. try
  1365. {
  1366. // Issue dismount only for online volumes.
  1367. if (VolumeIsMountable(pwszVolume))
  1368. {
  1369. BOOL bIO = FALSE;
  1370. DWORD bytes;
  1371. DWORD cch;
  1372. cch = wcslen(pwszVolume);
  1373. pwszVolume[cch - 1] = 0;
  1374. hVol = CreateFile(pwszVolume, GENERIC_READ | GENERIC_WRITE,
  1375. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  1376. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE);
  1377. pwszVolume[cch - 1] = '\\';
  1378. if (hVol != INVALID_HANDLE_VALUE)
  1379. {
  1380. if (fPermanent) // Put the volume in an offline state
  1381. {
  1382. // Make sure there are no mount points for the volume
  1383. if (VolumeHasMountPoints(pwszVolume))
  1384. throw DISMOUNT_RC_VOLUME_HAS_MOUNT_POINTS;
  1385. // Make sure the volume supports ONLINE/OFFLINE
  1386. bIO = DeviceIoControl(hVol, IOCTL_VOLUME_SUPPORTS_ONLINE_OFFLINE, NULL, 0,
  1387. NULL, 0, &bytes, NULL);
  1388. if (!bIO)
  1389. throw DISMOUNT_RC_NOT_SUPPORTED;
  1390. // Lock the volume so that apps have a chance to dismount gracefully.
  1391. // If the LOCK fails, continue only if Force is specified.
  1392. bIO = DeviceIoControl(hVol, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &bytes, NULL);
  1393. if (!fForce && !bIO)
  1394. throw DISMOUNT_RC_FORCE_OPTION_REQUIRED;
  1395. // Dismount the volume
  1396. bIO = DeviceIoControl(hVol, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &bytes, NULL);
  1397. if (!bIO)
  1398. throw DISMOUNT_RC_UNEXPECTED;
  1399. // Set the volume offline
  1400. bIO = DeviceIoControl(hVol, IOCTL_VOLUME_OFFLINE, NULL, 0, NULL, 0, &bytes, NULL);
  1401. if (!bIO)
  1402. throw DISMOUNT_RC_UNEXPECTED;
  1403. }
  1404. else
  1405. {
  1406. // Lock the volume so that apps have a chance to dismount gracefully.
  1407. // If the LOCK fails, continue only if Force is specified.
  1408. bIO = DeviceIoControl(hVol, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &bytes, NULL);
  1409. if (!fForce && !bIO)
  1410. throw DISMOUNT_RC_FORCE_OPTION_REQUIRED;
  1411. bIO = DeviceIoControl(hVol, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &bytes, NULL);
  1412. if (!bIO)
  1413. throw DISMOUNT_RC_UNEXPECTED;
  1414. }
  1415. }
  1416. else
  1417. {
  1418. switch(GetLastError())
  1419. {
  1420. case ERROR_FILE_NOT_FOUND:
  1421. case ERROR_INVALID_PARAMETER:
  1422. case ERROR_INVALID_NAME:
  1423. ft.hr = WBEM_E_NOT_FOUND;
  1424. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"CVolume::Dismount: CreateFile failed %#x", GetLastError());
  1425. break;
  1426. case ERROR_ACCESS_DENIED:
  1427. rcStatus = DISMOUNT_RC_ACCESS_DENIED;
  1428. break;
  1429. default:
  1430. rcStatus = GetLastError();
  1431. ft.Trace(VSSDBG_VSSADMIN, L"CVolume::Dismount: CreateFile failed %#x", rcStatus);
  1432. }
  1433. }
  1434. }
  1435. }
  1436. catch (DISMOUNT_ERROR rcEx)
  1437. {
  1438. rcStatus = rcEx;
  1439. }
  1440. catch (...)
  1441. {
  1442. if (hVol != INVALID_HANDLE_VALUE)
  1443. CloseHandle(hVol);
  1444. throw;
  1445. }
  1446. if (hVol != INVALID_HANDLE_VALUE)
  1447. CloseHandle(hVol);
  1448. return rcStatus;
  1449. }
  1450. DWORD
  1451. CVolume::Defrag(
  1452. IN WCHAR* pwszVolume,
  1453. IN BOOL fForce,
  1454. IN IWbemObjectSink* pHandler,
  1455. IN OUT IWbemClassObject* pObject
  1456. )
  1457. {
  1458. DWORD rcStatus = DEFRAG_RC_NO_ERROR;
  1459. CComPtr<IFsuDefrag> spIDefrag;
  1460. CComPtr<IFsuAsync> spAsync;
  1461. HRESULT hrDefrag = E_FAIL;
  1462. DEFRAG_REPORT DefragReport;
  1463. BOOL fDirty = FALSE;
  1464. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::Defrag");
  1465. _ASSERTE(pObject != NULL);
  1466. if (GetDriveType(pwszVolume) == DRIVE_REMOVABLE && !VolumeIsReady(pwszVolume))
  1467. return DEFRAG_RC_NOT_SUPPORTED;
  1468. VolumeIsDirty(pwszVolume, &fDirty);
  1469. if (fDirty)
  1470. return DEFRAG_RC_DIRTY_BIT_SET;
  1471. ft.hr = spIDefrag.CoCreateInstance(__uuidof(FsuDefrag));
  1472. if (ft.HrFailed())
  1473. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"IFsuDefrag CoCreateInstance failed, %#x", ft.hr);
  1474. ft.hr = spIDefrag->Defrag(
  1475. pwszVolume,
  1476. fForce,
  1477. &spAsync);
  1478. if (ft.HrFailed())
  1479. ft.Trace(VSSDBG_VSSADMIN, L"IFsuDefrag::Defrag failed, %#x", ft.hr);
  1480. hrDefrag = ft.hr;
  1481. if (ft.HrSucceeded())
  1482. {
  1483. do
  1484. {
  1485. ULONG ulPercentDone = 0;
  1486. ft.hr = spAsync->QueryStatus(&hrDefrag, &ulPercentDone);
  1487. if (ft.HrFailed())
  1488. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"IFsuAsync::QueryStatus failed, %#x", ft.hr);
  1489. ft.hr = pHandler->SetStatus(
  1490. WBEM_STATUS_PROGRESS, // progress report
  1491. MAKELONG(ulPercentDone, 100), // LOWORD is work done so far, HIWORD is total work
  1492. NULL,
  1493. NULL);
  1494. if (ft.HrFailed())
  1495. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Defrag: unable to set intermediate status, SetStatus returned %#x", ft.hr);
  1496. Sleep(200);
  1497. }
  1498. while (hrDefrag == E_PENDING);
  1499. ft.hr = spAsync->Wait(&hrDefrag);
  1500. if (ft.HrFailed())
  1501. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"IFsuAsync::Wait failed, %#x", ft.hr);
  1502. }
  1503. if(SUCCEEDED(hrDefrag))
  1504. {
  1505. memset(&DefragReport, 0, sizeof(DefragReport));
  1506. ft.hr = spAsync->GetDefragReport(&DefragReport);
  1507. if (ft.HrFailed())
  1508. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"IFsuAsync::GetDefragReport failed, %#x", ft.hr);
  1509. LoadDefragAnalysis(&DefragReport, pObject);
  1510. }
  1511. else
  1512. {
  1513. TranslateDefragError(hrDefrag, &rcStatus);
  1514. }
  1515. return rcStatus;
  1516. }
  1517. DWORD
  1518. CVolume::DefragAnalysis(
  1519. IN WCHAR* pwszVolume,
  1520. OUT BOOL* pfDefragRecommended,
  1521. IN OUT IWbemClassObject* pObject
  1522. )
  1523. {
  1524. DWORD rcStatus = DEFRAG_RC_NO_ERROR;
  1525. CComPtr<IFsuDefrag> spIDefrag;
  1526. CComPtr<IFsuAsync> spAsync;
  1527. HRESULT hrDefrag = E_FAIL;
  1528. DEFRAG_REPORT DefragReport;
  1529. BOOL fDirty = FALSE;
  1530. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::DefragAnalysis");
  1531. _ASSERTE(pfDefragRecommended != NULL);
  1532. _ASSERTE(pObject != NULL);
  1533. *pfDefragRecommended = FALSE;
  1534. if (GetDriveType(pwszVolume) == DRIVE_REMOVABLE && !VolumeIsReady(pwszVolume))
  1535. return DEFRAG_RC_NOT_SUPPORTED;
  1536. VolumeIsDirty(pwszVolume, &fDirty);
  1537. if (fDirty)
  1538. return DEFRAG_RC_DIRTY_BIT_SET;
  1539. ft.hr = spIDefrag.CoCreateInstance(__uuidof(FsuDefrag));
  1540. //ft.hr = spIDefrag.CoCreateInstance(CLSID_Defrag);
  1541. if (ft.HrFailed())
  1542. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"IDefrag CoCreateInstance failed, %#x", ft.hr);
  1543. ft.hr = spIDefrag->DefragAnalysis(
  1544. pwszVolume,
  1545. &spAsync);
  1546. if (ft.HrFailed())
  1547. ft.Trace(VSSDBG_VSSADMIN, L"IDefrag::DefragAnalysis failed, %#x", ft.hr);
  1548. hrDefrag = ft.hr;
  1549. if (ft.HrSucceeded())
  1550. {
  1551. ft.hr = spAsync->Wait(&hrDefrag);
  1552. if (ft.HrFailed())
  1553. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"IFsuAsync::Wait failed, %#x", ft.hr);
  1554. }
  1555. if(SUCCEEDED(hrDefrag))
  1556. {
  1557. memset(&DefragReport, 0, sizeof(DefragReport));
  1558. ft.hr = spAsync->GetDefragReport(&DefragReport);
  1559. if (ft.HrFailed())
  1560. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"IFsuAsync::GetDefragReport failed, %#x", ft.hr);
  1561. //If the fragmentation on the disk exceeds 10% fragmentation, then recommend defragging.
  1562. if ((DefragReport.PercentDiskFragged + DefragReport.FreeSpaceFragPercent)/2 > 10)
  1563. {
  1564. *pfDefragRecommended = TRUE;
  1565. }
  1566. ft.Trace(VSSDBG_VSSADMIN, L"bDefragRecommended<%d>", *pfDefragRecommended);
  1567. LoadDefragAnalysis(&DefragReport, pObject);
  1568. }
  1569. else
  1570. {
  1571. TranslateDefragError(hrDefrag, &rcStatus);
  1572. }
  1573. return rcStatus;
  1574. }
  1575. DWORD
  1576. CVolume::Chkdsk(
  1577. IN WCHAR* pwszVolume,
  1578. IN BOOL fFixErrors,
  1579. IN BOOL fVigorousIndexCheck,
  1580. IN BOOL fSkipFolderCycle,
  1581. IN BOOL fForceDismount,
  1582. IN BOOL fRecoverBadSectors,
  1583. IN BOOL fOkToRunAtBootup
  1584. )
  1585. {
  1586. DWORD rcStatus = CHKDSK_RC_NO_ERROR;
  1587. DWORD dwThreadID = GetCurrentThreadId();
  1588. HINSTANCE hDLL = NULL;
  1589. CHKDSK_THREAD_DATA threadData;
  1590. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::Chkdsk");
  1591. if (GetDriveType(pwszVolume) == DRIVE_REMOVABLE && !VolumeIsReady(pwszVolume))
  1592. return CHKDSK_RC_NO_MEDIA;
  1593. threadData.fOkToRunAtBootup = fOkToRunAtBootup;
  1594. threadData.rcStatus = rcStatus;
  1595. SetThreadData(dwThreadID, &threadData);
  1596. try
  1597. {
  1598. WCHAR wszFileSystem[g_cchFileSystemNameMax+1];
  1599. DWORD dwDontCare = 0;
  1600. PFMIFS_CHKDSKEX_ROUTINE ChkDskExRoutine = NULL;
  1601. FMIFS_CHKDSKEX_PARAM Param;
  1602. // Get the file system
  1603. if (!GetVolumeInformation(
  1604. pwszVolume,
  1605. NULL,
  1606. 0,
  1607. &dwDontCare,
  1608. &dwDontCare,
  1609. &dwDontCare,
  1610. wszFileSystem,
  1611. g_cchFileSystemNameMax))
  1612. {
  1613. ft.hr = HRESULT_FROM_WIN32(GetLastError());
  1614. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"GetVolumeInformation failed for volume %lS, %#x", pwszVolume, GetLastError());
  1615. }
  1616. if (lstrcmpi(L"FAT", wszFileSystem) != 0 &&
  1617. lstrcmpi(L"FAT32", wszFileSystem) != 0 &&
  1618. lstrcmpi(L"NTFS", wszFileSystem) != 0)
  1619. {
  1620. rcStatus = CHKDSK_RC_UNSUPPORTED_FS;
  1621. }
  1622. else
  1623. {
  1624. // Load the chkdsk function
  1625. hDLL = LoadLibrary(L"fmifs.dll");
  1626. if (hDLL == NULL)
  1627. {
  1628. ft.hr = HRESULT_FROM_WIN32(GetLastError());
  1629. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Unable to load library fmifs.dll, %#x", GetLastError());
  1630. }
  1631. ChkDskExRoutine = (PFMIFS_CHKDSKEX_ROUTINE) GetProcAddress(hDLL, "ChkdskEx");
  1632. if (ChkDskExRoutine == NULL)
  1633. {
  1634. ft.hr = HRESULT_FROM_WIN32(GetLastError());
  1635. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"GetProcAddress failed for ChkdskEx, %#x", GetLastError());
  1636. }
  1637. Param.Major = 1;
  1638. Param.Minor = 0;
  1639. Param.Flags = 0; // For the Verbose Flag
  1640. Param.Flags |= fRecoverBadSectors ? FMIFS_CHKDSK_RECOVER : 0;
  1641. Param.Flags |= fForceDismount ? FMIFS_CHKDSK_FORCE : 0;
  1642. Param.Flags |= fVigorousIndexCheck ? FMIFS_CHKDSK_SKIP_INDEX_SCAN : 0;
  1643. Param.Flags |= fSkipFolderCycle ? FMIFS_CHKDSK_SKIP_CYCLE_SCAN : 0;
  1644. if (fRecoverBadSectors || fForceDismount)
  1645. {
  1646. fFixErrors = true;
  1647. }
  1648. // Return value captured in callback routine
  1649. ChkDskExRoutine (
  1650. pwszVolume,
  1651. wszFileSystem,
  1652. (BOOLEAN)fFixErrors,
  1653. &Param,
  1654. ChkdskCallback);
  1655. }
  1656. rcStatus = threadData.rcStatus;
  1657. }
  1658. catch (...)
  1659. {
  1660. RemoveThreadData(dwThreadID);
  1661. if (hDLL)
  1662. FreeLibrary(hDLL);
  1663. throw;
  1664. }
  1665. RemoveThreadData(dwThreadID);
  1666. if (hDLL)
  1667. FreeLibrary(hDLL);
  1668. return rcStatus;
  1669. }
  1670. #define VOLUME_GUID_PREFIX L"\\\\?\\Volume"
  1671. DWORD
  1672. CVolume::AutoChk(
  1673. IN const WCHAR* pwszAutoChkCommand,
  1674. IN WCHAR* pwmszVolumes
  1675. )
  1676. {
  1677. DWORD rcStatus = AUTOCHK_RC_NO_ERROR;
  1678. CCmdProcessor CmdProc;
  1679. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::ScheduleAutoChk");
  1680. WCHAR* pwszCurrentVolume = NULL;
  1681. do
  1682. {
  1683. DWORD dwExecStatus = 0;
  1684. DWORD cchVolumes = 0;
  1685. // Validate the volumes
  1686. pwszCurrentVolume = pwmszVolumes;
  1687. while(true)
  1688. {
  1689. DWORD dwDriveType = 0;
  1690. // End of iteration?
  1691. LONG lCurrentVolumeLength = (LONG) ::wcslen(pwszCurrentVolume);
  1692. if (lCurrentVolumeLength < 1)
  1693. break;
  1694. WCHAR wcDrive = towupper(pwszCurrentVolume[0]);
  1695. // Drive letter, drive path or volume
  1696. if (wcslen(pwszCurrentVolume) < 2)
  1697. {
  1698. ft.hr = WBEM_E_INVALID_METHOD_PARAMETERS;
  1699. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Invalid volume name, %lS", pwszCurrentVolume);
  1700. }
  1701. if ((pwszCurrentVolume[1] == L':' && (wcDrive < L'A' || wcDrive > L'Z')) ||
  1702. (pwszCurrentVolume[1] != L':' &&_wcsnicmp(pwszCurrentVolume, VOLUME_GUID_PREFIX, wcslen(VOLUME_GUID_PREFIX)) != 0))
  1703. {
  1704. ft.hr = WBEM_E_INVALID_METHOD_PARAMETERS;
  1705. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Invalid volume name, %lS", pwszCurrentVolume);
  1706. }
  1707. dwDriveType = GetDriveType(pwszCurrentVolume);
  1708. switch (dwDriveType)
  1709. {
  1710. case DRIVE_REMOTE:
  1711. return AUTOCHK_RC_NETWORK_DRIVE;
  1712. case DRIVE_CDROM:
  1713. case DRIVE_REMOVABLE:
  1714. return AUTOCHK_RC_REMOVABLE_DRIVE;
  1715. case DRIVE_UNKNOWN:
  1716. return AUTOCHK_RC_UNKNOWN_DRIVE;
  1717. case DRIVE_NO_ROOT_DIR:
  1718. return AUTOCHK_RC_NOT_ROOT_DIRECTORY ;
  1719. case DRIVE_FIXED:
  1720. break;
  1721. default:
  1722. return AUTOCHK_RC_UNEXPECTED;
  1723. }
  1724. // Destroy the multi-sz as we go along, transforming it into the command line
  1725. // Last volume will have a trailing space character; the NULL that terminates
  1726. // the multi-sz will terminate the string; the calling function throws the multi-sz
  1727. // away without re-use anyway.
  1728. if (*(pwszCurrentVolume + lCurrentVolumeLength - 1) == L'\\')
  1729. *(pwszCurrentVolume + lCurrentVolumeLength - 1) = L' '; // remove trailing '\' if any
  1730. *(pwszCurrentVolume + lCurrentVolumeLength) = L' '; // change the intermediate NULL to a space.
  1731. cchVolumes += lCurrentVolumeLength + 1; // add one for the space (was term-NULL)
  1732. // Go to the next one. Skip the zero character.
  1733. pwszCurrentVolume += lCurrentVolumeLength + 1;
  1734. }
  1735. // Allocate and build the command line
  1736. CVssAutoPWSZ awszCommand;
  1737. DWORD cchCommand = wcslen(pwszAutoChkCommand) + cchVolumes + 1;
  1738. awszCommand.Allocate(cchCommand); // internally accounts for terminating NULL
  1739. ft.hr = StringCchPrintf(awszCommand, cchCommand+1, L"%s %s", pwszAutoChkCommand, pwmszVolumes);
  1740. ft.hr = CmdProc.InitializeAsClient(L"chkntfs.exe", awszCommand);
  1741. if (ft.HrFailed())
  1742. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"CCmdProcessor::InitializeAsClient failed, %#x", ft.hr);
  1743. ft.hr = CmdProc.LaunchProcess();
  1744. if (ft.HrFailed())
  1745. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"CCmdProcessor::LaunchProcess failed, %#x", ft.hr);
  1746. do
  1747. {
  1748. ft.hr = CmdProc.Wait(200, &dwExecStatus);
  1749. if (ft.HrFailed())
  1750. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"CCmdProcessor::Wait failed, %#x", ft.hr);
  1751. } while (dwExecStatus == STILL_ACTIVE);
  1752. if (dwExecStatus != ERROR_SUCCESS)
  1753. {
  1754. rcStatus = AUTOCHK_RC_UNEXPECTED;
  1755. }
  1756. }
  1757. while (false);
  1758. return rcStatus;
  1759. }
  1760. DWORD
  1761. CVolume::Format(
  1762. IN WCHAR* pwszVolume,
  1763. IN BOOL fQuickFormat,
  1764. IN BOOL fEnableCompression,
  1765. IN WCHAR* pwszFileSystem,
  1766. IN DWORD cbClusterSize,
  1767. IN WCHAR* pwszLabel,
  1768. IN IWbemObjectSink* pHandler
  1769. )
  1770. {
  1771. DWORD rcStatus = FORMAT_RC_NO_ERROR;
  1772. HRESULT hrStatus = E_UNEXPECTED;
  1773. CComPtr<IFsuFormat> spIFormat;
  1774. CComPtr<IFsuAsync> spAsync;
  1775. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::Format");
  1776. _ASSERTE(pwszVolume != NULL);
  1777. _ASSERTE(pwszFileSystem != NULL);
  1778. _ASSERTE(pwszLabel != NULL);
  1779. if (GetDriveType(pwszVolume) == DRIVE_REMOVABLE && !VolumeIsReady(pwszVolume))
  1780. return FORMAT_RC_NO_MEDIA;
  1781. ft.hr = spIFormat.CoCreateInstance(__uuidof(FsuFormat));
  1782. if (ft.HrFailed())
  1783. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"IFsuFormat CoCreateInstance failed, %#x", ft.hr);
  1784. ft.hr = spIFormat->Format(
  1785. pwszVolume,
  1786. pwszFileSystem,
  1787. pwszLabel,
  1788. fQuickFormat,
  1789. fEnableCompression,
  1790. cbClusterSize,
  1791. &spAsync);
  1792. if (ft.HrFailed())
  1793. ft.Trace(VSSDBG_VSSADMIN, L"IFsuFormat::Format failed, %#x", ft.hr);
  1794. hrStatus = ft.hr;
  1795. if (ft.HrSucceeded())
  1796. {
  1797. do
  1798. {
  1799. ULONG ulPercentDone = 0;
  1800. ft.hr = spAsync->QueryStatus(&hrStatus, &ulPercentDone);
  1801. if (ft.HrFailed())
  1802. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"IFsuAsync::QueryStatus failed, %#x", ft.hr);
  1803. ft.hr = pHandler->SetStatus(
  1804. WBEM_STATUS_PROGRESS, // progress report
  1805. MAKELONG(ulPercentDone, 100), // LOWORD is work done so far, HIWORD is total work
  1806. NULL,
  1807. NULL);
  1808. if (ft.HrFailed())
  1809. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Format: unable to set intermediate status, SetStatus returned %#x", ft.hr);
  1810. Sleep(200);
  1811. }
  1812. while (hrStatus == E_PENDING);
  1813. ft.hr = spAsync->Wait(&hrStatus);
  1814. if (ft.HrFailed())
  1815. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"IFsuAsync::Wait failed, %#x", ft.hr);
  1816. }
  1817. switch (hrStatus)
  1818. {
  1819. case S_OK:
  1820. rcStatus = FORMAT_RC_NO_ERROR;
  1821. break;
  1822. case E_ACCESSDENIED:
  1823. rcStatus = FORMAT_RC_ACCESS_DENIED;
  1824. break;
  1825. case E_ABORT:
  1826. rcStatus = FORMAT_RC_CALL_CANCELLED;
  1827. break;
  1828. case FMT_E_UNSUPPORTED_FS:
  1829. rcStatus = FORMAT_RC_UNSUPPORTED_FS;
  1830. break;
  1831. case FMT_E_CANT_QUICKFORMAT:
  1832. rcStatus = FORMAT_RC_CANT_QUICKFORMAT;
  1833. break;
  1834. case FMT_E_CANCEL_TOO_LATE:
  1835. rcStatus = FORMAT_RC_CANCEL_TOO_LATE;
  1836. break;
  1837. case FMT_E_IO_ERROR:
  1838. rcStatus = FORMAT_RC_IO_ERROR;
  1839. break;
  1840. case FMT_E_BAD_LABEL:
  1841. rcStatus = FORMAT_RC_BAD_LABEL;
  1842. break;
  1843. case FMT_E_INCOMPATIBLE_MEDIA:
  1844. rcStatus = FORMAT_RC_INCOMPATIBLE_MEDIA;
  1845. break;
  1846. case FMT_E_WRITE_PROTECTED:
  1847. rcStatus = FORMAT_RC_WRITE_PROTECTED;
  1848. break;
  1849. case FMT_E_CANT_LOCK:
  1850. rcStatus = FORMAT_RC_CANT_LOCK;
  1851. break;
  1852. case FMT_E_NO_MEDIA:
  1853. rcStatus = FORMAT_RC_NO_MEDIA;
  1854. break;
  1855. case FMT_E_VOLUME_TOO_SMALL:
  1856. rcStatus = FORMAT_RC_VOLUME_TOO_SMALL;
  1857. break;
  1858. case FMT_E_VOLUME_TOO_BIG:
  1859. rcStatus = FORMAT_RC_VOLUME_TOO_BIG;
  1860. break;
  1861. case FMT_E_VOLUME_NOT_MOUNTED:
  1862. rcStatus = FORMAT_RC_VOLUME_NOT_MOUNTED;
  1863. break;
  1864. case FMT_E_CLUSTER_SIZE_TOO_SMALL:
  1865. rcStatus = FORMAT_RC_CLUSTER_SIZE_TOO_SMALL;
  1866. break;
  1867. case FMT_E_CLUSTER_SIZE_TOO_BIG:
  1868. rcStatus = FORMAT_RC_CLUSTER_SIZE_TOO_BIG;
  1869. break;
  1870. case FMT_E_CLUSTER_COUNT_BEYOND_32BITS:
  1871. rcStatus = FORMAT_RC_CLUSTER_COUNT_BEYOND_32BITS;
  1872. break;
  1873. default:
  1874. rcStatus = FORMAT_RC_UNEXPECTED;
  1875. }
  1876. return rcStatus;
  1877. }
  1878. //****************************************************************************
  1879. //
  1880. // CMountPoint
  1881. //
  1882. //****************************************************************************
  1883. CMountPoint::CMountPoint(
  1884. IN LPCWSTR pwszName,
  1885. IN CWbemServices* pNamespace
  1886. )
  1887. : CProvBase(pwszName, pNamespace)
  1888. {
  1889. } //*** CMountPoint::CMountPoint()
  1890. CProvBase *
  1891. CMountPoint::S_CreateThis(
  1892. IN LPCWSTR pwszName,
  1893. IN CWbemServices* pNamespace
  1894. )
  1895. {
  1896. HRESULT hr = WBEM_E_FAILED;
  1897. CMountPoint * pObj= NULL;
  1898. pObj = new CMountPoint(pwszName, pNamespace);
  1899. if (pObj)
  1900. {
  1901. hr = pObj->Initialize();
  1902. }
  1903. else
  1904. {
  1905. hr = E_OUTOFMEMORY;
  1906. }
  1907. if (FAILED(hr))
  1908. {
  1909. delete pObj;
  1910. pObj = NULL;
  1911. }
  1912. return pObj;
  1913. } //*** CMountPoint::S_CreateThis()
  1914. HRESULT
  1915. CMountPoint::Initialize()
  1916. {
  1917. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CMountPoint::Initialize");
  1918. return ft.hr;
  1919. }
  1920. HRESULT
  1921. CMountPoint::EnumInstance(
  1922. IN long lFlags,
  1923. IN IWbemContext* pCtx,
  1924. IN IWbemObjectSink * pHandler
  1925. )
  1926. {
  1927. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CMountPoint::EnumInstance");
  1928. CVssAutoPWSZ awszVolume;
  1929. try
  1930. {
  1931. awszVolume.Allocate(MAX_PATH);
  1932. CVssVolumeIterator volumeIterator;
  1933. while (true)
  1934. {
  1935. CVssAutoPWSZ awszMountPoints;
  1936. WCHAR* pwszCurrentMountPoint = NULL;
  1937. // Get the volume name
  1938. if (!volumeIterator.SelectNewVolume(ft, awszVolume, MAX_PATH))
  1939. break;
  1940. // Get the list of all mount points
  1941. // Get the length of the multi-string array
  1942. DWORD cchVolumesBufferLen = 0;
  1943. BOOL bResult = GetVolumePathNamesForVolumeName(awszVolume, NULL, 0, &cchVolumesBufferLen);
  1944. if (!bResult && (GetLastError() != ERROR_MORE_DATA))
  1945. ft.TranslateGenericError(VSSDBG_VSSADMIN, HRESULT_FROM_WIN32(GetLastError()),
  1946. L"GetVolumePathNamesForVolumeName(%s, 0, 0, %p)", (LPWSTR)awszVolume, &cchVolumesBufferLen);
  1947. // Allocate the array
  1948. awszMountPoints.Allocate(cchVolumesBufferLen);
  1949. // Get the mount points
  1950. // Note: this API was introduced in WinXP so it will need to be replaced if backported
  1951. bResult = GetVolumePathNamesForVolumeName(awszVolume, awszMountPoints, cchVolumesBufferLen, NULL);
  1952. if (!bResult)
  1953. ft.Throw(VSSDBG_VSSADMIN, HRESULT_FROM_WIN32(GetLastError()),
  1954. L"GetVolumePathNamesForVolumeName(%s, %p, %lu, 0)", (LPWSTR)awszVolume, awszMountPoints, cchVolumesBufferLen);
  1955. // If the volume has mount points
  1956. pwszCurrentMountPoint = awszMountPoints;
  1957. if ( pwszCurrentMountPoint[0] )
  1958. {
  1959. while(true)
  1960. {
  1961. CComPtr<IWbemClassObject> spInstance;
  1962. // End of iteration?
  1963. LONG lCurrentMountPointLength = (LONG) ::wcslen(pwszCurrentMountPoint);
  1964. if (lCurrentMountPointLength == 0)
  1965. break;
  1966. ft.hr = m_pClass->SpawnInstance(0, &spInstance);
  1967. if (ft.HrFailed())
  1968. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SpawnInstance failed, hr<%#x>", ft.hr);
  1969. // Only a root directory should have a trailing backslash character
  1970. if (lCurrentMountPointLength > 2 &&
  1971. pwszCurrentMountPoint[lCurrentMountPointLength-1] == L'\\' &&
  1972. pwszCurrentMountPoint[lCurrentMountPointLength-2] != L':')
  1973. {
  1974. pwszCurrentMountPoint[lCurrentMountPointLength-1] = L'\0';
  1975. }
  1976. LoadInstance(awszVolume, pwszCurrentMountPoint, spInstance.p);
  1977. ft.hr = pHandler->Indicate(1, &spInstance.p);
  1978. // Go to the next one. Skip the zero character.
  1979. pwszCurrentMountPoint += lCurrentMountPointLength + 1;
  1980. }
  1981. }
  1982. }
  1983. }
  1984. catch (HRESULT hrEx)
  1985. {
  1986. ft.hr = hrEx;
  1987. }
  1988. return ft.hr;
  1989. } //*** CMountPoint::EnumInstance()
  1990. HRESULT
  1991. CMountPoint::GetObject(
  1992. IN CObjPath& rObjPath,
  1993. IN long lFlags,
  1994. IN IWbemContext* pCtx,
  1995. IN IWbemObjectSink* pHandler
  1996. )
  1997. {
  1998. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CMountPoint::GetObject");
  1999. try
  2000. {
  2001. _bstr_t bstrVolumeRef, bstrVolumeName;
  2002. _bstr_t bstrDirectoryRef, bstrDirectoryName;
  2003. CObjPath objPathVolume;
  2004. CObjPath objPathDirectory;
  2005. CVssAutoPWSZ awszMountPoints;
  2006. WCHAR* pwszCurrentMountPoint = NULL;
  2007. BOOL fFound = FALSE;
  2008. CComPtr<IWbemClassObject> spInstance;
  2009. // Get the Volume reference
  2010. bstrVolumeRef = rObjPath.GetStringValueForProperty(PVDR_PROP_VOLUME);
  2011. IF_WSTR_NULL_THROW(bstrVolumeRef, WBEM_E_INVALID_OBJECT_PATH, L"MountPoint volume key property not found")
  2012. // Get the Directory reference
  2013. bstrDirectoryRef = rObjPath.GetStringValueForProperty(PVDR_PROP_DIRECTORY);
  2014. IF_WSTR_NULL_THROW(bstrDirectoryRef, WBEM_E_INVALID_OBJECT_PATH, L"MountPoint directory key property not found")
  2015. // Extract the Volume and Directory Names
  2016. objPathVolume.Init(bstrVolumeRef);
  2017. objPathDirectory.Init(bstrDirectoryRef);
  2018. bstrVolumeName = objPathVolume.GetStringValueForProperty(PVDR_PROP_DEVICEID);
  2019. IF_WSTR_NULL_THROW(bstrVolumeName, WBEM_E_INVALID_OBJECT_PATH, L"MountPoint volume key property DeviceID not found")
  2020. bstrDirectoryName = objPathDirectory.GetStringValueForProperty(PVDR_PROP_NAME);
  2021. IF_WSTR_NULL_THROW(bstrDirectoryName, WBEM_E_INVALID_OBJECT_PATH, L"MountPoint directory key property Name not found")
  2022. if (VolumeMountPointExists(bstrVolumeName, bstrDirectoryName))
  2023. {
  2024. CComPtr<IWbemClassObject> spInstance;
  2025. ft.hr = m_pClass->SpawnInstance(0, &spInstance);
  2026. if (ft.HrFailed())
  2027. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SpawnInstance failed, hr<%#x>", ft.hr);
  2028. LoadInstance(bstrVolumeName, bstrDirectoryName, spInstance.p);
  2029. ft.hr = pHandler->Indicate(1, &spInstance.p);
  2030. }
  2031. else
  2032. {
  2033. ft.hr = WBEM_E_NOT_FOUND;
  2034. }
  2035. }
  2036. catch (HRESULT hrEx)
  2037. {
  2038. ft.hr = hrEx;
  2039. }
  2040. return ft.hr;
  2041. } //*** CMountPoint::GetObject()
  2042. void
  2043. CMountPoint:: LoadInstance(
  2044. IN WCHAR* pwszVolume,
  2045. IN WCHAR* pwszDirectory,
  2046. IN OUT IWbemClassObject* pObject)
  2047. {
  2048. CWbemClassObject wcoInstance(pObject);
  2049. CObjPath pathDirectory;
  2050. CObjPath pathVolume;
  2051. _ASSERTE(pwszVolume != NULL);
  2052. _ASSERTE(pwszDirectory != NULL);
  2053. // Set the Directory Ref property
  2054. pathDirectory.Init(PVDR_CLASS_DIRECTORY);
  2055. pathDirectory.AddProperty(PVDR_PROP_NAME, pwszDirectory);
  2056. wcoInstance.SetProperty((wchar_t*)pathDirectory.GetObjectPathString(), PVDR_PROP_DIRECTORY);
  2057. // Set the Volume Ref property
  2058. pathVolume.Init(PVDR_CLASS_VOLUME);
  2059. pathVolume.AddProperty(PVDR_PROP_DEVICEID, pwszVolume);
  2060. wcoInstance.SetProperty((wchar_t*)pathVolume.GetObjectPathString(), PVDR_PROP_VOLUME);
  2061. }
  2062. HRESULT
  2063. CMountPoint::PutInstance(
  2064. IN CWbemClassObject& rInstToPut,
  2065. IN long lFlag,
  2066. IN IWbemContext* pCtx,
  2067. IN IWbemObjectSink* pHandler
  2068. )
  2069. {
  2070. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CMountPoint::PutInstance");
  2071. try
  2072. {
  2073. _bstr_t bstrVolumeRef, bstrVolumeName;
  2074. _bstr_t bstrDirectoryRef, bstrDirectoryName;
  2075. CObjPath objPathVolume;
  2076. CObjPath objPathDirectory;
  2077. if ( lFlag & WBEM_FLAG_UPDATE_ONLY )
  2078. {
  2079. return WBEM_E_UNSUPPORTED_PARAMETER ;
  2080. }
  2081. // Retrieve key properties of the object to be saved.
  2082. rInstToPut.GetProperty(bstrVolumeRef, PVDR_PROP_VOLUME);
  2083. IF_WSTR_NULL_THROW(bstrVolumeRef, WBEM_E_INVALID_OBJECT, L"MountPoint volume key property not found")
  2084. rInstToPut.GetProperty(bstrDirectoryRef, PVDR_PROP_DIRECTORY);
  2085. IF_WSTR_NULL_THROW(bstrDirectoryRef, WBEM_E_INVALID_OBJECT, L"MountPoint directory key property not found")
  2086. // Extract the Volume and Directory Names
  2087. objPathVolume.Init(bstrVolumeRef);
  2088. objPathDirectory.Init(bstrDirectoryRef);
  2089. bstrVolumeName = objPathVolume.GetStringValueForProperty(PVDR_PROP_DEVICEID);
  2090. IF_WSTR_NULL_THROW(bstrVolumeName, WBEM_E_INVALID_OBJECT_PATH, L"MountPoint volume key property DeviceID not found")
  2091. bstrDirectoryName = objPathDirectory.GetStringValueForProperty(PVDR_PROP_NAME);
  2092. IF_WSTR_NULL_THROW(bstrDirectoryName, WBEM_E_INVALID_OBJECT_PATH, L"MountPoint directory key property Name not found")
  2093. ft.Trace(VSSDBG_VSSADMIN, L"CMountPoint::PutInstance Volume<%lS> Directory<%lS>",
  2094. (WCHAR*)bstrVolumeName, (WCHAR*)bstrDirectoryName);
  2095. if (VolumeMountPointExists(bstrVolumeName, bstrDirectoryName))
  2096. {
  2097. ft.hr = WBEM_E_ALREADY_EXISTS;
  2098. ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"CMountPoint:PutInstance mount point already exists");
  2099. }
  2100. // Only root directories have the trailing backslash; fix the others
  2101. WCHAR* pwszDirectoryName = bstrDirectoryName;
  2102. if (pwszDirectoryName[wcslen(bstrDirectoryName) -1] != L'\\')
  2103. bstrDirectoryName += _bstr_t(L"\\");
  2104. if (!SetVolumeMountPoint(bstrDirectoryName, bstrVolumeName))
  2105. {
  2106. switch(GetLastError())
  2107. {
  2108. case ERROR_FILE_NOT_FOUND:
  2109. case ERROR_DIR_NOT_EMPTY:
  2110. case ERROR_INVALID_PARAMETER:
  2111. case ERROR_INVALID_NAME:
  2112. ft.hr = WBEM_E_INVALID_PARAMETER;
  2113. break;
  2114. case ERROR_ACCESS_DENIED:
  2115. ft.hr = WBEM_E_ACCESS_DENIED;
  2116. break;
  2117. case ERROR_INVALID_FUNCTION:
  2118. ft.hr = WBEM_E_NOT_SUPPORTED;
  2119. break;
  2120. default:
  2121. ft.hr = HRESULT_FROM_WIN32(GetLastError());
  2122. ft.Trace(VSSDBG_VSSADMIN, L"C MountPoint: PutInstance: SetVolumeMountPoint failed %#x", ft.hr);
  2123. }
  2124. }
  2125. }
  2126. catch (HRESULT hrEx)
  2127. {
  2128. ft.hr = hrEx;
  2129. }
  2130. return ft.hr;
  2131. }
  2132. HRESULT
  2133. CMountPoint::DeleteInstance(
  2134. IN CObjPath& rObjPath,
  2135. IN long lFlag,
  2136. IN IWbemContext* pCtx,
  2137. IN IWbemObjectSink* pHandler
  2138. )
  2139. {
  2140. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CMountPoint::DeleteInstance");
  2141. try
  2142. {
  2143. _bstr_t bstrVolumeRef, bstrVolumeName;
  2144. _bstr_t bstrDirectoryRef, bstrDirectoryName;
  2145. CObjPath objPathVolume;
  2146. CObjPath objPathDirectory;
  2147. // Get the Volume reference
  2148. bstrVolumeRef = rObjPath.GetStringValueForProperty(PVDR_PROP_VOLUME);
  2149. IF_WSTR_NULL_THROW(bstrVolumeRef, WBEM_E_INVALID_OBJECT_PATH, L"MountPoint volume key property not found")
  2150. // Get the Directory reference
  2151. bstrDirectoryRef = rObjPath.GetStringValueForProperty(PVDR_PROP_DIRECTORY);
  2152. IF_WSTR_NULL_THROW(bstrDirectoryRef, WBEM_E_INVALID_OBJECT_PATH, L"MountPoint directory key property not found")
  2153. // Extract the Volume and Directory Names
  2154. objPathVolume.Init(bstrVolumeRef);
  2155. objPathDirectory.Init(bstrDirectoryRef);
  2156. bstrVolumeName = objPathVolume.GetStringValueForProperty(PVDR_PROP_DEVICEID);
  2157. IF_WSTR_NULL_THROW(bstrVolumeName, WBEM_E_INVALID_OBJECT_PATH, L"MountPoint volume key property DeviceID not found")
  2158. bstrDirectoryName = objPathDirectory.GetStringValueForProperty(PVDR_PROP_NAME);
  2159. IF_WSTR_NULL_THROW(bstrDirectoryName, WBEM_E_INVALID_OBJECT_PATH, L"MountPoint directory key property Name not found")
  2160. ft.Trace(VSSDBG_VSSADMIN, L"CMountPoint::DeleteInstance Volume<%lS> Directory<%lS>",
  2161. (WCHAR*)bstrVolumeName, (WCHAR*)bstrDirectoryName);
  2162. // Only root directories have the trailing backslash; fix the others
  2163. WCHAR* pwszDirectoryName = bstrDirectoryName;
  2164. if (pwszDirectoryName[wcslen(bstrDirectoryName) -1] != L'\\')
  2165. bstrDirectoryName += _bstr_t(L"\\");
  2166. if (!DeleteVolumeMountPoint(bstrDirectoryName))
  2167. ft.Throw(VSSDBG_VSSADMIN, HRESULT_FROM_WIN32(GetLastError()), L"DeleteVolumeMountPoint failed %#x", GetLastError());
  2168. }
  2169. catch (HRESULT hrEx)
  2170. {
  2171. ft.hr = hrEx;
  2172. }
  2173. return ft.hr;
  2174. }
  2175. void
  2176. LoadDefragAnalysis(
  2177. IN DEFRAG_REPORT* pDefragReport,
  2178. IN OUT IWbemClassObject* pObject)
  2179. {
  2180. DWORD dwPercent = 0;
  2181. CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolume::LoadDefragAnalysis");
  2182. _ASSERTE(pDefragReport != NULL);
  2183. _ASSERTE(pObject != NULL);
  2184. CWbemClassObject wcoInstance(pObject);
  2185. ft.Trace(VSSDBG_VSSADMIN, L"PercentDiskFragged<%d>", pDefragReport->PercentDiskFragged);
  2186. ft.Trace(VSSDBG_VSSADMIN, L"FreeSpaceFragPercent<%d>", pDefragReport->FreeSpaceFragPercent);
  2187. ft.Trace(VSSDBG_VSSADMIN, L"FreeSpacePercent<%d>", pDefragReport->FreeSpacePercent);
  2188. // General volume properties
  2189. wcoInstance.SetPropertyI64(pDefragReport->DiskSize, PVDR_PROP_VOLUMESIZE);
  2190. wcoInstance.SetPropertyI64(pDefragReport->BytesPerCluster, PVDR_PROP_CLUSTERSIZE);
  2191. wcoInstance.SetPropertyI64(pDefragReport->UsedSpace, PVDR_PROP_USEDSPACE);
  2192. wcoInstance.SetPropertyI64(pDefragReport->FreeSpace, PVDR_PROP_FREESPACE);
  2193. wcoInstance.SetProperty(pDefragReport->FreeSpacePercent, PVDR_PROP_FRAGFREEPCT);
  2194. // Volume fragmentation
  2195. dwPercent = ((pDefragReport->PercentDiskFragged + pDefragReport->FreeSpaceFragPercent)/2);
  2196. wcoInstance.SetProperty(dwPercent, PVDR_PROP_FRAGTOTALPCT);
  2197. wcoInstance.SetProperty(pDefragReport->PercentDiskFragged, PVDR_PROP_FILESFRAGPCT);
  2198. wcoInstance.SetProperty(pDefragReport->FreeSpaceFragPercent, PVDR_PROP_FREEFRAGPCT);
  2199. // File fragmentation
  2200. wcoInstance.SetPropertyI64(pDefragReport->TotalFiles, PVDR_PROP_FILESTOTAL);
  2201. wcoInstance.SetPropertyI64(pDefragReport->AvgFileSize, PVDR_PROP_FILESIZEAVG);
  2202. wcoInstance.SetPropertyI64(pDefragReport->NumFraggedFiles, PVDR_PROP_FILESFRAGTOTAL);
  2203. wcoInstance.SetPropertyI64(pDefragReport->NumExcessFrags, PVDR_PROP_EXCESSFRAGTOTAL);
  2204. // IDefrag interface currently reports this statistic per 100 files
  2205. double dblAvgFragsPerFile = (double)(pDefragReport->AvgFragsPerFile)/100.0;
  2206. wcoInstance.SetPropertyR64(dblAvgFragsPerFile, PVDR_PROP_FILESFRAGAVG);
  2207. // Pagefile fragmentation
  2208. wcoInstance.SetPropertyI64(pDefragReport->PagefileBytes, PVDR_PROP_PAGEFILESIZE);
  2209. wcoInstance.SetPropertyI64(pDefragReport->PagefileFrags, PVDR_PROP_PAGEFILEFRAG);
  2210. // Folder fragmentation
  2211. wcoInstance.SetPropertyI64(pDefragReport->TotalDirectories, PVDR_PROP_FOLDERSTOTAL);
  2212. wcoInstance.SetPropertyI64(pDefragReport->FragmentedDirectories, PVDR_PROP_FOLDERSFRAG);
  2213. wcoInstance.SetPropertyI64(pDefragReport->ExcessDirFrags, PVDR_PROP_FOLDERSFRAGEXCESS);
  2214. // Master File Table fragmentation
  2215. wcoInstance.SetPropertyI64(pDefragReport->MFTBytes, PVDR_PROP_MFTSIZE);
  2216. wcoInstance.SetPropertyI64(pDefragReport->InUseMFTRecords, PVDR_PROP_MFTRECORDS);
  2217. dwPercent = pDefragReport->TotalMFTRecords?(100*pDefragReport->InUseMFTRecords/pDefragReport->TotalMFTRecords):0;
  2218. wcoInstance.SetProperty(dwPercent, PVDR_PROP_MFTINUSEPCT);
  2219. wcoInstance.SetPropertyI64(pDefragReport->MFTExtents, PVDR_PROP_MFTFRAGTOTAL);
  2220. }
  2221. void
  2222. TranslateDefragError(
  2223. IN HRESULT hr,
  2224. OUT DWORD* pdwError)
  2225. {
  2226. _ASSERTE(pdwError != NULL);
  2227. if (hr == HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED))
  2228. *pdwError = DEFRAG_RC_NOT_SUPPORTED;
  2229. else
  2230. {
  2231. switch (hr)
  2232. {
  2233. case DFRG_E_LOW_FREESPACE:
  2234. *pdwError = DEFRAG_RC_LOW_FREESPACE;
  2235. break;
  2236. case DFRG_E_CORRUPT_MFT:
  2237. *pdwError = DEFRAG_RC_CORRUPT_MFT;
  2238. break;
  2239. case E_ABORT:
  2240. *pdwError = DEFRAG_RC_CALL_CANCELLED;
  2241. break;
  2242. case DFRG_E_CANCEL_TOO_LATE:
  2243. *pdwError = DEFRAG_RC_CANCEL_TOO_LATE;
  2244. break;
  2245. case DFRG_E_ALREADY_RUNNING:
  2246. *pdwError = DEFRAG_RC_ALREADY_RUNNING;
  2247. break;
  2248. case DFRG_E_ENGINE_CONNECT:
  2249. *pdwError = DEFRAG_RC_ENGINE_CONNECT;
  2250. break;
  2251. case DFRG_E_ENGINE_ERROR:
  2252. *pdwError = DEFRAG_RC_ENGINE_ERROR;
  2253. break;
  2254. default:
  2255. *pdwError = DEFRAG_RC_UNEXPECTED;
  2256. }
  2257. }
  2258. }