windows-nt/Source/XPSP1/NT/base/fs/hsm/rms/server/rmsntms.cpp

4975 lines
189 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
<EFBFBD> 1998 Seagate Software, Inc. All rights reserved
Module Name:
RmsNTMS.cpp
Abstract:
Implementation of CRmsNTMS
Author:
Brian Dodd [brian] 14-May-1997
Revision History:
--*/
#include "stdafx.h"
#include "RmsServr.h"
#include "RmsNTMS.h"
typedef struct RmsNTMSSearchHandle {
WCHAR FindName[NTMS_OBJECTNAME_LENGTH];
NTMS_GUID FindId;
DWORD FindType;
LPNTMS_GUID Objects;
DWORD NumberOfObjects;
DWORD MaxObjects;
DWORD Next;
DWORD LastError;
} RMS_NTMS_SEARCH_HANDLE, *LPRMS_NTMS_SEARCH_HANDLE;
#define ADD_ACE_MASK_BITS 1
#define REMOVE_ACE_MASK_BITS 2
//
// We use application name in RSM interface for media pool name.
// Media pool name is an identifier of the media pool in RSM, therefore, we cannot allow
// this string to be localized. Localizing this string would create another pool after
// installing a foreign language MUI.
//
#define REMOTE_STORAGE_APP_NAME OLESTR("Remote Storage")
/////////////////////////////////////////////////////////////////////////////
// IRmsNTMS implementation
/*
HINSTANCE hInstDll;
typedef DWORD (*FunctionName)( void );
FunctionName FunctionNameFn;
hInstDll = LoadLibrary( "dll" );
FunctionNameFn = (FunctionName) GetProcAddress( hInstDll, "FunctionName" );
result = (FunctionNameFn)();
*/
STDMETHODIMP
CRmsNTMS::FinalConstruct(void)
/*++
Implements:
CComObjectRoot::FinalConstruct
--*/
{
HRESULT hr = S_OK;
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
WsbTraceIn(OLESTR("CRmsNTMS::FinalConstruct"), OLESTR(""));
m_pLibGuids = NULL;
m_dwNofLibs = 0;
try {
WsbAffirmHr(CComObjectRoot::FinalConstruct());
WsbAffirmHr( changeState( RmsNtmsStateStarting ));
m_SessionHandle = INVALID_HANDLE_VALUE;
m_IsRmsConfiguredForNTMS = FALSE;
m_IsNTMSRegistered = FALSE;
m_Name = RMS_NTMS_OBJECT_NAME;
m_Description = RMS_NTMS_OBJECT_DESCRIPTION;
if ( S_OK == getNtmsSupportFromRegistry(NULL) ) {
m_IsRmsConfiguredForNTMS = TRUE;
}
HKEY hKeyMachine = 0;
HKEY hKey = 0;
if ( S_OK == WsbOpenRegistryKey(NULL, RMS_NTMS_REGISTRY_STRING, KEY_QUERY_VALUE, &hKeyMachine, &hKey) ) {
WsbCloseRegistryKey (&hKeyMachine, &hKey);
m_IsNTMSRegistered = TRUE;
}
// Failure precedence.
WsbAffirm(m_IsRmsConfiguredForNTMS, RMS_E_NOT_CONFIGURED_FOR_NTMS);
WsbAffirm(m_IsNTMSRegistered, RMS_E_NTMS_NOT_REGISTERED);
WsbAffirmHr( changeState( RmsNtmsStateStarted ));
} WsbCatchAndDo(hr,
pObject->Disable( hr );
WsbLogEvent(RMS_MESSAGE_NTMS_CONNECTION_NOT_ESABLISHED, 0, NULL, WsbHrAsString(hr), NULL);
// Always construct!
hr = S_OK;
);
WsbTraceOut(OLESTR("CRmsNTMS::FinalConstruct"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return hr;
}
STDMETHODIMP
CRmsNTMS::FinalRelease(void)
/*++
Implements:
CComObjectRoot::FinalRelease
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CRmsNTMS::FinalRelease"), OLESTR(""));
try {
WsbAffirmHr( changeState( RmsNtmsStateStopping ));
endSession();
if (m_pLibGuids) {
WsbFree(m_pLibGuids);
}
CComObjectRoot::FinalRelease();
WsbAffirmHr( changeState( RmsNtmsStateStopped ));
} WsbCatch(hr);
WsbTraceOut(OLESTR("CRmsNTMS::FinalRelease"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return hr;
}
STDMETHODIMP
CRmsNTMS::IsInstalled(void)
{
HRESULT hr = S_OK;
try {
if ( !m_IsEnabled ) {
if ( !m_IsNTMSRegistered ) {
// check again... NTMS can get registered at anytime.
HKEY hKeyMachine = 0;
HKEY hKey = 0;
WsbAffirm(S_OK == WsbOpenRegistryKey(NULL, RMS_NTMS_REGISTRY_STRING, KEY_QUERY_VALUE, &hKeyMachine, &hKey), RMS_E_NTMS_NOT_REGISTERED);
WsbCloseRegistryKey (&hKeyMachine, &hKey);
m_IsNTMSRegistered = TRUE;
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
pObject->Enable();
// now need to initialize
WsbAffirmHr(InitializeInAnotherThread());
}
WsbAffirm(m_IsRmsConfiguredForNTMS, RMS_E_NOT_CONFIGURED_FOR_NTMS);
WsbAffirm(m_IsNTMSRegistered, RMS_E_NTMS_NOT_REGISTERED);
}
} WsbCatch(hr);
return hr;
}
STDMETHODIMP
CRmsNTMS::Initialize(void)
{
HRESULT hr = E_FAIL;
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
WsbTraceIn(OLESTR("CRmsNTMS::Initialize"), OLESTR(""));
try {
WsbAffirmHr( changeState( RmsNtmsStateInitializing ));
if ( INVALID_HANDLE_VALUE == m_SessionHandle ) {
WsbAffirmHr(beginSession());
}
HANDLE hSession = m_SessionHandle;
//
// Create Remote Storage specific NTMS media pools
//
WsbAffirmHr( createMediaPools() );
//
// Report on other NTMS objects of interest
//
HANDLE hFind = NULL;
NTMS_OBJECTINFORMATION objectInfo;
hr = findFirstNtmsObject( NTMS_MEDIA_TYPE, GUID_NULL, NULL, GUID_NULL, &hFind, &objectInfo);
while( S_OK == hr ) {
reportNtmsObjectInformation( &objectInfo );
hr = findNextNtmsObject( hFind, &objectInfo );
}
findCloseNtmsObject( hFind );
hr = findFirstNtmsObject( NTMS_CHANGER, GUID_NULL, NULL, GUID_NULL, &hFind, &objectInfo);
while( S_OK == hr ) {
reportNtmsObjectInformation( &objectInfo );
hr = findNextNtmsObject( hFind, &objectInfo );
}
findCloseNtmsObject( hFind );
hr = findFirstNtmsObject( NTMS_CHANGER_TYPE, GUID_NULL, NULL, GUID_NULL, &hFind, &objectInfo);
while( S_OK == hr ) {
reportNtmsObjectInformation( &objectInfo );
hr = findNextNtmsObject( hFind, &objectInfo );
}
findCloseNtmsObject( hFind );
hr = findFirstNtmsObject( NTMS_DRIVE, GUID_NULL, NULL, GUID_NULL, &hFind, &objectInfo);
while( S_OK == hr ) {
reportNtmsObjectInformation( &objectInfo );
hr = findNextNtmsObject( hFind, &objectInfo );
}
findCloseNtmsObject( hFind );
hr = findFirstNtmsObject( NTMS_DRIVE_TYPE, GUID_NULL, NULL, GUID_NULL, &hFind, &objectInfo);
while( S_OK == hr ) {
reportNtmsObjectInformation( &objectInfo );
hr = findNextNtmsObject( hFind, &objectInfo );
}
findCloseNtmsObject( hFind );
WsbAffirmHr( changeState( RmsNtmsStateReady ));
hr = S_OK;
} WsbCatchAndDo(hr,
pObject->Disable( hr );
WsbLogEvent( RMS_MESSAGE_NTMS_INITIALIZATION_FAILED, 0, NULL, WsbHrAsString(hr), NULL );
);
WsbTraceOut( OLESTR("CRmsNTMS::Initialize"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
return hr;
}
HRESULT
CRmsNTMS::findFirstNtmsObject(
IN DWORD objectType,
IN REFGUID containerId,
IN WCHAR *objectName,
IN REFGUID objectId,
OUT HANDLE *hFindObject,
OUT LPNTMS_OBJECTINFORMATION pFindObjectData
)
{
HRESULT hr = E_FAIL;
try {
int maxObjects = 16; // Initial size of object id array to allocate
LPRMS_NTMS_SEARCH_HANDLE pFind;
HANDLE hSession = m_SessionHandle;
DWORD errCode;
DWORD numberOfObjects = maxObjects;
LPNTMS_GUID pId = ( containerId == GUID_NULL ) ? NULL : (GUID *)&containerId;
LPNTMS_GUID pObjects = NULL;
NTMS_OBJECTINFORMATION objectInfo;
WsbAssertPointer( hFindObject );
if ( INVALID_HANDLE_VALUE == hSession ) {
WsbThrow( E_UNEXPECTED );
}
*hFindObject = NULL;
memset( &objectInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
pObjects = (LPNTMS_GUID)WsbAlloc( maxObjects*sizeof(NTMS_GUID) );
WsbAffirmPointer( pObjects );
// NTMS - enumerate all objects of the given type
WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
errCode = EnumerateNtmsObject( hSession, pId, pObjects, &numberOfObjects, objectType, 0 );
if ( (ERROR_OBJECT_NOT_FOUND == errCode) || (0 == numberOfObjects) ) { // Don't count on NTMS returning the correct errCode
WsbThrow( RMS_E_NTMS_OBJECT_NOT_FOUND );
}
else if ( ERROR_INSUFFICIENT_BUFFER == errCode ) {
while ( ERROR_INSUFFICIENT_BUFFER == errCode ) {
// Allocate a new buffer, and retry.
WsbTrace(OLESTR("CRmsNTMS::findFirstNtmsObject - Reallocating for %d objects @1.\n"), numberOfObjects);
maxObjects = numberOfObjects;
LPVOID pTemp = WsbRealloc( pObjects, maxObjects*sizeof(NTMS_GUID) );
if( !pTemp ) {
WsbFree( pObjects );
WsbThrow( E_OUTOFMEMORY );
}
pObjects = (LPNTMS_GUID)pTemp;
// NTMS - enumerate all objects of the given type
WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
errCode = EnumerateNtmsObject( hSession, pId, pObjects, &numberOfObjects, objectType, 0 );
}
}
WsbAffirmNoError( errCode );
HANDLE hTemp = (HANDLE)WsbAlloc( sizeof( RMS_NTMS_SEARCH_HANDLE) );
*hFindObject = hTemp;
WsbAffirmPointer( *hFindObject );
pFind = (LPRMS_NTMS_SEARCH_HANDLE)*hFindObject;
// Initialize the search handle
if ( objectName ) {
wcscpy( pFind->FindName, objectName );
}
else {
wcscpy( pFind->FindName, OLESTR("") );
}
pFind->FindId = objectId;
pFind->FindType = objectType;
pFind->Objects = pObjects;
pFind->NumberOfObjects = numberOfObjects;
pFind->MaxObjects = maxObjects;
pFind->Next = 0;
pFind->LastError = NO_ERROR;
BOOL bFound = FALSE;
while( pFind->Next < pFind->NumberOfObjects ) {
objectInfo.dwType = pFind->FindType;
objectInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
// NTMS - Get object information
WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
errCode = GetNtmsObjectInformation( hSession, &pObjects[pFind->Next++], &objectInfo );
pFind->LastError = errCode;
// Media Pools require special handling because they contain other Media Pools
if ( (NTMS_MEDIA_POOL == pFind->FindType) &&
(objectInfo.Info.MediaPool.dwNumberOfMediaPools > 0) ) {
DWORD numberToAdd = objectInfo.Info.MediaPool.dwNumberOfMediaPools;
do {
numberOfObjects = pFind->NumberOfObjects + numberToAdd;
// Allocate a new buffer, and retry.
WsbTrace(OLESTR("CRmsNTMS::findFirstNtmsObject - Reallocating for %d objects @2.\n"), numberOfObjects);
maxObjects = numberOfObjects;
pObjects = (LPNTMS_GUID)WsbRealloc( pFind->Objects, maxObjects*sizeof(NTMS_GUID) );
WsbAffirmAlloc( pObjects );
pFind->Objects = pObjects;
// NTMS - enumerate all objects of the given type
WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
errCode = EnumerateNtmsObject( hSession,
&objectInfo.ObjectGuid, &pObjects[pFind->NumberOfObjects],
&numberToAdd, pFind->FindType, 0 );
} while ( ERROR_INSUFFICIENT_BUFFER == errCode ) ;
if ( NO_ERROR == errCode ) {
pFind->NumberOfObjects += numberToAdd;
pFind->MaxObjects = maxObjects;
}
else {
WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
OLESTR("EnumerateNtmsObject"),
WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
NULL );
WsbAffirmNoError(errCode);
}
}
if ( NO_ERROR == pFind->LastError ) {
// Now see if it is the one we're looking for
if ( GUID_NULL != pFind->FindId ) {
if ( pFind->FindId == objectInfo.ObjectGuid ) { // Match the GUID
bFound = TRUE;
if ( pFindObjectData != NULL ) {
memcpy( pFindObjectData, &objectInfo, sizeof( NTMS_OBJECTINFORMATION ) );
}
break;
}
}
else if ( wcslen( pFind->FindName ) > 0 ) { // Match the Name
if ( 0 == wcscmp( pFind->FindName, objectInfo.szName ) ) {
bFound = TRUE;
if ( pFindObjectData != NULL ) {
memcpy( pFindObjectData, &objectInfo, sizeof( NTMS_OBJECTINFORMATION ) );
}
break;
}
}
else { // Any GUID or Name
bFound = TRUE;
if ( pFindObjectData != NULL ) {
memcpy( pFindObjectData, &objectInfo, sizeof( NTMS_OBJECTINFORMATION ) );
}
break;
}
}
else {
WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
OLESTR("GetNTMSObjectInformation"),
WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
NULL );
WsbThrow( RMS_E_NTMS_OBJECT_NOT_FOUND );
}
}
hr = ( bFound ) ? S_OK : RMS_E_NTMS_OBJECT_NOT_FOUND;
} WsbCatch(hr);
return hr;
}
HRESULT
CRmsNTMS::findNextNtmsObject(
IN HANDLE hFindObject,
OUT LPNTMS_OBJECTINFORMATION pFindObjectData
)
{
HRESULT hr = E_FAIL;
try {
HANDLE hSession = m_SessionHandle;
DWORD errCode;
LPRMS_NTMS_SEARCH_HANDLE pFind = (LPRMS_NTMS_SEARCH_HANDLE)hFindObject;
LPNTMS_GUID pObjects = pFind->Objects;
NTMS_OBJECTINFORMATION objectInfo;
if ( INVALID_HANDLE_VALUE == hSession ) {
WsbThrow( E_UNEXPECTED );
}
BOOL bFound = FALSE;
while( pFind->Next < pFind->NumberOfObjects ) {
objectInfo.dwType = pFind->FindType;
objectInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
// NTMS - get object information of next object
WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
errCode = GetNtmsObjectInformation( hSession, &pObjects[pFind->Next++], &objectInfo );
pFind->LastError = errCode;
// Media Pools require special handling because they contain other Media Pools
if ( (NTMS_MEDIA_POOL == pFind->FindType) &&
(objectInfo.Info.MediaPool.dwNumberOfMediaPools > 0) ) {
DWORD maxObjects;
DWORD numberOfObjects;
DWORD numberToAdd = objectInfo.Info.MediaPool.dwNumberOfMediaPools;
do {
numberOfObjects = pFind->NumberOfObjects + numberToAdd;
// Allocate a new buffer, and retry.
WsbTrace(OLESTR("CRmsNTMS::findNextNtmsObject - Reallocating for %d objects.\n"), numberOfObjects);
maxObjects = numberOfObjects;
pObjects = (LPNTMS_GUID)WsbRealloc( pFind->Objects, maxObjects*sizeof(NTMS_GUID) );
WsbAffirmAlloc( pObjects );
pFind->Objects = pObjects;
// NTMS - enumerate all objects of the given type
WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
errCode = EnumerateNtmsObject( hSession,
&objectInfo.ObjectGuid, &pObjects[pFind->NumberOfObjects],
&numberToAdd, pFind->FindType, 0 );
} while ( ERROR_INSUFFICIENT_BUFFER == errCode ) ;
if ( NO_ERROR == errCode ) {
pFind->NumberOfObjects += numberToAdd;
pFind->MaxObjects = maxObjects;
}
else {
WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
OLESTR("EnumerateNtmsObject"),
WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
NULL );
WsbAffirmNoError(errCode);
}
}
if ( NO_ERROR == pFind->LastError ) {
// Now see if it is the one we're looking for
if ( GUID_NULL != pFind->FindId ) {
if ( pFind->FindId == objectInfo.ObjectGuid ) { // Match the GUID
bFound = TRUE;
if ( pFindObjectData != NULL ) {
memcpy( pFindObjectData, &objectInfo, sizeof( NTMS_OBJECTINFORMATION ) );
}
break;
}
}
else if ( wcslen( pFind->FindName ) > 0 ) { // Match the Name
if ( 0 == wcscmp( pFind->FindName, objectInfo.szName ) ) {
bFound = TRUE;
if ( pFindObjectData != NULL ) {
memcpy( pFindObjectData, &objectInfo, sizeof( NTMS_OBJECTINFORMATION ) );
}
break;
}
}
else { // Any GUID or Name
bFound = TRUE;
if ( pFindObjectData != NULL ) {
memcpy( pFindObjectData, &objectInfo, sizeof( NTMS_OBJECTINFORMATION ) );
}
break;
}
}
else {
WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
OLESTR("GetNTMSObjectInformation"),
WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
NULL );
WsbThrow( RMS_E_NTMS_OBJECT_NOT_FOUND );
}
}
hr = (bFound) ? S_OK : RMS_E_NTMS_OBJECT_NOT_FOUND;
} WsbCatch(hr);
return hr;
}
HRESULT
CRmsNTMS::findCloseNtmsObject(
IN HANDLE hFindObject)
{
HRESULT hr = S_OK;
try {
WsbAffirmPointer(hFindObject); // We don't need to assert here... It's possible to call
// findCloseNtmsObject even if nothing was found with
// findFirstNtmsObject. Skip the free step.
WsbFree(((LPRMS_NTMS_SEARCH_HANDLE)hFindObject)->Objects);
WsbFree(hFindObject);
} WsbCatch(hr);
return hr;
}
HRESULT
CRmsNTMS::reportNtmsObjectInformation(
IN LPNTMS_OBJECTINFORMATION pObjectInfo)
{
HRESULT hr = S_OK;
static DWORD lastTypeReported = 0;
try {
WsbAssertPointer( pObjectInfo );
BOOL bHeaders = (lastTypeReported == pObjectInfo->dwType) ? FALSE : TRUE;
lastTypeReported = pObjectInfo->dwType;
// Output a header to trace file
if ( bHeaders ) {
switch ( pObjectInfo->dwType ) {
case NTMS_UNKNOWN:
case NTMS_OBJECT:
WsbTrace( OLESTR("!!! WARNING !!! - CRmsServer::reportNtmsObjectInformation: report for NTMS object type: %d is not available.\n") );
break;
case NTMS_CHANGER:
break;
case NTMS_CHANGER_TYPE:
break;
case NTMS_COMPUTER:
WsbTrace( OLESTR("!!! WARNING !!! - CRmsServer::reportNtmsObjectInformation: report for NTMS object type: %d is not available.\n") );
break;
case NTMS_DRIVE:
case NTMS_DRIVE_TYPE:
break;
case NTMS_IEDOOR:
case NTMS_IEPORT:
WsbTrace( OLESTR("!!! WARNING !!! - CRmsServer::reportNtmsObjectInformation: report for NTMS object type: %d is not available.\n") );
break;
case NTMS_LIBRARY:
break;
case NTMS_LIBREQUEST:
case NTMS_LOGICAL_MEDIA:
WsbTrace( OLESTR("!!! WARNING !!! - CRmsServer::reportNtmsObjectInformation: report for NTMS object type: %d is not available.\n") );
break;
case NTMS_MEDIA_POOL:
WsbTrace( OLESTR("GUID Enabl Type Media Type GUID Parent GUID A-Pol D-Pol Allocate Physical Logical Pools Name / Description\n") );
WsbTrace( OLESTR("====================================== ===== ==== ====================================== ====================================== ===== ===== ======== ======== ======== ===== ========================================\n") );
break;
case NTMS_MEDIA_TYPE:
WsbTrace( OLESTR("GUID Enabl Type Sides RW Name / Description\n") );
WsbTrace( OLESTR("====================================== ===== ==== ===== == ========================================\n") );
break;
case NTMS_PARTITION:
break;
case NTMS_PHYSICAL_MEDIA:
case NTMS_STORAGESLOT:
case NTMS_OPREQUEST:
default:
WsbTrace( OLESTR("!!! WARNING !!! - CRmsServer::reportNtmsObjectInformation: report for object type: %d is not supported\n") );
break;
}
}
// Convert SYSTEMTIME to FILETIME for output.
SYSTEMTIME sCreated, sModified;
FILETIME fCreated, fModified;
sCreated = pObjectInfo->Created;
sModified = pObjectInfo->Modified;
SystemTimeToFileTime(&sCreated, &fCreated);
SystemTimeToFileTime(&sModified, &fModified);
switch ( pObjectInfo->dwType ) {
case NTMS_UNKNOWN:
case NTMS_OBJECT:
break;
case NTMS_CHANGER:
WsbTrace(OLESTR("Changer %d Information:\n"), pObjectInfo->Info.Changer.Number );
WsbTrace(OLESTR(" GUID........... %-ls\n"), WsbGuidAsString(pObjectInfo->ObjectGuid) );
WsbTrace(OLESTR(" Name........... <%-ls>\n"), pObjectInfo->szName );
WsbTrace(OLESTR(" Description.... <%-ls>\n"), pObjectInfo->szDescription );
WsbTrace(OLESTR(" Enabled........ %-ls\n"), WsbBoolAsString(pObjectInfo->Enabled) );
WsbTrace(OLESTR(" Op State....... %-ls\n"), WsbLongAsString(pObjectInfo->dwOperationalState) );
WsbTrace(OLESTR(" Created........ %-ls\n"), WsbFiletimeAsString(FALSE, fCreated) );
WsbTrace(OLESTR(" Modified....... %-ls\n"), WsbFiletimeAsString(FALSE, fModified) );
WsbTrace(OLESTR(" Number......... %-d\n"), pObjectInfo->Info.Changer.Number );
WsbTrace(OLESTR(" Changer Type... %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Changer.ChangerType) );
WsbTrace(OLESTR(" Serial Number.. <%-ls>\n"), pObjectInfo->Info.Changer.szSerialNumber );
WsbTrace(OLESTR(" Revision....... <%-ls>\n"), pObjectInfo->Info.Changer.szRevision );
WsbTrace(OLESTR(" Device Name.... <%-ls>\n"), pObjectInfo->Info.Changer.szDeviceName );
WsbTrace(OLESTR(" SCSI Port...... %-d\n"), pObjectInfo->Info.Changer.ScsiPort );
WsbTrace(OLESTR(" SCSI Bus....... %-d\n"), pObjectInfo->Info.Changer.ScsiBus );
WsbTrace(OLESTR(" SCSI Target.... %-d\n"), pObjectInfo->Info.Changer.ScsiTarget );
WsbTrace(OLESTR(" SCSI Lun....... %-d\n"), pObjectInfo->Info.Changer.ScsiLun );
WsbTrace(OLESTR(" Library....... %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Changer.Library) );
break;
case NTMS_CHANGER_TYPE:
WsbTrace(OLESTR("Changer Type Information:\n") );
WsbTrace(OLESTR(" GUID........... %-ls\n"), WsbGuidAsString(pObjectInfo->ObjectGuid) );
WsbTrace(OLESTR(" Name........... <%-ls>\n"), pObjectInfo->szName );
WsbTrace(OLESTR(" Description.... <%-ls>\n"), pObjectInfo->szDescription );
WsbTrace(OLESTR(" Enabled........ %-ls\n"), WsbBoolAsString(pObjectInfo->Enabled) );
WsbTrace(OLESTR(" Op State....... %-ls\n"), WsbLongAsString(pObjectInfo->dwOperationalState) );
WsbTrace(OLESTR(" Created........ %-ls\n"), WsbFiletimeAsString(FALSE, fCreated) );
WsbTrace(OLESTR(" Modified....... %-ls\n"), WsbFiletimeAsString(FALSE, fModified) );
WsbTrace(OLESTR(" Vendor......... <%-ls>\n"), pObjectInfo->Info.ChangerType.szVendor );
WsbTrace(OLESTR(" Product........ <%-ls>\n"), pObjectInfo->Info.ChangerType.szProduct );
WsbTrace(OLESTR(" Device Type.... %-d\n"), pObjectInfo->Info.ChangerType.DeviceType );
break;
case NTMS_COMPUTER:
break;
case NTMS_DRIVE:
WsbTrace(OLESTR("Drive %d Information:\n"), pObjectInfo->Info.Drive.Number );
WsbTrace(OLESTR(" GUID........... %-ls\n"), WsbGuidAsString(pObjectInfo->ObjectGuid) );
WsbTrace(OLESTR(" Name........... <%-ls>\n"), pObjectInfo->szName );
WsbTrace(OLESTR(" Description.... <%-ls>\n"), pObjectInfo->szDescription );
WsbTrace(OLESTR(" Enabled........ %-ls\n"), WsbBoolAsString(pObjectInfo->Enabled) );
WsbTrace(OLESTR(" Op State....... %-ls\n"), WsbLongAsString(pObjectInfo->dwOperationalState) );
WsbTrace(OLESTR(" Created........ %-ls\n"), WsbFiletimeAsString(FALSE, fCreated) );
WsbTrace(OLESTR(" Modified....... %-ls\n"), WsbFiletimeAsString(FALSE, fModified) );
WsbTrace(OLESTR(" Number......... %-d\n"), pObjectInfo->Info.Drive.Number );
WsbTrace(OLESTR(" State.......... %-d\n"), pObjectInfo->Info.Drive.State );
WsbTrace(OLESTR(" Drive Type..... %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Drive.DriveType) );
WsbTrace(OLESTR(" Device Name.... <%-ls>\n"), pObjectInfo->Info.Drive.szDeviceName );
WsbTrace(OLESTR(" Serial Number.. <%-ls>\n"), pObjectInfo->Info.Drive.szSerialNumber );
WsbTrace(OLESTR(" Revision....... <%-ls>\n"), pObjectInfo->Info.Drive.szRevision );
WsbTrace(OLESTR(" SCSI Port...... %-d\n"), pObjectInfo->Info.Drive.ScsiPort );
WsbTrace(OLESTR(" SCSI Bus....... %-d\n"), pObjectInfo->Info.Drive.ScsiBus );
WsbTrace(OLESTR(" SCSI Target.... %-d\n"), pObjectInfo->Info.Drive.ScsiTarget );
WsbTrace(OLESTR(" SCSI Lun....... %-d\n"), pObjectInfo->Info.Drive.ScsiLun );
WsbTrace(OLESTR(" Mount Count.... %-d\n"), pObjectInfo->Info.Drive.dwMountCount );
WsbTrace(OLESTR(" Last Cleaned... %02d/%02d/%02d %02d:%02d:%02d.%03d\n"),
pObjectInfo->Info.Drive.LastCleanedTs.wMonth,
pObjectInfo->Info.Drive.LastCleanedTs.wDay,
pObjectInfo->Info.Drive.LastCleanedTs.wYear,
pObjectInfo->Info.Drive.LastCleanedTs.wHour,
pObjectInfo->Info.Drive.LastCleanedTs.wMinute,
pObjectInfo->Info.Drive.LastCleanedTs.wSecond,
pObjectInfo->Info.Drive.LastCleanedTs.wMilliseconds );
WsbTrace(OLESTR(" Partition...... %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Drive.SavedPartitionId) );
WsbTrace(OLESTR(" Library........ %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Drive.Library) );
break;
case NTMS_DRIVE_TYPE:
WsbTrace(OLESTR("Drive Type Information:\n") );
WsbTrace(OLESTR(" GUID........... %-ls\n"), WsbGuidAsString(pObjectInfo->ObjectGuid) );
WsbTrace(OLESTR(" Name........... <%-ls>\n"), pObjectInfo->szName );
WsbTrace(OLESTR(" Description.... <%-ls>\n"), pObjectInfo->szDescription );
WsbTrace(OLESTR(" Enabled........ %-ls\n"), WsbBoolAsString(pObjectInfo->Enabled) );
WsbTrace(OLESTR(" Op State....... %-ls\n"), WsbLongAsString(pObjectInfo->dwOperationalState) );
WsbTrace(OLESTR(" Created........ %-ls\n"), WsbFiletimeAsString(FALSE, fCreated) );
WsbTrace(OLESTR(" Modified....... %-ls\n"), WsbFiletimeAsString(FALSE, fModified) );
WsbTrace(OLESTR(" Vendor......... <%-ls>\n"), pObjectInfo->Info.DriveType.szVendor );
WsbTrace(OLESTR(" Product........ <%-ls>\n"), pObjectInfo->Info.DriveType.szProduct );
WsbTrace(OLESTR(" Number of Heads %-d\n"), pObjectInfo->Info.DriveType.NumberOfHeads );
WsbTrace(OLESTR(" Device Type.... %-d\n"), pObjectInfo->Info.DriveType.DeviceType );
break;
case NTMS_IEDOOR:
case NTMS_IEPORT:
break;
case NTMS_LIBRARY:
WsbTrace(OLESTR("Library Information:\n") );
WsbTrace(OLESTR(" GUID........... %-ls\n"), WsbGuidAsString(pObjectInfo->ObjectGuid) );
WsbTrace(OLESTR(" Name........... <%-ls>\n"), pObjectInfo->szName );
WsbTrace(OLESTR(" Description.... <%-ls>\n"), pObjectInfo->szDescription );
WsbTrace(OLESTR(" Enabled........ %-ls\n"), WsbBoolAsString(pObjectInfo->Enabled) );
WsbTrace(OLESTR(" Op State....... %-ls\n"), WsbLongAsString(pObjectInfo->dwOperationalState) );
WsbTrace(OLESTR(" Created........ %-ls\n"), WsbFiletimeAsString(FALSE, fCreated) );
WsbTrace(OLESTR(" Modified....... %-ls\n"), WsbFiletimeAsString(FALSE, fModified) );
WsbTrace(OLESTR(" Library Type... %-d\n"), pObjectInfo->Info.Library.LibraryType );
WsbTrace(OLESTR(" CleanerSlot.... %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Library.CleanerSlot) );
WsbTrace(OLESTR(" CleanerSlotD... %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Library.CleanerSlotDefault) );
WsbTrace(OLESTR(" Can Clean...... %-ls\n"), WsbBoolAsString(pObjectInfo->Info.Library.LibrarySupportsDriveCleaning) );
WsbTrace(OLESTR(" Has Bar Code... %-ls\n"), WsbBoolAsString(pObjectInfo->Info.Library.BarCodeReaderInstalled) );
WsbTrace(OLESTR(" Inventory Method %-d\n"), pObjectInfo->Info.Library.InventoryMethod );
WsbTrace(OLESTR(" Cleans Remaining %-d\n"), pObjectInfo->Info.Library.dwCleanerUsesRemaining );
WsbTrace(OLESTR(" Drives......... %-d (%d)\n"),
pObjectInfo->Info.Library.dwNumberOfDrives,
pObjectInfo->Info.Library.FirstDriveNumber);
WsbTrace(OLESTR(" Slots.......... %-d (%d)\n"),
pObjectInfo->Info.Library.dwNumberOfSlots,
pObjectInfo->Info.Library.FirstSlotNumber);
WsbTrace(OLESTR(" Doors.......... %-d (%d)\n"),
pObjectInfo->Info.Library.dwNumberOfDoors,
pObjectInfo->Info.Library.FirstDoorNumber);
WsbTrace(OLESTR(" Ports.......... %-d (%d)\n"),
pObjectInfo->Info.Library.dwNumberOfPorts,
pObjectInfo->Info.Library.FirstPortNumber);
WsbTrace(OLESTR(" Changers....... %-d (%d)\n"),
pObjectInfo->Info.Library.dwNumberOfChangers,
pObjectInfo->Info.Library.FirstChangerNumber);
WsbTrace(OLESTR(" Media Count.... %-d\n"), pObjectInfo->Info.Library.dwNumberOfMedia );
WsbTrace(OLESTR(" Media Types.... %-d\n"), pObjectInfo->Info.Library.dwNumberOfMediaTypes );
WsbTrace(OLESTR(" Requests....... %-d\n"), pObjectInfo->Info.Library.dwNumberOfLibRequests );
break;
case NTMS_LIBREQUEST:
case NTMS_LOGICAL_MEDIA:
break;
case NTMS_MEDIA_POOL:
{
// We need some temporaries since WsbGuidAsString() uses static memory to store string.
CWsbStringPtr g1 = pObjectInfo->ObjectGuid;
CWsbStringPtr g2 = pObjectInfo->Info.MediaPool.MediaType;
CWsbStringPtr g3 = pObjectInfo->Info.MediaPool.Parent;
WsbTrace( OLESTR("%ls %5ls %4d %ls %ls %5d %5d %8d %8d %8d %5d <%ls> / <%ls>\n"),
(WCHAR *)g1,
WsbBoolAsString(pObjectInfo->Enabled),
pObjectInfo->Info.MediaPool.PoolType,
(WCHAR *)g2,
(WCHAR *)g3,
pObjectInfo->Info.MediaPool.AllocationPolicy,
pObjectInfo->Info.MediaPool.DeallocationPolicy,
pObjectInfo->Info.MediaPool.dwMaxAllocates,
pObjectInfo->Info.MediaPool.dwNumberOfPhysicalMedia,
pObjectInfo->Info.MediaPool.dwNumberOfLogicalMedia,
pObjectInfo->Info.MediaPool.dwNumberOfMediaPools,
pObjectInfo->szName,
pObjectInfo->szDescription );
}
break;
case NTMS_MEDIA_TYPE:
WsbTrace( OLESTR("%ls %5ls %4d %5d %2d <%ls> / <%ls>\n"),
WsbGuidAsString(pObjectInfo->ObjectGuid),
WsbBoolAsString(pObjectInfo->Enabled),
pObjectInfo->Info.MediaType.MediaType,
pObjectInfo->Info.MediaType.NumberOfSides,
pObjectInfo->Info.MediaType.ReadWriteCharacteristics,
pObjectInfo->szName,
pObjectInfo->szDescription );
break;
case NTMS_PARTITION:
WsbTrace(OLESTR("Partion Information:\n") );
WsbTrace(OLESTR(" GUID........... %-ls\n"), WsbGuidAsString(pObjectInfo->ObjectGuid) );
WsbTrace(OLESTR(" Name........... <%-ls>\n"), pObjectInfo->szName );
WsbTrace(OLESTR(" Description.... <%-ls>\n"), pObjectInfo->szDescription );
WsbTrace(OLESTR(" Enabled........ %-ls\n"), WsbBoolAsString(pObjectInfo->Enabled) );
WsbTrace(OLESTR(" Op State....... %-ls\n"), WsbLongAsString(pObjectInfo->dwOperationalState) );
WsbTrace(OLESTR(" Created........ %-ls\n"), WsbFiletimeAsString(FALSE, fCreated) );
WsbTrace(OLESTR(" Modified....... %-ls\n"), WsbFiletimeAsString(FALSE, fModified) );
WsbTrace(OLESTR(" PhysicalMedia.. %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Partition.PhysicalMedia));
WsbTrace(OLESTR(" LogicalMedia... %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Partition.LogicalMedia));
WsbTrace(OLESTR(" State.......... %-d\n"), pObjectInfo->Info.Partition.State);
WsbTrace(OLESTR(" Side........... %-d\n"), pObjectInfo->Info.Partition.Side);
WsbTrace(OLESTR(" OmidLabelIdLen %-d\n"), pObjectInfo->Info.Partition.dwOmidLabelIdLength);
WsbTrace(OLESTR(" OmidLableId:\n"));
WsbTraceBuffer(pObjectInfo->Info.Partition.dwOmidLabelIdLength, pObjectInfo->Info.Partition.OmidLabelId);
WsbTrace(OLESTR(" OmidLabelType.. %-ls\n"), pObjectInfo->Info.Partition.szOmidLabelType);
WsbTrace(OLESTR(" OmidLabelInfo.. %-ls\n"), pObjectInfo->Info.Partition.szOmidLabelInfo);
WsbTrace(OLESTR(" MountCount..... %-d\n"), pObjectInfo->Info.Partition.dwMountCount);
WsbTrace(OLESTR(" AllocateCount.. %-d\n"), pObjectInfo->Info.Partition.dwAllocateCount);
WsbTrace(OLESTR(" Capacity....... %-I64d\n"), pObjectInfo->Info.Partition.Capacity.QuadPart);
break;
case NTMS_PHYSICAL_MEDIA:
case NTMS_STORAGESLOT:
case NTMS_OPREQUEST:
default:
break;
}
} WsbCatch(hr);
return hr;
}
HRESULT
CRmsNTMS::getNtmsSupportFromRegistry(
OUT DWORD *pNTMSSupportValue)
/*++
Routine Description:
Determines if NTMS flag is set in the Registry.
Arguments:
pNTMSSupportValue - Receives the actual value of the regstry key value. Any non-zero
values indicates NTMS support.
Return Values:
S_OK - NTMS support flag is on.
S_FALSE - NTMS support flag is off.
--*/
{
HRESULT hr = S_OK;
DWORD val = RMS_DEFAULT_NTMS_SUPPORT;
WsbTraceIn(OLESTR("CRmsNTMS::getNtmsSupportFromRegistry"), OLESTR(""));
try {
DWORD sizeGot;
const int cDataSizeToGet = 100;
OLECHAR dataString[cDataSizeToGet];
OLECHAR *stopString;
//
// Get the value. If the key doesn't exists, the default value is used.
//
try {
WsbAffirmHrOk(WsbEnsureRegistryKeyExists(NULL, RMS_REGISTRY_STRING));
WsbAffirmHrOk(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_NTMS_SUPPORT,
dataString, cDataSizeToGet, &sizeGot));
val = wcstoul(dataString, &stopString, 10);
} WsbCatch(hr);
if (pNTMSSupportValue != NULL) {
*pNTMSSupportValue = val;
}
hr = (val) ? S_OK : S_FALSE;
} WsbCatchAndDo( hr,
hr = S_FALSE;
);
WsbTraceOut(OLESTR("CRmsNTMS::getNtmsSupportFromRegistry"), OLESTR("hr = <%ls>, val = <%ld>"), WsbHrAsString(hr), val);
return hr;
}
HRESULT
CRmsNTMS::beginSession(void)
/*++
Implements:
CRmsNTMS::beginSession
--*/
{
HRESULT hr = S_OK;
WsbTraceIn( OLESTR("CRmsNTMS::beginSession"), OLESTR("") );
try {
WsbAffirmHrOk(IsInstalled());
WsbAffirmHrOk(endSession()); // clear the old session
WsbAffirmHrOk(waitUntilReady()); // starts a new session
//WsbAffirmHrOk(waitForScratchPool());
} WsbCatch(hr);
WsbTraceOut( OLESTR("CRmsNTMS::beginSession"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
return hr;
}
HRESULT
CRmsNTMS::endSession(void)
/*++
Implements:
CRmsNTMS::endSession
--*/
{
HRESULT hr = S_OK;
WsbTraceIn( OLESTR("CRmsNTMS::endSession"), OLESTR("") );
try {
if ( m_SessionHandle != INVALID_HANDLE_VALUE ) {
// NTMS - Close session
WsbTraceAlways(OLESTR("CloseNtmsSession()\n"));
WsbAffirmNoError(CloseNtmsSession(m_SessionHandle));
}
} WsbCatchAndDo(hr,
switch (HRESULT_CODE(hr)) {
case ERROR_CONNECTION_UNAVAIL:
case ERROR_INVALID_HANDLE:
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("CloseNtmsSession"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
);
m_SessionHandle = INVALID_HANDLE_VALUE;
hr = S_OK;
WsbTraceOut( OLESTR("CRmsNTMS::endSession"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
return hr;
}
HRESULT
CRmsNTMS::waitUntilReady(void)
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CRmsNTMS::waitUntilReady"), OLESTR(""));
try {
int retry = 360; // number of retries
// Retrieve the NotificationWaitTime parameter
DWORD size;
OLECHAR tmpString[256];
DWORD notificationWaitTime = RMS_DEFAULT_NOTIFICATION_WAIT_TIME;
if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_NOTIFICATION_WAIT_TIME, tmpString, 256, &size))) {
notificationWaitTime = wcstol(tmpString, NULL, 10);
WsbTrace(OLESTR("NotificationWaitTime is %d milliseconds.\n"), notificationWaitTime);
}
do {
// NTMS - Open session
WsbTraceAlways(OLESTR("OpenNtmsSession()\n"));
CWsbStringPtr appName;
WsbAffirmHr(appName.LoadFromRsc(_Module.m_hInst, IDS_PRODUCT_NAME));
m_SessionHandle = OpenNtmsSession(NULL, (WCHAR *) appName, 0);
if ( m_SessionHandle != INVALID_HANDLE_VALUE ) {
break;
}
else {
hr = HRESULT_FROM_WIN32(GetLastError());
switch (HRESULT_CODE(hr)) {
case ERROR_NOT_READY:
if ( retry > 0 ) {
WsbTrace(OLESTR("Waiting for NTMS to come ready - Seconds remaining before timeout: %d\n"), retry*notificationWaitTime/1000);
Sleep(notificationWaitTime);
hr = S_OK;
}
else {
//
// This is the last try, so log the failure.
//
WsbLogEvent(RMS_MESSAGE_NTMS_CONNECTION_NOT_ESABLISHED,
0, NULL, WsbHrAsString(hr), NULL);
WsbThrow(RMS_E_NTMS_NOT_CONNECTED);
}
break;
case ERROR_INVALID_COMPUTERNAME:
case ERROR_INVALID_PARAMETER:
case ERROR_NO_NETWORK:
case ERROR_NOT_CONNECTED:
WsbLogEvent(RMS_MESSAGE_NTMS_CONNECTION_NOT_ESABLISHED,
0, NULL, WsbHrAsString(hr), NULL);
WsbThrow(hr);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("OpenNtmsSession"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
WsbThrow(hr);
break;
}
}
} while( retry-- > 0 ) ;
} WsbCatch(hr);
WsbTraceOut(OLESTR("CRmsNTMS::waitUntilReady"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return hr;
}
HRESULT
CRmsNTMS::waitForScratchPool(void)
{
HRESULT hr = S_OK;
DWORD err1 = NO_ERROR;
DWORD err2 = NO_ERROR;
DWORD err3 = NO_ERROR;
HANDLE hNotify = INVALID_HANDLE_VALUE;
WsbTraceIn(OLESTR("CRmsNTMS::waitForScratchPool"), OLESTR(""));
try {
int retry = 60; // number of retries
// Retrieve the NotificationWaitTime parameter
DWORD size;
OLECHAR tmpString[256];
DWORD notificationWaitTime = RMS_DEFAULT_NOTIFICATION_WAIT_TIME;
if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_NOTIFICATION_WAIT_TIME, tmpString, 256, &size))) {
notificationWaitTime = wcstol(tmpString, NULL, 10);
WsbTrace(OLESTR("NotificationWaitTime is %d milliseconds.\n"), notificationWaitTime);
}
if ( INVALID_HANDLE_VALUE == m_SessionHandle ) {
WsbThrow(E_UNEXPECTED);
}
HANDLE hSession = m_SessionHandle;
NTMS_OBJECTINFORMATION objectInfo;
NTMS_OBJECTINFORMATION scratchInfo;
NTMS_NOTIFICATIONINFORMATION notifyInfo;
HANDLE hFind = NULL;
BOOL bFound = FALSE;
// TODO: We really should wait around until all libraries are classified.
DWORD mediaCount = 0;
hr = findFirstNtmsObject( NTMS_LIBRARY, GUID_NULL, NULL, GUID_NULL, &hFind, &objectInfo);
while( S_OK == hr ) {
reportNtmsObjectInformation( &objectInfo );
mediaCount += objectInfo.Info.Library.dwNumberOfMedia;
hr = findNextNtmsObject( hFind, &objectInfo );
}
findCloseNtmsObject( hFind );
if ( 0 == mediaCount) {
WsbThrow( RMS_E_NTMS_OBJECT_NOT_FOUND );
}
/*
// First see if there is any media to be classified, if not we don't bother waiting around for
// nothing to happen.
hr = findFirstNtmsObject( NTMS_PHYSICAL_MEDIA, GUID_NULL, NULL, GUID_NULL, &hFind, &objectInfo);
WsbAffirmHrOk( hr );
findCloseNtmsObject( hFind );
*/
// NTMS - Open notification channel
WsbTraceAlways(OLESTR("OpenNtmsNotification()\n"));
hNotify = OpenNtmsNotification(hSession, NTMS_MEDIA_POOL);
if ( INVALID_HANDLE_VALUE == hNotify ) {
err1 = GetLastError();
WsbAffirmNoError(err1);
WsbThrow(E_UNEXPECTED);
}
do {
err2 = NO_ERROR;
//
// Count the number of NTMS Scratch pools, and if
// there are more than one, we return. If not,
// we wait until the root level scratch pool object
// is updated.
//
// More that one scratch media pools implies that at
// least one unit of media was classified. We don't
// know until we complete the initialization if it
// was one of the media types supported by RemoteStorage.
//
int count = 0;
hr = findFirstNtmsObject( NTMS_MEDIA_POOL, GUID_NULL, NULL, GUID_NULL, &hFind, &objectInfo);
while( S_OK == hr ) {
if ( NTMS_POOLTYPE_SCRATCH == objectInfo.Info.MediaPool.PoolType ) {
count++;
if ( count == 1 ) {
// Assueme this is the rool pool and one we'll check on for updates
// If the assumption is wrong count will end up > 1.
memcpy(&scratchInfo, &objectInfo, sizeof(NTMS_OBJECTINFORMATION));
}
}
hr = findNextNtmsObject( hFind, &objectInfo );
}
findCloseNtmsObject( hFind );
if ( count > 1 ) {
bFound = TRUE;
hr = S_OK;
break; // Normal exit.
}
if ( count == 0 ) {
WsbThrow(E_UNEXPECTED);
}
// Just one scratch pool detected... wait until a media-type specific pool
// is added root scratch pool. This will show up as an update to the root
// scratch pool.
do {
WsbTrace(OLESTR("Waiting for NTMS scratch pool - Seconds remaining before timeout: %d\n"), retry*notificationWaitTime/1000);
// NTMS - Wait for notification
WsbTraceAlways(OLESTR("WaitForNtmsNotification()\n"));
err2 = WaitForNtmsNotification(hNotify, &notifyInfo, notificationWaitTime);
if ( NO_ERROR == err2 ) {
//
// Note: With this notification mechanism, chances
// are slim that we got notified on the object we really
// care about.
//
WsbTrace(OLESTR("Processing: <%d> %ls\n"), notifyInfo.dwOperation, WsbGuidAsString(notifyInfo.ObjectId));
if ( notifyInfo.ObjectId != scratchInfo.ObjectGuid ) {
WsbTrace(OLESTR("Wrong object, try again...\n"));
continue; // skip this one
}
else {
if ( NTMS_OBJ_UPDATE != notifyInfo.dwOperation ) {
WsbTrace(OLESTR("Wrong operation, try again...\n"));
continue; // skip this one
}
else {
WsbTrace(OLESTR("Scratch pool update detected.\n"));
break; // A scratch pool may have inserted, go check it out...
}
}
}
else if ( ERROR_TIMEOUT != err2 && ERROR_NO_DATA != err2 ) {
WsbAffirmNoError(err2);
}
retry--;
} while( (retry > 0) && (!bFound) );
} while( (retry > 0) && (!bFound) );
// NTMS - Close notification channel
WsbTraceAlways(OLESTR("CloseNtmsNotification()\n"));
err3 = CloseNtmsNotification(hNotify);
WsbAffirmNoError(err3);
if ( !bFound ) {
hr = RMS_E_RESOURCE_UNAVAILABLE;
}
} WsbCatchAndDo(hr,
if ( hNotify != INVALID_HANDLE_VALUE ) {
// NTMS - Close notification channel
WsbTraceAlways(OLESTR("CloseNtmsNotification()\n"));
err3 = CloseNtmsNotification(hNotify);
}
if (err1 != NO_ERROR) {
// OpenNtmsNotification
switch (HRESULT_CODE(hr)) {
case ERROR_DATABASE_FAILURE:
case ERROR_INVALID_HANDLE:
case ERROR_NOT_CONNECTED:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("OpenNtmsNotification"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("OpenNtmsNotification"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
if (err2 != NO_ERROR) {
// WaitForNtmsNotification
switch (HRESULT_CODE(hr)) {
case ERROR_INVALID_HANDLE:
case ERROR_NOT_CONNECTED:
case ERROR_DATABASE_FAILURE:
case ERROR_TIMEOUT:
case ERROR_NO_DATA:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("WaitForNtmsNotification"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("WaitForNtmsNotification"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
if (err3 != NO_ERROR) {
// CloseNtmsNotification
switch (HRESULT_CODE(hr)) {
case ERROR_INVALID_HANDLE:
case ERROR_NOT_CONNECTED:
case ERROR_DATABASE_FAILURE:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("CloseNtmsNotification"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("CloseNtmsNotification"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
);
WsbTraceOut(OLESTR("CRmsNTMS::waitForScratchPool"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return hr;
}
HRESULT
CRmsNTMS::storageMediaTypeToRmsMedia(
IN NTMS_MEDIATYPEINFORMATION *pMediaTypeInfo,
OUT RmsMedia *pTranslatedMediaType)
{
HRESULT hr = S_OK;
DWORD size;
OLECHAR tmpString[256];
// Media type is the main criteria
WsbAssertPointer(pMediaTypeInfo);
STORAGE_MEDIA_TYPE mediaType = (STORAGE_MEDIA_TYPE)(pMediaTypeInfo->MediaType);
DWORD tapeEnabled = RMS_DEFAULT_TAPE;
if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_TAPE, tmpString, 256, &size))) {
// Get the value.
tapeEnabled = wcstol(tmpString, NULL, 10);
}
DWORD opticalEnabled = RMS_DEFAULT_OPTICAL;
if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_OPTICAL, tmpString, 256, &size))) {
// Get the value.
opticalEnabled = wcstol(tmpString, NULL, 10);
}
DWORD dvdEnabled = RMS_DEFAULT_DVD;
if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_DVD, tmpString, 256, &size))) {
// Get the value.
dvdEnabled = wcstol(tmpString, NULL, 10);
}
switch ( mediaType ) {
case DDS_4mm: // Tape - DAT DDS1,2,... (all vendors) (0x20)
*pTranslatedMediaType = (tapeEnabled) ? RmsMedia4mm : RmsMediaUnknown;
break;
case MiniQic: // Tape - miniQIC Tape
case Travan: // Tape - Travan TR-1,2,3,...
case QIC: // Tape - QIC
*pTranslatedMediaType = RmsMediaUnknown;
break;
case MP_8mm: // Tape - 8mm Exabyte Metal Particle
case AME_8mm: // Tape - 8mm Exabyte Advanced Metal Evap
case AIT1_8mm: // Tape - 8mm Sony AIT1
*pTranslatedMediaType = (tapeEnabled) ? RmsMedia8mm : RmsMediaUnknown;
break;
case DLT: // Tape - DLT Compact IIIxt: IV
*pTranslatedMediaType = (tapeEnabled) ? RmsMediaDLT : RmsMediaUnknown;
break;
case NCTP: // Tape - Philips NCTP
case IBM_3480: // Tape - IBM 3480
case IBM_3490E: // Tape - IBM 3490E
case IBM_Magstar_3590: // Tape - IBM Magstar 3590
case IBM_Magstar_MP: // Tape - IBM Magstar MP
case STK_DATA_D3: // Tape - STK Data D3
case SONY_DTF: // Tape - Sony DTF
case DV_6mm: // Tape - 6mm Digital Video
case DMI: // Tape - Exabyte DMI and compatibles
case SONY_D2: // Tape - Sony D2S and D2L
case CLEANER_CARTRIDGE: // Cleaner - All Drive types that support Drive Cleaners
case CD_ROM: // Opt_Disk - CD
case CD_R: // Opt_Disk - CD-Recordable (Write Once)
case CD_RW: // Opt_Disk - CD-Rewriteable
case DVD_ROM: // Opt_Disk - DVD-ROM
case DVD_R: // Opt_Disk - DVD-Recordable (Write Once)
case MO_5_WO: // Opt_Disk - MO 5.25" Write Once
*pTranslatedMediaType = RmsMediaUnknown;
break;
case DVD_RW: // Opt_Disk - DVD-Rewriteable
*pTranslatedMediaType = (dvdEnabled) ? RmsMediaDVD : RmsMediaUnknown;
break;
case MO_5_RW: // Opt_Disk - MO 5.25" Rewriteable (not LIMDOW)
case MO_3_RW: // Opt_Disk - 3.5" Rewriteable MO Disk
case MO_5_LIMDOW: // Opt_Disk - MO 5.25" Rewriteable (LIMDOW)
case PC_5_RW: // Opt_Disk - Phase Change 5.25" Rewriteable
case PD_5_RW: // Opt_Disk - PhaseChange Dual Rewriteable
case PINNACLE_APEX_5_RW: // Opt_Disk - Pinnacle Apex 4.6GB Rewriteable Optical
case NIKON_12_RW: // Opt_Disk - Nikon 12" Rewriteable
*pTranslatedMediaType = (opticalEnabled) ? RmsMediaOptical : RmsMediaUnknown;
break;
case PC_5_WO: // Opt_Disk - Phase Change 5.25" Write Once Optical
case ABL_5_WO: // Opt_Disk - Ablative 5.25" Write Once Optical
*pTranslatedMediaType = RmsMediaUnknown;
break;
case SONY_12_WO: // Opt_Disk - Sony 12" Write Once
case PHILIPS_12_WO: // Opt_Disk - Philips/LMS 12" Write Once
case HITACHI_12_WO: // Opt_Disk - Hitachi 12" Write Once
case CYGNET_12_WO: // Opt_Disk - Cygnet/ATG 12" Write Once
case KODAK_14_WO: // Opt_Disk - Kodak 14" Write Once
case MO_NFR_525: // Opt_Disk - Near Field Recording (Terastor)
case IOMEGA_ZIP: // Mag_Disk - Iomega Zip
case IOMEGA_JAZ: // Mag_Disk - Iomega Jaz
case SYQUEST_EZ135: // Mag_Disk - Syquest EZ135
case SYQUEST_EZFLYER: // Mag_Disk - Syquest EzFlyer
case SYQUEST_SYJET: // Mag_Disk - Syquest SyJet
case AVATAR_F2: // Mag_Disk - 2.5" Floppy
*pTranslatedMediaType = RmsMediaUnknown;
break;
case RemovableMedia: // This is reported on stand-alone optical drives.
default:
// Check RSM characteristics for Rewriteable Disk
if ((pMediaTypeInfo->ReadWriteCharacteristics == NTMS_MEDIARW_REWRITABLE) &&
(pMediaTypeInfo->DeviceType == FILE_DEVICE_DISK)) {
*pTranslatedMediaType = (opticalEnabled) ? RmsMediaOptical : RmsMediaUnknown;
} else {
// Not a rewritable disk and not one of the supported tape types...
*pTranslatedMediaType = RmsMediaUnknown;
}
break;
}
if ((*pTranslatedMediaType == RmsMediaUnknown) &&
(pMediaTypeInfo->DeviceType == FILE_DEVICE_TAPE)) {
// Check in the Registry whether there are additional tapes that we need to support
ULONG *pTypes= NULL;
ULONG uTypes = 0;
if (SUCCEEDED(WsbGetRegistryValueUlongAsMultiString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_ADDITIONAL_TAPE, &pTypes, &uTypes))) {
// Compare Registry types to the media type we have
for (ULONG u=0; u<uTypes; u++) {
if ((STORAGE_MEDIA_TYPE)(pTypes[u]) == mediaType) {
// Support it !!
WsbTraceAlways(OLESTR("CRmsNTMS::storageMediaTypeToRmsMedia: Registry asks to support tape type %lu\n"),
pTypes[u]);
*pTranslatedMediaType = RmsMediaTape;
break;
}
}
}
if (pTypes != NULL) {
WsbFree(pTypes);
pTypes = NULL;
}
}
return hr;
}
HRESULT
CRmsNTMS::createMediaPools(void)
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CRmsNTMS::createMediaPools"), OLESTR(""));
try {
HANDLE hSession;
NTMS_GUID rootPoolId = GUID_NULL;
if ( INVALID_HANDLE_VALUE == m_SessionHandle ) {
WsbAffirmHr(beginSession());
}
hSession = m_SessionHandle;
try {
// NTMS - Create Application Media Pool.
WsbTraceAlways(OLESTR("CreateNtmsMediaPool()\n"));
WsbAffirmNoError(CreateNtmsMediaPool(hSession, REMOTE_STORAGE_APP_NAME, NULL, NTMS_OPEN_ALWAYS, NULL, &rootPoolId));
// Now set access permissions on the pool: turn off ordinary users access
WsbAffirmHrOk(setPoolDACL(&rootPoolId, DOMAIN_ALIAS_RID_USERS, REMOVE_ACE_MASK_BITS,NTMS_USE_ACCESS | NTMS_MODIFY_ACCESS | NTMS_CONTROL_ACCESS));
} WsbCatchAndDo(hr,
switch(HRESULT_CODE(hr)) {
case ERROR_INVALID_PARAMETER:
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_NAME:
case ERROR_OBJECT_NOT_FOUND:
case ERROR_ALREADY_EXISTS:
case ERROR_ACCESS_DENIED:
case ERROR_DATABASE_FAILURE:
case ERROR_DATABASE_FULL:
WsbLogEvent( RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("CreateNtmsMediaPool"), OLESTR(""),
WsbHrAsString(hr),
NULL );
break;
default:
WsbLogEvent( RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("CreateNtmsMediaPool"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr),
NULL );
break;
}
WsbThrow(hr);
);
//
// Only one of the following should be executed, comment out the other.
//
WsbAffirmHr( createMediaPoolForEveryMediaType(rootPoolId) ); // New way
/*
WsbAffirmHr( replicateScratchMediaPool(rootPoolId) ); // Old way
*/
} WsbCatch(hr);
WsbTraceOut( OLESTR("CRmsNTMS::createMediaPools"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
return hr;
}
HRESULT
CRmsNTMS::replicateScratchMediaPool(
IN REFGUID /*rootPoolId*/)
{
HRESULT hr = E_FAIL;
WsbTraceIn(OLESTR("CRmsNTMS::replicateScratchMediaPool"), OLESTR(""));
try {
HANDLE hSession;
DWORD errCode;
NTMS_OBJECTINFORMATION mediaTypeInfo;
NTMS_OBJECTINFORMATION mediaPoolInfo;
HANDLE hFind = NULL;
NTMS_GUID poolId = GUID_NULL;
if ( INVALID_HANDLE_VALUE == m_SessionHandle ) {
WsbAffirmHr(beginSession());
}
hSession = m_SessionHandle;
// For each media pool in the scratch pool create an application specific pool.
hr = findFirstNtmsObject( NTMS_MEDIA_POOL, GUID_NULL, NULL, GUID_NULL, &hFind, &mediaPoolInfo);
while( S_OK == hr ) {
reportNtmsObjectInformation( &mediaPoolInfo );
poolId = GUID_NULL;
try {
// Set up application specific NTMS Media Pools. One for each compatible type.
//
// To get here we had to already detect a media-type specific scratch pool
// in waitForScratchPool()
if ( NTMS_POOLTYPE_SCRATCH == mediaPoolInfo.Info.MediaPool.PoolType &&
0 == mediaPoolInfo.Info.MediaPool.dwNumberOfMediaPools ) {
// This is a base level scratch media pool.
// Create a similar pool for application specific use.
CWsbStringPtr name = REMOTE_STORAGE_APP_NAME;
name.Append( OLESTR("\\") );
name.Append( mediaPoolInfo.szName );
NTMS_GUID mediaTypeId = mediaPoolInfo.Info.MediaPool.MediaType;
// We need more information about the media type.
memset( &mediaTypeInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
mediaTypeInfo.dwType = NTMS_MEDIA_TYPE;
mediaTypeInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
// NTMS - Get Media Pool Information
WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
errCode = GetNtmsObjectInformation( hSession, &mediaTypeId, &mediaTypeInfo );
if ( errCode != NO_ERROR ) {
WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
OLESTR("GetNtmsObjectInformation"),
WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
NULL );
WsbThrow( E_UNEXPECTED );
}
// Translate the NTMS media type into something understood by RMS
RmsMedia translatedMediaType;
storageMediaTypeToRmsMedia(&(mediaTypeInfo.Info.MediaType), &translatedMediaType);
if ( translatedMediaType != RmsMediaUnknown ) {
// This something that Remote Storage can deal with
CWsbBstrPtr mediaSetName = RMS_UNDEFINED_STRING;
CWsbBstrPtr mediaSetDesc = RMS_UNDEFINED_STRING;
BOOL mediaSetIsEnabled = FALSE;
// NTMS - Create Application Media Pool.
WsbTraceAlways(OLESTR("CreateNtmsMediaPool()\n"));
errCode = CreateNtmsMediaPool( hSession, (WCHAR *) name, &mediaTypeId, NTMS_CREATE_NEW, NULL, &poolId );
if ( ERROR_ALREADY_EXISTS == errCode ) {
// We still need the poolId of the existing pool.
// NTMS - Create Application Media Pool.
WsbTraceAlways(OLESTR("CreateNtmsMediaPool()\n"));
errCode = CreateNtmsMediaPool( hSession, (WCHAR *)name, &mediaTypeId, NTMS_OPEN_EXISTING, NULL, &poolId );
if ( errCode != NO_ERROR ) {
WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
OLESTR("CreateNtmsMediaPool"),
WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
NULL );
WsbThrow( E_UNEXPECTED );
}
NTMS_OBJECTINFORMATION mediaPoolInfo;
memset( &mediaPoolInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
mediaPoolInfo.dwType = NTMS_MEDIA_POOL;
mediaPoolInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
// NTMS - Get Media Pool Information
WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
errCode = GetNtmsObjectInformation( hSession, &poolId, &mediaPoolInfo );
if ( errCode != NO_ERROR ) {
WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
OLESTR("GetNtmsObjectInformation"),
WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
NULL );
WsbThrow( E_UNEXPECTED );
}
// Save relevant info
mediaSetName = mediaPoolInfo.szName;
mediaSetDesc = mediaPoolInfo.szDescription;
mediaSetIsEnabled = mediaPoolInfo.Enabled;
}
else if ( NO_ERROR == errCode ) {
memset( &mediaPoolInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
mediaPoolInfo.dwType = NTMS_MEDIA_POOL;
mediaPoolInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
// NTMS - Get Media Pool Information
WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
errCode = GetNtmsObjectInformation( hSession, &poolId, &mediaPoolInfo );
if ( errCode != NO_ERROR ) {
WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
OLESTR("GetNtmsObjectInformation"),
WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
NULL );
WsbThrow( E_UNEXPECTED );
}
WsbAssert( NTMS_POOLTYPE_APPLICATION == mediaPoolInfo.Info.MediaPool.PoolType, E_UNEXPECTED );
// Set media pool parameters
// Aallocation/deallocation policy
mediaPoolInfo.Info.MediaPool.AllocationPolicy = NTMS_ALLOCATE_FROMSCRATCH;
mediaPoolInfo.Info.MediaPool.DeallocationPolicy = 0;
// Max number of allocates per media
mediaPoolInfo.Info.MediaPool.dwMaxAllocates = 5;// Just a few... we automatically
// deallocate media if there's
// problem with scratch mount
// operation.
// NOTE: This can be overridden using
// the NTMS GUI.
// NTMS - Set Media Pool Information.
WsbTraceAlways(OLESTR("SetNtmsObjectInformation()\n"));
errCode = SetNtmsObjectInformation( hSession, &poolId, &mediaPoolInfo );
if ( errCode != NO_ERROR ) {
WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
OLESTR("SetNtmsObjectInformation"),
WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
NULL );
WsbThrow( E_UNEXPECTED );
}
// Save relevant info
mediaSetName = mediaPoolInfo.szName;
mediaSetDesc = mediaPoolInfo.szDescription;
mediaSetIsEnabled = mediaPoolInfo.Enabled;
}
else {
WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
OLESTR("CreateNtmsMediaPool"),
WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
NULL );
WsbThrow( E_UNEXPECTED );
}
// Now we have an NTMS media pool for our specific use. Now expose it
// through the RMS interface by creating a CRmsMediaSet.
if ( poolId != GUID_NULL ) {
CComPtr<IRmsMediaSet> pMediaSet;
// Find the RmsMediaSet with the same id, or create a new one.
CComQIPtr<IRmsServer, &IID_IRmsServer> pServer = g_pServer;
WsbAffirmHr( pServer->CreateObject( poolId, CLSID_CRmsMediaSet, IID_IRmsMediaSet, RmsOpenAlways, (void **)&pMediaSet ) );
WsbTrace(OLESTR("CRmsNTMS::replicateScratchMediaPool - type %d CRmsMediaSet created.\n"), translatedMediaType);
WsbAffirmHr( pMediaSet->SetMediaSetType( RmsMediaSetNTMS ) );
WsbAffirmHr( pMediaSet->SetMediaSupported( translatedMediaType ) );
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pMediaSet;
WsbTrace(OLESTR("CRmsNTMS::createMediaPoolForEveryMediaType - MediaSet: <%ls/%ls>; Enabled: %ls\n"),
WsbQuickString(WsbStringAsString(mediaSetName)),
WsbQuickString(WsbStringAsString(mediaSetDesc)),
WsbQuickString(WsbBoolAsString(mediaSetIsEnabled)));
WsbAffirmHr(pObject->SetName(mediaSetName));
WsbAffirmHr(pObject->SetDescription(mediaSetDesc));
if (!mediaSetIsEnabled) {
WsbAffirmHr(pObject->Disable(E_FAIL));
}
if (S_OK == IsMediaCopySupported(poolId)) {
WsbAffirmHr( pMediaSet->SetIsMediaCopySupported(TRUE));
}
hr = pMediaSet->IsMediaCopySupported();
WsbTrace(OLESTR("CRmsNTMS::replicateScratchMediaPool - media copies are %ls.\n"),
(S_OK == pMediaSet->IsMediaCopySupported()) ? OLESTR("enabled") : OLESTR("disabled"));
}
}
}
} WsbCatch(hr);
hr = findNextNtmsObject( hFind, &mediaPoolInfo );
} // while finding media pools
findCloseNtmsObject( hFind );
hr = S_OK;
} WsbCatch(hr);
WsbTraceOut( OLESTR("CRmsNTMS::replicateScratchMediaPool"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
return hr;
}
HRESULT
CRmsNTMS::createMediaPoolForEveryMediaType(
IN REFGUID /*rootPoolId*/)
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CRmsNTMS::createMediaPoolForEveryMediaType"), OLESTR(""));
try {
DWORD errCode;
if ( INVALID_HANDLE_VALUE == m_SessionHandle ) {
WsbAffirmHr(beginSession());
}
HANDLE hSession = m_SessionHandle;
HANDLE hFindLib = NULL;
NTMS_OBJECTINFORMATION libraryInfo;
BOOL bSupportedLib = FALSE;
m_dwNofLibs = 0;
hr = findFirstNtmsObject( NTMS_LIBRARY, GUID_NULL, NULL, GUID_NULL, &hFindLib, &libraryInfo);
while( S_OK == hr ) {
bSupportedLib = FALSE;
reportNtmsObjectInformation( &libraryInfo );
if (libraryInfo.Info.Library.dwNumberOfMediaTypes > 0) {
HANDLE hFindType = NULL;
NTMS_OBJECTINFORMATION mediaTypeInfo;
hr = findFirstNtmsObject( NTMS_MEDIA_TYPE, libraryInfo.ObjectGuid, NULL, GUID_NULL, &hFindType, &mediaTypeInfo);
while( S_OK == hr ) {
//
// Create an application Media Pool for each type
//
NTMS_GUID poolId;
// This is a base level scratch media pool.
// Create a similar pool for application specific use.
CWsbStringPtr name = REMOTE_STORAGE_APP_NAME;
name.Append( OLESTR("\\") );
name.Append( mediaTypeInfo.szName );
NTMS_GUID mediaTypeId = mediaTypeInfo.ObjectGuid;
// Translate the NTMS media type into something understood by RMS
RmsMedia translatedMediaType;
storageMediaTypeToRmsMedia(&(mediaTypeInfo.Info.MediaType), &translatedMediaType);
if ( translatedMediaType != RmsMediaUnknown ) {
// This something that Remote Storage can deal with
CWsbBstrPtr mediaSetName = RMS_UNDEFINED_STRING;
CWsbBstrPtr mediaSetDesc = RMS_UNDEFINED_STRING;
BOOL mediaSetIsEnabled = FALSE;
// NTMS - Create Application Media Pool.
WsbTraceAlways(OLESTR("CreateNtmsMediaPool(<%ls>) - Try New.\n"), (WCHAR *) name);
errCode = CreateNtmsMediaPool( hSession, (WCHAR *) name, &mediaTypeId, NTMS_CREATE_NEW, NULL, &poolId );
if ( ERROR_ALREADY_EXISTS == errCode ) {
WsbTraceAlways(OLESTR("MediaPool <%ls> already exists.\n"), (WCHAR *) name);
// We still need the poolId of the existing pool.
// NTMS - Create Application Media Pool.
WsbTraceAlways(OLESTR("CreateNtmsMediaPool(<%ls>) - Try Existing.\n"), (WCHAR *) name);
errCode = CreateNtmsMediaPool( hSession, (WCHAR *)name, &mediaTypeId, NTMS_OPEN_EXISTING, NULL, &poolId );
if ( errCode != NO_ERROR ) {
WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
OLESTR("CreateNtmsMediaPool"),
WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
NULL );
WsbThrow( E_UNEXPECTED );
}
WsbTraceAlways(OLESTR("Media Pool %ls detected.\n"), WsbGuidAsString(poolId));
NTMS_OBJECTINFORMATION mediaPoolInfo;
memset( &mediaPoolInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
mediaPoolInfo.dwType = NTMS_MEDIA_POOL;
mediaPoolInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
// NTMS - Get Media Pool Information
WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
errCode = GetNtmsObjectInformation( hSession, &poolId, &mediaPoolInfo );
if ( errCode != NO_ERROR ) {
WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
OLESTR("GetNtmsObjectInformation"),
WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
NULL );
WsbThrow( E_UNEXPECTED );
}
// Save relevant info
mediaSetName = mediaPoolInfo.szName;
mediaSetDesc = mediaPoolInfo.szDescription;
mediaSetIsEnabled = mediaPoolInfo.Enabled;
}
else if ( NO_ERROR == errCode ) {
WsbTraceAlways(OLESTR("MediaPool <%ls> created.\n"), (WCHAR *) name);
NTMS_OBJECTINFORMATION mediaPoolInfo;
memset( &mediaPoolInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
mediaPoolInfo.dwType = NTMS_MEDIA_POOL;
mediaPoolInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
// NTMS - Get Media Pool Information
WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
errCode = GetNtmsObjectInformation( hSession, &poolId, &mediaPoolInfo );
if ( errCode != NO_ERROR ) {
WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
OLESTR("GetNtmsObjectInformation"),
WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
NULL );
WsbThrow( E_UNEXPECTED );
}
WsbAssert( NTMS_POOLTYPE_APPLICATION == mediaPoolInfo.Info.MediaPool.PoolType, E_UNEXPECTED );
// Set media pool parameters
// Aallocation/deallocation policy
mediaPoolInfo.Info.MediaPool.AllocationPolicy = NTMS_ALLOCATE_FROMSCRATCH;
mediaPoolInfo.Info.MediaPool.DeallocationPolicy = 0;
// Max number of allocates per media
mediaPoolInfo.Info.MediaPool.dwMaxAllocates = 0;// Unlimited... we automatically
// deallocate media if there's
// problem with scratch mount
// operation.
// TODO: Verify that NTMS always allocates
// media with the lowest allocation
// count.
// NOTE: This can be overridden using
// the NTMS GUI.
// NTMS - Set Media Pool Information.
WsbTraceAlways(OLESTR("SetNtmsObjectInformation()\n"));
errCode = SetNtmsObjectInformation( hSession, &poolId, &mediaPoolInfo );
if ( errCode != NO_ERROR ) {
WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
OLESTR("SetNtmsObjectInformation"),
WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
NULL );
WsbThrow( E_UNEXPECTED );
}
// Save relevant info
mediaSetName = mediaPoolInfo.szName;
mediaSetDesc = mediaPoolInfo.szDescription;
mediaSetIsEnabled = mediaPoolInfo.Enabled;
}
else {
WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
OLESTR("CreateNtmsMediaPool"),
WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
NULL );
WsbThrow( E_UNEXPECTED );
}
// Now set access permissions on the pool: turn off ordinary users access
WsbAffirmHrOk(setPoolDACL(&poolId, DOMAIN_ALIAS_RID_USERS, REMOVE_ACE_MASK_BITS,NTMS_USE_ACCESS | NTMS_MODIFY_ACCESS | NTMS_CONTROL_ACCESS));
// Now we have an NTMS media pool for our specific use. Now expose it
// through the RMS interface by creating a CRmsMediaSet.
if ( poolId != GUID_NULL ) {
//
// Add to CRmsMediaSet collection
//
CComPtr<IRmsMediaSet> pMediaSet;
// Find the CRmsMediaSet with the same id, or create a new one.
CComQIPtr<IRmsServer, &IID_IRmsServer> pServer = g_pServer;
WsbAffirmHr( pServer->CreateObject( poolId, CLSID_CRmsMediaSet, IID_IRmsMediaSet, RmsOpenAlways, (void **)&pMediaSet ) );
WsbTrace(OLESTR("CRmsNTMS::createMediaPoolForEveryMediaType - type %d CRmsMediaSet established.\n"), translatedMediaType);
WsbAffirmHr( pMediaSet->SetMediaSetType( RmsMediaSetNTMS ) );
WsbAffirmHr( pMediaSet->SetMediaSupported( translatedMediaType ) );
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pMediaSet;
WsbTrace(OLESTR("CRmsNTMS::createMediaPoolForEveryMediaType - MediaSet: <%ls/%ls> %ls; Enabled: %ls\n"),
WsbQuickString(WsbStringAsString(mediaSetName)),
WsbQuickString(WsbStringAsString(mediaSetDesc)),
WsbQuickString(WsbGuidAsString(poolId)),
WsbQuickString(WsbBoolAsString(mediaSetIsEnabled)));
WsbAffirmHr(pObject->SetName(mediaSetName));
WsbAffirmHr(pObject->SetDescription(mediaSetDesc));
if (!mediaSetIsEnabled) {
WsbAffirmHr(pObject->Disable(E_FAIL));
}
if (S_OK == IsMediaCopySupported(poolId)) {
WsbAffirmHr( pMediaSet->SetIsMediaCopySupported(TRUE));
}
hr = pMediaSet->IsMediaCopySupported();
WsbTrace(OLESTR("CRmsNTMS::createMediaPoolForEveryMediaType - media copies are %ls.\n"),
(S_OK == pMediaSet->IsMediaCopySupported()) ? OLESTR("enabled") : OLESTR("disabled"));
}
// The library has a supported media type
bSupportedLib = TRUE;
}
hr = findNextNtmsObject( hFindType, &mediaTypeInfo );
}
findCloseNtmsObject( hFindType );
}
// Check if the library has supported media type
if (bSupportedLib) {
// Add library GUI to the libraries list
// (Realloc one item each time since we don't expect many items)
m_dwNofLibs++;
LPVOID pTemp = WsbRealloc(m_pLibGuids, m_dwNofLibs*sizeof(NTMS_GUID));
if (!pTemp) {
WsbThrow(E_OUTOFMEMORY);
}
m_pLibGuids = (LPNTMS_GUID)pTemp;
m_pLibGuids[m_dwNofLibs-1] = libraryInfo.ObjectGuid;
}
// Continue library enumeration
hr = findNextNtmsObject( hFindLib, &libraryInfo );
}
findCloseNtmsObject( hFindLib );
hr = S_OK;
} WsbCatch(hr);
WsbTraceOut( OLESTR("CRmsNTMS::createMediaPoolForEveryMediaType"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
return hr;
}
STDMETHODIMP
CRmsNTMS::Allocate(
IN REFGUID fromMediaSet,
IN REFGUID prevSideId,
IN OUT LONGLONG *pFreeSpace,
IN BSTR displayName,
IN DWORD dwOptions,
OUT IRmsCartridge **ppCartridge)
/*++
Implements:
IRmsNTMS::Allocate
--*/
{
HRESULT hr = S_OK;
DWORD err1 = NO_ERROR;
DWORD err2 = NO_ERROR;
DWORD err3 = NO_ERROR;
DWORD err4 = NO_ERROR;
DWORD err5 = NO_ERROR;
DWORD err6 = NO_ERROR;
DWORD err7 = NO_ERROR;
WsbTraceIn(OLESTR("CRmsNTMS::Allocate"), OLESTR("<%ls> <%ls> <%ls> <%ls> <0x%08x"),
WsbGuidAsString(fromMediaSet), WsbGuidAsString(prevSideId),
WsbPtrToLonglongAsString(pFreeSpace), WsbStringAsString(displayName), dwOptions);
try {
WsbAssert(fromMediaSet != GUID_NULL, E_INVALIDARG);
WsbAssertPointer(ppCartridge);
// Retrieve the AllocateWaitTime and RequestWaitTime parameters
DWORD size;
OLECHAR tmpString[256];
DWORD allocateWaitTime;
DWORD requestWaitTime;
BOOL bShortTimeout = ( dwOptions & RMS_SHORT_TIMEOUT ) ? TRUE : FALSE;
if (bShortTimeout) {
allocateWaitTime = RMS_DEFAULT_SHORT_WAIT_TIME;
requestWaitTime = RMS_DEFAULT_SHORT_WAIT_TIME;
if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_SHORT_WAIT_TIME, tmpString, 256, &size))) {
allocateWaitTime = wcstol(tmpString, NULL, 10);
requestWaitTime = wcstol(tmpString, NULL, 10);
WsbTrace(OLESTR("allocateWaitTime (Short) is %d milliseconds.\n"), allocateWaitTime);
WsbTrace(OLESTR("RequestWaitTime (Short) is %d milliseconds.\n"), requestWaitTime);
}
} else {
allocateWaitTime = RMS_DEFAULT_ALLOCATE_WAIT_TIME;
if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_ALLOCATE_WAIT_TIME, tmpString, 256, &size))) {
allocateWaitTime = wcstol(tmpString, NULL, 10);
WsbTrace(OLESTR("AllocateWaitTime is %d milliseconds.\n"), allocateWaitTime);
}
requestWaitTime = RMS_DEFAULT_REQUEST_WAIT_TIME;
if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_REQUEST_WAIT_TIME, tmpString, 256, &size))) {
requestWaitTime = wcstol(tmpString, NULL, 10);
WsbTrace(OLESTR("RequestWaitTime is %d milliseconds.\n"), requestWaitTime);
}
}
// Special error recovery to handle when NTMS is down, or was cycled.
do {
hr = S_OK;
HANDLE hSession = m_SessionHandle;
NTMS_GUID setId = fromMediaSet;
NTMS_GUID partId = GUID_NULL;
NTMS_GUID *pPartId = NULL;
NTMS_GUID requestId;
err1 = NO_ERROR;
err2 = NO_ERROR;
err3 = NO_ERROR;
err4 = NO_ERROR;
err5 = NO_ERROR;
err6 = NO_ERROR;
err7 = NO_ERROR;
try {
// Look for a specific media ourselves if:
// 1. A specific capacity is required AND
// 2. We do not try to allocate a second side
if (pFreeSpace && (prevSideId == GUID_NULL)) {
if (*pFreeSpace > 0) {
int retry = 3; // Give the operator 3 chances to get it right!
do {
// We need to allocate a unit of media that matches the capacity specified.
//
// Enumerate the partitions in the scratch pool of the same type as
// specified to find a capatible unit of media
//
// First find the media type we looking for
NTMS_OBJECTINFORMATION mediaPoolInfo;
NTMS_OBJECTINFORMATION partitionInfo;
HANDLE hFindPool = NULL;
HANDLE hFindPart = NULL;
BOOL bFound = FALSE;
NTMS_GUID scratchPoolId;
err1 = NO_ERROR;
err2 = NO_ERROR;
err3 = NO_ERROR;
err4 = NO_ERROR;
err5 = NO_ERROR;
err6 = NO_ERROR;
err7 = NO_ERROR;
// First look in our pool for scratch media of the correct size
hr = findFirstNtmsObject(NTMS_PARTITION, setId, NULL, GUID_NULL, &hFindPart, &partitionInfo);
while(S_OK == hr) {
reportNtmsObjectInformation(&partitionInfo);
if ((TRUE == partitionInfo.Enabled) &&
(NTMS_READY == partitionInfo.dwOperationalState) &&
(NTMS_PARTSTATE_AVAILABLE == partitionInfo.Info.Partition.State) &&
(partitionInfo.Info.Partition.Capacity.QuadPart >= *pFreeSpace)) {
NTMS_GUID physicalPartMediaId = partitionInfo.Info.Partition.PhysicalMedia;
try {
// Check if the media is online and enabled
NTMS_OBJECTINFORMATION mediaPartInfo;
mediaPartInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
mediaPartInfo.dwType = NTMS_PHYSICAL_MEDIA;
// NTMS - Get physical media information
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PHYSICAL_MEDIA)\n"));
WsbAffirmNoError( GetNtmsObjectInformation( hSession, &physicalPartMediaId, &mediaPartInfo ) );
// Check location type, if enabled & if all new
if ( (mediaPartInfo.Info.PhysicalMedia.LocationType != NTMS_UNKNOWN)
&& (mediaPartInfo.Enabled) ) {
// Ensure that ALL sides are not allocated yet
hr = EnsureAllSidesNotAllocated(physicalPartMediaId);
if (S_OK == hr) {
// We'll use this unit of media.
// Save parameterers required for Allocate.
bFound = TRUE;
partId = partitionInfo.ObjectGuid;
pPartId = &partId;
break;
} else if (S_FALSE != hr) {
WsbAffirmHr(hr);
}
}
} WsbCatchAndDo (hr,
WsbTraceAlways(OLESTR("CRmsNTMS::Allocate: Failed to check media <%ls> hr = <%ls>\n"),
WsbGuidAsString(physicalPartMediaId), WsbHrAsString(hr));
hr = S_OK;
)
}
hr = findNextNtmsObject(hFindPart, &partitionInfo);
} // while finding media pools
findCloseNtmsObject(hFindPart);
hr = S_OK;
if (!bFound) {
// Now try the Scratch Pool
memset(&mediaPoolInfo, 0, sizeof(NTMS_OBJECTINFORMATION));
mediaPoolInfo.dwType = NTMS_MEDIA_POOL;
mediaPoolInfo.dwSize = sizeof(NTMS_OBJECTINFORMATION);
// NTMS - Get Media Pool Information
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_MEDIA_POOL)\n"));
err3 = GetNtmsObjectInformation(hSession, &setId, &mediaPoolInfo);
WsbAffirmNoError( err3 );
// Save the media type for the media pool
NTMS_GUID mediaTypeId = mediaPoolInfo.Info.MediaPool.MediaType;
// Find the scratch pool with the same media type
hr = findFirstNtmsObject(NTMS_MEDIA_POOL, GUID_NULL, NULL, GUID_NULL, &hFindPool, &mediaPoolInfo);
while(S_OK == hr) {
if ((NTMS_POOLTYPE_SCRATCH == mediaPoolInfo.Info.MediaPool.PoolType) &&
(mediaTypeId == mediaPoolInfo.Info.MediaPool.MediaType)) {
// This is a base level scratch media pool for type we're looking for.
scratchPoolId = mediaPoolInfo.ObjectGuid;
hr = findFirstNtmsObject(NTMS_PARTITION, scratchPoolId, NULL, GUID_NULL, &hFindPart, &partitionInfo);
while(S_OK == hr) {
reportNtmsObjectInformation(&partitionInfo);
if ((TRUE == partitionInfo.Enabled) &&
(NTMS_READY == partitionInfo.dwOperationalState) &&
(NTMS_PARTSTATE_AVAILABLE == partitionInfo.Info.Partition.State) &&
(partitionInfo.Info.Partition.Capacity.QuadPart >= *pFreeSpace)) {
// Check if the media is online and enabled
DWORD errPart = NO_ERROR;
NTMS_OBJECTINFORMATION mediaPartInfo;
NTMS_GUID physicalPartMediaId = partitionInfo.Info.Partition.PhysicalMedia;
mediaPartInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
mediaPartInfo.dwType = NTMS_PHYSICAL_MEDIA;
// NTMS - Get physical media information
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PHYSICAL_MEDIA)\n"));
errPart = GetNtmsObjectInformation( hSession, &physicalPartMediaId, &mediaPartInfo );
// Ignore error here, just don't use this partition
if (errPart == NO_ERROR) {
// Check location type and if enabled
if ( (mediaPartInfo.Info.PhysicalMedia.LocationType != NTMS_UNKNOWN)
&& (mediaPartInfo.Enabled) ) {
// We'll use this unit of media.
// Save parameterers required for Allocate.
bFound = TRUE;
partId = partitionInfo.ObjectGuid;
pPartId = &partId;
break;
}
} else {
WsbTraceAlways(OLESTR("CRmsNTMS::Allocate: Failed to get object info for media <%ls> hr = <%ls>\n"),
WsbGuidAsString(physicalPartMediaId), WsbHrAsString(HRESULT_FROM_WIN32(errPart)));
}
}
hr = findNextNtmsObject(hFindPart, &partitionInfo);
} // while finding media pools
findCloseNtmsObject(hFindPart);
hr = S_OK;
break;
}
hr = findNextNtmsObject(hFindPool, &mediaPoolInfo);
} // while finding media pools
findCloseNtmsObject(hFindPool);
hr = S_OK;
}
if (bFound) {
break;
}
else {
OLECHAR * messageText = NULL;
WCHAR *stringArr[2];
WCHAR capString[40];
WsbShortSizeFormat64(*pFreeSpace, capString);
stringArr[0] = mediaPoolInfo.szName;
stringArr[1] = capString;
if (0 == FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY,
LoadLibraryEx( WSB_FACILITY_PLATFORM_NAME, NULL, LOAD_LIBRARY_AS_DATAFILE ),
RMS_MESSAGE_SCRATCH_MEDIA_REQUEST, MAKELANGID ( LANG_NEUTRAL, SUBLANG_DEFAULT ),
(LPTSTR)&messageText, 0, (va_list *)stringArr)) {
WsbTrace(OLESTR("CRmsNTMS::Allocate: FormatMessage failed: %ls\n"),
WsbHrAsString(HRESULT_FROM_WIN32(GetLastError())));
}
// NTMS - Submit operator request
WsbTraceAlways(OLESTR("SubmitNtmsOperatorRequest()\n"));
err5 = SubmitNtmsOperatorRequest(hSession, NTMS_OPREQ_NEWMEDIA, messageText, &scratchPoolId, NULL, &requestId);
LocalFree(messageText);
WsbAffirmNoError(err5);
// NTMS - Wait for operator request
WsbTraceAlways(OLESTR("WaitForNtmsOperatorRequest()\n"));
err6 = WaitForNtmsOperatorRequest(hSession, &requestId, requestWaitTime);
//
// !!! NOTE !!! At the time of this writting WaitForNtmsOperatorRequest
// did not return ERROR_TIMEOUT.
//
if (ERROR_TIMEOUT == err6) {
// Best effort cleanup...
// NTMS - Cancel operator request
WsbTraceAlways(OLESTR("CancelNtmsOperatorRequest()\n"));
err7 = CancelNtmsOperatorRequest(hSession, &requestId);
}
WsbAffirmNoError(err6);
}
WsbAssertHrOk(hr);
// At this point the operator added a compatable unit of media...
// Verify until we're exceed the retry count.
retry--;
} while (retry > 0);
if (0 == retry) {
WsbThrow(RMS_E_SCRATCH_NOT_FOUND);
}
}
}
// NTMS - Allocate a unit of scratch media
WsbTraceAlways(OLESTR("AllocateNtmsMedia()\n"));
// Set additional allocation settings
DWORD dwAllocateOptions = 0;
NTMS_GUID mediaId = prevSideId;
if (mediaId == GUID_NULL) {
dwAllocateOptions |= NTMS_ALLOCATE_NEW;
} else {
// Allocating the second side: mediaId should hold the LMID of the first side
dwAllocateOptions |= NTMS_ALLOCATE_NEXT;
}
if (dwOptions & RMS_ALLOCATE_NO_BLOCK) {
dwAllocateOptions |= NTMS_ALLOCATE_ERROR_IF_UNAVAILABLE;
allocateWaitTime = 0;
}
err1 = AllocateNtmsMedia( hSession, &setId, pPartId, &mediaId,
dwAllocateOptions, allocateWaitTime, NULL );
WsbAffirmNoError( err1 );
// Now get/set the various information fields for the unit of media.
DWORD sideNo = 2;
NTMS_GUID side[2];
// NTMS - Enumerate the sides of a unit of media
WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
err2 = EnumerateNtmsObject(hSession, &mediaId, side, &sideNo, NTMS_PARTITION, 0);
WsbAffirmNoError( err2 );
NTMS_OBJECTINFORMATION partitionInfo;
partitionInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
partitionInfo.dwType = NTMS_PARTITION;
// NTMS - Get partition information
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PARTITION)\n"));
err3 = GetNtmsObjectInformation( hSession, &side[0], &partitionInfo );
WsbAffirmNoError( err3 );
NTMS_OBJECTINFORMATION mediaInfo;
NTMS_GUID physicalMediaId = partitionInfo.Info.Partition.PhysicalMedia;
mediaInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
mediaInfo.dwType = NTMS_PHYSICAL_MEDIA;
// NTMS - Get physical media information
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PHYSICAL_MEDIA)\n"));
err3 = GetNtmsObjectInformation( hSession, &physicalMediaId, &mediaInfo );
WsbAffirmNoError( err3 );
NTMS_OBJECTINFORMATION logicalMediaInfo;
logicalMediaInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
logicalMediaInfo.dwType = NTMS_LOGICAL_MEDIA;
// NTMS - Get physical media information
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_LOGICAL_MEDIA)\n"));
err3 = GetNtmsObjectInformation( hSession, &mediaId, &logicalMediaInfo );
WsbAffirmNoError( err3 );
// Save the capacity for the return arg.
if (pFreeSpace) {
*pFreeSpace = partitionInfo.Info.Partition.Capacity.QuadPart;
}
// Set name & description
CWsbStringPtr mediaDisplayName;
// Set new physical media name for first side
// Modify original name for second side
if ( !(dwAllocateOptions & NTMS_ALLOCATE_NEXT) ) {
mediaDisplayName = (WCHAR *)displayName;
} else {
WCHAR *dashPtr = wcsrchr((WCHAR *)displayName, L'-');
mediaDisplayName = mediaInfo.szName;
if (dashPtr) {
WsbAffirmHr(mediaDisplayName.Append(dashPtr));
}
}
// Set the Name to the displayName, only if there's no bar code.
if ( NTMS_BARCODESTATE_OK != mediaInfo.Info.PhysicalMedia.BarCodeState) {
wcscpy(mediaInfo.szName, mediaDisplayName);
wcscpy(partitionInfo.szName, (WCHAR *) displayName);
// NTMS doesn't allow dup logical media names. We set
// the name to the mediaId to keep it unique. The logical
// media name is not displayed in the Removable Storage UI.
wcscpy(logicalMediaInfo.szName, (WCHAR *) WsbGuidAsString(mediaId));
}
// Set the Description to the displayName
wcscpy(logicalMediaInfo.szDescription, (WCHAR *) displayName);
wcscpy(partitionInfo.szDescription, (WCHAR *) displayName);
wcscpy(mediaInfo.szDescription, (WCHAR *) mediaDisplayName);
// NTMS - Set partition information.
WsbTraceAlways(OLESTR("SetNtmsObjectInformation()\n"));
err4 = SetNtmsObjectInformation( hSession, &side[0], &partitionInfo );
WsbAffirmNoError( err4 );
// NTMS - Set physical media information.
WsbTraceAlways(OLESTR("SetNtmsObjectInformation()\n"));
err4 = SetNtmsObjectInformation( hSession, &physicalMediaId, &mediaInfo );
WsbAffirmNoError( err4 );
// NTMS - Set logical media information.
WsbTraceAlways(OLESTR("SetNtmsObjectInformation()\n"));
err4 = SetNtmsObjectInformation( hSession, &mediaId, &logicalMediaInfo );
WsbAffirmNoError( err4 );
WsbAssertHrOk(FindCartridge(mediaId, ppCartridge));
WsbAssertHr((*ppCartridge)->SetStatus(RmsStatusScratch));
break;
} WsbCatchAndDo(hr,
switch (HRESULT_CODE(hr)) {
case ERROR_INVALID_HANDLE:
case ERROR_NOT_CONNECTED:
case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running
case RPC_S_CALL_FAILED_DNE: // Media Services is up, handle is not valid.
case RPC_S_CALL_FAILED: // Media Services crashed.
WsbAffirmHr(beginSession());
continue;
}
WsbThrow(hr);
);
} while(1);
} WsbCatchAndDo(hr,
if (err1 != NO_ERROR) {
// AllocateNtmsMedia
switch (HRESULT_CODE(hr)) {
case ERROR_TIMEOUT:
case ERROR_MEDIA_UNAVAILABLE:
hr = RMS_E_SCRATCH_NOT_FOUND;
break;
case ERROR_CANCELLED:
hr = RMS_E_CANCELLED;
break;
case ERROR_MEDIA_OFFLINE:
hr = RMS_E_MEDIA_OFFLINE;
break;
case ERROR_REQUEST_REFUSED:
hr = RMS_E_REQUEST_REFUSED;
break;
case ERROR_WRITE_PROTECT:
hr = RMS_E_WRITE_PROTECT;
break;
case ERROR_INVALID_MEDIA_POOL:
hr = RMS_E_MEDIASET_NOT_FOUND;
break;
case ERROR_ACCESS_DENIED:
case ERROR_DATABASE_FAILURE:
case ERROR_DATABASE_FULL:
case ERROR_DEVICE_NOT_AVAILABLE:
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_MEDIA:
case ERROR_INVALID_PARAMETER:
case ERROR_NOT_ENOUGH_MEMORY:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("AllocateNtmsMedia"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("AllocateNtmsMedia"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
else if (err2 != NO_ERROR ) {
// EnumerateNtmsObject
switch (HRESULT_CODE(hr)) {
case ERROR_OBJECT_NOT_FOUND:
hr = RMS_E_CARTRIDGE_NOT_FOUND;
break;
case ERROR_INVALID_PARAMETER:
case ERROR_INSUFFICIENT_BUFFER:
case ERROR_INVALID_HANDLE:
case ERROR_NOT_ENOUGH_MEMORY:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("EnumerateNtmsObject"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("EnumerateNtmsObject"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
else if (err3 != NO_ERROR) {
// GetNtmsObjectInformation
switch (HRESULT_CODE(hr)) {
case ERROR_OBJECT_NOT_FOUND:
hr = RMS_E_CARTRIDGE_NOT_FOUND;
break;
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_PARAMETER:
case ERROR_NOT_ENOUGH_MEMORY:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectInformation"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectInformation"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
else if (err4 != NO_ERROR) {
// SetNtmsObjectInformation
switch (HRESULT_CODE(hr)) {
case ERROR_ACCESS_DENIED:
case ERROR_DATABASE_FAILURE:
case ERROR_DATABASE_FULL:
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_PARAMETER:
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_OBJECT_NOT_FOUND:
case ERROR_OBJECT_ALREADY_EXISTS: // bmd: 1/18/99 - Not documented, but NTMS doesn't allow dup logical media names.
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("SetNtmsObjectInformation"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("SetNtmsObjectInformation"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
else if (err5 != NO_ERROR) {
// SubmitNtmsOperatorRequest
switch (HRESULT_CODE(hr)) {
case ERROR_ACCESS_DENIED:
case ERROR_DATABASE_FAILURE:
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_PARAMETER:
case ERROR_NOT_CONNECTED:
case ERROR_OBJECT_NOT_FOUND:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("SubmitNtmsOperatorRequest"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("SubmitNtmsOperatorRequest"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
else if (err6 != NO_ERROR) {
// WaitForNtmsOperatorRequest
switch (HRESULT_CODE(hr)) {
case ERROR_TIMEOUT:
hr = RMS_E_TIMEOUT;
break;
case ERROR_CANCELLED:
hr = RMS_E_CANCELLED;
break;
case ERROR_REQUEST_REFUSED:
hr = RMS_E_REQUEST_REFUSED;
break;
case ERROR_ACCESS_DENIED:
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_PARAMETER:
case ERROR_NOT_CONNECTED:
case ERROR_OBJECT_NOT_FOUND:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("WaitForNtmsOperatorRequest"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("WaitForNtmsOperatorRequest"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
);
WsbTraceOut(OLESTR("CRmsNTMS::Allocate"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return hr;
}
STDMETHODIMP
CRmsNTMS::Mount(
IN IRmsCartridge *pCart,
IN OUT IRmsDrive **ppDrive,
IN DWORD dwOptions OPTIONAL,
IN DWORD threadId OPTIONAL)
/*++
Implements:
IRmsNTMS::Mount
--*/
{
HRESULT hr = S_OK;
DWORD err1 = NO_ERROR;
DWORD err2 = NO_ERROR;
DWORD err3 = NO_ERROR;
DWORD err4 = NO_ERROR;
BOOL mediaMounted = FALSE;
BOOL bNoBlock = ( dwOptions & RMS_MOUNT_NO_BLOCK ) ? TRUE : FALSE;
// declared outside try block so it can be accessible throughout the method
DWORD sideNo = 2;
NTMS_GUID side[2];
WsbTraceIn( OLESTR("CRmsNTMS::Mount"), OLESTR("") );
try {
WsbAssertPointer(pCart);
CComPtr<IRmsDrive> pDrive;
// determine the timeout for the operator request
DWORD size;
OLECHAR tmpString[256];
BOOL bShortTimeout = ( dwOptions & RMS_SHORT_TIMEOUT ) ? TRUE : FALSE;
DWORD mountWaitTime;
if (bShortTimeout) {
mountWaitTime = RMS_DEFAULT_SHORT_WAIT_TIME;
if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_SHORT_WAIT_TIME, tmpString, 256, &size))) {
mountWaitTime = wcstol(tmpString, NULL, 10);
WsbTrace(OLESTR("MountWaitTime (Short) is %d milliseconds.\n"), mountWaitTime);
}
} else {
mountWaitTime = RMS_DEFAULT_MOUNT_WAIT_TIME;
if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_MOUNT_WAIT_TIME, tmpString, 256, &size))) {
mountWaitTime = wcstol(tmpString, NULL, 10);
WsbTrace(OLESTR("MountWaitTime is %d milliseconds.\n"), mountWaitTime);
}
}
NTMS_OBJECTINFORMATION driveInfo;
memset( &driveInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
// Special error recovery to handle when NTMS is down, or was cycled.
do {
hr = S_OK;
HANDLE hSession = m_SessionHandle;
NTMS_GUID mediaId = GUID_NULL;
WsbAffirmHr(pCart->GetCartridgeId(&mediaId));
WsbAssert(mediaId != GUID_NULL, E_INVALIDARG);
err1 = NO_ERROR;
err2 = NO_ERROR;
err3 = NO_ERROR;
try {
// NTMS - enumerate the sides of a unit of media
WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
err1 = EnumerateNtmsObject( hSession, &mediaId, side, &sideNo, NTMS_PARTITION, 0 );
WsbAffirmNoError( err1 );
DWORD count = 1;
NTMS_GUID driveId;
// NTMS - issue mount request
WsbTraceAlways(OLESTR("MountNtmsMedia()\n"));
DWORD dwOpt = NTMS_MOUNT_READ | NTMS_MOUNT_WRITE;
if (bNoBlock) {
dwOpt |= (NTMS_MOUNT_ERROR_NOT_AVAILABLE | NTMS_MOUNT_ERROR_OFFLINE);
}
if (dwOptions & RMS_USE_MOUNT_NO_DEADLOCK) {
/*
DEADLOCK AVOIDANCE: when RSM support for MountNtmsMediaDA is
in, the next line should be uncommented, and the other 2 lines
in this 'if' block should be removed.
err2 = MountNtmsMediaDA( hSession, &side[0], &driveId, count, dwOpt, NTMS_PRIORITY_NORMAL, mountWaitTime, NULL, &threadId, 1);
*/
UNREFERENCED_PARAMETER(threadId);
err2 = MountNtmsMedia( hSession, &side[0], &driveId, count, dwOpt, NTMS_PRIORITY_NORMAL, mountWaitTime, NULL);
} else {
err2 = MountNtmsMedia( hSession, &side[0], &driveId, count, dwOpt, NTMS_PRIORITY_NORMAL, mountWaitTime, NULL);
}
WsbAffirmNoError( err2 );
mediaMounted = TRUE;
//
// We now need two critical pieces of information. The Device name and
// the kind of media we just mounted. This gives use the essential information
// to create a data mover. Since we drill through NTMS to get this information
// we also create cartridge, drive objects.
//
driveInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
driveInfo.dwType = NTMS_DRIVE;
// NTMS - get drive information
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_DRIVE)\n"));
err3 = GetNtmsObjectInformation( hSession, &driveId, &driveInfo );
WsbAffirmNoError( err3 );
break;
} WsbCatchAndDo(hr,
switch (HRESULT_CODE(hr)) {
case ERROR_INVALID_HANDLE:
case ERROR_NOT_CONNECTED:
case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running
case RPC_S_CALL_FAILED_DNE: // Media Services is up, handle is not valid.
case RPC_S_CALL_FAILED: // Media Services crashed.
WsbAffirmHr(beginSession());
continue;
}
WsbThrow(hr);
);
} while(1);
RmsMedia mediaType;
WsbAffirmHr(pCart->GetType((LONG *)&mediaType));
// Create Drive
WsbAssertHr(CoCreateInstance(CLSID_CRmsDrive, 0, CLSCTX_SERVER, IID_IRmsDrive, (void **)&pDrive));
CComQIPtr<IRmsChangerElement, &IID_IRmsChangerElement> pElmt = pDrive;
WsbAssertHr(pElmt->SetMediaSupported(mediaType));
CComQIPtr<IRmsDevice, &IID_IRmsDevice> pDevice = pDrive;
WsbAssertHr(pDevice->SetDeviceAddress(
(BYTE) driveInfo.Info.Drive.ScsiPort,
(BYTE) driveInfo.Info.Drive.ScsiBus,
(BYTE) driveInfo.Info.Drive.ScsiTarget,
(BYTE) driveInfo.Info.Drive.ScsiLun));
CWsbBstrPtr deviceName = driveInfo.Info.Drive.szDeviceName;
////////////////////////////////////////////////////////////////////////////////////////
// Convert the NTMS device name to something usable.
//
switch (mediaType) {
case RmsMediaOptical:
case RmsMediaDVD:
case RmsMediaDisk:
{
// We need to convert \\.\PhysicalDriveN to something accessible by the file system.
WCHAR *szDriveLetter = NULL;
WCHAR *szVolumeName = NULL;
err4 = GetVolumesFromDrive( (WCHAR *)deviceName, &szVolumeName, &szDriveLetter );
if (szVolumeName) {
delete [] szVolumeName; // don't need it for now
}
if (NO_ERROR == err4) {
if (szDriveLetter) {
deviceName = szDriveLetter;
} else {
WsbTraceAlways(OLESTR("CRmsNTMS::Mount: GetVolumesFromDrive succeeded but output drive is NULL !!\n"));
WsbThrow(RMS_E_RESOURCE_UNAVAILABLE);
}
}
if (szDriveLetter) {
delete [] szDriveLetter;
}
WsbAffirmNoError( err4 );
WsbTrace(OLESTR("CRmsNTMS::Mount: device name after convert is %s\n"), (WCHAR *)deviceName);
}
break;
default:
break;
}
////////////////////////////////////////////////////////////////////////////////////////
WsbAssertHr(pDevice->SetDeviceName(deviceName));
WsbAssertHr(pCart->SetDrive(pDrive));
// Fill in the return arguments.
*ppDrive = pDrive;
pDrive->AddRef();
} WsbCatchAndDo(hr,
// Process the exception
if (err1 != NO_ERROR ) {
// EnumerateNtmsObject
switch (HRESULT_CODE(hr)) {
case ERROR_OBJECT_NOT_FOUND:
hr = RMS_E_CARTRIDGE_NOT_FOUND;
break;
case ERROR_INVALID_PARAMETER:
case ERROR_INSUFFICIENT_BUFFER:
case ERROR_INVALID_HANDLE:
case ERROR_NOT_ENOUGH_MEMORY:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("EnumerateNtmsObject"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("EnumerateNtmsObject"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
else if (err2 != NO_ERROR) {
// MountNtmsMedia
switch (HRESULT_CODE(hr)) {
case ERROR_TIMEOUT:
hr = RMS_E_CARTRIDGE_UNAVAILABLE;
break;
case ERROR_CANCELLED:
hr = RMS_E_CANCELLED;
break;
case ERROR_MEDIA_OFFLINE:
hr = RMS_E_MEDIA_OFFLINE;
if (bNoBlock) {
DWORD errSub = NO_ERROR;
try {
// Since we are not blocking for NTMS to ask the operator
// to mount the offline media, we do it ourselves
// create operator message
CWsbBstrPtr cartridgeName = "";
CWsbBstrPtr cartridgeDesc = "";
OLECHAR * messageText = NULL;
WCHAR *stringArr[2];
cartridgeName.Free();
WsbAffirmHr(pCart->GetName(&cartridgeName));
cartridgeDesc.Free();
WsbAffirmHr(pCart->GetDescription(&cartridgeDesc));
stringArr[0] = (WCHAR *) cartridgeName;
stringArr[1] = (WCHAR *) cartridgeDesc;
if (0 == FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY,
LoadLibraryEx( WSB_FACILITY_PLATFORM_NAME, NULL, LOAD_LIBRARY_AS_DATAFILE ),
RMS_MESSAGE_OFFLINE_MEDIA_REQUEST, MAKELANGID ( LANG_NEUTRAL, SUBLANG_DEFAULT ),
(LPTSTR)&messageText, 0, (va_list *)stringArr)) {
WsbTrace(OLESTR("CRmsNTMS::Mount: FormatMessage failed: %ls\n"),
WsbHrAsString(HRESULT_FROM_WIN32(GetLastError())));
messageText = NULL;
}
NTMS_GUID mediaId = GUID_NULL;
NTMS_GUID libId = GUID_NULL;
NTMS_GUID requestId = GUID_NULL;
WsbAffirmHr(pCart->GetCartridgeId(&mediaId));
WsbAssert(mediaId != GUID_NULL, E_INVALIDARG);
// Library Id should be gathered here - need to clarify why
// does the GetHome return a null id !!!
// WsbAffirmHr(pCart->GetHome(NULL, &libId, NULL, NULL, NULL, NULL, NULL, NULL));
// WsbAssert(libId != GUID_NULL, E_INVALIDARG);
// submit operator request
errSub = SubmitNtmsOperatorRequest(m_SessionHandle, NTMS_OPREQ_MOVEMEDIA,
messageText, &mediaId, &libId, &requestId);
LocalFree(messageText);
WsbAffirmNoError (errSub);
} WsbCatchAndDo(hr,
// Process the error of the Corrective Action
if (errSub != NO_ERROR ) {
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("SubmitNtmsOperatorRequest"), OLESTR(""),
WsbHrAsString(hr), NULL);
}
// place back the original mane error
hr = RMS_E_MEDIA_OFFLINE;
);
}
break;
case ERROR_REQUEST_REFUSED:
hr = RMS_E_REQUEST_REFUSED;
break;
case ERROR_WRITE_PROTECT:
hr = RMS_E_WRITE_PROTECT;
break;
case ERROR_INVALID_STATE:
case ERROR_INVALID_DRIVE: {
// when performing NTMS mount in non-blocking mode , this error may
// just mean that a corrective action such as drive cleaning should
// be performed before mounting (note that ONLY when not blocking,
// NTMS can not instruct corrective actions by itself)
if (bNoBlock) {
try {
CWsbBstrPtr cartridgeName = "";
CWsbBstrPtr cartridgeDesc = "";
cartridgeName.Free();
WsbAffirmHr(pCart->GetName(&cartridgeName));
cartridgeDesc.Free();
WsbAffirmHr(pCart->GetDescription(&cartridgeDesc));
WsbLogEvent(RMS_MESSAGE_DRIVE_NOT_AVAILABLE, 0, NULL,
(WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, NULL);
} WsbCatch(hr);
break;
}
}
case ERROR_RESOURCE_DISABLED: {
// Check if the the media (cartridge) is disabled - different error should
// be returned for media and for other resources (library, drive, etc.)
HRESULT hrOrg = hr;
DWORD errSub1 = NO_ERROR;
DWORD errSub2 = NO_ERROR;
try {
// get physical media information
NTMS_OBJECTINFORMATION objectInfo;
objectInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
objectInfo.dwType = NTMS_PARTITION;
WsbAssert(side[0] != GUID_NULL, E_INVALIDARG);
errSub1 = GetNtmsObjectInformation( m_SessionHandle, &side[0], &objectInfo );
WsbAffirmNoError (errSub1);
NTMS_GUID physicalMediaId = objectInfo.Info.Partition.PhysicalMedia;
WsbAssert(physicalMediaId != GUID_NULL, E_INVALIDARG);
objectInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
objectInfo.dwType = NTMS_PHYSICAL_MEDIA;
errSub2 = GetNtmsObjectInformation( m_SessionHandle, &physicalMediaId, &objectInfo );
WsbAffirmNoError (errSub2);
// set our dedicated error only if (physical) media is disabled
if (! objectInfo.Enabled) {
hr = RMS_E_CARTRIDGE_DISABLED;
}
} WsbCatchAndDo(hr,
// Process the error of the get-info requests
if (errSub1 != NO_ERROR ) {
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectInformation (Partition)"), OLESTR(""),
WsbHrAsString(hr), NULL);
} else if (errSub2 != NO_ERROR ) {
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectInformation (Physical Media)"), OLESTR(""),
WsbHrAsString(hr), NULL);
}
// place back the original mane error
hr = hrOrg;
);
break;
}
case ERROR_ACCESS_DENIED:
case ERROR_BUSY:
case ERROR_DATABASE_FAILURE:
case ERROR_DATABASE_FULL:
case ERROR_DRIVE_MEDIA_MISMATCH:
case ERROR_INVALID_LIBRARY:
case ERROR_INVALID_MEDIA:
case ERROR_NOT_ENOUGH_MEMORY: {
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("MountNtmsMedia"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
}
default: {
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("MountNtmsMedia"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
}
else if (err3 != NO_ERROR) {
// GetNtmsObjectInformation
switch (HRESULT_CODE(hr)) {
case ERROR_OBJECT_NOT_FOUND:
hr = RMS_E_CARTRIDGE_NOT_FOUND;
break;
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_PARAMETER:
case ERROR_NOT_ENOUGH_MEMORY:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectInformation"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectInformation"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
} else if (err4 != NO_ERROR) {
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetVolumesFromDrive"), OLESTR("Unexpected Failure: "),
WsbHrAsString(hr), NULL);
}
if (mediaMounted) {
// Something failed after the mount completed, so need to clean up...
// Dismount the media to release the resource before returning.
Dismount(pCart, FALSE);
}
);
WsbTraceOut( OLESTR("CRmsNTMS::Mount"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
return hr;
}
STDMETHODIMP
CRmsNTMS::Dismount(
IN IRmsCartridge *pCart, IN DWORD dwOptions)
/*++
Implements:
IRmsNTMS::Dismount
--*/
{
HRESULT hr = S_OK;
DWORD err1 = NO_ERROR;
DWORD err2 = NO_ERROR;
WsbTraceIn( OLESTR("CRmsNTMS::Dismount"), OLESTR("") );
try {
WsbAssertPointer(pCart);
do {
hr = S_OK;
HANDLE hSession = m_SessionHandle;
NTMS_GUID mediaId = GUID_NULL;
WsbAffirmHr(pCart->GetCartridgeId(&mediaId));
WsbAssert(mediaId != GUID_NULL, E_INVALIDARG);
NTMS_GUID side[2];
DWORD sideNo = 2;
err1 = NO_ERROR;
err2 = NO_ERROR;
try {
// NTMS - enumerate the sides of a unit of media
WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
err1 = EnumerateNtmsObject( hSession, &mediaId, side, &sideNo, NTMS_PARTITION, 0 );
WsbAffirmNoError( err1 );
// NTMS - dismount media
DWORD dwNtmsOptions = 0;
WsbTraceAlways(OLESTR("DismountNtmsMedia()\n"));
if (! ( dwOptions & RMS_DISMOUNT_IMMEDIATE )) {
dwNtmsOptions |= NTMS_DISMOUNT_DEFERRED;
}
err2 = DismountNtmsMedia( hSession, &side[0], 1, dwNtmsOptions );
#ifdef DBG
// TODO: Remove this trap for the unexpected ERROR_ACCESS_DENIED error.
WsbAssert(err2 != ERROR_ACCESS_DENIED, HRESULT_FROM_WIN32(err2));
#endif
WsbAffirmNoError( err2 );
// Since RSM Dismount is asyncronous, we may need to wait some arbitrary time,
// in order that when we come back, the media is really dismounted
if ( (dwOptions & RMS_DISMOUNT_DEFERRED_ONLY) && (!(dwOptions & RMS_DISMOUNT_IMMEDIATE)) ) {
CComQIPtr<IRmsServer, &IID_IRmsServer> pServer = g_pServer;
if (S_OK == pServer->IsReady()) {
DWORD size;
OLECHAR tmpString[256];
DWORD waitTime = RMS_DEFAULT_AFTER_DISMOUNT_WAIT_TIME;
if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_AFTER_DISMOUNT_WAIT_TIME, tmpString, 256, &size))) {
waitTime = wcstol(tmpString, NULL, 10);
WsbTrace(OLESTR("AfterDismountWaitTime is %d milliseconds.\n"), waitTime);
}
Sleep(waitTime);
}
}
break;
} WsbCatchAndDo(hr,
switch (HRESULT_CODE(hr)) {
case ERROR_INVALID_HANDLE:
case ERROR_NOT_CONNECTED:
case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running
case RPC_S_CALL_FAILED_DNE: // Media Services is up, handle is not valid.
case RPC_S_CALL_FAILED: // Media Services crashed.
WsbAffirmHr(beginSession());
continue;
}
WsbThrow(hr);
);
} while(1);
} WsbCatchAndDo(hr,
if (err1 != NO_ERROR) {
// EnumerateNtmsObject
switch (HRESULT_CODE(hr)) {
case ERROR_INVALID_PARAMETER:
case ERROR_INVALID_HANDLE:
case ERROR_OBJECT_NOT_FOUND:
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_INSUFFICIENT_BUFFER:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("EnumerateNtmsObject"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("EnumerateNtmsObject"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
else if (err2 != NO_ERROR) {
// DismountNtmsMedia
switch (HRESULT_CODE(hr)) {
case ERROR_MEDIA_OFFLINE:
hr = RMS_E_MEDIA_OFFLINE;
break;
case ERROR_TIMEOUT:
case ERROR_INVALID_MEDIA:
case ERROR_INVALID_LIBRARY:
case ERROR_DEVICE_NOT_AVAILABLE:
case ERROR_MEDIA_NOT_AVAILABLE:
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_INVALID_STATE:
case ERROR_ACCESS_DENIED:
case ERROR_DATABASE_FAILURE:
case ERROR_DATABASE_FULL:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("DismountNtmsMedia"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("DismountNtmsMedia"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
);
WsbTraceOut( OLESTR("CRmsNTMS::Dismount"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
return hr;
}
STDMETHODIMP
CRmsNTMS::Deallocate(
IN IRmsCartridge *pCart)
/*++
Implements:
IRmsNTMS::DeallocateMedia
--*/
{
HRESULT hr = S_OK;
DWORD err1 = NO_ERROR;
DWORD err2 = NO_ERROR;
DWORD err3 = NO_ERROR;
DWORD err4 = NO_ERROR;
WsbTraceIn(OLESTR("CRmsNTMS::Deallocate"), OLESTR(""));
try {
WsbAssertPointer(pCart);
do {
hr = S_OK;
HANDLE hSession = m_SessionHandle;
NTMS_GUID mediaId = GUID_NULL;
WsbAffirmHr(pCart->GetCartridgeId(&mediaId));
WsbAssert(mediaId != GUID_NULL, E_INVALIDARG);
err1 = NO_ERROR;
err2 = NO_ERROR;
err3 = NO_ERROR;
err4 = NO_ERROR;
NTMS_OBJECTINFORMATION partitionInfo;
memset( &partitionInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
DWORD sideNo = 2;
NTMS_GUID side[2];
try {
// NTMS - enumerate the sides of a unit of media
WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
err1 = EnumerateNtmsObject( hSession, &mediaId, side, &sideNo, NTMS_PARTITION, 0 );
WsbAffirmNoError( err1 );
// NTMS - get partition information
partitionInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
partitionInfo.dwType = NTMS_PARTITION;
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PARTITION)\n"));
err2 = GetNtmsObjectInformation( hSession, &side[0], &partitionInfo );
WsbAffirmNoError( err2 );
// NULL the Description
wcscpy(partitionInfo.szDescription, L"");
// NTMS - Set partition information.
WsbTraceAlways(OLESTR("SetNtmsObjectInformation()\n"));
err3 = SetNtmsObjectInformation( hSession, &side[0], &partitionInfo );
WsbAffirmNoError( err3 );
// NTMS - deallocate media
WsbTraceAlways(OLESTR("DeallocateNtmsMedia()\n"));
err4 = DeallocateNtmsMedia( hSession, &mediaId, 0 );
WsbAffirmNoError( err4 );
break;
} WsbCatchAndDo(hr,
switch (HRESULT_CODE(hr)) {
case ERROR_INVALID_HANDLE:
case ERROR_NOT_CONNECTED:
case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running
case RPC_S_CALL_FAILED_DNE: // Media Services is up, handle is not valid.
case RPC_S_CALL_FAILED: // Media Services crashed.
WsbAffirmHr(beginSession());
continue;
}
WsbThrow(hr);
);
} while(1);
} WsbCatchAndDo(hr,
if (err1 != NO_ERROR ) {
// EnumerateNtmsObject
switch (HRESULT_CODE(hr)) {
case ERROR_OBJECT_NOT_FOUND:
hr = RMS_E_CARTRIDGE_NOT_FOUND;
break;
case ERROR_INVALID_PARAMETER:
case ERROR_INVALID_HANDLE:
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_INSUFFICIENT_BUFFER:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("EnumerateNtmsObject"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("EnumerateNtmsObject"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
else if (err2 != NO_ERROR) {
// GetNtmsObjectInformation
switch (HRESULT_CODE(hr)) {
case ERROR_OBJECT_NOT_FOUND:
hr = RMS_E_CARTRIDGE_NOT_FOUND;
break;
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_PARAMETER:
case ERROR_NOT_ENOUGH_MEMORY:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectInformation"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectInformation"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
else if (err3 != NO_ERROR) {
// SetNtmsObjectInformation
switch (HRESULT_CODE(hr)) {
case ERROR_ACCESS_DENIED:
case ERROR_DATABASE_FAILURE:
case ERROR_DATABASE_FULL:
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_PARAMETER:
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_OBJECT_NOT_FOUND:
case ERROR_OBJECT_ALREADY_EXISTS: // bmd: 1/18/99 - Not documented, but NTMS doesn't allow dup logical media names.
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("SetNtmsObjectInformation"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("SetNtmsObjectInformation"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
else if (err4 != NO_ERROR) {
// DeallocateNtmsMedia
switch (HRESULT_CODE(hr)) {
case ERROR_INVALID_PARAMETER:
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_MEDIA:
//case ERROR_INVALID_PARTITION:
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_DATABASE_FAILURE:
case ERROR_DATABASE_FULL:
case ERROR_ACCESS_DENIED:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("DeallocateNtmsMedia"), OLESTR(""),
WsbHrAsString(hr),
NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("DeallocateNtmsMedia"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
);
WsbTraceOut(OLESTR("CRmsNTMS::Deallocate"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return hr;
}
STDMETHODIMP
CRmsNTMS::UpdateOmidInfo(
IN REFGUID cartId,
IN BYTE *pBuffer,
IN LONG size,
IN LONG type)
/*++
Implements:
IRmsNTMS::UpdateOmidInfo
--*/
{
HRESULT hr = S_OK;
DWORD err1 = NO_ERROR;
WsbTraceIn( OLESTR("CRmsNTMS::UpdateOmidInfo"), OLESTR("<%ls> <0x%08x> <%d>"), WsbGuidAsString(cartId), pBuffer, size );
try {
WsbAssert(cartId != GUID_NULL, E_INVALIDARG);
WsbAssertPointer(pBuffer);
WsbAssert(size > 0, E_INVALIDARG);
WsbTraceBuffer(size, pBuffer);
do {
hr = S_OK;
HANDLE hSession = m_SessionHandle;
NTMS_GUID mediaId = cartId;
err1 = NO_ERROR;
try {
// NTMS - update on media information.
WsbTraceAlways(OLESTR("UpdateNtmsOmidInfo()\n"));
switch((RmsOnMediaIdentifier)type) {
case RmsOnMediaIdentifierMTF:
err1 = UpdateNtmsOmidInfo(hSession, &mediaId, NTMS_OMID_TYPE_RAW_LABEL, size, pBuffer);
break;
case RmsOnMediaIdentifierWIN32:
WsbAssert(size == sizeof(NTMS_FILESYSTEM_INFO), E_UNEXPECTED);
err1 = UpdateNtmsOmidInfo(hSession, &mediaId, NTMS_OMID_TYPE_FILESYSTEM_INFO, size, pBuffer);
break;
default:
WsbThrow(E_UNEXPECTED);
}
WsbAffirmNoError( err1 );
break;
} WsbCatchAndDo(hr,
switch (HRESULT_CODE(hr)) {
case ERROR_INVALID_HANDLE:
case ERROR_NOT_CONNECTED:
case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running
case RPC_S_CALL_FAILED_DNE: // Media Services is up, handle is not valid.
case RPC_S_CALL_FAILED: // Media Services crashed.
WsbAffirmHr(beginSession());
continue;
}
WsbThrow(hr);
);
} while(1);
} WsbCatchAndDo(hr,
if (err1 != NO_ERROR) {
// UpdateNtmsOmidInfo
switch (HRESULT_CODE(hr)) {
case ERROR_ACCESS_DENIED:
case ERROR_DATABASE_FAILURE:
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_MEDIA:
//case ERROR_INVALID_PARTITION:
case ERROR_INVALID_PARAMETER:
case ERROR_NOT_CONNECTED:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("UpdateNtmsOmidInfo"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("UpdateNtmsOmidInfo"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
);
WsbTraceOut( OLESTR("CRmsNTMS::UpdateOmidInfo"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
return hr;
}
STDMETHODIMP
CRmsNTMS::GetBlockSize(
IN REFGUID cartId,
OUT LONG *pBlockSize
)
/*++
Implements:
IRmsNTMS::GetBlockSize
--*/
{
HRESULT hr = S_OK;
DWORD err1 = NO_ERROR;
WsbTraceIn(OLESTR("CRmsNTMS::GetBlockSize"), OLESTR("<%ls> <x%08x>"), WsbGuidAsString(cartId), pBlockSize);
try {
WsbAssertPointer(pBlockSize);
do {
hr = S_OK;
err1 = NO_ERROR;
HANDLE hSession = m_SessionHandle;
NTMS_GUID mediaId = cartId;
DWORD nBlockSize;
DWORD sizeOfBlockSize = sizeof(DWORD);
try {
err1 = GetNtmsObjectAttribute(hSession, &mediaId, NTMS_LOGICAL_MEDIA, OLESTR("BlockSize"), (LPVOID) &nBlockSize, &sizeOfBlockSize);
WsbAffirmNoError(err1);
*pBlockSize = (LONG) nBlockSize;
break;
} WsbCatchAndDo(hr,
switch (HRESULT_CODE(hr)) {
case ERROR_INVALID_HANDLE:
case ERROR_NOT_CONNECTED:
case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running
case RPC_S_CALL_FAILED_DNE: // Media Services is up, handle is not valid.
case RPC_S_CALL_FAILED: // Media Services crashed.
WsbAffirmHr(beginSession());
continue;
}
WsbThrow(hr);
);
} while(1);
} WsbCatchAndDo(hr,
if (err1 != NO_ERROR) {
// GetNtmsObjectAttribute
switch (HRESULT_CODE(hr)) {
case ERROR_OBJECT_NOT_FOUND: // Don't log this error. Attribute doesn't
break; // exist for new media. We skip this error
// and let the caller deal with it.
case ERROR_DATABASE_FAILURE: // Log these errors.
case ERROR_INVALID_HANDLE:
case ERROR_NOT_CONNECTED:
case ERROR_INSUFFICIENT_BUFFER:
case ERROR_NO_DATA:
case ERROR_INVALID_PARAMETER:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectAttribute"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectAttribute"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
);
WsbTraceOut(OLESTR("CRmsNTMS::GetBlockSize"), OLESTR("hr = <%ls>, BlockSize = <%d>"), WsbHrAsString(hr), *pBlockSize);
return hr;
}
STDMETHODIMP
CRmsNTMS::SetBlockSize(
IN REFGUID cartId,
IN LONG blockSize
)
/*++
Implements:
IRmsNTMS::SetBlockSize
--*/
{
HRESULT hr = S_OK;
DWORD err1 = NO_ERROR;
WsbTraceIn(OLESTR("CRmsNTMS::SetBlockSize"), OLESTR("<%ls> <%d>"), WsbGuidAsString(cartId), blockSize);
try {
do {
hr = S_OK;
err1 = NO_ERROR;
HANDLE hSession = m_SessionHandle;
NTMS_GUID mediaId = cartId;
DWORD nBlockSize = blockSize;
DWORD sizeOfBlockSize = sizeof(DWORD);
try {
err1 = SetNtmsObjectAttribute(hSession, &mediaId, NTMS_LOGICAL_MEDIA, OLESTR("BlockSize"), (LPVOID) &nBlockSize, sizeOfBlockSize);
WsbAffirmNoError(err1);
break;
} WsbCatchAndDo(hr,
switch (HRESULT_CODE(hr)) {
case ERROR_INVALID_HANDLE:
case ERROR_NOT_CONNECTED:
case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running
case RPC_S_CALL_FAILED_DNE: // Media Services is up, handle is not valid.
case RPC_S_CALL_FAILED: // Media Services crashed.
WsbAffirmHr(beginSession());
continue;
}
WsbThrow(hr);
);
} while(1);
} WsbCatchAndDo(hr,
if (err1 != NO_ERROR) {
// SetNtmsObjectAttribute
switch (HRESULT_CODE(hr)) {
case ERROR_DATABASE_FAILURE:
case ERROR_INVALID_HANDLE:
case ERROR_INSUFFICIENT_BUFFER:
case ERROR_NOT_CONNECTED:
case ERROR_NO_DATA:
case ERROR_INVALID_PARAMETER:
case ERROR_OBJECT_NOT_FOUND:
case ERROR_INVALID_NAME:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("SetNtmsObjectAttribute"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("SetNtmsObjectAttribute"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
);
WsbTraceOut(OLESTR("CRmsNTMS::SetBlockSize"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return hr;
}
HRESULT
CRmsNTMS::changeState(
IN LONG newState
)
/*++
Routine Description:
Changes the state of the NTMS object.
Arguments:
None.
Return Values:
S_OK - Success.
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CRmsNTMS::changeState"), OLESTR("<%d>"), newState);
try {
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
WsbAssertPointer( pObject );
// TODO: Validate the state change
WsbAffirmHr(pObject->SetState(newState));
} WsbCatch(hr);
WsbTraceOut(OLESTR("CRmsNTMS::changeState"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return hr;
}
STDMETHODIMP
CRmsNTMS::ExportDatabase(void)
/*++
Implements:
CRmsNTMS::ExportDatabase
--*/
{
HRESULT hr = S_OK;
DWORD err1 = NO_ERROR;
WsbTraceIn( OLESTR("CRmsNTMS::ExportDatabase"), OLESTR(""));
try {
do {
hr = S_OK;
HANDLE hSession = m_SessionHandle;
err1 = NO_ERROR;
try {
err1 = ExportNtmsDatabase(hSession);
WsbAffirmNoError(err1);
break;
} WsbCatchAndDo(hr,
switch (HRESULT_CODE(hr)) {
case ERROR_INVALID_HANDLE:
case ERROR_NOT_CONNECTED:
case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running
case RPC_S_CALL_FAILED_DNE: // Media Services is up, handle is not valid.
case RPC_S_CALL_FAILED: // Media Services crashed.
WsbAffirmHr(beginSession());
continue;
}
WsbThrow(hr);
);
} while(1);
} WsbCatchAndDo(hr,
if (err1 != NO_ERROR) {
// ExportNtmsDatabase
switch (HRESULT_CODE(hr)) {
case ERROR_ACCESS_DENIED:
case ERROR_DATABASE_FAILURE:
case ERROR_INVALID_HANDLE:
case ERROR_NOT_CONNECTED:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("ExportNtmsDatabase"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("ExportNtmsDatabase"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
);
WsbTraceOut(OLESTR("CRmsNTMS::ExportDatabase"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return hr;
}
STDMETHODIMP
CRmsNTMS::FindCartridge(
IN REFGUID cartId,
OUT IRmsCartridge **ppCartridge)
/*++
Implements:
CRmsNTMS::FindCartridge
--*/
{
HRESULT hr = S_OK;
DWORD err1 = NO_ERROR;
DWORD err2 = NO_ERROR;
WsbTraceIn( OLESTR("CRmsNTMS::FindCartridge"), OLESTR("<%ls> <0x%08x>"), WsbGuidAsString(cartId), ppCartridge);
try {
WsbAssert(cartId != GUID_NULL, E_INVALIDARG);
WsbAssertPointer(ppCartridge);
NTMS_OBJECTINFORMATION partitionInfo;
memset( &partitionInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
NTMS_OBJECTINFORMATION mediaInfo;
memset( &mediaInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
NTMS_OBJECTINFORMATION mediaTypeInfo;
memset( &mediaTypeInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
NTMS_OBJECTINFORMATION libraryInfo;
memset( &libraryInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
NTMS_OBJECTINFORMATION logicalMediaInfo;
memset( &logicalMediaInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
RmsMedia translatedMediaType = RmsMediaUnknown;
// Special error recovery to handle when NTMS is down, or was cycled.
do {
hr = S_OK;
HANDLE hSession = m_SessionHandle;
NTMS_GUID mediaId = cartId;
DWORD sideNo = 2;
NTMS_GUID side[2];
err1 = NO_ERROR;
err2 = NO_ERROR;
try {
// NTMS - enumerate the sides of a unit of media
WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
err1 = EnumerateNtmsObject( hSession, &mediaId, side, &sideNo, NTMS_PARTITION, 0 );
WsbAffirmNoError( err1 );
// NTMS - get partition information
partitionInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
partitionInfo.dwType = NTMS_PARTITION;
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PARTITION)\n"));
err2 = GetNtmsObjectInformation( hSession, &side[0], &partitionInfo );
WsbAffirmNoError( err2 );
// NTMS - get physical media information
NTMS_GUID physicalMediaId = partitionInfo.Info.Partition.PhysicalMedia;
mediaInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
mediaInfo.dwType = NTMS_PHYSICAL_MEDIA;
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PHYSICAL_MEDIA)\n"));
err2 = GetNtmsObjectInformation( hSession, &physicalMediaId, &mediaInfo );
WsbAffirmNoError( err2);
// NTMS - get media type information
NTMS_GUID mediaTypeId = mediaInfo.Info.PhysicalMedia.MediaType;
mediaTypeInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
mediaTypeInfo.dwType = NTMS_MEDIA_TYPE;
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_MEDIA_TYPE)\n"));
err2 = GetNtmsObjectInformation( hSession, &mediaTypeId, &mediaTypeInfo );
WsbAffirmNoError( err2 );
// Translate the NTMS media type into something understood by RMS
storageMediaTypeToRmsMedia(&(mediaTypeInfo.Info.MediaType), &translatedMediaType);
// NTMS - get logical media information
logicalMediaInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
logicalMediaInfo.dwType = NTMS_LOGICAL_MEDIA;
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_LOGICAL_MEDIA)\n"));
err2 = GetNtmsObjectInformation( hSession, &mediaId, &logicalMediaInfo );
WsbAffirmNoError( err2 );
// NTMS - get library information
NTMS_GUID libraryId = mediaInfo.Info.PhysicalMedia.CurrentLibrary;
libraryInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
libraryInfo.dwType = NTMS_LIBRARY;
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_LIBRARY)\n"));
err2 = GetNtmsObjectInformation( hSession, &libraryId, &libraryInfo );
WsbAffirmNoError( err2 );
break;
} WsbCatchAndDo(hr,
switch (HRESULT_CODE(hr)) {
case ERROR_INVALID_HANDLE:
case ERROR_NOT_CONNECTED:
case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running.
case RPC_S_CALL_FAILED_DNE: // Media Services is up; handle is not valid.
case RPC_S_CALL_FAILED: // Media Services crashed.
WsbAffirmHr(beginSession());
continue;
}
WsbThrow(hr);
);
} while(1);
// Create Cartridge
IRmsCartridge *pCart = 0;
WsbAssertHr(CoCreateInstance(CLSID_CRmsCartridge, 0, CLSCTX_SERVER,
IID_IRmsCartridge, (void **)&pCart));
// Fill in the object data
// The media Name is what is displaye by NTMS UI
CWsbBstrPtr name = mediaInfo.szName;
WsbAffirmHr(pCart->SetName(name));
// The partition Description is what is displayed by NTMS UI.
CWsbBstrPtr desc = partitionInfo.szDescription;
WsbAffirmHr(pCart->SetDescription(desc));
WsbAffirmHr(pCart->SetCartridgeId(cartId));
CWsbBstrPtr barCode = mediaInfo.Info.PhysicalMedia.szBarCode;
CWsbBstrPtr seqNo = mediaInfo.Info.PhysicalMedia.szSequenceNumber; // Not used
WsbAffirmHr(pCart->SetTagAndNumber(barCode, 0));
WsbAffirmHr(pCart->SetType((LONG) translatedMediaType));
switch (mediaInfo.Info.PhysicalMedia.MediaState) {
case NTMS_MEDIASTATE_IDLE:
case NTMS_MEDIASTATE_UNLOADED:
WsbAffirmHr(pCart->SetIsAvailable(TRUE));
break;
default:
WsbAffirmHr(pCart->SetIsAvailable(FALSE));
break;
}
RmsElement type = RmsElementUnknown;
if ( NTMS_LIBRARYTYPE_ONLINE == libraryInfo.Info.Library.LibraryType ) {
switch (mediaInfo.Info.PhysicalMedia.LocationType) {
case NTMS_STORAGESLOT:
type = RmsElementStorage;
break;
case NTMS_DRIVE:
type = RmsElementDrive;
break;
case NTMS_IEPORT:
type = RmsElementIEPort;
break;
case NTMS_CHANGER:
type = RmsElementChanger;
break;
default:
type = RmsElementUnknown;
break;
}
}
else if ( NTMS_LIBRARYTYPE_STANDALONE == libraryInfo.Info.Library.LibraryType ) {
switch (mediaInfo.Info.PhysicalMedia.LocationType) {
case NTMS_DRIVE:
type = RmsElementDrive;
break;
default:
type = RmsElementUnknown;
break;
}
} else {
type = RmsElementShelf;
}
WsbAffirmHr(pCart->SetLocation(type,
mediaInfo.Info.PhysicalMedia.CurrentLibrary,
logicalMediaInfo.Info.LogicalMedia.MediaPool,
0, 0, 0, 0, 0));
WsbAffirmHr(pCart->SetManagedBy((LONG)RmsMediaManagerNTMS));
WsbAssertHr(pCart->SetStatus(RmsStatusPrivate));
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObj = pCart;
if (!mediaInfo.Enabled) {
WsbAffirmHr(pObj->Disable(RMS_E_CARTRIDGE_DISABLED));
}
CComQIPtr<IRmsStorageInfo, &IID_IRmsStorageInfo> pInfo = pCart;
WsbAffirmHr(pInfo->SetCapacity(partitionInfo.Info.Partition.Capacity.QuadPart));
WsbTrace(OLESTR("Cartridge id <name/desc>: %ls <%ls/%ls>\n"), WsbGuidAsString(cartId), (WCHAR *) name, (WCHAR *) desc);
WsbTrace(OLESTR("Cartridge <barCode/seqNo>: <%ls/%ls>\n"), (WCHAR *) barCode, (WCHAR *) seqNo );
WsbTrace(OLESTR("Cartridge Enabled: %ls\n"), WsbHrAsString(pObj->IsEnabled()));
WsbTrace(OLESTR("Cartridge type: %d\n"), translatedMediaType);
WsbTrace(OLESTR("Cartridge capacity: %I64d\n"), partitionInfo.Info.Partition.Capacity.QuadPart);
WsbTrace(OLESTR("Cartridge domain: %ls\n"), WsbGuidAsString(logicalMediaInfo.Info.LogicalMedia.MediaPool));
if (mediaInfo.Info.PhysicalMedia.MediaPool != logicalMediaInfo.Info.LogicalMedia.MediaPool) {
CWsbStringPtr idPhysical = mediaInfo.Info.PhysicalMedia.CurrentLibrary;
CWsbStringPtr idLogical = logicalMediaInfo.Info.LogicalMedia.MediaPool;
WsbTraceAlways(OLESTR("CRmsNTMS::FindCartridge - Media Pool Id mismatch %ls != %ls\n"), idPhysical, idLogical );
}
// Fill in the return argument.
*ppCartridge = pCart;
} WsbCatchAndDo( hr,
WsbTrace(OLESTR("CRmsNTMS::FindCartridge - %ls Not Found. hr = <%ls>\n"),WsbGuidAsString(cartId),WsbHrAsString(hr));
if (err1 != NO_ERROR ) {
// EnumerateNtmsObject
switch (HRESULT_CODE(hr)) {
case ERROR_OBJECT_NOT_FOUND:
hr = RMS_E_CARTRIDGE_NOT_FOUND;
break;
case ERROR_INVALID_PARAMETER:
case ERROR_INVALID_HANDLE:
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_INSUFFICIENT_BUFFER:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("EnumerateNtmsObject"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("EnumerateNtmsObject"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
else if (err2 != NO_ERROR) {
// GetNtmsObjectInformation
switch (HRESULT_CODE(hr)) {
case ERROR_OBJECT_NOT_FOUND:
hr = RMS_E_CARTRIDGE_NOT_FOUND;
break;
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_PARAMETER:
case ERROR_NOT_ENOUGH_MEMORY:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectInformation"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectInformation"), OLESTR("Undocumented Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
);
WsbTraceOut( OLESTR("CRmsNTMS::FindCartridge"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
return hr;
}
STDMETHODIMP
CRmsNTMS::Suspend(void)
/*++
Implements:
CRmsNTMS::Suspend
--*/
{
HRESULT hr = S_OK;
WsbTraceIn( OLESTR("CRmsNTMS::Suspend"), OLESTR(""));
try {
WsbAffirmHr(changeState(RmsNtmsStateSuspending));
WsbAffirmHr(endSession());
WsbAffirmHr(changeState(RmsNtmsStateSuspended));
} WsbCatch(hr);
WsbTraceOut( OLESTR("CRmsNTMS::Suspend"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
return hr;
}
STDMETHODIMP
CRmsNTMS::Resume(void)
/*++
Implements:
CRmsNTMS::Resume
--*/
{
HRESULT hr = S_OK;
WsbTraceIn( OLESTR("CRmsNTMS::Resume"), OLESTR(""));
try {
WsbAffirmHr(changeState(RmsNtmsStateResuming));
WsbAffirmHr(beginSession());
WsbAffirmHr(changeState(RmsNtmsStateReady));
} WsbCatch(hr);
WsbTraceOut( OLESTR("CRmsNTMS::Resume"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
return hr;
}
HRESULT
CRmsNTMS::InitializeInAnotherThread(void)
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CRmsNTMS::InitializeInAnotherThread"), OLESTR(""));
try {
DWORD threadId;
HANDLE hThread;
CComQIPtr<IRmsServer, &IID_IRmsServer> pServer = g_pServer;
WsbAffirmHr( pServer->ChangeState( RmsServerStateInitializing ));
WsbAffirmHandle(hThread = CreateThread(NULL, 1024, CRmsNTMS::InitializationThread, this, 0, &threadId));
CloseHandle(hThread);
} WsbCatch(hr);
WsbTraceOut(OLESTR("CRmsNTMS::InitializeInAnotherThread"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return hr;
}
DWORD WINAPI
CRmsNTMS::InitializationThread(
IN LPVOID pv)
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CRmsNTMS::InitializationThread"), OLESTR(""));
try {
WsbAssertPointer(pv);
CRmsNTMS *pNTMS = (CRmsNTMS*)pv;
WsbAffirmHr(pNTMS->Initialize());
CComQIPtr<IRmsServer, &IID_IRmsServer> pServer = g_pServer;
WsbAffirmHr( pServer->ChangeState( RmsServerStateReady ));
} WsbCatch(hr);
WsbTraceOut(OLESTR("CRmsNTMS::InitializationThread"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return hr;
}
HRESULT
CRmsNTMS::isReady(void)
{
HRESULT hr = S_OK;
try {
BOOL isEnabled;
HRESULT status;
RmsServerState state;
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
WsbAssertPointer( pObject );
WsbAffirmHr( isEnabled = pObject->IsEnabled());
WsbAffirmHr( pObject->GetState( (LONG *)&state ));
WsbAffirmHr( pObject->GetStatusCode( &status ));
if ( S_OK == isEnabled ) {
if ( RmsServerStateReady == state ) {
hr = S_OK;
}
else {
if ( S_OK == status ) {
WsbThrow(E_UNEXPECTED);
}
else {
WsbThrow(status);
}
}
}
else {
if ( S_OK == status ) {
WsbThrow(E_UNEXPECTED);
}
else {
WsbThrow(status);
}
}
} WsbCatch(hr);
return hr;
}
HRESULT
CRmsNTMS::setPoolDACL (
IN OUT NTMS_GUID *pPoolId,
IN DWORD subAuthority,
IN DWORD action,
IN DWORD mask)
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CRmsNTMS::SetPoolDACL"), OLESTR("%ls <%d> <%d> <%d>"), WsbGuidAsString(*pPoolId), subAuthority, action, mask);
PSID psidAccount = NULL;
PSECURITY_DESCRIPTOR psdRePoolSd = NULL;
try {
SID_IDENTIFIER_AUTHORITY ntauth = SECURITY_NT_AUTHORITY;
DWORD errCode = NO_ERROR, sizeTry = 5, sizeReturned = 0;
PACL paclDis = NULL;
ACCESS_ALLOWED_ACE *pAce = NULL;
BOOL daclPresent = FALSE, daclDefaulted = FALSE;
HANDLE hSession = m_SessionHandle;
WsbAffirmStatus(AllocateAndInitializeSid(&ntauth, 2, SECURITY_BUILTIN_DOMAIN_RID, subAuthority, 0, 0, 0, 0, 0, 0, &psidAccount));
//Get the security descriptor for the pool
for (;;) {
if (psdRePoolSd != NULL) {
free(psdRePoolSd);
}
psdRePoolSd = (PSECURITY_DESCRIPTOR)malloc(sizeTry);
WsbAffirm(NULL != psdRePoolSd, E_OUTOFMEMORY);
errCode = GetNtmsObjectSecurity(hSession, pPoolId, NTMS_MEDIA_POOL, DACL_SECURITY_INFORMATION, psdRePoolSd, sizeTry, &sizeReturned);
if (errCode == ERROR_SUCCESS) {
break;
}
else if (errCode == ERROR_INSUFFICIENT_BUFFER) {
sizeTry = sizeReturned;
continue;
}
else {
WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
OLESTR("GetNtmsObjectSecurity"),
WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
NULL );
WsbAffirmNoError(errCode);
}
}
// Get a pointer to the DACL
WsbAffirmStatus(GetSecurityDescriptorDacl(psdRePoolSd, &daclPresent, &paclDis, &daclDefaulted));
// Go through the DACL and change the mask of the ACE that matches the SID
for (DWORD i = 0;i < paclDis->AceCount; ++i) {
WsbAffirmStatus(GetAce(paclDis, i, (LPVOID*) &pAce));
if (EqualSid(psidAccount, &(pAce->SidStart))) {
if (action == ADD_ACE_MASK_BITS) {
pAce->Mask |= mask;
} else {
pAce->Mask &= ~mask;
}
}
}
// Set the pool security descriptor
errCode = SetNtmsObjectSecurity(hSession, pPoolId, NTMS_MEDIA_POOL, DACL_SECURITY_INFORMATION, psdRePoolSd);
WsbAffirmNoError(errCode);
} WsbCatch(hr);
if (psdRePoolSd) {
free(psdRePoolSd);
}
if (psidAccount) {
FreeSid(psidAccount);
}
WsbTraceOut(OLESTR("CRmsNTMS::SetPoolDACL"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return hr;
}
HRESULT
CRmsNTMS::IsMediaCopySupported (
IN REFGUID mediaPoolId)
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CRmsNTMS::IsMediaCopySupported"), OLESTR("%ls"), WsbGuidAsString(mediaPoolId));
try {
// If we can find two drives that support this media type then
// the media copy operation is supported.
// For each drive known to NTMS we need to find what media types
// it supports. NTMS doesn't keep media type information for the
// drive, but assumes homogeneous drives in a library (per HighGound) -
// so detecting this is a bit convoluted.
// we'll search through each library and find the media types
// supported, and count the number of drives in the library.
if ( INVALID_HANDLE_VALUE == m_SessionHandle ) {
WsbAffirmHr(beginSession());
}
HANDLE hSession = m_SessionHandle;
NTMS_OBJECTINFORMATION mediaPoolInfo;
NTMS_GUID poolId = mediaPoolId;
memset(&mediaPoolInfo, 0, sizeof(NTMS_OBJECTINFORMATION));
mediaPoolInfo.dwType = NTMS_MEDIA_POOL;
mediaPoolInfo.dwSize = sizeof(NTMS_OBJECTINFORMATION);
// NTMS - Get Media Pool Information
WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
DWORD errCode = GetNtmsObjectInformation( hSession, &poolId, &mediaPoolInfo );
if ( errCode != NO_ERROR ) {
WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
OLESTR("GetNtmsObjectInformation"),
WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
NULL );
WsbThrow( E_UNEXPECTED );
}
NTMS_GUID mediaTypeId = mediaPoolInfo.Info.MediaPool.MediaType;
NTMS_OBJECTINFORMATION libInfo;
HANDLE hFindLib = NULL;
int driveCount = 0;
hr = findFirstNtmsObject( NTMS_LIBRARY,
GUID_NULL, NULL, GUID_NULL, &hFindLib, &libInfo);
while( S_OK == hr ) {
HANDLE hFindLib2 = NULL;
// now see if the library in which the drive is contained supported
// the specified media type
if ( libInfo.Info.Library.dwNumberOfDrives > 0 ) {
hr = findFirstNtmsObject( NTMS_MEDIA_TYPE,
libInfo.ObjectGuid, NULL, mediaTypeId, &hFindLib2, NULL);
WsbTrace(OLESTR("Searching <%ls> for media type and drives; hr = %ls (state = %d, enabled = %ls, drives = %d)\n"),
libInfo.szName, WsbHrAsString(hr),
libInfo.dwOperationalState,
WsbBoolAsString(libInfo.Enabled),
libInfo.Info.Library.dwNumberOfDrives);
if ((S_OK == hr) &&
((NTMS_READY == libInfo.dwOperationalState) ||
(NTMS_INITIALIZING == libInfo.dwOperationalState)) &&
(libInfo.Enabled)) {
driveCount += libInfo.Info.Library.dwNumberOfDrives;
}
findCloseNtmsObject( hFindLib2 );
}
hr = findNextNtmsObject( hFindLib, &libInfo );
}
findCloseNtmsObject( hFindLib );
hr = (driveCount > 1) ? S_OK : S_FALSE;
} WsbCatch(hr);
WsbTraceOut(OLESTR("CRmsNTMS::IsMediaCopySupported"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return hr;
}
STDMETHODIMP
CRmsNTMS::UpdateDrive(
IN IRmsDrive *pDrive)
/*++
Implements:
IRmsNTMS::UpdateDrive
--*/
{
HRESULT hr = S_OK;
CComPtr<IRmsComObject> pObject;
GUID driveId;
DWORD err1 = NO_ERROR;
WsbTraceIn(OLESTR("CRmsNTMS::UpdateDrive"), OLESTR(""));
try {
// get drive information
WsbAffirmHr(pDrive->QueryInterface(IID_IRmsComObject, (void **)&pObject));
WsbAffirmHr(pObject->GetObjectId(&driveId));
NTMS_OBJECTINFORMATION objectInfo;
objectInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
objectInfo.dwType = NTMS_DRIVE;
WsbAssert(driveId != GUID_NULL, E_INVALIDARG);
err1 = GetNtmsObjectInformation( m_SessionHandle, &driveId, &objectInfo );
WsbAffirmNoError (err1);
// Note: Currently, the method updates only the enable/disable state of the drive
// If required, the method may update more fields
if (objectInfo.Enabled) {
WsbAffirmHr(pObject->Enable());
} else {
WsbAffirmHr(pObject->Disable(S_OK));
}
} WsbCatchAndDo(hr,
// Process the error of the get-info request
if (err1 != NO_ERROR ) {
if (err1 == ERROR_OBJECT_NOT_FOUND) {
hr = RMS_E_NTMS_OBJECT_NOT_FOUND;
}
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectInformation (Drive)"), OLESTR(""),
WsbHrAsString(hr), NULL);
}
);
WsbTraceOut(OLESTR("CRmsNTMS::UpdateDrive"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CRmsNTMS::GetNofAvailableDrives(
OUT DWORD* pdwNofDrives
)
/*++
Implements:
IRmsNTMS::GetNofAvailableDrives().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CRmsNTMS::GetNofAvailableDrives"), OLESTR(""));
*pdwNofDrives = 0;
// Enumerate over all libraries that HSM uses
// (Outside the try block, since we want to continue if a failure occur on a specific library)
WsbTrace(OLESTR("CRmsNTMS::GetNofAvailableDrives: Total number of libraries is %lu\n"), m_dwNofLibs);
for (int j=0; j<(int)m_dwNofLibs; j++) {
LPNTMS_GUID pObjects = NULL;
DWORD errCode = NO_ERROR;
// get library id
GUID libId = m_pLibGuids[j];
try {
// Enumerate on all drives in the library
DWORD dwNofObjects = 16; // Initial size of object id array to allocate
int nRetry = 0;
// Allocate according to
pObjects = (LPNTMS_GUID)WsbAlloc( dwNofObjects*sizeof(NTMS_GUID) );
WsbAffirmPointer( pObjects );
// Enumerate all drives
do {
errCode = EnumerateNtmsObject(m_SessionHandle, &libId, pObjects, &dwNofObjects, NTMS_DRIVE, 0);
WsbTraceAlways(OLESTR("CRmsNTMS::GetNofAvailableDrives: Total number of drives is %lu\n"),
dwNofObjects);
nRetry++;
if ( (ERROR_OBJECT_NOT_FOUND == errCode) || (0 == dwNofObjects) ) { // Don't count on NTMS returning the correct errCode
// Not considered as an NTMS error, prevent logging by setting to NO_ERROR
errCode = NO_ERROR;
WsbThrow( RMS_E_NTMS_OBJECT_NOT_FOUND );
} else if (ERROR_INSUFFICIENT_BUFFER == errCode) {
// Don't retry more than 3 times
if (3 <= nRetry) {
WsbThrow(HRESULT_FROM_WIN32(errCode));
}
// Allocate a new buffer, and retry.
WsbTrace(OLESTR("CRmsNTMS::GetNofAvailableDrives: Reallocating buffer\n"));
LPVOID pTemp = WsbRealloc( pObjects, dwNofObjects*sizeof(NTMS_GUID) );
if (!pTemp) {
WsbThrow(E_OUTOFMEMORY);
}
pObjects = (LPNTMS_GUID)pTemp;
} else {
// Other unexpected error
WsbAffirmNoError(errCode);
}
} while (ERROR_INSUFFICIENT_BUFFER == errCode);
// go over all drives, get information and check availablity
for (int i = 0; i < (int)dwNofObjects; i++) {
GUID driveId = pObjects[i];
try {
NTMS_OBJECTINFORMATION objectInfo;
memset( &objectInfo, 0, sizeof(NTMS_OBJECTINFORMATION) );
objectInfo.dwSize = sizeof(NTMS_OBJECTINFORMATION);
objectInfo.dwType = NTMS_DRIVE;
WsbAssert(driveId != GUID_NULL, E_INVALIDARG);
errCode = GetNtmsObjectInformation(m_SessionHandle, &driveId, &objectInfo );
WsbAffirmNoError (errCode);
WsbTrace(OLESTR("CRmsNTMS::GetNofAvailableDrives: drive <%ls> enable/disable = %ls\n"),
WsbGuidAsString(driveId), WsbBoolAsString(objectInfo.Enabled));
if (objectInfo.Enabled) {
(*pdwNofDrives)++;
}
} WsbCatchAndDo(hr,
// Log error and go on to the next drive
if (errCode != NO_ERROR ) {
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectInformation (Drive)"), OLESTR(""),
WsbHrAsString(hr), NULL);
}
WsbTraceAlways(OLESTR("CRmsNTMS::GetNofAvailableDrives: Failed to get info for drive <%ls> hr = <%ls>\n"),
WsbGuidAsString(driveId), WsbHrAsString(hr));
hr = S_OK;
);
}
} WsbCatchAndDo(hr,
// Log error and go on to the next library
if (errCode != NO_ERROR ) {
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("EnumerateNtmsObject (Drive)"), OLESTR(""),
WsbHrAsString(hr), NULL);
}
WsbTraceAlways(OLESTR("CRmsNTMS::GetNofAvailableDrives: Failed to enumerate drives in library <%ls> hr = <%ls>\n"),
WsbGuidAsString(libId), WsbHrAsString(hr));
hr = S_OK;
);
if (pObjects) {
WsbFree(pObjects);
}
} // of for
WsbTraceOut(OLESTR("CRmsNTMS::GetNofAvailableDrives"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CRmsNTMS::CheckSecondSide(
IN REFGUID firstSideId,
OUT BOOL *pbValid,
OUT GUID *pSecondSideId
)
/*++
Implements:
IRmsNTMS::CheckSecondSide().
--*/
{
HRESULT hr = S_OK;
DWORD err1 = NO_ERROR;
DWORD err2 = NO_ERROR;
WsbTraceIn(OLESTR("CRmsNTMS::CheckSecondSide"), OLESTR(""));
*pbValid = FALSE;
*pSecondSideId = GUID_NULL;
try {
WsbAssert(firstSideId != GUID_NULL, E_INVALIDARG);
WsbAssertPointer(pbValid);
WsbAssertPointer(pSecondSideId);
NTMS_OBJECTINFORMATION partitionInfo;
memset( &partitionInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
NTMS_OBJECTINFORMATION mediaInfo;
memset( &mediaInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
HANDLE hSession = m_SessionHandle;
NTMS_GUID mediaId = firstSideId;
NTMS_GUID firstSidePartitionId;
NTMS_GUID side[2];
DWORD sideNo = 2;
// NTMS - get Partition from LMID
WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
err1 = EnumerateNtmsObject(hSession, &mediaId, side, &sideNo, NTMS_PARTITION, 0);
WsbAffirmNoError(err1);
firstSidePartitionId = side[0];
// NTMS - get partition information (using size 0 - LMID relates 1:1 to Partition
partitionInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
partitionInfo.dwType = NTMS_PARTITION;
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PARTITION)\n"));
err2 = GetNtmsObjectInformation(hSession, &firstSidePartitionId, &partitionInfo);
WsbAffirmNoError(err2);
// NTMS - get physical media information
NTMS_GUID physicalMediaId = partitionInfo.Info.Partition.PhysicalMedia;
mediaInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
mediaInfo.dwType = NTMS_PHYSICAL_MEDIA;
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PHYSICAL_MEDIA)\n"));
err2 = GetNtmsObjectInformation(hSession, &physicalMediaId, &mediaInfo);
WsbAffirmNoError(err2);
// Check whether there are more than one side
if (mediaInfo.Info.PhysicalMedia.dwNumberOfPartitions > 1) {
// Enumerate physical meida - expect 2 sides here.
WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
sideNo = 2;
err1 = EnumerateNtmsObject(hSession, &physicalMediaId, side, &sideNo, NTMS_PARTITION, 0);
WsbAffirmNoError(err1);
WsbAffirm(sideNo > 1, RMS_E_NOT_FOUND);
// Look for a side whos partition id is different from first side
for (DWORD i=0; i<sideNo; i++) {
if (firstSidePartitionId != side[i]) {
*pbValid = TRUE; // Valid second side found
// Get its LMID
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PARTITION)\n"));
err2 = GetNtmsObjectInformation(hSession, &side[i], &partitionInfo);
WsbAffirmNoError(err2);
*pSecondSideId = partitionInfo.Info.Partition.LogicalMedia;
}
}
} // of if two sides
} WsbCatchAndDo( hr,
WsbTrace(OLESTR("CRmsNTMS::CheckSecondSide - of %ls failed: hr = <%ls>\n"),WsbGuidAsString(firstSideId),WsbHrAsString(hr));
if (err1 != NO_ERROR ) {
// EnumerateNtmsObject
switch (HRESULT_CODE(hr)) {
case ERROR_OBJECT_NOT_FOUND:
hr = RMS_E_CARTRIDGE_NOT_FOUND;
break;
case ERROR_INVALID_PARAMETER:
case ERROR_INVALID_HANDLE:
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_INSUFFICIENT_BUFFER:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("EnumerateNtmsObject"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("EnumerateNtmsObject"), OLESTR("Unexpected Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
else if (err2 != NO_ERROR) {
// GetNtmsObjectInformation
switch (HRESULT_CODE(hr)) {
case ERROR_OBJECT_NOT_FOUND:
hr = RMS_E_CARTRIDGE_NOT_FOUND;
break;
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_PARAMETER:
case ERROR_NOT_ENOUGH_MEMORY:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectInformation"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectInformation"), OLESTR("Unexpected Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
);
WsbTraceOut(OLESTR("CRmsNTMS::CheckSecondSide"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CRmsNTMS::EnsureAllSidesNotAllocated(
IN REFGUID mediaId
)
{
HRESULT hr = S_OK;
DWORD err1 = NO_ERROR;
DWORD err2 = NO_ERROR;
WsbTraceIn(OLESTR("CRmsNTMS::EnsureAllSidesNotAllocated"), OLESTR(""));
try {
WsbAssert(mediaId != GUID_NULL, E_INVALIDARG);
NTMS_OBJECTINFORMATION partitionInfo;
memset( &partitionInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
NTMS_OBJECTINFORMATION mediaInfo;
memset( &mediaInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
HANDLE hSession = m_SessionHandle;
NTMS_GUID physicalMediaId = mediaId;
mediaInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
mediaInfo.dwType = NTMS_PHYSICAL_MEDIA;
partitionInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
partitionInfo.dwType = NTMS_PARTITION;
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PHYSICAL_MEDIA)\n"));
err2 = GetNtmsObjectInformation(hSession, &physicalMediaId, &mediaInfo);
WsbAffirmNoError(err2);
// Check whether there are more than one side
if (mediaInfo.Info.PhysicalMedia.dwNumberOfPartitions > 1) {
// Enumerate physical meida - expect 2 sides here.
NTMS_GUID side[2];
DWORD sideNo = 2;
WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
err1 = EnumerateNtmsObject(hSession, &physicalMediaId, side, &sideNo, NTMS_PARTITION, 0);
WsbAffirmNoError(err1);
// Look for a side which is allocated
for (DWORD i=0; i<sideNo; i++) {
WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PARTITION)\n"));
err2 = GetNtmsObjectInformation(hSession, &side[i], &partitionInfo);
WsbAffirmNoError(err2);
if (GUID_NULL != partitionInfo.Info.Partition.LogicalMedia) {
hr = S_FALSE;
break;
}
}
} // of if two sides
} WsbCatchAndDo( hr,
WsbTrace(OLESTR("CRmsNTMS::EnsureAllSidesNotAllocated - of %ls failed: hr = <%ls>\n"),WsbGuidAsString(mediaId),WsbHrAsString(hr));
if (err1 != NO_ERROR ) {
// EnumerateNtmsObject
switch (HRESULT_CODE(hr)) {
case ERROR_OBJECT_NOT_FOUND:
hr = RMS_E_CARTRIDGE_NOT_FOUND;
break;
case ERROR_INVALID_PARAMETER:
case ERROR_INVALID_HANDLE:
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_INSUFFICIENT_BUFFER:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("EnumerateNtmsObject"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("EnumerateNtmsObject"), OLESTR("Unexpected Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
else if (err2 != NO_ERROR) {
// GetNtmsObjectInformation
switch (HRESULT_CODE(hr)) {
case ERROR_OBJECT_NOT_FOUND:
hr = RMS_E_CARTRIDGE_NOT_FOUND;
break;
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_PARAMETER:
case ERROR_NOT_ENOUGH_MEMORY:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectInformation"), OLESTR(""),
WsbHrAsString(hr), NULL);
break;
default:
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("GetNtmsObjectInformation"), OLESTR("Unexpected Error: "),
WsbHrAsString(hr), NULL);
break;
}
}
);
WsbTraceOut(OLESTR("CRmsNTMS::EnsureAllSidesNotAllocated"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
STDMETHODIMP
CRmsNTMS::DismountAll(
IN REFGUID fromMediaSet,
IN DWORD dwOptions)
/*++
Implements:
IRmsNTMS::DismountAll
--*/
{
HRESULT hr = S_OK;
WsbTraceIn( OLESTR("CRmsNTMS::DismountAll"), OLESTR("") );
try {
WsbAssert(GUID_NULL != fromMediaSet, E_INVALIDARG);
HANDLE hFindMedia = NULL;
DWORD err1 = NO_ERROR;
HANDLE hSession = m_SessionHandle;
NTMS_OBJECTINFORMATION physicalMediaInfo;
NTMS_GUID setId = fromMediaSet;
NTMS_GUID partId = GUID_NULL;
// Dismount all mounted medias from the given pool
hr = findFirstNtmsObject(NTMS_PHYSICAL_MEDIA, setId, NULL, GUID_NULL, &hFindMedia, &physicalMediaInfo);
while(S_OK == hr) {
switch (physicalMediaInfo.Info.PhysicalMedia.MediaState) {
case NTMS_MEDIASTATE_LOADED:
case NTMS_MEDIASTATE_MOUNTED:
// Dismount the media
try {
partId = physicalMediaInfo.Info.PhysicalMedia.MountedPartition;
WsbAffirm(GUID_NULL != partId, E_UNEXPECTED);
DWORD dwNtmsOptions = 0;
WsbTraceAlways(OLESTR("DismountNtmsMedia()\n"));
if (! ( dwOptions & RMS_DISMOUNT_IMMEDIATE )) {
dwNtmsOptions |= NTMS_DISMOUNT_DEFERRED;
}
err1 = DismountNtmsMedia(hSession, &partId, 1, dwNtmsOptions);
WsbAffirmNoError(err1);
} WsbCatchAndDo(hr,
if (err1 != NO_ERROR) {
WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
OLESTR("DismountNtmsMedia"), OLESTR(""),
WsbHrAsString(hr), NULL);
}
);
break;
default:
// Media is not mounted - skip it
break;
}
hr = findNextNtmsObject(hFindMedia, &physicalMediaInfo);
}
findCloseNtmsObject(hFindMedia);
hr = S_OK;
} WsbCatch(hr);
WsbTraceOut( OLESTR("CRmsNTMS::DismountAll"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
return hr;
}