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.

1721 lines
56 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. clivol.cpp
  5. Abstract:
  6. Implements CLI VOLUME sub-interface
  7. Author:
  8. Ran Kalach [rankala] 3-March-2000
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #include "HsmConn.h"
  13. #include "fsa.h"
  14. #include "job.h"
  15. static GUID g_nullGuid = GUID_NULL;
  16. // Internal utilities and classes for VOLUME interface
  17. HRESULT SetResourceParams(IN IFsaResource *pResource, IN DWORD dwDfs, IN DWORD dwSize, IN DWORD dwAccess,
  18. IN LPWSTR pRulePath, IN LPWSTR pRuleFileSpec, IN BOOL bInclude, IN BOOL bRecursive,
  19. IN BOOL bSetDefaults);
  20. HRESULT ShowResourceParams(IN IFsaResource *pResource, IN BOOL bDfs, IN BOOL bSize,
  21. IN BOOL bAccess, IN BOOL bRules, IN BOOL bStatistics);
  22. HRESULT FindAndDeleteRule(IN IFsaResource *pResource, IN LPWSTR pRulePath, IN LPWSTR pRuleFileSpec, IN BOOL bDelete);
  23. HRESULT StartJob(IN IFsaResource *pResource, IN HSM_JOB_TYPE Job, IN BOOL bWait);
  24. HRESULT CancelJob(IN IFsaResource *pResource, IN HSM_JOB_TYPE Job);
  25. HRESULT QuickUnmanage(IN IFsaResource *pResource);
  26. HRESULT CreateJobName(IN HSM_JOB_TYPE Job, IN IFsaResource *pResource, OUT WCHAR **pJobName);
  27. #define CVOL_INVALID_INDEX (-1)
  28. class CVolumeEnum
  29. {
  30. // Constructors
  31. public:
  32. CVolumeEnum(IN LPWSTR *pVolumes, IN DWORD dwNumberOfVolumes, IN BOOL bSkipUnavailable = TRUE);
  33. // Public methods
  34. public:
  35. HRESULT First(OUT IFsaResource **ppResource);
  36. HRESULT Next(OUT IFsaResource **ppResource);
  37. HRESULT ErrorVolume(OUT int *pIndex);
  38. // Private data
  39. protected:
  40. LPWSTR *m_pVolumes;
  41. DWORD m_dwNumberOfVolumes;
  42. // If * enumeration or not
  43. BOOL m_bAllVols;
  44. CComPtr<IWsbEnum> m_pEnumResources;
  45. // Used only when m_bAllVols == FALSE
  46. int m_nCurrent;
  47. BOOL m_bInvalidVol;
  48. // Used only when m_bAllVols == TRUE
  49. BOOL m_bSkipUnavailable;
  50. };
  51. inline
  52. HRESULT CVolumeEnum::ErrorVolume(OUT int *pIndex)
  53. {
  54. HRESULT hr = S_FALSE;
  55. if (m_bInvalidVol) {
  56. // There was an error with last volume
  57. hr = S_OK;
  58. }
  59. *pIndex = m_nCurrent;
  60. return(hr);
  61. }
  62. //
  63. // VOLUME inetrafce implementors
  64. //
  65. HRESULT
  66. VolumeManage(
  67. IN LPWSTR *Volumes,
  68. IN DWORD NumberOfVolumes,
  69. IN DWORD Dfs,
  70. IN DWORD Size,
  71. IN DWORD Access,
  72. IN LPWSTR RulePath,
  73. IN LPWSTR RuleFileSpec,
  74. IN BOOL Include,
  75. IN BOOL Recursive
  76. )
  77. /*++
  78. Routine Description:
  79. Sets volume(s) to be managed by HSM
  80. Arguments:
  81. Volumes - List of volumes to manage
  82. NumberOfVolumes - List size
  83. Dfs - Desired free space
  84. Size - Minimal size to manage
  85. Access - Minimal not-accessed time (in days)
  86. RulePath - Path for the rule
  87. RuleFileSpec - File specification for the rule
  88. Include - Is this an include or exclude rule
  89. Recursive - Is the rule recursive or not
  90. Return Value:
  91. S_OK - If all the volumes are added to the managed list
  92. --*/
  93. {
  94. HRESULT hr = S_OK;
  95. WsbTraceIn(OLESTR("VolumeManage"), OLESTR(""));
  96. try {
  97. CComPtr<IFsaResource> pResource;
  98. CWsbStringPtr param;
  99. CComPtr<IHsmServer> pHsm;
  100. CComPtr<IWsbCreateLocalObject> pCreateObj;
  101. CComPtr<IWsbIndexedCollection> pMRCollection;
  102. // Verify that input parameters are valid
  103. if (0 == NumberOfVolumes) {
  104. WsbTraceAndPrint(CLI_MESSAGE_NO_VOLUMES, NULL);
  105. WsbThrow(E_INVALIDARG);
  106. }
  107. WsbAffirmHr(ValidateLimitsArg(Dfs, IDS_DFS, HSMADMIN_MIN_FREESPACE, HSMADMIN_MAX_FREESPACE));
  108. WsbAffirmHr(ValidateLimitsArg(Size, IDS_MIN_SIZE, HSMADMIN_MIN_MINSIZE, HSMADMIN_MAX_MINSIZE));
  109. WsbAffirmHr(ValidateLimitsArg(Access, IDS_NOT_ACCESSED, HSMADMIN_MIN_INACTIVITY, HSMADMIN_MAX_INACTIVITY));
  110. if (INVALID_POINTER_ARG != RuleFileSpec) {
  111. // Must have a rule path then
  112. if (INVALID_POINTER_ARG == RulePath) {
  113. WsbTraceAndPrint(CLI_MESSAGE_INVALID_RULE, NULL);
  114. WsbThrow(E_INVALIDARG);
  115. }
  116. }
  117. // Get necessary objects
  118. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm));
  119. WsbAffirmHr(pHsm->QueryInterface(IID_IWsbCreateLocalObject, (void**) &pCreateObj));
  120. WsbAffirmHr(pHsm->GetManagedResources(&pMRCollection));
  121. // Initialize an enumerator object
  122. CVolumeEnum volEnum(Volumes, NumberOfVolumes);
  123. hr = volEnum.First(&pResource);
  124. if (WSB_E_NOTFOUND == hr) {
  125. WsbTraceAndPrint(CLI_MESSAGE_NO_VOLUMES, NULL);
  126. WsbThrow(hr);
  127. } else if (S_OK != hr) {
  128. int index;
  129. if (S_OK == volEnum.ErrorVolume(&index)) {
  130. // Problem with a specific input volume
  131. WsbTraceAndPrint(CLI_MESSAGE_INVALID_VOLUME, Volumes[index], NULL);
  132. }
  133. WsbThrow(hr);
  134. }
  135. while(S_OK == hr) {
  136. CComPtr<IHsmManagedResource> pManagedResource;
  137. CComPtr<IHsmManagedResource> pFoundResource;
  138. // Find out if the volume is the Engine's managed resources list, if not - add it
  139. WsbAffirmHr(pCreateObj->CreateInstance(CLSID_CHsmManagedResource, IID_IHsmManagedResource, (void**) &pManagedResource));
  140. WsbAffirmHr(pManagedResource->InitFromFsaResource(pResource));
  141. hr = pMRCollection->Find(pManagedResource, IID_IHsmManagedResource, (void**) &pFoundResource);
  142. if (WSB_E_NOTFOUND == hr) {
  143. // Add it
  144. WsbAffirmHr(pMRCollection->Add(pManagedResource));
  145. } else {
  146. // Verify no other error
  147. WsbAffirmHr(hr);
  148. // No other error: notify the user that parameters will still be set for the already managed volume
  149. CWsbStringPtr volName;
  150. WsbAffirmHr(CliGetVolumeDisplayName(pResource, &volName));
  151. WsbTraceAndPrint(CLI_MESSAGE_ONLY_SET, (WCHAR *)volName, NULL);
  152. }
  153. // Set the parameters (whether it was managed before or not)
  154. WsbAffirmHr(SetResourceParams(pResource, Dfs, Size, Access, RulePath,
  155. RuleFileSpec, Include, Recursive, TRUE));
  156. pManagedResource = 0;
  157. pFoundResource = 0;
  158. pResource = 0;
  159. hr = volEnum.Next(&pResource);
  160. }
  161. if (WSB_E_NOTFOUND == hr) {
  162. hr = S_OK;
  163. } else {
  164. int index;
  165. if (S_OK == volEnum.ErrorVolume(&index)) {
  166. // Problem with a specific input volume
  167. WsbAssert(CVOL_INVALID_INDEX != index, E_UNEXPECTED);
  168. WsbTraceAndPrint(CLI_MESSAGE_INVALID_VOLUME, Volumes[index], NULL);
  169. }
  170. WsbThrow(hr);
  171. }
  172. } WsbCatch(hr);
  173. WsbTraceOut(OLESTR("VolumeManage"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  174. return hr;
  175. }
  176. HRESULT
  177. VolumeUnmanage(
  178. IN LPWSTR *Volumes,
  179. IN DWORD NumberOfVolumes,
  180. IN BOOL Full
  181. )
  182. /*++
  183. Routine Description:
  184. Unmanage volume(s)
  185. Arguments:
  186. Volumes - List of volumes to manage
  187. NumberOfVolumes - List size
  188. Full - If TRUE, run unmanage job which recalls all the files back
  189. - If FALSE, just remove volume from the managed volumes list.
  190. Return Value:
  191. S_OK - If all the volumes are unmanaged successfully
  192. --*/
  193. {
  194. HRESULT hr = S_OK;
  195. WsbTraceIn(OLESTR("VolumeUnmanage"), OLESTR(""));
  196. try {
  197. CComPtr<IFsaResource> pResource;
  198. // Verify that input parameters are valid
  199. if (0 == NumberOfVolumes) {
  200. WsbTraceAndPrint(CLI_MESSAGE_NO_VOLUMES, NULL);
  201. WsbThrow(E_INVALIDARG);
  202. }
  203. // Initialize an enumerator object
  204. // Eumerate also unavailable volumes
  205. CVolumeEnum volEnum(Volumes, NumberOfVolumes, FALSE);
  206. hr = volEnum.First(&pResource);
  207. if (WSB_E_NOTFOUND == hr) {
  208. WsbTraceAndPrint(CLI_MESSAGE_NO_VOLUMES, NULL);
  209. WsbThrow(hr);
  210. } else if (S_OK != hr) {
  211. int index;
  212. if (S_OK == volEnum.ErrorVolume(&index)) {
  213. // Problem with a specific input volume
  214. WsbTraceAndPrint(CLI_MESSAGE_INVALID_VOLUME, Volumes[index], NULL);
  215. }
  216. WsbThrow(hr);
  217. }
  218. while(S_OK == hr) {
  219. if (pResource->IsManaged() == S_OK) {
  220. BOOL bForceQuick = FALSE;
  221. // If it is an unavailable volume, must set a quick unmanage
  222. if (S_OK != pResource->IsAvailable()) {
  223. bForceQuick = TRUE;
  224. }
  225. // Unmanage the volume
  226. if (Full && (! bForceQuick)) {
  227. WsbAffirmHr(StartJob(pResource, Unmanage, FALSE));
  228. } else {
  229. WsbAffirmHr(QuickUnmanage(pResource));
  230. }
  231. } else {
  232. int index;
  233. volEnum.ErrorVolume(&index);
  234. if (CVOL_INVALID_INDEX != index) {
  235. // invalid input from user
  236. WsbTraceAndPrint(CLI_MESSAGE_INVALID_VOLUME, Volumes[index], NULL);
  237. WsbThrow(E_INVALIDARG);
  238. } else {
  239. // just skip the volume...
  240. }
  241. }
  242. pResource = 0;
  243. hr = volEnum.Next(&pResource);
  244. }
  245. if (WSB_E_NOTFOUND == hr) {
  246. hr = S_OK;
  247. } else {
  248. int index;
  249. if (S_OK == volEnum.ErrorVolume(&index)) {
  250. // Problem with a specific input volume
  251. WsbTraceAndPrint(CLI_MESSAGE_INVALID_VOLUME, Volumes[index], NULL);
  252. }
  253. WsbThrow(hr);
  254. }
  255. } WsbCatch(hr);
  256. WsbTraceOut(OLESTR("VolumeUnmanage"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  257. return hr;
  258. }
  259. HRESULT
  260. VolumeSet(
  261. IN LPWSTR *Volumes,
  262. IN DWORD NumberOfVolumes,
  263. IN DWORD Dfs,
  264. IN DWORD Size,
  265. IN DWORD Access,
  266. IN LPWSTR RulePath,
  267. IN LPWSTR RuleFileSpec,
  268. IN BOOL Include,
  269. IN BOOL Recursive
  270. )
  271. /*++
  272. Routine Description:
  273. Sets parameters for volume(s) which are already managed by HSM
  274. Arguments:
  275. Volumes - List of volumes to manage
  276. NumberOfVolumes - List size
  277. Dfs - Desired free space
  278. Size - Minimal size to manage
  279. Access - Minimal not-accessed time (in days)
  280. RulePath - Path for the rule
  281. RuleFileSpec - File specification for the rule
  282. Include - Is this an include or exclude rule
  283. Recursive - Is the rule recursive or not
  284. Return Value:
  285. S_OK - If all the parameters are set for all the volumes
  286. --*/
  287. {
  288. HRESULT hr = S_OK;
  289. WsbTraceIn(OLESTR("VolumeSet"), OLESTR(""));
  290. try {
  291. CComPtr<IFsaResource> pResource;
  292. CWsbStringPtr param;
  293. // Verify that input parameters are valid
  294. if (0 == NumberOfVolumes) {
  295. WsbTraceAndPrint(CLI_MESSAGE_NO_VOLUMES, NULL);
  296. WsbThrow(E_INVALIDARG);
  297. }
  298. WsbAffirmHr(ValidateLimitsArg(Dfs, IDS_DFS, HSMADMIN_MIN_FREESPACE, HSMADMIN_MAX_FREESPACE));
  299. WsbAffirmHr(ValidateLimitsArg(Size, IDS_MIN_SIZE, HSMADMIN_MIN_MINSIZE, HSMADMIN_MAX_MINSIZE));
  300. WsbAffirmHr(ValidateLimitsArg(Access, IDS_NOT_ACCESSED, HSMADMIN_MIN_INACTIVITY, HSMADMIN_MAX_INACTIVITY));
  301. if (INVALID_POINTER_ARG != RuleFileSpec) {
  302. // Must have a rule path then
  303. if (INVALID_POINTER_ARG == RulePath) {
  304. WsbTraceAndPrint(CLI_MESSAGE_INVALID_RULE, NULL);
  305. WsbThrow(E_INVALIDARG);
  306. }
  307. }
  308. // Initialize an enumerator object
  309. CVolumeEnum volEnum(Volumes, NumberOfVolumes);
  310. hr = volEnum.First(&pResource);
  311. if (WSB_E_NOTFOUND == hr) {
  312. WsbTraceAndPrint(CLI_MESSAGE_NO_VOLUMES, NULL);
  313. WsbThrow(hr);
  314. } else if (S_OK != hr) {
  315. int index;
  316. if (S_OK == volEnum.ErrorVolume(&index)) {
  317. // Problem with a specific input volume
  318. WsbTraceAndPrint(CLI_MESSAGE_INVALID_VOLUME, Volumes[index], NULL);
  319. }
  320. WsbThrow(hr);
  321. }
  322. while(S_OK == hr) {
  323. // Set the parameters (only if the volume is managed)
  324. if (pResource->IsManaged() == S_OK) {
  325. WsbAffirmHr(SetResourceParams(pResource, Dfs, Size, Access, RulePath,
  326. RuleFileSpec, Include, Recursive, FALSE));
  327. } else {
  328. int index;
  329. volEnum.ErrorVolume(&index);
  330. if (CVOL_INVALID_INDEX != index) {
  331. // invalid input from user
  332. WsbTraceAndPrint(CLI_MESSAGE_INVALID_VOLUME, Volumes[index], NULL);
  333. WsbThrow(E_INVALIDARG);
  334. } else {
  335. // just skip the volume...
  336. }
  337. }
  338. pResource = 0;
  339. hr = volEnum.Next(&pResource);
  340. }
  341. if (WSB_E_NOTFOUND == hr) {
  342. hr = S_OK;
  343. } else {
  344. int index;
  345. if (S_OK == volEnum.ErrorVolume(&index)) {
  346. // Problem with a specific input volume
  347. WsbTraceAndPrint(CLI_MESSAGE_INVALID_VOLUME, Volumes[index], NULL);
  348. }
  349. WsbThrow(hr);
  350. }
  351. } WsbCatch(hr);
  352. WsbTraceOut(OLESTR("VolumeSet"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  353. return hr;
  354. }
  355. HRESULT
  356. VolumeShow(
  357. IN LPWSTR *Volumes,
  358. IN DWORD NumberOfVolumes,
  359. IN BOOL Dfs,
  360. IN BOOL Size,
  361. IN BOOL Access,
  362. IN BOOL Rules,
  363. IN BOOL Statistics
  364. )
  365. /*++
  366. Routine Description:
  367. Shows (prints) parameters for the given volume(s)
  368. Arguments:
  369. Volumes -
  370. NumberOfVolumes -
  371. Dfs -
  372. Size -
  373. Access -
  374. Rules -
  375. Statistics -
  376. Return Value:
  377. S_OK - If all the parameters could be retrieved for all volumes
  378. --*/
  379. {
  380. HRESULT hr = S_OK;
  381. WsbTraceIn(OLESTR("VolumeShow"), OLESTR(""));
  382. try {
  383. CComPtr<IFsaResource> pResource;
  384. // Initialize an enumerator object
  385. CVolumeEnum volEnum(Volumes, NumberOfVolumes);
  386. hr = volEnum.First(&pResource);
  387. if (WSB_E_NOTFOUND == hr) {
  388. WsbTraceAndPrint(CLI_MESSAGE_NO_VOLUMES, NULL);
  389. WsbThrow(hr);
  390. } else if (S_OK != hr) {
  391. int index;
  392. if (S_OK == volEnum.ErrorVolume(&index)) {
  393. // Problem with a specific input volume
  394. WsbTraceAndPrint(CLI_MESSAGE_INVALID_VOLUME, Volumes[index], NULL);
  395. }
  396. WsbThrow(hr);
  397. }
  398. while(S_OK == hr) {
  399. // Show the parameters (only if the volume is managed)
  400. if (pResource->IsManaged() == S_OK) {
  401. // Show volume settings
  402. WsbAffirmHr(ShowResourceParams(pResource, Dfs, Size, Access, Rules, Statistics));
  403. } else {
  404. int index;
  405. volEnum.ErrorVolume(&index);
  406. if (CVOL_INVALID_INDEX != index) {
  407. // invalid input from user
  408. WsbTraceAndPrint(CLI_MESSAGE_INVALID_VOLUME, Volumes[index], NULL);
  409. WsbThrow(E_INVALIDARG);
  410. } else {
  411. // just skip the volume...
  412. }
  413. }
  414. pResource = 0;
  415. hr = volEnum.Next(&pResource);
  416. }
  417. if (WSB_E_NOTFOUND == hr) {
  418. hr = S_OK;
  419. } else {
  420. int index;
  421. if (S_OK == volEnum.ErrorVolume(&index)) {
  422. // Problem with a specific input volume
  423. WsbTraceAndPrint(CLI_MESSAGE_INVALID_VOLUME, Volumes[index], NULL);
  424. }
  425. WsbThrow(hr);
  426. }
  427. } WsbCatch(hr);
  428. WsbTraceOut(OLESTR("VolumeShow"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  429. return hr;
  430. }
  431. HRESULT
  432. VolumeDeleteRule(
  433. IN LPWSTR *Volumes,
  434. IN DWORD NumberOfVolumes,
  435. IN LPWSTR RulePath,
  436. IN LPWSTR RuleFileSpec
  437. )
  438. /*++
  439. Routine Description:
  440. Deletes a specific rule from all of the given volumes
  441. Arguments:
  442. Volumes -
  443. NumberOfVolumes -
  444. RulePath -
  445. RuleFileSpec -
  446. Return Value:
  447. S_OK - If the rule is found and deleted successfully for all volumes
  448. --*/
  449. {
  450. HRESULT hr = S_OK;
  451. WsbTraceIn(OLESTR("VolumeDeleteRule"), OLESTR(""));
  452. try {
  453. CComPtr<IFsaResource> pResource;
  454. // Verify that input parameters are valid
  455. if (0 == NumberOfVolumes) {
  456. WsbTraceAndPrint(CLI_MESSAGE_NO_VOLUMES, NULL);
  457. WsbThrow(E_INVALIDARG);
  458. }
  459. if (INVALID_POINTER_ARG != RuleFileSpec) {
  460. // Must have a rule path then
  461. if (INVALID_POINTER_ARG == RulePath) {
  462. WsbTraceAndPrint(CLI_MESSAGE_INVALID_RULE, NULL);
  463. WsbThrow(E_INVALIDARG);
  464. }
  465. }
  466. // Initialize an enumerator object
  467. CVolumeEnum volEnum(Volumes, NumberOfVolumes);
  468. hr = volEnum.First(&pResource);
  469. if (WSB_E_NOTFOUND == hr) {
  470. WsbTraceAndPrint(CLI_MESSAGE_NO_VOLUMES, NULL);
  471. WsbThrow(hr);
  472. } else if (S_OK != hr) {
  473. int index;
  474. if (S_OK == volEnum.ErrorVolume(&index)) {
  475. // Problem with a specific input volume
  476. WsbTraceAndPrint(CLI_MESSAGE_INVALID_VOLUME, Volumes[index], NULL);
  477. }
  478. WsbThrow(hr);
  479. }
  480. while(S_OK == hr) {
  481. // Delete rules only if the volume is managed
  482. if (pResource->IsManaged() == S_OK) {
  483. // Delete the rule
  484. hr = FindAndDeleteRule(pResource, RulePath, RuleFileSpec, TRUE);
  485. if (WSB_E_NOTFOUND == hr) {
  486. CWsbStringPtr volName;
  487. WsbAffirmHr(CliGetVolumeDisplayName(pResource, &volName));
  488. WsbTraceAndPrint(CLI_MESSAGE_RULE_NOT_FOUND, RulePath, RuleFileSpec, (WCHAR *)volName, NULL);
  489. }
  490. WsbAffirmHr(hr);
  491. } else {
  492. int index;
  493. volEnum.ErrorVolume(&index);
  494. if (CVOL_INVALID_INDEX != index) {
  495. // invalid input from user
  496. WsbTraceAndPrint(CLI_MESSAGE_INVALID_VOLUME, Volumes[index], NULL);
  497. WsbThrow(E_INVALIDARG);
  498. } else {
  499. // just skip the volume...
  500. }
  501. }
  502. pResource = 0;
  503. hr = volEnum.Next(&pResource);
  504. }
  505. if (WSB_E_NOTFOUND == hr) {
  506. hr = S_OK;
  507. } else {
  508. int index;
  509. if (S_OK == volEnum.ErrorVolume(&index)) {
  510. // Problem with a specific input volume
  511. WsbTraceAndPrint(CLI_MESSAGE_INVALID_VOLUME, Volumes[index], NULL);
  512. }
  513. WsbThrow(hr);
  514. }
  515. } WsbCatch(hr);
  516. WsbTraceOut(OLESTR("VolumeDeleteRule"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  517. return hr;
  518. }
  519. HRESULT
  520. VolumeJob(
  521. IN LPWSTR *Volumes,
  522. IN DWORD NumberOfVolumes,
  523. IN HSM_JOB_TYPE Job,
  524. IN BOOL RunOrCancel,
  525. IN BOOL Synchronous
  526. )
  527. /*++
  528. Routine Description:
  529. Runs the specified job on the given volume(s)
  530. Arguments:
  531. Volumes -
  532. NumberOfVolumes -
  533. Job -
  534. RunOrCancel -
  535. Synchronous -
  536. Return Value:
  537. S_OK - If the job is started successfully for all volumes
  538. --*/
  539. {
  540. HRESULT hr = S_OK;
  541. WsbTraceIn(OLESTR("VolumeJob"), OLESTR(""));
  542. try {
  543. CComPtr<IFsaResource> pResource;
  544. // Verify that input parameters are valid
  545. if (0 == NumberOfVolumes) {
  546. WsbTraceAndPrint(CLI_MESSAGE_NO_VOLUMES, NULL);
  547. WsbThrow(E_INVALIDARG);
  548. }
  549. if ((! RunOrCancel) && Synchronous) {
  550. // Wait is available only with Run
  551. WsbTraceAndPrint(CLI_MESSAGE_WAIT_FOR_CANCEL, NULL);
  552. WsbThrow(E_INVALIDARG);
  553. }
  554. // Initialize an enumerator object
  555. CVolumeEnum volEnum(Volumes, NumberOfVolumes);
  556. hr = volEnum.First(&pResource);
  557. if (WSB_E_NOTFOUND == hr) {
  558. WsbTraceAndPrint(CLI_MESSAGE_NO_VOLUMES, NULL);
  559. WsbThrow(hr);
  560. } else if (S_OK != hr) {
  561. int index;
  562. if (S_OK == volEnum.ErrorVolume(&index)) {
  563. // Problem with a specific input volume
  564. WsbTraceAndPrint(CLI_MESSAGE_INVALID_VOLUME, Volumes[index], NULL);
  565. }
  566. WsbThrow(hr);
  567. }
  568. while(S_OK == hr) {
  569. if (pResource->IsManaged() == S_OK) {
  570. // Run or Cancel a job
  571. if (RunOrCancel) {
  572. WsbAffirmHr(StartJob(pResource, Job, Synchronous));
  573. } else {
  574. WsbAffirmHr(CancelJob(pResource, Job));
  575. }
  576. } else {
  577. int index;
  578. volEnum.ErrorVolume(&index);
  579. if (CVOL_INVALID_INDEX != index) {
  580. // invalid input from user
  581. WsbTraceAndPrint(CLI_MESSAGE_INVALID_VOLUME, Volumes[index], NULL);
  582. WsbThrow(E_INVALIDARG);
  583. } else {
  584. // just skip the volume...
  585. }
  586. }
  587. pResource = 0;
  588. hr = volEnum.Next(&pResource);
  589. }
  590. if (WSB_E_NOTFOUND == hr) {
  591. hr = S_OK;
  592. } else {
  593. int index;
  594. if (S_OK == volEnum.ErrorVolume(&index)) {
  595. // Problem with a specific input volume
  596. WsbTraceAndPrint(CLI_MESSAGE_INVALID_VOLUME, Volumes[index], NULL);
  597. }
  598. WsbThrow(hr);
  599. }
  600. } WsbCatch(hr);
  601. WsbTraceOut(OLESTR("VolumeJob"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  602. return hr;
  603. }
  604. //
  605. // Internal utilities
  606. //
  607. HRESULT SetResourceParams(IN IFsaResource *pResource, IN DWORD dwDfs, IN DWORD dwSize, IN DWORD dwAccess,
  608. IN LPWSTR pRulePath, IN LPWSTR pRuleFileSpec, IN BOOL bInclude, IN BOOL bRecursive,
  609. IN BOOL bSetDefaults)
  610. /*++
  611. Routine Description:
  612. Sets parameters for a specific volume
  613. Arguments:
  614. pResourse - A resource object to set parameters for
  615. ... (see above)
  616. Return Value:
  617. S_OK - If all the parameters are set succeessfully for the volume
  618. --*/
  619. {
  620. HRESULT hr = S_OK;
  621. WsbTraceIn(OLESTR("SetResourceParams"), OLESTR(""));
  622. try {
  623. // DFS
  624. if (INVALID_DWORD_ARG != dwDfs) {
  625. WsbAffirmHr(pResource->SetHsmLevel((ULONG)(dwDfs * FSA_HSMLEVEL_1)));
  626. } else if (bSetDefaults) {
  627. dwDfs = HSMADMIN_DEFAULT_FREESPACE;
  628. WsbAffirmHr(pResource->SetHsmLevel((ULONG)(dwDfs * FSA_HSMLEVEL_1)));
  629. }
  630. // Min size
  631. if (INVALID_DWORD_ARG != dwSize) {
  632. WsbAffirmHr(pResource->SetManageableItemLogicalSize(dwSize * 1024));
  633. } else if (bSetDefaults) {
  634. dwSize = HSMADMIN_DEFAULT_MINSIZE;
  635. WsbAffirmHr(pResource->SetManageableItemLogicalSize(dwSize * 1024));
  636. }
  637. // Not Accessed
  638. if (INVALID_DWORD_ARG != dwAccess) {
  639. FILETIME ftAccess = WsbLLtoFT(((LONGLONG)dwAccess) * WSB_FT_TICKS_PER_DAY);
  640. WsbAffirmHr(pResource->SetManageableItemAccessTime(TRUE, ftAccess));
  641. } else if (bSetDefaults) {
  642. FILETIME ftAccess = WsbLLtoFT(((LONGLONG)HSMADMIN_DEFAULT_INACTIVITY) * WSB_FT_TICKS_PER_DAY);
  643. WsbAffirmHr(pResource->SetManageableItemAccessTime(TRUE, ftAccess));
  644. }
  645. // Rules
  646. if (INVALID_POINTER_ARG != pRulePath) {
  647. // Verify that Rule does not exist
  648. hr = FindAndDeleteRule(pResource, pRulePath, pRuleFileSpec, FALSE);
  649. if (S_OK == hr) {
  650. // Rule is already there - print a warning message and ignore it
  651. CWsbStringPtr volName;
  652. WsbAffirmHr(CliGetVolumeDisplayName(pResource, &volName));
  653. WsbTraceAndPrint(CLI_MESSAGE_RULE_ALREADY_EXIST, pRulePath, pRuleFileSpec, (WCHAR *)volName, NULL);
  654. pRulePath = INVALID_POINTER_ARG;
  655. }
  656. else if (WSB_E_NOTFOUND == hr) {
  657. // Rule is not there yet
  658. hr = S_OK;
  659. } else {
  660. // unexpected error - abort
  661. WsbAffirmHr(hr);
  662. }
  663. }
  664. if (INVALID_POINTER_ARG != pRulePath) {
  665. CComPtr<IFsaServer> pFsa;
  666. CComPtr<IWsbCreateLocalObject> pCreateObj;
  667. CComPtr<IWsbCollection> pDefaultRules;
  668. CComPtr<IWsbIndexedCollection> pRulesIndexedCollection;
  669. CComPtr<IHsmRule> pRule;
  670. CComPtr<IWsbCollection> pCriteriaCollection;
  671. CComPtr<IHsmCriteria> pCriteria;
  672. // Get Fsa server for creating objects in Fsa scope
  673. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_FSA, g_nullGuid, IID_IFsaServer, (void**)&pFsa));
  674. WsbAffirmHr(pFsa->QueryInterface(IID_IWsbCreateLocalObject, (void **)&pCreateObj));
  675. // get rules collection as an indexed collection
  676. WsbAffirmHr(pResource->GetDefaultRules(&pDefaultRules));
  677. WsbAffirmHr(pDefaultRules->QueryInterface (IID_IWsbIndexedCollection, (void **) &pRulesIndexedCollection));
  678. // Create a rule and set parameters
  679. WsbAffirmHr(pCreateObj->CreateInstance(CLSID_CHsmRule, IID_IHsmRule, (void**) &pRule));
  680. WsbAffirmHr(pRule->SetPath(pRulePath));
  681. if (INVALID_POINTER_ARG != pRuleFileSpec) {
  682. WsbAffirmHr(pRule->SetName(pRuleFileSpec));
  683. } else {
  684. WsbAffirmHr(pRule->SetName(OLESTR("*")));
  685. }
  686. WsbAffirmHr(pRule->SetIsInclude(bInclude));
  687. WsbAffirmHr(pRule->SetIsUsedInSubDirs(bRecursive));
  688. WsbAffirmHr(pRule->SetIsUserDefined(TRUE));
  689. // Set the criteria appropriately, depending on whether it is an include or exclude rule.
  690. WsbAssertHr(pRule->Criteria(&pCriteriaCollection));
  691. if (bInclude) {
  692. WsbAffirmHr(pCreateObj->CreateInstance(CLSID_CHsmCritManageable, IID_IHsmCriteria, (void**) &pCriteria));
  693. } else {
  694. WsbAffirmHr(pCreateObj->CreateInstance(CLSID_CHsmCritAlways, IID_IHsmCriteria, (void**) &pCriteria));
  695. }
  696. WsbAssertHr(pCriteria->SetIsNegated(FALSE));
  697. WsbAssertHr(pCriteriaCollection->Add(pCriteria));
  698. // Now that the rule has been set up properly, add it to the default rules collection.
  699. WsbAffirmHr(pRulesIndexedCollection->Append(pRule));
  700. }
  701. } WsbCatch(hr);
  702. WsbTraceOut(OLESTR("SetResourceParams"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  703. return (hr);
  704. }
  705. HRESULT ShowResourceParams(IN IFsaResource *pResource, IN BOOL bDfs, IN BOOL bSize,
  706. IN BOOL bAccess, IN BOOL bRules, IN BOOL bStatistics)
  707. /*++
  708. Routine Description:
  709. Get and display parameters for a specific volume
  710. Arguments:
  711. pResourse - A resource object to get parameters for
  712. ... (see above)
  713. Return Value:
  714. S_OK - If all the parameters are retrieved succeessfully for the volume
  715. --*/
  716. {
  717. HRESULT hr = S_OK;
  718. WsbTraceIn(OLESTR("ShowResourceParams"), OLESTR(""));
  719. try {
  720. CWsbStringPtr volName;
  721. CWsbStringPtr param, param2;
  722. WCHAR longData[100];
  723. WsbAffirmHr(CliGetVolumeDisplayName(pResource, &volName));
  724. WsbTraceAndPrint(CLI_MESSAGE_VOLUME_PARAMS, (WCHAR *)volName, NULL);
  725. // Dfs
  726. if (bDfs) {
  727. ULONG hsmLevel;
  728. WsbAffirmHr(pResource->GetHsmLevel(&hsmLevel));
  729. hsmLevel = hsmLevel / FSA_HSMLEVEL_1;
  730. WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_DFS));
  731. WsbAffirmHr(param2.LoadFromRsc(g_hInstance, IDS_PERCENT_SUFFIX));
  732. swprintf(longData, OLESTR("%lu"), hsmLevel);
  733. WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY2, (WCHAR *)param, longData, (WCHAR *)param2, NULL);
  734. }
  735. // Min size
  736. if (bSize) {
  737. LONGLONG fileSize;
  738. ULONG fileSizeKb;
  739. WsbAffirmHr(pResource->GetManageableItemLogicalSize(&fileSize));
  740. fileSizeKb = (ULONG)(fileSize / 1024); // Show KBytes
  741. WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_MIN_SIZE));
  742. WsbAffirmHr(param2.LoadFromRsc(g_hInstance, IDS_KB_SUFFIX));
  743. swprintf(longData, OLESTR("%lu"), fileSizeKb);
  744. WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY2, (WCHAR *)param, longData, (WCHAR *)param2, NULL);
  745. }
  746. // Not accessed
  747. if (bAccess) {
  748. FILETIME accessTime;
  749. ULONG accessTimeDays;
  750. BOOL dummy;
  751. WsbAffirmHr(pResource->GetManageableItemAccessTime(&dummy, &accessTime));
  752. accessTimeDays = (ULONG)(WsbFTtoLL(accessTime) / WSB_FT_TICKS_PER_DAY);
  753. WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_NOT_ACCESSED));
  754. WsbAffirmHr(param2.LoadFromRsc(g_hInstance, IDS_DAYS_SUFFIX));
  755. swprintf(longData, OLESTR("%lu"), accessTimeDays);
  756. WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY2, (WCHAR *)param, longData, (WCHAR *)param2, NULL);
  757. }
  758. //Statistics
  759. if (bStatistics) {
  760. LONGLONG total;
  761. LONGLONG free;
  762. LONGLONG premigrated;
  763. LONGLONG truncated;
  764. LONGLONG hsmData;
  765. LONGLONG notHsmData;
  766. WCHAR pctData[10];
  767. int freePct;
  768. int premigratedPct;
  769. int notHsmDataPct;
  770. // Get and calculate sizes
  771. WsbAffirmHr(pResource->GetSizes(&total, &free, &premigrated, &truncated));
  772. hsmData = premigrated + truncated;
  773. notHsmData = max((total - free - premigrated ), 0);
  774. freePct = (int)((free * 100) / total);
  775. premigratedPct = (int)((premigrated * 100) / total);
  776. notHsmDataPct = (int)((notHsmData * 100) / total);
  777. // Print statistics
  778. WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_VOL_CAPACITY));
  779. WsbAffirmHr(ShortSizeFormat64(total, longData));
  780. WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY, (WCHAR *)param, longData, NULL);
  781. WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_VOL_FREE_SPACE));
  782. WsbAffirmHr(ShortSizeFormat64(free, longData));
  783. swprintf(pctData, OLESTR(" (%d%%%%)"), freePct);
  784. WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY2, (WCHAR *)param, longData, pctData, NULL);
  785. WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_VOL_NOT_RSS_DATA));
  786. WsbAffirmHr(ShortSizeFormat64(notHsmData, longData));
  787. swprintf(pctData, OLESTR(" (%d%%%%)"), notHsmDataPct);
  788. WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY2, (WCHAR *)param, longData, pctData, NULL);
  789. WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_VOL_CACHED_DATA));
  790. WsbAffirmHr(ShortSizeFormat64(premigrated, longData));
  791. swprintf(pctData, OLESTR(" (%d%%%%)"), premigratedPct);
  792. WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY2, (WCHAR *)param, longData, pctData, NULL);
  793. WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_VOL_RSS_DATA));
  794. WsbAffirmHr(ShortSizeFormat64(hsmData, longData));
  795. WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY, (WCHAR *)param, longData, NULL);
  796. }
  797. // Rules
  798. if (bRules) {
  799. CComPtr<IWsbCollection> pDefaultRules;
  800. CComPtr<IWsbIndexedCollection> pRulesIndexedCollection;
  801. CComPtr<IHsmRule> pHsmRule;
  802. CWsbStringPtr rulePath;
  803. CWsbStringPtr ruleFileSpec;
  804. BOOL include;
  805. CWsbStringPtr includeStr;
  806. BOOL recursive;
  807. CWsbStringPtr recursiveStr;
  808. ULONG count;
  809. WsbTraceAndPrint(CLI_MESSAGE_RULES_LIST, NULL);
  810. // Get the rules collection
  811. WsbAffirmHr(pResource->GetDefaultRules(&pDefaultRules));
  812. WsbAffirmHr(pDefaultRules->QueryInterface(IID_IWsbIndexedCollection, (void **)&pRulesIndexedCollection));
  813. // Itterate through the indexed collection
  814. WsbAffirmHr(pRulesIndexedCollection->GetEntries(&count));
  815. for (int i = 0; i < (int) count; i++) {
  816. // Get rule and rule parameters
  817. WsbAffirmHr(pRulesIndexedCollection->At(i, IID_IHsmRule, (void**) &pHsmRule));
  818. WsbAffirmHr(pHsmRule->GetPath(&rulePath, 0));
  819. WsbAffirmHr(pHsmRule->GetName(&ruleFileSpec, 0));
  820. include = (S_OK == pHsmRule->IsInclude()) ? TRUE : FALSE;
  821. recursive = (S_OK == pHsmRule->IsUsedInSubDirs()) ? TRUE : FALSE;
  822. // Print rule
  823. if (include) {
  824. WsbAffirmHr(includeStr.LoadFromRsc(g_hInstance, IDS_INCLUDE_RULE));
  825. } else {
  826. WsbAffirmHr(includeStr.LoadFromRsc(g_hInstance, IDS_EXCLUDE_RULE));
  827. }
  828. if (recursive) {
  829. WsbAffirmHr(recursiveStr.LoadFromRsc(g_hInstance, IDS_RECURSIVE_RULE));
  830. } else {
  831. WsbAffirmHr(recursiveStr.LoadFromRsc(g_hInstance, IDS_NON_RECURSIVE_RULE));
  832. }
  833. WsbTraceAndPrint(CLI_MESSAGE_RULE_SPEC, (WCHAR *)rulePath, (WCHAR *)ruleFileSpec,
  834. (WCHAR *)includeStr, (WCHAR *)recursiveStr, NULL);
  835. // Free resources before next iteration
  836. pHsmRule = 0;
  837. rulePath.Free();
  838. ruleFileSpec.Free();
  839. includeStr.Free();
  840. recursiveStr.Free();
  841. }
  842. }
  843. } WsbCatch(hr);
  844. WsbTraceOut(OLESTR("ShowResourceParams"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  845. return (hr);
  846. }
  847. HRESULT FindAndDeleteRule(IN IFsaResource *pResource, IN LPWSTR pRulePath, IN LPWSTR pRuleFileSpec, IN BOOL bDelete)
  848. /*++
  849. Routine Description:
  850. Deletes a rule that match the given path & file specification from a specific volume
  851. If more than one exists, the first one found is deleted
  852. Arguments:
  853. bDelete - A flag of whether to delete or just find the rule
  854. pResourse - A resource object to delete rule from
  855. ... (see above)
  856. Return Value:
  857. S_OK - If the rule is found and deleted (deleted only if bDelete is TRUE)
  858. WSB_E_NOTFOUND - If the rule could not be found
  859. --*/
  860. {
  861. HRESULT hr = S_OK;
  862. WsbTraceIn(OLESTR("DeleteRule"), OLESTR(""));
  863. try {
  864. CComPtr<IWsbCollection> pDefaultRules;
  865. CComPtr<IWsbIndexedCollection> pRulesIndexedCollection;
  866. CComPtr<IHsmRule> pHsmRule;
  867. ULONG count;
  868. SHORT dummy;
  869. // Get the default rules collection
  870. WsbAffirmHr(pResource->GetDefaultRules(&pDefaultRules));
  871. WsbAffirmHr(pDefaultRules->QueryInterface(IID_IWsbIndexedCollection, (void **) &pRulesIndexedCollection));
  872. // Itterate through the indexed collection
  873. hr = WSB_E_NOTFOUND;
  874. WsbAffirmHr(pRulesIndexedCollection->GetEntries(&count));
  875. for (int i = 0; i < (int)count; i++) {
  876. WsbAffirmHr(pRulesIndexedCollection->At(i, IID_IHsmRule, (void**)&pHsmRule));
  877. if (pHsmRule->CompareToPathAndName(pRulePath, pRuleFileSpec, &dummy) == S_OK) {
  878. if (bDelete) {
  879. pHsmRule = 0;
  880. WsbAffirmHr(pRulesIndexedCollection->RemoveAt(i, IID_IHsmRule, (void**) &pHsmRule));
  881. }
  882. hr = S_OK;
  883. break;
  884. }
  885. // Release before continuing loop
  886. pHsmRule = 0;
  887. }
  888. // If we got to the end of the for loop without a match, hr stays WSB_E_NOTFOUND
  889. } WsbCatch(hr);
  890. WsbTraceOut(OLESTR("DeleteRule"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  891. return (hr);
  892. }
  893. HRESULT QuickUnmanage(IN IFsaResource *pResource)
  894. /*++
  895. Routine Description:
  896. Remove a volume from the set of managed volumes
  897. Arguments:
  898. pResourse - A resource object to unmanage
  899. Return Value:
  900. S_OK - If the volume is removed from the list of managed volumes successfully
  901. --*/
  902. {
  903. HRESULT hr = S_OK;
  904. WsbTraceIn(OLESTR("QuickUnmanage"), OLESTR(""));
  905. try {
  906. CComPtr<IHsmServer> pHsm;
  907. CComPtr<IWsbCreateLocalObject> pCreateObj;
  908. CComPtr<IHsmManagedResource> pManagedResource;
  909. CComPtr<IWsbIndexedCollection> pMRCollection;
  910. // Get Hsm (Engine) server
  911. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm));
  912. WsbAffirmHr(pHsm->QueryInterface(IID_IWsbCreateLocalObject, (void**) &pCreateObj));
  913. // Create an object to remove
  914. WsbAffirmHr(pCreateObj->CreateInstance(CLSID_CHsmManagedResource, IID_IHsmManagedResource, (void**) &pManagedResource));
  915. WsbAffirmHr(pManagedResource->InitFromFsaResource(pResource));
  916. // Remove from the collection
  917. WsbAffirmHr(pHsm->GetManagedResources(&pMRCollection));
  918. WsbAffirmHr(pMRCollection->RemoveAndRelease(pManagedResource));
  919. // TEMPORARY: Should we call now SaveServersPersistData to flush changes into
  920. // servers persistency files ?! What about Manage, Set, ... ?
  921. } WsbCatch(hr);
  922. WsbTraceOut(OLESTR("QuickUnmanage"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  923. return (hr);
  924. }
  925. HRESULT StartJob(IN IFsaResource *pResource, IN HSM_JOB_TYPE Job, IN BOOL bWait)
  926. /*++
  927. Routine Description:
  928. Start a job of the specified type
  929. Arguments:
  930. pResourse - A resource object to start a job on
  931. Job - The job type
  932. bWait - If TRUE, wait until the job is done
  933. If FALSE, return immediately after starting the job
  934. Return Value:
  935. S_OK - If the job is started successfully
  936. --*/
  937. {
  938. HRESULT hr = S_OK;
  939. WsbTraceIn(OLESTR("StartJob"), OLESTR(""));
  940. try {
  941. CComPtr<IHsmServer> pHsm;
  942. CComPtr<IHsmJob> pJob;
  943. CWsbStringPtr jobName;
  944. HSM_JOB_DEF_TYPE jobType;
  945. // Set job type
  946. switch (Job) {
  947. case CopyFiles:
  948. jobType = HSM_JOB_DEF_TYPE_MANAGE;
  949. break;
  950. case CreateFreeSpace:
  951. jobType = HSM_JOB_DEF_TYPE_TRUNCATE;
  952. break;
  953. case Validate:
  954. jobType = HSM_JOB_DEF_TYPE_VALIDATE;
  955. break;
  956. case Unmanage:
  957. jobType = HSM_JOB_DEF_TYPE_FULL_UNMANAGE;
  958. break;
  959. default:
  960. WsbThrow(E_INVALIDARG);
  961. }
  962. // Create job name
  963. // TEMPORARY: Should the job name and job object match those that are created by the GUI ?!
  964. // If so, RsCreateJobName (rsadutil.cpp) + all the resource strings that it uses,
  965. // should be moved from HsmAdmin DLL to RsCommon DLL
  966. WsbAffirmHr(CreateJobName(Job, pResource, &jobName));
  967. // If job exists - use it, otherwize, craete and add an appropriate job object
  968. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm));
  969. hr = pHsm->FindJobByName(jobName, &pJob);
  970. if (S_OK == hr) {
  971. // Job already exists
  972. } else if (WSB_E_NOTFOUND == hr) {
  973. // No such job yet
  974. CComPtr<IWsbCreateLocalObject> pCreateObj;
  975. CComPtr<IWsbIndexedCollection> pJobs;
  976. CComPtr<IWsbIndexedCollection> pCollection;
  977. CComPtr<IHsmStoragePool> pStoragePool;
  978. GUID poolId;
  979. ULONG count;
  980. hr = S_OK;
  981. pJob = 0;
  982. // Create and add the job
  983. WsbAffirmHr(pHsm->QueryInterface(IID_IWsbCreateLocalObject, (void**) &pCreateObj));
  984. WsbAffirmHr(pCreateObj->CreateInstance(CLSID_CHsmJob, IID_IHsmJob, (void**) &pJob));
  985. WsbAffirmHr(pHsm->GetStoragePools(&pCollection));
  986. WsbAffirmHr(pCollection->GetEntries(&count));
  987. WsbAffirm(1 == count, E_FAIL);
  988. WsbAffirmHr(pCollection->At(0, IID_IHsmStoragePool, (void **)&pStoragePool));
  989. WsbAffirmHr(pStoragePool->GetId(&poolId));
  990. WsbAffirmHr(pJob->InitAs(jobName, NULL, jobType, poolId, pHsm, TRUE, pResource));
  991. WsbAffirmHr(pHsm->GetJobs(&pJobs));
  992. WsbAffirmHr(pJobs->Add(pJob));
  993. } else {
  994. // Other error - abort
  995. WsbThrow(hr);
  996. }
  997. // Start the job
  998. WsbAffirmHr(pJob->Start());
  999. // Wait if required
  1000. if (bWait) {
  1001. WsbAffirmHr(pJob->WaitUntilDone());
  1002. }
  1003. } WsbCatch(hr);
  1004. WsbTraceOut(OLESTR("StartJob"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1005. return (hr);
  1006. }
  1007. HRESULT CancelJob(IN IFsaResource *pResource, IN HSM_JOB_TYPE Job)
  1008. /*++
  1009. Routine Description:
  1010. Cancel a job on the volume
  1011. Arguments:
  1012. pResourse - A resource object to cancel a job for
  1013. Job - The job type
  1014. Return Value:
  1015. S_OK - If the job is canceled
  1016. Notes:
  1017. 1) The function just issue the cancellation, it does not wait for it to finish
  1018. 2) If the job is not found or not started, it is not considered as an error
  1019. --*/
  1020. {
  1021. HRESULT hr = S_OK;
  1022. WsbTraceIn(OLESTR("CancelJob"), OLESTR(""));
  1023. try {
  1024. CComPtr<IHsmServer> pHsm;
  1025. CComPtr<IHsmJob> pJob;
  1026. CWsbStringPtr jobName;
  1027. HSM_JOB_DEF_TYPE jobType;
  1028. // Set job type
  1029. switch (Job) {
  1030. case CopyFiles:
  1031. jobType = HSM_JOB_DEF_TYPE_MANAGE;
  1032. break;
  1033. case CreateFreeSpace:
  1034. jobType = HSM_JOB_DEF_TYPE_TRUNCATE;
  1035. break;
  1036. case Validate:
  1037. jobType = HSM_JOB_DEF_TYPE_VALIDATE;
  1038. break;
  1039. case Unmanage:
  1040. jobType = HSM_JOB_DEF_TYPE_FULL_UNMANAGE;
  1041. break;
  1042. default:
  1043. WsbThrow(E_INVALIDARG);
  1044. }
  1045. // Create job name
  1046. WsbAffirmHr(CreateJobName(Job, pResource, &jobName));
  1047. // If job exists, try to cancel it
  1048. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm));
  1049. hr = pHsm->FindJobByName(jobName, &pJob);
  1050. if (S_OK == hr) {
  1051. // Cancel (we don't care if it's actually running or not)
  1052. WsbAffirmHr(pJob->Cancel(HSM_JOB_PHASE_ALL));
  1053. } else if (WSB_E_NOTFOUND == hr) {
  1054. // No such job, for sure it is not running...
  1055. hr = S_OK;
  1056. } else {
  1057. // Other error - abort
  1058. WsbThrow(hr);
  1059. }
  1060. } WsbCatch(hr);
  1061. WsbTraceOut(OLESTR("CancelJob"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1062. return (hr);
  1063. }
  1064. HRESULT
  1065. CreateJobName(IN HSM_JOB_TYPE Job, IN IFsaResource *pResource, OUT WCHAR **ppJobName)
  1066. /*++
  1067. Routine Description:
  1068. Create a job name based on its type and the volume properties
  1069. Arguments:
  1070. Job - The job type
  1071. pResource - Fsa resource that the job is created for
  1072. ppJobName - The job name
  1073. Return Value:
  1074. S_OK - The job name is created successfully
  1075. Notes:
  1076. This utility uses similar algorithm to RsCreateJobName (rsadutil.cpp).
  1077. Howevere, since RsCreateJobName uses internal HsmAdmin resource strings, the final
  1078. name might be different than the GUI name, especially in a localaized system.
  1079. Therefore, I use here different strings for CLI jobs to ensure consistent behavior.
  1080. --*/
  1081. {
  1082. HRESULT hr = S_OK;
  1083. WsbTraceIn(OLESTR("CreateJobName"), OLESTR(""));
  1084. try {
  1085. CWsbStringPtr jobPrefix;
  1086. CWsbStringPtr jobTypeString;
  1087. CWsbStringPtr volumeName;
  1088. CWsbStringPtr volumeString;
  1089. // Type string
  1090. switch (Job) {
  1091. case CopyFiles:
  1092. WsbAffirmHr(jobTypeString.LoadFromRsc(g_hInstance, IDS_JOB_MANAGE));
  1093. break;
  1094. case CreateFreeSpace:
  1095. WsbAffirmHr(jobTypeString.LoadFromRsc(g_hInstance, IDS_JOB_TRUNCATE));
  1096. break;
  1097. case Validate:
  1098. WsbAffirmHr(jobTypeString.LoadFromRsc(g_hInstance, IDS_JOB_VALIDATE));
  1099. break;
  1100. case Unmanage:
  1101. WsbAffirmHr(jobTypeString.LoadFromRsc(g_hInstance, IDS_JOB_FULL_UNMANAGE));
  1102. break;
  1103. default:
  1104. WsbThrow(E_INVALIDARG);
  1105. }
  1106. WsbAffirmHr(pResource->GetUserFriendlyName(&volumeName, 0));
  1107. // For now, ignore the user-name if it's not a drive letter
  1108. size_t nameLen = wcslen(volumeName);
  1109. if ((nameLen != 3) || (volumeName[1] != L':')) {
  1110. volumeName = L"";
  1111. }
  1112. if (volumeName.IsEqual(L"")) {
  1113. // No drive letter - use the volume name and serial number instead
  1114. ULONG serial;
  1115. CWsbStringPtr name;
  1116. WsbAffirmHr(pResource->GetName(&name, 0 ));
  1117. WsbAffirmHr(pResource->GetSerial(&serial));
  1118. if (name == L"" ) {
  1119. // No name, no drive letter - just have serial number
  1120. WsbAffirmHr(volumeString.Alloc(40));
  1121. swprintf(volumeString, L"%8.8lx", serial);
  1122. } else {
  1123. // Use name and serial
  1124. WsbAffirmHr(volumeString.Alloc(40 + wcslen(name)));
  1125. swprintf(volumeString, L"%ls-%8.8lx", (WCHAR *)name, serial);
  1126. }
  1127. } else {
  1128. // Use drive letter
  1129. WsbAffirmHr(volumeString.Alloc(1));
  1130. volumeString[0] = volumeName[0];
  1131. volumeString[1] = L'\0';
  1132. }
  1133. // Create job name
  1134. WsbAffirmHr(jobPrefix.LoadFromRsc(g_hInstance, IDS_JOB_NAME_PREFIX));
  1135. int allocLen = wcslen(jobPrefix) + wcslen(jobTypeString) + wcslen(volumeString) + 40;
  1136. WCHAR* tmpString = (WCHAR*)WsbRealloc(*ppJobName, allocLen * sizeof(WCHAR));
  1137. WsbAffirm(0 != tmpString, E_OUTOFMEMORY);
  1138. *ppJobName = tmpString;
  1139. swprintf(*ppJobName, jobPrefix, (WCHAR *)jobTypeString, (WCHAR *)volumeString);
  1140. } WsbCatch(hr);
  1141. WsbTraceOut(OLESTR("CreateJobName"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1142. return (hr);
  1143. }
  1144. //
  1145. // Enumerator class methods
  1146. //
  1147. CVolumeEnum::CVolumeEnum(IN LPWSTR *pVolumes, IN DWORD dwNumberOfVolumes, IN BOOL bSkipUnavailable)
  1148. /*++
  1149. Routine Description:
  1150. Constructor
  1151. Arguments:
  1152. pVolumes - Volumes to enumerate
  1153. dwNumberOfVolumes - Number of volumes
  1154. Return Value:
  1155. None
  1156. Notes:
  1157. There are two kinds of enumerations:
  1158. 1) If * is specified, the base for the enumeration is the FSA resource collection
  1159. In that case, there could be no error in the input volumes themselves
  1160. 2) If a list of volumes is given, the base for the enumeration is this list. This is
  1161. less efficient that using the FSA collection, but it keeps the order of volumes
  1162. according to the input list. If a volume from the list is not valid, the invalid flag is set.
  1163. --*/
  1164. {
  1165. HRESULT hr = S_OK;
  1166. WsbTraceIn(OLESTR("CVolumeEnum::CVolumeEnum"), OLESTR(""));
  1167. try {
  1168. m_pVolumes = pVolumes;
  1169. m_dwNumberOfVolumes = dwNumberOfVolumes;
  1170. m_nCurrent = CVOL_INVALID_INDEX;
  1171. m_bInvalidVol = FALSE;
  1172. m_bAllVols = FALSE;
  1173. m_bSkipUnavailable = bSkipUnavailable;
  1174. // Check mode of enumeration
  1175. WsbAssert(m_dwNumberOfVolumes > 0, E_INVALIDARG);
  1176. if ((1 == m_dwNumberOfVolumes) && (0 == wcscmp(m_pVolumes[0], CLI_ALL_STR))) {
  1177. // * enumeration
  1178. m_bAllVols = TRUE;
  1179. }
  1180. } WsbCatch(hr);
  1181. WsbTraceOut(OLESTR("CVolumeEnum::CVolumeEnum"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1182. }
  1183. HRESULT CVolumeEnum::First(OUT IFsaResource **ppResource)
  1184. /*++
  1185. Routine Description:
  1186. Gets first volume
  1187. Arguments:
  1188. ppResourse - First resource to get
  1189. Return Value:
  1190. S_OK - If first volume is retrieved
  1191. WSB_E_NOTFOUND - If no more volumes to enumerate
  1192. E_INVALIDARG - If volume given by the user is not found
  1193. (Only on a non * enumeration, m_bInvalidVol is set)
  1194. --*/
  1195. {
  1196. HRESULT hr = S_OK;
  1197. WsbTraceIn(OLESTR("CVolumeEnum::First"), OLESTR(""));
  1198. try {
  1199. // Get FSA resources collection (only once during the object life time)
  1200. if (!m_pEnumResources) {
  1201. CComPtr<IFsaServer> pFsa;
  1202. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_FSA, g_nullGuid, IID_IFsaServer, (void**)&pFsa));
  1203. WsbAffirmHr(pFsa->EnumResources(&m_pEnumResources));
  1204. }
  1205. if (m_bAllVols) {
  1206. if (m_bSkipUnavailable) {
  1207. // Get first volume, skip unavailable resources
  1208. CComPtr<IFsaResource> pFindResource;
  1209. hr = m_pEnumResources->First(IID_IFsaResource, (void**)&pFindResource);
  1210. while (S_OK == hr) {
  1211. if (S_OK == pFindResource->IsAvailable()) {
  1212. // Found one
  1213. *ppResource = pFindResource;
  1214. (*ppResource)->AddRef();
  1215. break;
  1216. } else {
  1217. // Skip it
  1218. pFindResource = 0;
  1219. }
  1220. hr = m_pEnumResources->Next(IID_IFsaResource, (void**)&pFindResource);
  1221. }
  1222. WsbAffirmHr(hr);
  1223. } else {
  1224. // Get first volume
  1225. hr = m_pEnumResources->First(IID_IFsaResource, (void**)ppResource);
  1226. WsbAffirmHr(hr);
  1227. }
  1228. } else {
  1229. CWsbStringPtr volName;
  1230. CWsbStringPtr findName;
  1231. CComPtr<IFsaResource> pFindResource;
  1232. // Enumerate user collection and try to find it in FSA
  1233. m_nCurrent = 0;
  1234. if (m_nCurrent >= (int)m_dwNumberOfVolumes) {
  1235. WsbThrow(WSB_E_NOTFOUND);
  1236. }
  1237. // Validate current name and add trailing backslash if missing
  1238. volName = m_pVolumes[m_nCurrent];
  1239. WsbAssert (NULL != (WCHAR *)volName, E_UNEXPECTED);
  1240. int len = wcslen(volName);
  1241. WsbAssert (0 != len, E_UNEXPECTED);
  1242. if (volName[len-1] != L'\\') {
  1243. volName.Append(OLESTR("\\"));
  1244. }
  1245. // Find it
  1246. hr = m_pEnumResources->First(IID_IFsaResource, (void**)&pFindResource);
  1247. while(S_OK == hr) {
  1248. WsbAffirmHr(pFindResource->GetUserFriendlyName(&findName, 0));
  1249. if (_wcsicmp(volName, findName) == 0) {
  1250. // Fount it !!
  1251. *ppResource = pFindResource;
  1252. (*ppResource)->AddRef();
  1253. break;
  1254. }
  1255. findName.Free();
  1256. pFindResource = 0;
  1257. hr = m_pEnumResources->Next(IID_IFsaResource, (void**)&pFindResource);
  1258. }
  1259. if (WSB_E_NOTFOUND == hr) {
  1260. // Volume given by user not found
  1261. m_bInvalidVol = TRUE;
  1262. hr = E_INVALIDARG;
  1263. }
  1264. WsbAffirmHr(hr);
  1265. }
  1266. } WsbCatch(hr);
  1267. WsbTraceOut(OLESTR("CVolumeEnum::First"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1268. return hr;
  1269. }
  1270. HRESULT CVolumeEnum::Next(OUT IFsaResource **ppResource)
  1271. /*++
  1272. Routine Description:
  1273. Gets next volume
  1274. Arguments:
  1275. ppResourse - Next resource to get
  1276. Return Value:
  1277. S_OK - If next volume is retrieved
  1278. WSB_E_NOTFOUND - If no more volumes to enumerate
  1279. E_INVALIDARG - If volume given by the user is not found
  1280. (Only on a non * enumeration, m_bInvalidVol is set)
  1281. --*/
  1282. {
  1283. HRESULT hr = S_OK;
  1284. WsbTraceIn(OLESTR("CVolumeEnum::Next"), OLESTR(""));
  1285. try {
  1286. if (m_bAllVols) {
  1287. if (m_bSkipUnavailable) {
  1288. // Get next volume, skip unavailable resources
  1289. CComPtr<IFsaResource> pFindResource;
  1290. hr = m_pEnumResources->Next(IID_IFsaResource, (void**)&pFindResource);
  1291. while (S_OK == hr) {
  1292. if (S_OK == pFindResource->IsAvailable()) {
  1293. // Found one
  1294. *ppResource = pFindResource;
  1295. (*ppResource)->AddRef();
  1296. break;
  1297. } else {
  1298. // Skip it
  1299. pFindResource = 0;
  1300. }
  1301. hr = m_pEnumResources->Next(IID_IFsaResource, (void**)&pFindResource);
  1302. }
  1303. WsbAffirmHr(hr);
  1304. } else {
  1305. // Get next volume
  1306. hr = m_pEnumResources->Next(IID_IFsaResource, (void**)ppResource);
  1307. WsbAffirmHr(hr);
  1308. }
  1309. } else {
  1310. CWsbStringPtr volName;
  1311. CWsbStringPtr findName;
  1312. CComPtr<IFsaResource> pFindResource;
  1313. // Enumerate user collection and try to find it in FSA
  1314. m_nCurrent++;
  1315. if (m_nCurrent >= (int)m_dwNumberOfVolumes) {
  1316. WsbThrow(WSB_E_NOTFOUND);
  1317. }
  1318. // Validate current name and add trailing backslash if missing
  1319. volName = m_pVolumes[m_nCurrent];
  1320. WsbAssert (NULL != (WCHAR *)volName, E_UNEXPECTED);
  1321. int len = wcslen(volName);
  1322. WsbAssert (0 != len, E_UNEXPECTED);
  1323. if (volName[len-1] != L'\\') {
  1324. volName.Append(OLESTR("\\"));
  1325. }
  1326. // Find it
  1327. hr = m_pEnumResources->First(IID_IFsaResource, (void**)&pFindResource);
  1328. while(S_OK == hr) {
  1329. WsbAffirmHr(pFindResource->GetUserFriendlyName(&findName, 0));
  1330. if (_wcsicmp(volName, findName) == 0) {
  1331. // Fount it !!
  1332. *ppResource = pFindResource;
  1333. (*ppResource)->AddRef();
  1334. break;
  1335. }
  1336. findName.Free();
  1337. pFindResource = 0;
  1338. hr = m_pEnumResources->Next( IID_IFsaResource, (void**)&pFindResource );
  1339. }
  1340. if (WSB_E_NOTFOUND == hr) {
  1341. // Volume given by user not found
  1342. m_bInvalidVol = TRUE;
  1343. hr = E_INVALIDARG;
  1344. }
  1345. WsbAffirmHr(hr);
  1346. }
  1347. } WsbCatch(hr);
  1348. WsbTraceOut(OLESTR("CVolumeEnum::Next"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1349. return hr;
  1350. }