/*++ Copyright (c) 2000 Microsoft Corporation Module Name: climedia.cpp Abstract: Implements CLI MEDIA sub-interface Author: Ran Kalach [rankala] 3-March-2000 Revision History: --*/ #include "stdafx.h" #include "HsmConn.h" #include "engine.h" static GUID g_nullGuid = GUID_NULL; // Internal utilities and classes for MEDIA interface #define CMEDIA_INVALID_INDEX (-1) HRESULT IsMediaValid(IN IMediaInfo *pMediaInfo); HRESULT ShowMediaParams(IN IMediaInfo *pMediaInfo, BOOL bName, IN BOOL bStatus, IN BOOL bCapacity, IN BOOL bFreeSpace, IN BOOL Version, IN BOOL Copies); HRESULT IsCopySetValid (IN IHsmServer *pHsm, IN DWORD dwCopySetNumber); class CMediaEnum { // Constructors, destructors public: CMediaEnum(IN LPWSTR *pMediaNames, IN DWORD dwNumberOfMedia); ~CMediaEnum(); // Public methods public: HRESULT First(OUT IMediaInfo **ppMediaInfo); HRESULT Next(OUT IMediaInfo **ppMediaInfo); HRESULT ErrorMedia(OUT int *pIndex); // Private data protected: LPWSTR *m_pMediaNames; DWORD m_dwNumberOfMedia; // If * enumeration or not BOOL m_bAllMedias; // Data for the enumeration CComPtr m_pDb; CComPtr m_pDbSession; CComPtr m_pMediaInfo; // Used only when m_bAllMedias == FALSE int m_nCurrent; BOOL m_bInvalidMedia; }; inline HRESULT CMediaEnum::ErrorMedia(OUT int *pIndex) { HRESULT hr = S_FALSE; if (m_bInvalidMedia) { // There was an error with last media hr = S_OK; } *pIndex = m_nCurrent; return(hr); } // // MEDIA inetrafce implementors // HRESULT MediaSynchronize( IN DWORD CopySetNumber, IN BOOL Synchronous ) /*++ Routine Description: Creates/updates the specified media copy set Arguments: CopySetNumber - The copy set number to create/synchronize Synchronous - If TRUE, the function waits for the operation to complete before returning. If not, it returns immediately after starting the job Return Value: S_OK - If the copy set was created/updated successfully --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("MediaSynchronize"), OLESTR("")); try { CComPtr pHsm; // Get HSM server WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm)); // Verify that input parameters are valid WsbAffirmHr(ValidateLimitsArg(CopySetNumber, IDS_MEDIA_COPY_SET, HSMADMIN_MIN_COPY_SETS + 1, HSMADMIN_MAX_COPY_SETS)); hr = IsCopySetValid(pHsm, CopySetNumber); if (S_FALSE == hr) { WsbTraceAndPrint(CLI_MESSAGE_IVALID_COPY_SET, NULL); WsbThrow(E_INVALIDARG); } else { WsbAffirmHr(hr); } // Synchronize copy set if (Synchronous) { // Call directly Engine method WsbAffirmHr(pHsm->SynchronizeMedia(g_nullGuid, (USHORT)CopySetNumber)); } else { // Use RsLaunch // Note: Another possibility here would be using the CLI (rss.exex) itself // with synchronous flag on, but it's better to depend here on internal HSM // interface (RsLaunch) and not an external one (RSS) that only the parser knows CWsbStringPtr cmdLine; WCHAR cmdParams[40]; STARTUPINFO startupInfo; PROCESS_INFORMATION exeInfo; // Startup info memset(&startupInfo, 0, sizeof(startupInfo)); startupInfo.cb = sizeof( startupInfo ); startupInfo.wShowWindow = SW_HIDE; startupInfo.dwFlags = STARTF_USESHOWWINDOW; // Create command line swprintf(cmdParams, OLESTR(" sync %lu"), CopySetNumber); WsbAffirmHr(cmdLine.Alloc(MAX_PATH + wcslen(WSB_FACILITY_LAUNCH_NAME) + wcslen(cmdParams) + 10)); WsbAffirmStatus(GetSystemDirectory(cmdLine, MAX_PATH)); WsbAffirmHr(cmdLine.Append(OLESTR("\\"))); WsbAffirmHr(cmdLine.Append(WSB_FACILITY_LAUNCH_NAME)); WsbAffirmHr(cmdLine.Append(cmdParams)); // Run the RsLaunch process WsbAffirmStatus(CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, NULL, NULL, NULL, &startupInfo, &exeInfo)); // Cleanup CloseHandle(exeInfo.hProcess); CloseHandle(exeInfo.hThread); } } WsbCatch(hr); WsbTraceOut(OLESTR("MediaSynchronize"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return hr; } HRESULT MediaRecreateMaster( IN LPWSTR MediaName, IN DWORD CopySetNumber, IN BOOL Synchronous ) /*++ Routine Description: Recreate a master for the given meida out of the specified copy Arguments: MediaName - Master media name of media to recreate CopySetNumber - The copy number to use for recreating the master Synchronous - If TRUE, the function waits for the operation to complete before returning. If not, it returns immediately after starting the job Return Value: S_OK - If the master is recreated successfully from the specified copy --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("MediaRecreateMaster"), OLESTR("")); try { CComPtr pHsm; GUID mediaId; // Get HSM server WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm)); // Verify that input parameters are valid if ((NULL == MediaName) || (NULL == *MediaName)) { WsbTraceAndPrint(CLI_MESSAGE_NO_MEDIAS, NULL); WsbThrow(E_INVALIDARG); } WsbAffirmHr(ValidateLimitsArg(CopySetNumber, IDS_MEDIA_COPY_SET, HSMADMIN_MIN_COPY_SETS + 1, HSMADMIN_MAX_COPY_SETS)); hr = IsCopySetValid(pHsm, CopySetNumber); if (S_FALSE == hr) { WsbTraceAndPrint(CLI_MESSAGE_IVALID_COPY_SET, NULL); WsbThrow(E_INVALIDARG); } else { WsbAffirmHr(hr); } // Find the media id according to the given display name hr = pHsm->FindMediaIdByDescription(MediaName, &mediaId); if ((WSB_E_NOTFOUND == hr) || (GUID_NULL == mediaId)) { // Given media name is invalid WsbTraceAndPrint(CLI_MESSAGE_INVALID_MEDIA, MediaName, NULL); WsbThrow(E_INVALIDARG); } WsbAffirmHr(hr); // Mark media for recreation WsbAffirmHr(pHsm->MarkMediaForRecreation(mediaId)); if (Synchronous) { // Recreate the master WsbAffirmHr(pHsm->RecreateMaster(mediaId, (USHORT)CopySetNumber)); } else { // Use RsLaunch // Note: Another possibility here would be using the CLI (rss.exex) itself // with synchronous flag on, but it's better to depend here on internal HSM // interface (RsLaunch) and not an external one (RSS) that only the parser knows CWsbStringPtr cmdLine; CWsbStringPtr cmdParams; STARTUPINFO startupInfo; PROCESS_INFORMATION exeInfo; CWsbStringPtr stringId(mediaId); // Startup info memset(&startupInfo, 0, sizeof(startupInfo)); startupInfo.cb = sizeof( startupInfo ); startupInfo.wShowWindow = SW_HIDE; startupInfo.dwFlags = STARTF_USESHOWWINDOW; // Create command line WsbAffirmHr(cmdParams.Alloc(wcslen(stringId) + 40)); swprintf(cmdParams, OLESTR(" recreate -i %ls -c %lu"), (WCHAR *)stringId, CopySetNumber); WsbAffirmHr(cmdLine.Alloc(MAX_PATH + wcslen(WSB_FACILITY_LAUNCH_NAME) + wcslen(cmdParams) + 10)); WsbAffirmStatus(GetSystemDirectory(cmdLine, MAX_PATH)); WsbAffirmHr(cmdLine.Append(OLESTR("\\"))); WsbAffirmHr(cmdLine.Append(WSB_FACILITY_LAUNCH_NAME)); WsbAffirmHr(cmdLine.Append(cmdParams)); // Run the RsLaunch process WsbAffirmStatus(CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, NULL, NULL, NULL, &startupInfo, &exeInfo)); // Cleanup CloseHandle(exeInfo.hProcess); CloseHandle(exeInfo.hThread); } } WsbCatch(hr); WsbTraceOut(OLESTR("MediaRecreateMaster"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return hr; } HRESULT MediaDelete( IN LPWSTR *MediaNames, IN DWORD NumberOfMedia, IN DWORD CopySetNumber ) /*++ Routine Description: Deletes the specified copy for all given (master) medias Arguments: MediaNames - The list of media to delete a copy for NumberOfMedia - Number of medias in the set CopySetNumber - Which copy to delete Return Value: S_OK - If the media copy is deleted successfully for all medias Notes: 1. MediaNames could point tp a "*" string for enumerating all medias. NumberOfMedia should be 1 then. 2. If a certain copy doesn't exist for a certain media, we report but not abort. --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("MediaDelete"), OLESTR("")); try { CComPtr pHsm; CComPtr pRms; CComPtr pMediaInfo; GUID mediaSubsystemId; // Get HSM server WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm)); // Verify that input parameters are valid if ((NULL == MediaNames) || (0 == NumberOfMedia)) { WsbTraceAndPrint(CLI_MESSAGE_NO_MEDIAS, NULL); WsbThrow(E_INVALIDARG); } WsbAffirmHr(ValidateLimitsArg(CopySetNumber, IDS_MEDIA_COPY_SET, HSMADMIN_MIN_COPY_SETS + 1, HSMADMIN_MAX_COPY_SETS)); hr = IsCopySetValid(pHsm, CopySetNumber); if (S_FALSE == hr) { WsbTraceAndPrint(CLI_MESSAGE_IVALID_COPY_SET, NULL); WsbThrow(E_INVALIDARG); } else { WsbAffirmHr(hr); } // Get RMS server WsbAffirmHr(pHsm->GetHsmMediaMgr(&pRms)); // Initialize an enumerator object CMediaEnum mediaEnum(MediaNames, NumberOfMedia); hr = mediaEnum.First(&pMediaInfo); if (WSB_E_NOTFOUND == hr) { WsbTraceAndPrint(CLI_MESSAGE_NO_MEDIAS, NULL); WsbThrow(hr); } else if (S_OK != hr) { int index; if (S_OK == mediaEnum.ErrorMedia(&index)) { // Problem with a specific input media WsbTraceAndPrint(CLI_MESSAGE_INVALID_MEDIA, MediaNames[index], NULL); } WsbThrow(hr); } while(S_OK == hr) { // Delete a copy WsbAffirmHr(pMediaInfo->GetCopyMediaSubsystemId((USHORT)CopySetNumber, &mediaSubsystemId)); if (GUID_NULL == mediaSubsystemId) { // No such copy - report and continue int index; mediaEnum.ErrorMedia(&index); if (CMEDIA_INVALID_INDEX != index) { // Input from user - report WCHAR copyStr[6]; swprintf(copyStr, OLESTR("%u"), (USHORT)CopySetNumber); WsbTraceAndPrint(CLI_MESSAGE_MEDIA_NO_COPY, copyStr, MediaNames[index], NULL); } } else { // We don't expect to get here RMS_E_CARTRIDGE_NOT_FOUND // because this has already been tested by the enumerator WsbAffirmHr(pRms->RecycleCartridge(mediaSubsystemId, 0)); // Delete from the table WsbAffirmHr(pMediaInfo->DeleteCopy((USHORT)CopySetNumber)); WsbAffirmHr(pMediaInfo->Write()); } pMediaInfo = 0; hr = mediaEnum.Next(&pMediaInfo); } if (WSB_E_NOTFOUND == hr) { hr = S_OK; } else { int index; if (S_OK == mediaEnum.ErrorMedia(&index)) { // Problem with a specific input media WsbTraceAndPrint(CLI_MESSAGE_INVALID_MEDIA, MediaNames[index], NULL); } WsbThrow(hr); } } WsbCatch(hr); WsbTraceOut(OLESTR("MediaDelete"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return hr; } HRESULT MediaShow( IN LPWSTR *MediaNames, IN DWORD NumberOfMedia, IN BOOL Name, IN BOOL Status, IN BOOL Capacity, IN BOOL FreeSpace, IN BOOL Version, IN BOOL Copies ) /*++ Routine Description: Shows (prints to stdout) given media(s) parameters Arguments: MediaNames - The list of media to show parameters for NumberOfMedia - Number of medias in the set Name - Media display name Status - HSM status of the media (i.e. - Healthy, Read-Only, etc.) Capacity, - Media capacity (in GB) FreeSpace - Amount of free space left on the media (in GB) Version - Last update date for that media Copies - Number of existing copies and the status of each copy Return Value: S_OK - If all the parameters could be retrieved for all medias --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("MediaShow"), OLESTR("")); try { CComPtr pMediaInfo; // Verify that input parameters are valid if ((NULL == MediaNames) || (0 == NumberOfMedia)) { WsbTraceAndPrint(CLI_MESSAGE_NO_MEDIAS, NULL); WsbThrow(E_INVALIDARG); } // Initialize an enumerator object CMediaEnum mediaEnum(MediaNames, NumberOfMedia); hr = mediaEnum.First(&pMediaInfo); if (WSB_E_NOTFOUND == hr) { WsbTraceAndPrint(CLI_MESSAGE_NO_MEDIAS, NULL); WsbThrow(hr); } else if (S_OK != hr) { int index; if (S_OK == mediaEnum.ErrorMedia(&index)) { // Problem with a specific input media WsbTraceAndPrint(CLI_MESSAGE_INVALID_MEDIA, MediaNames[index], NULL); } WsbThrow(hr); } while(S_OK == hr) { // Show parameters WsbAffirmHr(ShowMediaParams(pMediaInfo, Name, Status, Capacity, FreeSpace, Version, Copies)); pMediaInfo = 0; hr = mediaEnum.Next(&pMediaInfo); } if (WSB_E_NOTFOUND == hr) { hr = S_OK; } else { int index; if (S_OK == mediaEnum.ErrorMedia(&index)) { // Problem with a specific input media WsbTraceAndPrint(CLI_MESSAGE_INVALID_MEDIA, MediaNames[index], NULL); } WsbThrow(hr); } } WsbCatch(hr); WsbTraceOut(OLESTR("MediaShow"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return hr; } // // Enumerator class methods // CMediaEnum::CMediaEnum(IN LPWSTR *pMediaNames, IN DWORD dwNumberOfMedia) /*++ Routine Description: Constructor Arguments: pMediaNames - Medias to enumerate dwNumberOfMedia - Number of medias Return Value: None Notes: There are two kinds of enumerations: 1) If * is specified, the base for the enumeration is the Engine media (DB) table In that case, there could be no error in the input media names themselves 2) If a list of media names is given, the base for the enumeration is this list. This is less efficient that using the Engine media table, but it keeps the order of medias according to the input list. If a media name from the list is not valid, the invalid flag is set. --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CMediaEnum::CMediaEnum"), OLESTR("")); try { m_pMediaNames = pMediaNames; m_dwNumberOfMedia = dwNumberOfMedia; m_nCurrent = CMEDIA_INVALID_INDEX; m_bInvalidMedia = FALSE; m_bAllMedias = FALSE; // Check mode of enumeration WsbAssert(dwNumberOfMedia > 0, E_INVALIDARG); if ((1 == dwNumberOfMedia) && (0 == wcscmp(m_pMediaNames[0], CLI_ALL_STR))) { // * enumeration m_bAllMedias = TRUE; } } WsbCatch(hr); WsbTraceOut(OLESTR("CMediaEnum::CMediaEnum"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); } CMediaEnum::~CMediaEnum( ) /*++ Routine Description: Destructor - free DB resources Arguments: None Return Value: None --*/ { WsbTraceIn(OLESTR("CMediaEnum::~CMediaEnum"), OLESTR("")); // Release the entity first if( m_pMediaInfo ) { m_pMediaInfo = 0; } // Close the DB if( m_pDb ) { m_pDb->Close(m_pDbSession); } // m_pDb & m_pDbSession are released when the object terminates WsbTraceOut(OLESTR("CMediaEnum::~CMediaEnum"), OLESTR("")); } HRESULT CMediaEnum::First(OUT IMediaInfo **ppMediaInfo) /*++ Routine Description: Gets first media Arguments: ppMediaInfo - First media info record to get Return Value: S_OK - If first media is retrieved WSB_E_NOTFOUND - If no more medias to enumerate E_INVALIDARG - If media name given by the user is not found (Only on a non * enumeration, m_bInvalidMedia is set) --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CMediaEnum::First"), OLESTR("")); try { // Open database and get a session for the enumeration (only once during the object life time) if (!m_pDb) { CComPtr pHsm; WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm)); WsbAffirmHr(pHsm->GetSegmentDb(&m_pDb)); WsbAffirmHr(m_pDb->Open(&m_pDbSession)); WsbAffirmHr(m_pDb->GetEntity(m_pDbSession, HSM_MEDIA_INFO_REC_TYPE, IID_IMediaInfo, (void**)&m_pMediaInfo)); } // Enumerate if (m_bAllMedias) { // Get first media in the table WsbAffirmHr(m_pMediaInfo->First()); // Validate media, if it's not valid, continue until we find a valid one // If no valid media is found, the loop terminates by throwing WSB_E_NOTFOUND by the Next method HRESULT hrValid = IsMediaValid(m_pMediaInfo); while (S_OK != hrValid) { WsbAffirmHr(m_pMediaInfo->Next()); hrValid = IsMediaValid(m_pMediaInfo); } // Found a valid media *ppMediaInfo = m_pMediaInfo; (*ppMediaInfo)->AddRef(); } else { CWsbStringPtr mediaDescription; // Enumerate user collection and try to find it in the table m_nCurrent = 0; if (m_nCurrent >= (int)m_dwNumberOfMedia) { WsbThrow(WSB_E_NOTFOUND); } // Find it hr = m_pMediaInfo->First(); while(S_OK == hr) { WsbAffirmHr(m_pMediaInfo->GetDescription(&mediaDescription, 0)); if (_wcsicmp(m_pMediaNames[m_nCurrent], mediaDescription) == 0) { // Fount it !! *ppMediaInfo = m_pMediaInfo; (*ppMediaInfo)->AddRef(); // Validate media if (S_OK != IsMediaValid(m_pMediaInfo)) { // Return an error indication m_bInvalidMedia = TRUE; hr = E_INVALIDARG; WsbThrow(hr); } break; } mediaDescription.Free(); hr = m_pMediaInfo->Next(); } if (WSB_E_NOTFOUND == hr) { // Media given by user not found m_bInvalidMedia = TRUE; hr = E_INVALIDARG; } WsbAffirmHr(hr); } } WsbCatch(hr); WsbTraceOut(OLESTR("CMediaEnum::First"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return hr; } HRESULT CMediaEnum::Next(OUT IMediaInfo **ppMediaInfo) /*++ Routine Description: Gets next media Arguments: ppMediaInfo - Next media info record to get Return Value: S_OK - If next media is retrieved WSB_E_NOTFOUND - If no more medias to enumerate E_INVALIDARG - If media name given by the user is not found (Only on a non * enumeration, m_bInvalidMedia is set) --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CMediaEnum::Next"), OLESTR("")); try { // Enumerate if (m_bAllMedias) { // Get first media in the table WsbAffirmHr(m_pMediaInfo->Next()); // Validate media, if it's not valid, continue until we find a valid one // If no valid media is found, the loop terminates by throwing WSB_E_NOTFOUND by the Next method HRESULT hrValid = IsMediaValid(m_pMediaInfo); while (S_OK != hrValid) { WsbAffirmHr(m_pMediaInfo->Next()); hrValid = IsMediaValid(m_pMediaInfo); } // Found a valid media *ppMediaInfo = m_pMediaInfo; (*ppMediaInfo)->AddRef(); } else { CWsbStringPtr mediaDescription; // Enumerate user collection and try to find it in the table m_nCurrent++; if (m_nCurrent >= (int)m_dwNumberOfMedia) { WsbThrow(WSB_E_NOTFOUND); } // Find it hr = m_pMediaInfo->First(); while(S_OK == hr) { WsbAffirmHr(m_pMediaInfo->GetDescription(&mediaDescription, 0)); if (_wcsicmp(m_pMediaNames[m_nCurrent], mediaDescription) == 0) { // Fount it !! *ppMediaInfo = m_pMediaInfo; (*ppMediaInfo)->AddRef(); // Validate media if (S_OK != IsMediaValid(m_pMediaInfo)) { // Return an error indication m_bInvalidMedia = TRUE; hr = E_INVALIDARG; WsbThrow(hr); } break; } mediaDescription.Free(); hr = m_pMediaInfo->Next(); } if (WSB_E_NOTFOUND == hr) { // Media given by user not found m_bInvalidMedia = TRUE; hr = E_INVALIDARG; } WsbAffirmHr(hr); } } WsbCatch(hr); WsbTraceOut(OLESTR("CMediaEnum::Next"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return hr; } // // Internal utilities // HRESULT IsMediaValid(IN IMediaInfo *pMediaInfo) /*++ Routine Description: Checks with RMS unit (i.e. with RSM...) if the media is valid. The media could be gone if it was deallocated by the user for example Note: Currently, this utility does not check if media is enabled, online, etc - it just verifies that the media is still known to RSM. Arguments: pMediaInfo - Media record for media to check Return Value: S_OK - If media found in RSM S_FALSE - If media is not found in RSM --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("IsMediaValid"), OLESTR("")); try { CComPtr pHsm; CComPtr pRms; CComPtr pRmsCart; GUID mediaSubsystemId; WsbAffirmHr(pMediaInfo->GetMediaSubsystemId(&mediaSubsystemId)); WsbAffirm(GUID_NULL != mediaSubsystemId, S_FALSE); WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm)); WsbAffirmHr(pHsm->GetHsmMediaMgr(&pRms)); hr = pRms->FindCartridgeById(mediaSubsystemId, &pRmsCart); if (S_OK != hr) { // Media not found in RSM, don't care why hr = S_FALSE; } } WsbCatch(hr); WsbTraceOut(OLESTR("IsMediaValid"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return hr; } HRESULT IsCopySetValid (IN IHsmServer *pHsm, IN DWORD dwCopySetNumber) /*++ Routine Description: Checks with HSM (Engine) server that the speficied copy set number is within the configured copy set range. Arguments: pHsm - The HSM server to consult with dwCopySetNumber - The copy set number to check Return Value: S_OK - If the copy set number is within range S_FALSE - If the copy set number is out of range --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("IsCopySetValid"), OLESTR("")); try { CComPtr pStoragePool; CComPtr pCollection; ULONG count; USHORT numCopies; // Get the storage pools collection. There should only be one member. WsbAffirmHr(pHsm->GetStoragePools(&pCollection)); WsbAffirmHr(pCollection->GetEntries(&count)); WsbAffirm(1 == count, E_FAIL); WsbAffirmHr(pCollection->At(0, IID_IHsmStoragePool, (void **)&pStoragePool)); // Get and check number of configured copy sets WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm)); WsbAffirmHr(pStoragePool->GetNumMediaCopies(&numCopies)); if ((USHORT)dwCopySetNumber > numCopies) { hr = S_FALSE; } } WsbCatch(hr); WsbTraceOut(OLESTR("IsCopySetValid"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return hr; } HRESULT ShowMediaParams(IN IMediaInfo *pMediaInfo, BOOL bName, IN BOOL bStatus, IN BOOL bCapacity, IN BOOL bFreeSpace, IN BOOL bVersion, IN BOOL bCopies) /*++ Routine Description: Shows (prints to stdout) media parameters Arguments: pMediaInfo - Media record bName - Media display name bStatus - HSM status of the media (i.e. - Healthy, Read-Only, etc.) bCapacity, - Media capacity (in GB) bFreeSpace - Amount of free space left on the media (in GB) bVersion - Last update date for that media bCopies - Number of existing copies and the status of each copy Return Value: S_OK - If all the parameters could be displayed for the input media --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("ShowMediaParams"), OLESTR("")); try { CWsbStringPtr param; CWsbStringPtr data; WCHAR longData[100]; CWsbStringPtr mediaDescription; GUID mediaSubsystemId; LONGLONG lCapacity, lFreeSpace; FILETIME ftVersion; BOOL bReadOnly, bRecreate; SHORT nNextDataSet; HRESULT hrLast; CWsbStringPtr unusedName; GUID unusedGuid1; GUID unusedGuid2; HSM_JOB_MEDIA_TYPE unusedType; LONGLONG unusedLL1; // Get parameters - it is better to get them all at once even if we don't have to display everything WsbAffirmHr(pMediaInfo->GetMediaInfo(&unusedGuid1, &mediaSubsystemId, &unusedGuid2, &lFreeSpace, &lCapacity, &hrLast, &nNextDataSet, &mediaDescription, 0, &unusedType, &unusedName, 0, &bReadOnly, &ftVersion, &unusedLL1, &bRecreate)); WsbTraceAndPrint(CLI_MESSAGE_MEDIA_PARAMS, (WCHAR *)mediaDescription, NULL); // TEMPORARY: For showing most of these parameters, UI utilities and strings are duplicated // To avoid that, general media utilities should be moved from rsadutil.cpp to Wsb unit // and relevant strings should be moved from HsmAdmin DLL to RsCommon DLL // Name if (bName) { CComPtr pHsm; CComPtr pRms; CComPtr pRmsCart; CWsbBstrPtr rsmName; // Get RSM name WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, g_nullGuid, IID_IHsmServer, (void**)&pHsm)); WsbAffirmHr(pHsm->GetHsmMediaMgr(&pRms)); WsbAffirmHr(pRms->FindCartridgeById(mediaSubsystemId, &pRmsCart)); WsbAffirmHr(pRmsCart->GetName(&rsmName)); if (wcscmp(rsmName, OLESTR("")) == 0 ) { rsmName.Free(); WsbAffirmHr(rsmName.LoadFromRsc(g_hInstance, IDS_CAR_NAME_UNKNOWN)); } // Print WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_MEDIA_RSM_NAME)); WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY, (WCHAR *)param, (WCHAR *)(BSTR)rsmName, NULL); } // Status if (bStatus) { SHORT nLastGoodNextDataSet; ULONG resId; // Get more relevant status info WsbAffirmHr(pMediaInfo->GetLKGMasterNextRemoteDataSet(&nLastGoodNextDataSet)); // Compute status if (bRecreate) { resId = IDS_CAR_STATUS_RECREATE; } else if (nNextDataSet < nLastGoodNextDataSet) { resId = IDS_CAR_STATUS_ERROR_INCOMPLETE; } else if (SUCCEEDED(hrLast) || (RMS_E_CARTRIDGE_DISABLED == hrLast)) { resId = (bReadOnly ? IDS_CAR_STATUS_READONLY : IDS_CAR_STATUS_NORMAL); } else if (RMS_E_CARTRIDGE_NOT_FOUND == hrLast) { resId = IDS_CAR_STATUS_ERROR_MISSING; } else { resId = (bReadOnly ? IDS_CAR_STATUS_ERROR_RO : IDS_CAR_STATUS_ERROR_RW); } // Print WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_MEDIA_STATUS)); WsbAffirmHr(data.LoadFromRsc(g_hInstance, resId)); WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY, (WCHAR *)param, (WCHAR *)data, NULL); } // Capacity if (bCapacity) { WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_MEDIA_CAPACITY)); WsbAffirmHr(ShortSizeFormat64(lCapacity, longData)); WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY, (WCHAR *)param, longData, NULL); } // Free Space if (bFreeSpace) { WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_MEDIA_FREE_SPACE)); WsbAffirmHr(ShortSizeFormat64(lFreeSpace, longData)); WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY, (WCHAR *)param, longData, NULL); } // Version if (bVersion) { data.Free(); WsbAffirmHr(FormatFileTime(ftVersion, &data)); WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_MEDIA_VERSION)); WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY, (WCHAR *)param, (WCHAR *)data, NULL); } // Media copies information if (bCopies) { GUID copySubsystemId; HRESULT copyLastHr; SHORT copyNextRemoteDataSet, lastGoodNextDataSet; ULONG resId; WsbTraceAndPrint(CLI_MESSAGE_MEDIA_COPIES_LIST, NULL); WsbAffirmHr(param.LoadFromRsc(g_hInstance, IDS_MEDIA_COPY)); WsbAffirmHr(pMediaInfo->GetLKGMasterNextRemoteDataSet(&lastGoodNextDataSet)); for (USHORT copyNo=1; copyNo<=HSMADMIN_MAX_COPY_SETS; copyNo++) { // Get copy status information WsbAffirmHr(pMediaInfo->GetCopyMediaSubsystemId(copyNo, ©SubsystemId)); WsbAffirmHr(pMediaInfo->GetCopyLastError(copyNo, ©LastHr)); WsbAffirmHr(pMediaInfo->GetCopyNextRemoteDataSet(copyNo, ©NextRemoteDataSet)); // Compute status switch(copyLastHr) { case RMS_E_CANCELLED: case RMS_E_REQUEST_REFUSED: case RMS_E_WRITE_PROTECT: case RMS_E_MEDIA_OFFLINE: case RMS_E_TIMEOUT: case RMS_E_SCRATCH_NOT_FOUND: case RMS_E_CARTRIDGE_UNAVAILABLE: case RMS_E_CARTRIDGE_DISABLED: copyLastHr = S_OK; break; } if (copySubsystemId == GUID_NULL) { resId = IDS_CAR_COPYSET_NONE; } else if (RMS_E_CARTRIDGE_NOT_FOUND == copyLastHr) { resId = IDS_CAR_COPYSET_MISSING; } else if (FAILED(copyLastHr)) { resId = IDS_CAR_COPYSET_ERROR; } else if (copyNextRemoteDataSet < lastGoodNextDataSet) { resId = IDS_CAR_COPYSET_OUTSYNC; } else { resId = IDS_CAR_COPYSET_INSYNC; } // Print swprintf(longData, param, (int)copyNo); WsbAffirmHr(data.LoadFromRsc(g_hInstance, resId)); WsbTraceAndPrint(CLI_MESSAGE_PARAM_DISPLAY, longData, (WCHAR *)data, NULL); } } } WsbCatch(hr); WsbTraceOut(OLESTR("ShowMediaParams"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return hr; }