Source code of Windows XP (NT5)
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.

1064 lines
33 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. climedia.cpp
  5. Abstract:
  6. Implements CLI MEDIA 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 "engine.h"
  14. static GUID g_nullGuid = GUID_NULL;
  15. // Internal utilities and classes for MEDIA interface
  16. #define CMEDIA_INVALID_INDEX (-1)
  17. HRESULT IsMediaValid(IN IMediaInfo *pMediaInfo);
  18. HRESULT ShowMediaParams(IN IMediaInfo *pMediaInfo, BOOL bName, IN BOOL bStatus, IN BOOL bCapacity,
  19. IN BOOL bFreeSpace, IN BOOL Version, IN BOOL Copies);
  20. HRESULT IsCopySetValid (IN IHsmServer *pHsm, IN DWORD dwCopySetNumber);
  21. class CMediaEnum
  22. {
  23. // Constructors, destructors
  24. public:
  25. CMediaEnum(IN LPWSTR *pMediaNames, IN DWORD dwNumberOfMedia);
  26. ~CMediaEnum();
  27. // Public methods
  28. public:
  29. HRESULT First(OUT IMediaInfo **ppMediaInfo);
  30. HRESULT Next(OUT IMediaInfo **ppMediaInfo);
  31. HRESULT ErrorMedia(OUT int *pIndex);
  32. // Private data
  33. protected:
  34. LPWSTR *m_pMediaNames;
  35. DWORD m_dwNumberOfMedia;
  36. // If * enumeration or not
  37. BOOL m_bAllMedias;
  38. // Data for the enumeration
  39. CComPtr<IWsbDb> m_pDb;
  40. CComPtr<IWsbDbSession> m_pDbSession;
  41. CComPtr<IMediaInfo> m_pMediaInfo;
  42. // Used only when m_bAllMedias == FALSE
  43. int m_nCurrent;
  44. BOOL m_bInvalidMedia;
  45. };
  46. inline
  47. HRESULT CMediaEnum::ErrorMedia(OUT int *pIndex)
  48. {
  49. HRESULT hr = S_FALSE;
  50. if (m_bInvalidMedia) {
  51. // There was an error with last media
  52. hr = S_OK;
  53. }
  54. *pIndex = m_nCurrent;
  55. return(hr);
  56. }
  57. //
  58. // MEDIA inetrafce implementors
  59. //
  60. HRESULT
  61. MediaSynchronize(
  62. IN DWORD CopySetNumber,
  63. IN BOOL Synchronous
  64. )
  65. /*++
  66. Routine Description:
  67. Creates/updates the specified media copy set
  68. Arguments:
  69. CopySetNumber - The copy set number to create/synchronize
  70. Synchronous - If TRUE, the function waits for the operation
  71. to complete before returning. If not, it returns
  72. immediately after starting the job
  73. Return Value:
  74. S_OK - If the copy set was created/updated successfully
  75. --*/
  76. {
  77. HRESULT hr = S_OK;
  78. WsbTraceIn(OLESTR("MediaSynchronize"), OLESTR(""));
  79. try {
  80. CComPtr<IHsmServer> pHsm;
  81. // Get HSM server
  82. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm));
  83. // Verify that input parameters are valid
  84. WsbAffirmHr(ValidateLimitsArg(CopySetNumber, IDS_MEDIA_COPY_SET, HSMADMIN_MIN_COPY_SETS + 1, HSMADMIN_MAX_COPY_SETS));
  85. hr = IsCopySetValid(pHsm, CopySetNumber);
  86. if (S_FALSE == hr) {
  87. WsbTraceAndPrint(CLI_MESSAGE_IVALID_COPY_SET, NULL);
  88. WsbThrow(E_INVALIDARG);
  89. } else {
  90. WsbAffirmHr(hr);
  91. }
  92. // Synchronize copy set
  93. if (Synchronous) {
  94. // Call directly Engine method
  95. WsbAffirmHr(pHsm->SynchronizeMedia(g_nullGuid, (USHORT)CopySetNumber));
  96. } else {
  97. // Use RsLaunch
  98. // Note: Another possibility here would be using the CLI (rss.exex) itself
  99. // with synchronous flag on, but it's better to depend here on internal HSM
  100. // interface (RsLaunch) and not an external one (RSS) that only the parser knows
  101. CWsbStringPtr cmdLine;
  102. WCHAR cmdParams[40];
  103. STARTUPINFO startupInfo;
  104. PROCESS_INFORMATION exeInfo;
  105. // Startup info
  106. memset(&startupInfo, 0, sizeof(startupInfo));
  107. startupInfo.cb = sizeof( startupInfo );
  108. startupInfo.wShowWindow = SW_HIDE;
  109. startupInfo.dwFlags = STARTF_USESHOWWINDOW;
  110. // Create command line
  111. swprintf(cmdParams, OLESTR(" sync %lu"), CopySetNumber);
  112. WsbAffirmHr(cmdLine.Alloc(MAX_PATH + wcslen(WSB_FACILITY_LAUNCH_NAME) + wcslen(cmdParams) + 10));
  113. WsbAffirmStatus(GetSystemDirectory(cmdLine, MAX_PATH));
  114. WsbAffirmHr(cmdLine.Append(OLESTR("\\")));
  115. WsbAffirmHr(cmdLine.Append(WSB_FACILITY_LAUNCH_NAME));
  116. WsbAffirmHr(cmdLine.Append(cmdParams));
  117. // Run the RsLaunch process
  118. WsbAffirmStatus(CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, NULL, NULL, NULL,
  119. &startupInfo, &exeInfo));
  120. // Cleanup
  121. CloseHandle(exeInfo.hProcess);
  122. CloseHandle(exeInfo.hThread);
  123. }
  124. } WsbCatch(hr);
  125. WsbTraceOut(OLESTR("MediaSynchronize"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  126. return hr;
  127. }
  128. HRESULT
  129. MediaRecreateMaster(
  130. IN LPWSTR MediaName,
  131. IN DWORD CopySetNumber,
  132. IN BOOL Synchronous
  133. )
  134. /*++
  135. Routine Description:
  136. Recreate a master for the given meida out of the specified copy
  137. Arguments:
  138. MediaName - Master media name of media to recreate
  139. CopySetNumber - The copy number to use for recreating the master
  140. Synchronous - If TRUE, the function waits for the operation
  141. to complete before returning. If not, it returns
  142. immediately after starting the job
  143. Return Value:
  144. S_OK - If the master is recreated successfully from the specified copy
  145. --*/
  146. {
  147. HRESULT hr = S_OK;
  148. WsbTraceIn(OLESTR("MediaRecreateMaster"), OLESTR(""));
  149. try {
  150. CComPtr<IHsmServer> pHsm;
  151. GUID mediaId;
  152. // Get HSM server
  153. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm));
  154. // Verify that input parameters are valid
  155. if ((NULL == MediaName) || (NULL == *MediaName)) {
  156. WsbTraceAndPrint(CLI_MESSAGE_NO_MEDIAS, NULL);
  157. WsbThrow(E_INVALIDARG);
  158. }
  159. WsbAffirmHr(ValidateLimitsArg(CopySetNumber, IDS_MEDIA_COPY_SET, HSMADMIN_MIN_COPY_SETS + 1, HSMADMIN_MAX_COPY_SETS));
  160. hr = IsCopySetValid(pHsm, CopySetNumber);
  161. if (S_FALSE == hr) {
  162. WsbTraceAndPrint(CLI_MESSAGE_IVALID_COPY_SET, NULL);
  163. WsbThrow(E_INVALIDARG);
  164. } else {
  165. WsbAffirmHr(hr);
  166. }
  167. // Find the media id according to the given display name
  168. hr = pHsm->FindMediaIdByDescription(MediaName, &mediaId);
  169. if ((WSB_E_NOTFOUND == hr) || (GUID_NULL == mediaId)) {
  170. // Given media name is invalid
  171. WsbTraceAndPrint(CLI_MESSAGE_INVALID_MEDIA, MediaName, NULL);
  172. WsbThrow(E_INVALIDARG);
  173. }
  174. WsbAffirmHr(hr);
  175. // Mark media for recreation
  176. WsbAffirmHr(pHsm->MarkMediaForRecreation(mediaId));
  177. if (Synchronous) {
  178. // Recreate the master
  179. WsbAffirmHr(pHsm->RecreateMaster(mediaId, (USHORT)CopySetNumber));
  180. } else {
  181. // Use RsLaunch
  182. // Note: Another possibility here would be using the CLI (rss.exex) itself
  183. // with synchronous flag on, but it's better to depend here on internal HSM
  184. // interface (RsLaunch) and not an external one (RSS) that only the parser knows
  185. CWsbStringPtr cmdLine;
  186. CWsbStringPtr cmdParams;
  187. STARTUPINFO startupInfo;
  188. PROCESS_INFORMATION exeInfo;
  189. CWsbStringPtr stringId(mediaId);
  190. // Startup info
  191. memset(&startupInfo, 0, sizeof(startupInfo));
  192. startupInfo.cb = sizeof( startupInfo );
  193. startupInfo.wShowWindow = SW_HIDE;
  194. startupInfo.dwFlags = STARTF_USESHOWWINDOW;
  195. // Create command line
  196. WsbAffirmHr(cmdParams.Alloc(wcslen(stringId) + 40));
  197. swprintf(cmdParams, OLESTR(" recreate -i %ls -c %lu"), (WCHAR *)stringId, CopySetNumber);
  198. WsbAffirmHr(cmdLine.Alloc(MAX_PATH + wcslen(WSB_FACILITY_LAUNCH_NAME) + wcslen(cmdParams) + 10));
  199. WsbAffirmStatus(GetSystemDirectory(cmdLine, MAX_PATH));
  200. WsbAffirmHr(cmdLine.Append(OLESTR("\\")));
  201. WsbAffirmHr(cmdLine.Append(WSB_FACILITY_LAUNCH_NAME));
  202. WsbAffirmHr(cmdLine.Append(cmdParams));
  203. // Run the RsLaunch process
  204. WsbAffirmStatus(CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, NULL, NULL, NULL,
  205. &startupInfo, &exeInfo));
  206. // Cleanup
  207. CloseHandle(exeInfo.hProcess);
  208. CloseHandle(exeInfo.hThread);
  209. }
  210. } WsbCatch(hr);
  211. WsbTraceOut(OLESTR("MediaRecreateMaster"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  212. return hr;
  213. }
  214. HRESULT
  215. MediaDelete(
  216. IN LPWSTR *MediaNames,
  217. IN DWORD NumberOfMedia,
  218. IN DWORD CopySetNumber
  219. )
  220. /*++
  221. Routine Description:
  222. Deletes the specified copy for all given (master) medias
  223. Arguments:
  224. MediaNames - The list of media to delete a copy for
  225. NumberOfMedia - Number of medias in the set
  226. CopySetNumber - Which copy to delete
  227. Return Value:
  228. S_OK - If the media copy is deleted successfully for all medias
  229. Notes:
  230. 1. MediaNames could point tp a "*" string for enumerating all medias. NumberOfMedia should be 1 then.
  231. 2. If a certain copy doesn't exist for a certain media, we report but not abort.
  232. --*/
  233. {
  234. HRESULT hr = S_OK;
  235. WsbTraceIn(OLESTR("MediaDelete"), OLESTR(""));
  236. try {
  237. CComPtr<IHsmServer> pHsm;
  238. CComPtr<IRmsServer> pRms;
  239. CComPtr<IMediaInfo> pMediaInfo;
  240. GUID mediaSubsystemId;
  241. // Get HSM server
  242. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm));
  243. // Verify that input parameters are valid
  244. if ((NULL == MediaNames) || (0 == NumberOfMedia)) {
  245. WsbTraceAndPrint(CLI_MESSAGE_NO_MEDIAS, NULL);
  246. WsbThrow(E_INVALIDARG);
  247. }
  248. WsbAffirmHr(ValidateLimitsArg(CopySetNumber, IDS_MEDIA_COPY_SET, HSMADMIN_MIN_COPY_SETS + 1, HSMADMIN_MAX_COPY_SETS));
  249. hr = IsCopySetValid(pHsm, CopySetNumber);
  250. if (S_FALSE == hr) {
  251. WsbTraceAndPrint(CLI_MESSAGE_IVALID_COPY_SET, NULL);
  252. WsbThrow(E_INVALIDARG);
  253. } else {
  254. WsbAffirmHr(hr);
  255. }
  256. // Get RMS server
  257. WsbAffirmHr(pHsm->GetHsmMediaMgr(&pRms));
  258. // Initialize an enumerator object
  259. CMediaEnum mediaEnum(MediaNames, NumberOfMedia);
  260. hr = mediaEnum.First(&pMediaInfo);
  261. if (WSB_E_NOTFOUND == hr) {
  262. WsbTraceAndPrint(CLI_MESSAGE_NO_MEDIAS, NULL);
  263. WsbThrow(hr);
  264. } else if (S_OK != hr) {
  265. int index;
  266. if (S_OK == mediaEnum.ErrorMedia(&index)) {
  267. // Problem with a specific input media
  268. WsbTraceAndPrint(CLI_MESSAGE_INVALID_MEDIA, MediaNames[index], NULL);
  269. }
  270. WsbThrow(hr);
  271. }
  272. while(S_OK == hr) {
  273. // Delete a copy
  274. WsbAffirmHr(pMediaInfo->GetCopyMediaSubsystemId((USHORT)CopySetNumber, &mediaSubsystemId));
  275. if (GUID_NULL == mediaSubsystemId) {
  276. // No such copy - report and continue
  277. int index;
  278. mediaEnum.ErrorMedia(&index);
  279. if (CMEDIA_INVALID_INDEX != index) {
  280. // Input from user - report
  281. WCHAR copyStr[6];
  282. swprintf(copyStr, OLESTR("%u"), (USHORT)CopySetNumber);
  283. WsbTraceAndPrint(CLI_MESSAGE_MEDIA_NO_COPY, copyStr, MediaNames[index], NULL);
  284. }
  285. } else {
  286. // We don't expect to get here RMS_E_CARTRIDGE_NOT_FOUND
  287. // because this has already been tested by the enumerator
  288. WsbAffirmHr(pRms->RecycleCartridge(mediaSubsystemId, 0));
  289. // Delete from the table
  290. WsbAffirmHr(pMediaInfo->DeleteCopy((USHORT)CopySetNumber));
  291. WsbAffirmHr(pMediaInfo->Write());
  292. }
  293. pMediaInfo = 0;
  294. hr = mediaEnum.Next(&pMediaInfo);
  295. }
  296. if (WSB_E_NOTFOUND == hr) {
  297. hr = S_OK;
  298. } else {
  299. int index;
  300. if (S_OK == mediaEnum.ErrorMedia(&index)) {
  301. // Problem with a specific input media
  302. WsbTraceAndPrint(CLI_MESSAGE_INVALID_MEDIA, MediaNames[index], NULL);
  303. }
  304. WsbThrow(hr);
  305. }
  306. } WsbCatch(hr);
  307. WsbTraceOut(OLESTR("MediaDelete"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  308. return hr;
  309. }
  310. HRESULT
  311. MediaShow(
  312. IN LPWSTR *MediaNames,
  313. IN DWORD NumberOfMedia,
  314. IN BOOL Name,
  315. IN BOOL Status,
  316. IN BOOL Capacity,
  317. IN BOOL FreeSpace,
  318. IN BOOL Version,
  319. IN BOOL Copies
  320. )
  321. /*++
  322. Routine Description:
  323. Shows (prints to stdout) given media(s) parameters
  324. Arguments:
  325. MediaNames - The list of media to show parameters for
  326. NumberOfMedia - Number of medias in the set
  327. Name - Media display name
  328. Status - HSM status of the media (i.e. - Healthy, Read-Only, etc.)
  329. Capacity, - Media capacity (in GB)
  330. FreeSpace - Amount of free space left on the media (in GB)
  331. Version - Last update date for that media
  332. Copies - Number of existing copies and the status of each copy
  333. Return Value:
  334. S_OK - If all the parameters could be retrieved for all medias
  335. --*/
  336. {
  337. HRESULT hr = S_OK;
  338. WsbTraceIn(OLESTR("MediaShow"), OLESTR(""));
  339. try {
  340. CComPtr<IMediaInfo> pMediaInfo;
  341. // Verify that input parameters are valid
  342. if ((NULL == MediaNames) || (0 == NumberOfMedia)) {
  343. WsbTraceAndPrint(CLI_MESSAGE_NO_MEDIAS, NULL);
  344. WsbThrow(E_INVALIDARG);
  345. }
  346. // Initialize an enumerator object
  347. CMediaEnum mediaEnum(MediaNames, NumberOfMedia);
  348. hr = mediaEnum.First(&pMediaInfo);
  349. if (WSB_E_NOTFOUND == hr) {
  350. WsbTraceAndPrint(CLI_MESSAGE_NO_MEDIAS, NULL);
  351. WsbThrow(hr);
  352. } else if (S_OK != hr) {
  353. int index;
  354. if (S_OK == mediaEnum.ErrorMedia(&index)) {
  355. // Problem with a specific input media
  356. WsbTraceAndPrint(CLI_MESSAGE_INVALID_MEDIA, MediaNames[index], NULL);
  357. }
  358. WsbThrow(hr);
  359. }
  360. while(S_OK == hr) {
  361. // Show parameters
  362. WsbAffirmHr(ShowMediaParams(pMediaInfo, Name, Status, Capacity,
  363. FreeSpace, Version, Copies));
  364. pMediaInfo = 0;
  365. hr = mediaEnum.Next(&pMediaInfo);
  366. }
  367. if (WSB_E_NOTFOUND == hr) {
  368. hr = S_OK;
  369. } else {
  370. int index;
  371. if (S_OK == mediaEnum.ErrorMedia(&index)) {
  372. // Problem with a specific input media
  373. WsbTraceAndPrint(CLI_MESSAGE_INVALID_MEDIA, MediaNames[index], NULL);
  374. }
  375. WsbThrow(hr);
  376. }
  377. } WsbCatch(hr);
  378. WsbTraceOut(OLESTR("MediaShow"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  379. return hr;
  380. }
  381. //
  382. // Enumerator class methods
  383. //
  384. CMediaEnum::CMediaEnum(IN LPWSTR *pMediaNames, IN DWORD dwNumberOfMedia)
  385. /*++
  386. Routine Description:
  387. Constructor
  388. Arguments:
  389. pMediaNames - Medias to enumerate
  390. dwNumberOfMedia - Number of medias
  391. Return Value:
  392. None
  393. Notes:
  394. There are two kinds of enumerations:
  395. 1) If * is specified, the base for the enumeration is the Engine media (DB) table
  396. In that case, there could be no error in the input media names themselves
  397. 2) If a list of media names is given, the base for the enumeration is this list. This is
  398. less efficient that using the Engine media table, but it keeps the order of medias
  399. according to the input list. If a media name from the list is not valid, the invalid flag is set.
  400. --*/
  401. {
  402. HRESULT hr = S_OK;
  403. WsbTraceIn(OLESTR("CMediaEnum::CMediaEnum"), OLESTR(""));
  404. try {
  405. m_pMediaNames = pMediaNames;
  406. m_dwNumberOfMedia = dwNumberOfMedia;
  407. m_nCurrent = CMEDIA_INVALID_INDEX;
  408. m_bInvalidMedia = FALSE;
  409. m_bAllMedias = FALSE;
  410. // Check mode of enumeration
  411. WsbAssert(dwNumberOfMedia > 0, E_INVALIDARG);
  412. if ((1 == dwNumberOfMedia) && (0 == wcscmp(m_pMediaNames[0], CLI_ALL_STR))) {
  413. // * enumeration
  414. m_bAllMedias = TRUE;
  415. }
  416. } WsbCatch(hr);
  417. WsbTraceOut(OLESTR("CMediaEnum::CMediaEnum"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  418. }
  419. CMediaEnum::~CMediaEnum( )
  420. /*++
  421. Routine Description:
  422. Destructor - free DB resources
  423. Arguments:
  424. None
  425. Return Value:
  426. None
  427. --*/
  428. {
  429. WsbTraceIn(OLESTR("CMediaEnum::~CMediaEnum"), OLESTR(""));
  430. // Release the entity first
  431. if( m_pMediaInfo ) {
  432. m_pMediaInfo = 0;
  433. }
  434. // Close the DB
  435. if( m_pDb ) {
  436. m_pDb->Close(m_pDbSession);
  437. }
  438. // m_pDb & m_pDbSession are released when the object terminates
  439. WsbTraceOut(OLESTR("CMediaEnum::~CMediaEnum"), OLESTR(""));
  440. }
  441. HRESULT CMediaEnum::First(OUT IMediaInfo **ppMediaInfo)
  442. /*++
  443. Routine Description:
  444. Gets first media
  445. Arguments:
  446. ppMediaInfo - First media info record to get
  447. Return Value:
  448. S_OK - If first media is retrieved
  449. WSB_E_NOTFOUND - If no more medias to enumerate
  450. E_INVALIDARG - If media name given by the user is not found
  451. (Only on a non * enumeration, m_bInvalidMedia is set)
  452. --*/
  453. {
  454. HRESULT hr = S_OK;
  455. WsbTraceIn(OLESTR("CMediaEnum::First"), OLESTR(""));
  456. try {
  457. // Open database and get a session for the enumeration (only once during the object life time)
  458. if (!m_pDb) {
  459. CComPtr<IHsmServer> pHsm;
  460. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm));
  461. WsbAffirmHr(pHsm->GetSegmentDb(&m_pDb));
  462. WsbAffirmHr(m_pDb->Open(&m_pDbSession));
  463. WsbAffirmHr(m_pDb->GetEntity(m_pDbSession, HSM_MEDIA_INFO_REC_TYPE, IID_IMediaInfo, (void**)&m_pMediaInfo));
  464. }
  465. // Enumerate
  466. if (m_bAllMedias) {
  467. // Get first media in the table
  468. WsbAffirmHr(m_pMediaInfo->First());
  469. // Validate media, if it's not valid, continue until we find a valid one
  470. // If no valid media is found, the loop terminates by throwing WSB_E_NOTFOUND by the Next method
  471. HRESULT hrValid = IsMediaValid(m_pMediaInfo);
  472. while (S_OK != hrValid) {
  473. WsbAffirmHr(m_pMediaInfo->Next());
  474. hrValid = IsMediaValid(m_pMediaInfo);
  475. }
  476. // Found a valid media
  477. *ppMediaInfo = m_pMediaInfo;
  478. (*ppMediaInfo)->AddRef();
  479. } else {
  480. CWsbStringPtr mediaDescription;
  481. // Enumerate user collection and try to find it in the table
  482. m_nCurrent = 0;
  483. if (m_nCurrent >= (int)m_dwNumberOfMedia) {
  484. WsbThrow(WSB_E_NOTFOUND);
  485. }
  486. // Find it
  487. hr = m_pMediaInfo->First();
  488. while(S_OK == hr) {
  489. WsbAffirmHr(m_pMediaInfo->GetDescription(&mediaDescription, 0));
  490. if (_wcsicmp(m_pMediaNames[m_nCurrent], mediaDescription) == 0) {
  491. // Fount it !!
  492. *ppMediaInfo = m_pMediaInfo;
  493. (*ppMediaInfo)->AddRef();
  494. // Validate media
  495. if (S_OK != IsMediaValid(m_pMediaInfo)) {
  496. // Return an error indication
  497. m_bInvalidMedia = TRUE;
  498. hr = E_INVALIDARG;
  499. WsbThrow(hr);
  500. }
  501. break;
  502. }
  503. mediaDescription.Free();
  504. hr = m_pMediaInfo->Next();
  505. }
  506. if (WSB_E_NOTFOUND == hr) {
  507. // Media given by user not found
  508. m_bInvalidMedia = TRUE;
  509. hr = E_INVALIDARG;
  510. }
  511. WsbAffirmHr(hr);
  512. }
  513. } WsbCatch(hr);
  514. WsbTraceOut(OLESTR("CMediaEnum::First"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  515. return hr;
  516. }
  517. HRESULT CMediaEnum::Next(OUT IMediaInfo **ppMediaInfo)
  518. /*++
  519. Routine Description:
  520. Gets next media
  521. Arguments:
  522. ppMediaInfo - Next media info record to get
  523. Return Value:
  524. S_OK - If next media is retrieved
  525. WSB_E_NOTFOUND - If no more medias to enumerate
  526. E_INVALIDARG - If media name given by the user is not found
  527. (Only on a non * enumeration, m_bInvalidMedia is set)
  528. --*/
  529. {
  530. HRESULT hr = S_OK;
  531. WsbTraceIn(OLESTR("CMediaEnum::Next"), OLESTR(""));
  532. try {
  533. // Enumerate
  534. if (m_bAllMedias) {
  535. // Get first media in the table
  536. WsbAffirmHr(m_pMediaInfo->Next());
  537. // Validate media, if it's not valid, continue until we find a valid one
  538. // If no valid media is found, the loop terminates by throwing WSB_E_NOTFOUND by the Next method
  539. HRESULT hrValid = IsMediaValid(m_pMediaInfo);
  540. while (S_OK != hrValid) {
  541. WsbAffirmHr(m_pMediaInfo->Next());
  542. hrValid = IsMediaValid(m_pMediaInfo);
  543. }
  544. // Found a valid media
  545. *ppMediaInfo = m_pMediaInfo;
  546. (*ppMediaInfo)->AddRef();
  547. } else {
  548. CWsbStringPtr mediaDescription;
  549. // Enumerate user collection and try to find it in the table
  550. m_nCurrent++;
  551. if (m_nCurrent >= (int)m_dwNumberOfMedia) {
  552. WsbThrow(WSB_E_NOTFOUND);
  553. }
  554. // Find it
  555. hr = m_pMediaInfo->First();
  556. while(S_OK == hr) {
  557. WsbAffirmHr(m_pMediaInfo->GetDescription(&mediaDescription, 0));
  558. if (_wcsicmp(m_pMediaNames[m_nCurrent], mediaDescription) == 0) {
  559. // Fount it !!
  560. *ppMediaInfo = m_pMediaInfo;
  561. (*ppMediaInfo)->AddRef();
  562. // Validate media
  563. if (S_OK != IsMediaValid(m_pMediaInfo)) {
  564. // Return an error indication
  565. m_bInvalidMedia = TRUE;
  566. hr = E_INVALIDARG;
  567. WsbThrow(hr);
  568. }
  569. break;
  570. }
  571. mediaDescription.Free();
  572. hr = m_pMediaInfo->Next();
  573. }
  574. if (WSB_E_NOTFOUND == hr) {
  575. // Media given by user not found
  576. m_bInvalidMedia = TRUE;
  577. hr = E_INVALIDARG;
  578. }
  579. WsbAffirmHr(hr);
  580. }
  581. } WsbCatch(hr);
  582. WsbTraceOut(OLESTR("CMediaEnum::Next"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  583. return hr;
  584. }
  585. //
  586. // Internal utilities
  587. //
  588. HRESULT IsMediaValid(IN IMediaInfo *pMediaInfo)
  589. /*++
  590. Routine Description:
  591. Checks with RMS unit (i.e. with RSM...) if the media is valid.
  592. The media could be gone if it was deallocated by the user for example
  593. Note: Currently, this utility does not check if media is enabled, online, etc -
  594. it just verifies that the media is still known to RSM.
  595. Arguments:
  596. pMediaInfo - Media record for media to check
  597. Return Value:
  598. S_OK - If media found in RSM
  599. S_FALSE - If media is not found in RSM
  600. --*/
  601. {
  602. HRESULT hr = S_OK;
  603. WsbTraceIn(OLESTR("IsMediaValid"), OLESTR(""));
  604. try {
  605. CComPtr<IHsmServer> pHsm;
  606. CComPtr<IRmsServer> pRms;
  607. CComPtr<IRmsCartridge> pRmsCart;
  608. GUID mediaSubsystemId;
  609. WsbAffirmHr(pMediaInfo->GetMediaSubsystemId(&mediaSubsystemId));
  610. WsbAffirm(GUID_NULL != mediaSubsystemId, S_FALSE);
  611. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm));
  612. WsbAffirmHr(pHsm->GetHsmMediaMgr(&pRms));
  613. hr = pRms->FindCartridgeById(mediaSubsystemId, &pRmsCart);
  614. if (S_OK != hr) {
  615. // Media not found in RSM, don't care why
  616. hr = S_FALSE;
  617. }
  618. } WsbCatch(hr);
  619. WsbTraceOut(OLESTR("IsMediaValid"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  620. return hr;
  621. }
  622. HRESULT IsCopySetValid (IN IHsmServer *pHsm, IN DWORD dwCopySetNumber)
  623. /*++
  624. Routine Description:
  625. Checks with HSM (Engine) server that the speficied copy set number is within
  626. the configured copy set range.
  627. Arguments:
  628. pHsm - The HSM server to consult with
  629. dwCopySetNumber - The copy set number to check
  630. Return Value:
  631. S_OK - If the copy set number is within range
  632. S_FALSE - If the copy set number is out of range
  633. --*/
  634. {
  635. HRESULT hr = S_OK;
  636. WsbTraceIn(OLESTR("IsCopySetValid"), OLESTR(""));
  637. try {
  638. CComPtr<IHsmStoragePool> pStoragePool;
  639. CComPtr<IWsbIndexedCollection> pCollection;
  640. ULONG count;
  641. USHORT numCopies;
  642. // Get the storage pools collection. There should only be one member.
  643. WsbAffirmHr(pHsm->GetStoragePools(&pCollection));
  644. WsbAffirmHr(pCollection->GetEntries(&count));
  645. WsbAffirm(1 == count, E_FAIL);
  646. WsbAffirmHr(pCollection->At(0, IID_IHsmStoragePool, (void **)&pStoragePool));
  647. // Get and check number of configured copy sets
  648. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm));
  649. WsbAffirmHr(pStoragePool->GetNumMediaCopies(&numCopies));
  650. if ((USHORT)dwCopySetNumber > numCopies) {
  651. hr = S_FALSE;
  652. }
  653. } WsbCatch(hr);
  654. WsbTraceOut(OLESTR("IsCopySetValid"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  655. return hr;
  656. }
  657. HRESULT ShowMediaParams(IN IMediaInfo *pMediaInfo, BOOL bName, IN BOOL bStatus, IN BOOL bCapacity,
  658. IN BOOL bFreeSpace, IN BOOL bVersion, IN BOOL bCopies)
  659. /*++
  660. Routine Description:
  661. Shows (prints to stdout) media parameters
  662. Arguments:
  663. pMediaInfo - Media record
  664. bName - Media display name
  665. bStatus - HSM status of the media (i.e. - Healthy, Read-Only, etc.)
  666. bCapacity, - Media capacity (in GB)
  667. bFreeSpace - Amount of free space left on the media (in GB)
  668. bVersion - Last update date for that media
  669. bCopies - Number of existing copies and the status of each copy
  670. Return Value:
  671. S_OK - If all the parameters could be displayed for the input media
  672. --*/
  673. {
  674. HRESULT hr = S_OK;
  675. WsbTraceIn(OLESTR("ShowMediaParams"), OLESTR(""));
  676. try {
  677. CWsbStringPtr param;
  678. CWsbStringPtr data;
  679. WCHAR longData[100];
  680. CWsbStringPtr mediaDescription;
  681. GUID mediaSubsystemId;
  682. LONGLONG lCapacity, lFreeSpace;
  683. FILETIME ftVersion;
  684. BOOL bReadOnly, bRecreate;
  685. SHORT nNextDataSet;
  686. HRESULT hrLast;
  687. CWsbStringPtr unusedName;
  688. GUID unusedGuid1;
  689. GUID unusedGuid2;
  690. HSM_JOB_MEDIA_TYPE unusedType;
  691. LONGLONG unusedLL1;
  692. // Get parameters - it is better to get them all at once even if we don't have to display everything
  693. WsbAffirmHr(pMediaInfo->GetMediaInfo(&unusedGuid1, &mediaSubsystemId, &unusedGuid2,
  694. &lFreeSpace, &lCapacity, &hrLast, &nNextDataSet, &mediaDescription, 0,
  695. &unusedType, &unusedName, 0, &bReadOnly, &ftVersion, &unusedLL1, &bRecreate));
  696. WsbTraceAndPrint(CLI_MESSAGE_MEDIA_PARAMS, (WCHAR *)mediaDescription, NULL);
  697. // TEMPORARY: For showing most of these parameters, UI utilities and strings are duplicated
  698. // To avoid that, general media utilities should be moved from rsadutil.cpp to Wsb unit
  699. // and relevant strings should be moved from HsmAdmin DLL to RsCommon DLL
  700. // Name
  701. if (bName) {
  702. CComPtr<IHsmServer> pHsm;
  703. CComPtr<IRmsServer> pRms;
  704. CComPtr<IRmsCartridge> pRmsCart;
  705. CWsbBstrPtr rsmName;
  706. // Get RSM name
  707. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm));
  708. WsbAffirmHr(pHsm->GetHsmMediaMgr(&pRms));
  709. WsbAffirmHr(pRms->FindCartridgeById(mediaSubsystemId, &pRmsCart));
  710. WsbAffirmHr(pRmsCart->GetName(&rsmName));
  711. if (wcscmp(rsmName, OLESTR("")) == 0 ) {
  712. rsmName.Free();
  713. WsbAffirmHr(rsmName.LoadFromRsc(g_hInstance, IDS_CAR_NAME_UNKNOWN));
  714. }
  715. // Print
  716. WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_MEDIA_RSM_NAME));
  717. WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY, (WCHAR *)param, (WCHAR *)(BSTR)rsmName, NULL);
  718. }
  719. // Status
  720. if (bStatus) {
  721. SHORT nLastGoodNextDataSet;
  722. ULONG resId;
  723. // Get more relevant status info
  724. WsbAffirmHr(pMediaInfo->GetLKGMasterNextRemoteDataSet(&nLastGoodNextDataSet));
  725. // Compute status
  726. if (bRecreate) {
  727. resId = IDS_CAR_STATUS_RECREATE;
  728. } else if (nNextDataSet < nLastGoodNextDataSet) {
  729. resId = IDS_CAR_STATUS_ERROR_INCOMPLETE;
  730. } else if (SUCCEEDED(hrLast) || (RMS_E_CARTRIDGE_DISABLED == hrLast)) {
  731. resId = (bReadOnly ? IDS_CAR_STATUS_READONLY : IDS_CAR_STATUS_NORMAL);
  732. } else if (RMS_E_CARTRIDGE_NOT_FOUND == hrLast) {
  733. resId = IDS_CAR_STATUS_ERROR_MISSING;
  734. } else {
  735. resId = (bReadOnly ? IDS_CAR_STATUS_ERROR_RO : IDS_CAR_STATUS_ERROR_RW);
  736. }
  737. // Print
  738. WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_MEDIA_STATUS));
  739. WsbAffirmHr(data.LoadFromRsc(g_hInstance, resId));
  740. WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY, (WCHAR *)param, (WCHAR *)data, NULL);
  741. }
  742. // Capacity
  743. if (bCapacity) {
  744. WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_MEDIA_CAPACITY));
  745. WsbAffirmHr(ShortSizeFormat64(lCapacity, longData));
  746. WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY, (WCHAR *)param, longData, NULL);
  747. }
  748. // Free Space
  749. if (bFreeSpace) {
  750. WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_MEDIA_FREE_SPACE));
  751. WsbAffirmHr(ShortSizeFormat64(lFreeSpace, longData));
  752. WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY, (WCHAR *)param, longData, NULL);
  753. }
  754. // Version
  755. if (bVersion) {
  756. data.Free();
  757. WsbAffirmHr(FormatFileTime(ftVersion, &data));
  758. WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_MEDIA_VERSION));
  759. WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY, (WCHAR *)param, (WCHAR *)data, NULL);
  760. }
  761. // Media copies information
  762. if (bCopies) {
  763. GUID copySubsystemId;
  764. HRESULT copyLastHr;
  765. SHORT copyNextRemoteDataSet, lastGoodNextDataSet;
  766. ULONG resId;
  767. WsbTraceAndPrint(CLI_MESSAGE_MEDIA_COPIES_LIST, NULL);
  768. WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_MEDIA_COPY));
  769. WsbAffirmHr(pMediaInfo->GetLKGMasterNextRemoteDataSet(&lastGoodNextDataSet));
  770. for (USHORT copyNo=1; copyNo<=HSMADMIN_MAX_COPY_SETS; copyNo++) {
  771. // Get copy status information
  772. WsbAffirmHr(pMediaInfo->GetCopyMediaSubsystemId(copyNo, &copySubsystemId));
  773. WsbAffirmHr(pMediaInfo->GetCopyLastError(copyNo, &copyLastHr));
  774. WsbAffirmHr(pMediaInfo->GetCopyNextRemoteDataSet(copyNo, &copyNextRemoteDataSet));
  775. // Compute status
  776. switch(copyLastHr) {
  777. case RMS_E_CANCELLED:
  778. case RMS_E_REQUEST_REFUSED:
  779. case RMS_E_WRITE_PROTECT:
  780. case RMS_E_MEDIA_OFFLINE:
  781. case RMS_E_TIMEOUT:
  782. case RMS_E_SCRATCH_NOT_FOUND:
  783. case RMS_E_CARTRIDGE_UNAVAILABLE:
  784. case RMS_E_CARTRIDGE_DISABLED:
  785. copyLastHr = S_OK;
  786. break;
  787. }
  788. if (copySubsystemId == GUID_NULL) {
  789. resId = IDS_CAR_COPYSET_NONE;
  790. } else if (RMS_E_CARTRIDGE_NOT_FOUND == copyLastHr) {
  791. resId = IDS_CAR_COPYSET_MISSING;
  792. } else if (FAILED(copyLastHr)) {
  793. resId = IDS_CAR_COPYSET_ERROR;
  794. } else if (copyNextRemoteDataSet < lastGoodNextDataSet) {
  795. resId = IDS_CAR_COPYSET_OUTSYNC;
  796. } else {
  797. resId = IDS_CAR_COPYSET_INSYNC;
  798. }
  799. // Print
  800. swprintf(longData, param, (int)copyNo);
  801. WsbAffirmHr(data.LoadFromRsc(g_hInstance, resId));
  802. WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY, longData, (WCHAR *)data, NULL);
  803. }
  804. }
  805. } WsbCatch(hr);
  806. WsbTraceOut(OLESTR("ShowMediaParams"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  807. return hr;
  808. }