3915 lines
123 KiB
C++
3915 lines
123 KiB
C++
/*++
|
||
|
||
© 1998 Seagate Software, Inc. All rights reserved
|
||
|
||
Module Name:
|
||
|
||
RmsServr.cpp
|
||
|
||
Abstract:
|
||
|
||
Implementation of CRmsServer
|
||
|
||
Author:
|
||
|
||
Brian Dodd [brian] 15-Nov-1996
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "stdafx.h"
|
||
//#include <stl.h>
|
||
|
||
//using namespace std ;
|
||
|
||
//#pragma warning (disable : 4786)
|
||
//using namespace std ;
|
||
|
||
#include <devioctl.h>
|
||
#include <ntddscsi.h>
|
||
|
||
#include "RmsServr.h"
|
||
#include "rsbuild.h"
|
||
#include "wsb.h"
|
||
#include "ntverp.h"
|
||
|
||
#define PERSIST_CHECK_VALUE 0x526f6e57
|
||
|
||
#if 0
|
||
#define DebugPrint(a) { \
|
||
CWsbStringPtr out = a; \
|
||
out.Prepend(L": "); \
|
||
out.Prepend(WsbLongAsString(GetCurrentThreadId())); \
|
||
OutputDebugString((WCHAR *) out); \
|
||
}
|
||
#else
|
||
#define DebugPrint(a)
|
||
#endif // DBG
|
||
|
||
|
||
// This is made global so that anybody in the context of the server has
|
||
// quick access to it
|
||
IRmsServer *g_pServer = 0;
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// CComObjectRoot
|
||
|
||
|
||
HRESULT
|
||
CRmsServer::FinalConstruct(void)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This method does some initialization of the object that is necessary
|
||
after construction.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
S_OK
|
||
|
||
Anything returned by CWsbPersistStream::FinalConstruct().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CRmsServer::FinalConstruct"), OLESTR(""));
|
||
|
||
// Zeroing global variable
|
||
g_pServer = 0;
|
||
|
||
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
|
||
|
||
try {
|
||
WsbAssertPointer( pObject );
|
||
|
||
CWsbBstrPtr tmpString;
|
||
|
||
WsbAssertHr( CWsbPersistStream::FinalConstruct() );
|
||
|
||
WsbAffirmHr( ChangeState( RmsServerStateStarting ));
|
||
|
||
// Figure out where to store information and initialize trace.
|
||
|
||
// Setup the collections
|
||
WsbAssertHr(CoCreateInstance( CLSID_CWsbOrderedCollection,
|
||
0,
|
||
CLSCTX_SERVER,
|
||
IID_IWsbIndexedCollection,
|
||
(void **)&m_pCartridges ));
|
||
|
||
WsbAssertHr(CoCreateInstance( CLSID_CWsbOrderedCollection,
|
||
0,
|
||
CLSCTX_SERVER,
|
||
IID_IWsbIndexedCollection,
|
||
(void **)&m_pActiveCartridges ));
|
||
|
||
WsbAssertHr(CoCreateInstance( CLSID_CWsbOrderedCollection,
|
||
0,
|
||
CLSCTX_SERVER,
|
||
IID_IWsbIndexedCollection,
|
||
(void **)&m_pDataMovers ));
|
||
|
||
WsbAssertHr(CoCreateInstance( CLSID_CWsbOrderedCollection,
|
||
0,
|
||
CLSCTX_SERVER,
|
||
IID_IWsbIndexedCollection,
|
||
(void **)&m_pLibraries ));
|
||
|
||
WsbAssertHr(CoCreateInstance( CLSID_CWsbOrderedCollection,
|
||
0,
|
||
CLSCTX_SERVER,
|
||
IID_IWsbIndexedCollection,
|
||
(void **)&m_pMediaSets ));
|
||
|
||
WsbAssertHr(CoCreateInstance( CLSID_CWsbOrderedCollection,
|
||
0,
|
||
CLSCTX_SERVER,
|
||
IID_IWsbIndexedCollection,
|
||
(void **)&m_pRequests ));
|
||
|
||
WsbAssertHr(CoCreateInstance( CLSID_CWsbOrderedCollection,
|
||
0,
|
||
CLSCTX_SERVER,
|
||
IID_IWsbIndexedCollection,
|
||
(void **)&m_pClients ));
|
||
|
||
WsbAssertHr(CoCreateInstance( CLSID_CWsbOrderedCollection,
|
||
0,
|
||
CLSCTX_SERVER,
|
||
IID_IWsbIndexedCollection,
|
||
(void **)&m_pUnconfiguredDevices ));
|
||
|
||
// Create NTMS object
|
||
WsbAssertHr(CoCreateInstance( CLSID_CRmsNTMS,
|
||
0,
|
||
CLSCTX_SERVER,
|
||
IID_IRmsNTMS,
|
||
(void **)&m_pNTMS ));
|
||
|
||
// Get the name of the computer on which we running.
|
||
CWsbStringPtr serverNameString;
|
||
WsbAffirmHr( WsbGetComputerName( serverNameString ));
|
||
m_ServerName = serverNameString;
|
||
|
||
m_HardDrivesUsed = 0;
|
||
|
||
m_LockReference = 0;
|
||
|
||
WsbAffirmHr( ChangeState( RmsServerStateStarted ));
|
||
|
||
} WsbCatchAndDo(hr,
|
||
pObject->Disable( hr );
|
||
);
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::FinalConstruct"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CRmsServer::FinalRelease(void)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This method does some uninitialization of the object that is necessary
|
||
before destrucruction.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
S_OK
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
WsbTraceIn(OLESTR("CRmsServer::FinalRelease"), OLESTR(""));
|
||
|
||
try {
|
||
WsbAffirmHr( ChangeState( RmsServerStateStopping ));
|
||
|
||
CWsbPersistStream::FinalRelease();
|
||
WsbAffirmHr( ChangeState( RmsServerStateStopped ));
|
||
|
||
#ifdef WSB_TRACK_MEMORY
|
||
(void) WsbObjectTracePointers(WSB_OTP_SEQUENCE | WSB_OTP_STATISTICS | WSB_OTP_ALLOCATED);
|
||
(void) WsbObjectTraceTypes();
|
||
#endif
|
||
|
||
} WsbCatch(hr);
|
||
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::FinalRelease"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::InitializeInAnotherThread(void)
|
||
{
|
||
HRESULT hr = S_OK;
|
||
WsbTraceIn(OLESTR("CRmsServer::InitializeInAnotherThread"), OLESTR(""));
|
||
|
||
try {
|
||
|
||
DWORD threadId;
|
||
HANDLE hThread;
|
||
WsbAffirmHandle(hThread = CreateThread(NULL, 1024, CRmsServer::InitializationThread, this, 0, &threadId));
|
||
CloseHandle(hThread);
|
||
|
||
} WsbCatch(hr);
|
||
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::InitializeInAnotherThread"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
|
||
DWORD WINAPI
|
||
CRmsServer::InitializationThread(
|
||
IN LPVOID pv)
|
||
{
|
||
HRESULT hr = S_OK;
|
||
WsbTraceIn(OLESTR("CRmsServer::InitializationThread"), OLESTR(""));
|
||
|
||
|
||
try {
|
||
WsbAssertPointer(pv);
|
||
CRmsServer *pServer = (CRmsServer*)pv;
|
||
WsbAffirmHr(pServer->Initialize());
|
||
} WsbCatch(hr);
|
||
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::InitializationThread"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::Initialize(void)
|
||
{
|
||
HRESULT hr = S_OK;
|
||
WsbTraceIn(OLESTR("CRmsServer::Initialize"), OLESTR(""));
|
||
|
||
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
|
||
|
||
DWORD fixedDriveEnabled = RMS_DEFAULT_FIXED_DRIVE;
|
||
DWORD size;
|
||
OLECHAR tmpString[256];
|
||
if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_FIXED_DRIVE, tmpString, 256, &size))) {
|
||
// Get the value.
|
||
fixedDriveEnabled = 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 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 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);
|
||
}
|
||
|
||
WsbTraceAlways(OLESTR("Fixed Drive Media Enabled: %ls\n"), WsbBoolAsString((BOOL)fixedDriveEnabled));
|
||
WsbTraceAlways(OLESTR("Optical Media Enabled: %ls\n"), WsbBoolAsString((BOOL)opticalEnabled));
|
||
WsbTraceAlways(OLESTR("Tape Media Enabled: %ls\n"), WsbBoolAsString((BOOL)tapeEnabled));
|
||
WsbTraceAlways(OLESTR("DVD Media Enabled: %ls\n"), WsbBoolAsString((BOOL)dvdEnabled));
|
||
|
||
try {
|
||
if (0 == g_pServer) {
|
||
// Set global variable for quick access (if not set yet)
|
||
WsbAffirmHr(((IUnknown*)(IRmsServer *)this)->QueryInterface(IID_IRmsServer, (void**) &g_pServer));
|
||
|
||
// We don't want the reference count bumped for this global so release it here.
|
||
g_pServer->Release();
|
||
}
|
||
|
||
// initializing
|
||
WsbAssertPointer( pObject );
|
||
|
||
CWsbStringPtr tmpString;
|
||
|
||
WsbAffirmHr( ChangeState( RmsServerStateInitializing ));
|
||
|
||
hr = IsNTMSInstalled();
|
||
if ( S_OK == hr ) {
|
||
|
||
try {
|
||
// Perform any initialization required for using NTMS subsystem.
|
||
WsbAffirmHr( m_pNTMS->Initialize() );
|
||
} WsbCatch (hr);
|
||
hr = S_OK;
|
||
|
||
if (fixedDriveEnabled) {
|
||
// Scan for drives.
|
||
WsbAffirmHr( ScanForDrives() );
|
||
}
|
||
|
||
// Resolve the devices detected by the scan.
|
||
WsbAffirmHr( resolveUnconfiguredDevices() );
|
||
|
||
// Auto configure the remaining devices.
|
||
WsbAffirmHr( autoConfigureDevices() );
|
||
|
||
// Try to dismount all of our medias, ignore errors
|
||
HRESULT hrDismountAll = S_OK;
|
||
try {
|
||
CComPtr<IWsbEnum> pEnumSets;
|
||
CComPtr<IRmsMediaSet> pMediaSet;
|
||
CComPtr<IRmsComObject> pObject;
|
||
GUID mediaSetId;
|
||
|
||
WsbAffirmHr(m_pMediaSets->Enum(&pEnumSets));
|
||
WsbAssertPointer(pEnumSets);
|
||
hrDismountAll = pEnumSets->First(IID_IRmsMediaSet, (void **)&pMediaSet);
|
||
while (S_OK == hrDismountAll) {
|
||
WsbAffirmHr(pMediaSet->QueryInterface(IID_IRmsComObject, (void**) &pObject));
|
||
WsbAffirmHr(pObject->GetObjectId(&mediaSetId));
|
||
WsbAffirmHr(m_pNTMS->DismountAll(mediaSetId));
|
||
|
||
hrDismountAll = pEnumSets->Next(IID_IRmsMediaSet, (void **)&pMediaSet);
|
||
}
|
||
if (hrDismountAll == WSB_E_NOTFOUND) {
|
||
hrDismountAll = S_OK;
|
||
} else {
|
||
WsbAffirmHr(hrDismountAll);
|
||
}
|
||
} WsbCatch(hrDismountAll);
|
||
}
|
||
else if ( RMS_E_NOT_CONFIGURED_FOR_NTMS == hr ) {
|
||
hr = S_OK;
|
||
|
||
// Scan for devices.
|
||
WsbAffirmHr( ScanForDevices() );
|
||
|
||
if (fixedDriveEnabled) {
|
||
// Scan for drives.
|
||
WsbAffirmHr( ScanForDrives() );
|
||
}
|
||
|
||
// Resolve the devices detected by the scan.
|
||
WsbAffirmHr( resolveUnconfiguredDevices() );
|
||
|
||
// Auto configure the remaining devices.
|
||
WsbAffirmHr( autoConfigureDevices() );
|
||
|
||
}
|
||
else { // Some other NTMS connection failure (NTMS not installed, configured, or running)
|
||
hr = S_OK;
|
||
|
||
if (fixedDriveEnabled) {
|
||
// Scan for drives.
|
||
WsbAffirmHr( ScanForDrives() );
|
||
|
||
// Resolve the devices detected by the scan.
|
||
WsbAffirmHr( resolveUnconfiguredDevices() );
|
||
|
||
// Auto configure the remaining devices.
|
||
WsbAffirmHr( autoConfigureDevices() );
|
||
}
|
||
|
||
}
|
||
|
||
// Enable RMS process for backup operations.
|
||
WsbAffirmHr( enableAsBackupOperator() );
|
||
|
||
// Save the configuration information.
|
||
WsbAffirmHr( SaveAll() );
|
||
|
||
WsbAffirmHr( ChangeState( RmsServerStateReady ));
|
||
|
||
WsbTraceAlways(OLESTR("RMS is ready.\n"));
|
||
|
||
} WsbCatchAndDo(hr,
|
||
pObject->Disable( hr );
|
||
);
|
||
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::Initialize"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::IsNTMSInstalled(void)
|
||
{
|
||
|
||
return m_pNTMS->IsInstalled();
|
||
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::GetNTMS(
|
||
OUT IRmsNTMS **ptr)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::GetNTMS
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = E_FAIL;
|
||
|
||
try {
|
||
WsbAssertPointer( ptr );
|
||
|
||
*ptr = m_pNTMS;
|
||
m_pNTMS->AddRef();
|
||
|
||
hr = S_OK;
|
||
|
||
} WsbCatch( hr );
|
||
|
||
return hr;
|
||
}
|
||
|
||
//
|
||
// Rms no longer save independently its own .col file, but only the NTMS database
|
||
//
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::SaveAll(void)
|
||
{
|
||
HRESULT hr = S_OK;
|
||
WsbTraceIn(OLESTR("CRmsServer::SaveAll"), OLESTR(""));
|
||
|
||
static BOOL saving = FALSE;
|
||
|
||
try {
|
||
WsbAffirm(!saving, S_FALSE);
|
||
saving = TRUE;
|
||
|
||
hr = m_pNTMS->ExportDatabase();
|
||
|
||
saving = FALSE;
|
||
|
||
} WsbCatch(hr);
|
||
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::SaveAll"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::Unload(void)
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CRmsServer::Unload"), OLESTR(""));
|
||
|
||
try {
|
||
|
||
// We only need to release what may have gotten set/created by
|
||
// a failed Load attempt.
|
||
if (m_pCartridges) {
|
||
WsbAffirmHr(m_pCartridges->RemoveAllAndRelease());
|
||
}
|
||
if (m_pLibraries) {
|
||
WsbAffirmHr(m_pLibraries->RemoveAllAndRelease());
|
||
}
|
||
if (m_pMediaSets) {
|
||
WsbAffirmHr(m_pMediaSets->RemoveAllAndRelease());
|
||
}
|
||
if (m_pRequests) {
|
||
WsbAffirmHr(m_pRequests->RemoveAllAndRelease());
|
||
}
|
||
if (m_pClients) {
|
||
WsbAffirmHr(m_pClients->RemoveAllAndRelease());
|
||
}
|
||
|
||
} WsbCatch(hr);
|
||
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::Unload"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::GetClassID(
|
||
OUT CLSID* pClsid)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IPersist::GetClassId
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CRmsServer::GetClassID"), OLESTR(""));
|
||
|
||
try {
|
||
|
||
WsbAssert(0 != pClsid, E_POINTER);
|
||
|
||
*pClsid = CLSID_CRmsServer;
|
||
|
||
} WsbCatch(hr);
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::GetSizeMax(
|
||
OUT ULARGE_INTEGER* /*pcbSize*/)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IPersistStream::GetSizeMax
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = E_NOTIMPL;
|
||
|
||
// ULONG serverNameLen;
|
||
|
||
// ULARGE_INTEGER cartridgesLen;
|
||
// ULARGE_INTEGER librariesLen;
|
||
// ULARGE_INTEGER mediaSetsLen;
|
||
// ULARGE_INTEGER requestsLen;
|
||
// ULARGE_INTEGER clientsLen;
|
||
// ULARGE_INTEGER unconfiguredDevicesLen;
|
||
|
||
|
||
// WsbTraceIn(OLESTR("CRmsServer::GetSizeMax"), OLESTR(""));
|
||
|
||
// try {
|
||
// WsbAssert(0 != pcbSize, E_POINTER);
|
||
|
||
// m_pCartridges-> GetSizeMax (&cartridgesLen);
|
||
|
||
// set up size of CRmsServer
|
||
// pcbSize->QuadPart = WsbPersistSizeOf(ULONG) + // length of serverName
|
||
// cartridgesLen.QuadPart; // m_pCartridges
|
||
|
||
// } WsbCatch(hr);
|
||
|
||
// WsbTraceOut(OLESTR("CRmsServer::GetSizeMax"), OLESTR("hr = <%ls>, Size = <%ls>"), WsbHrAsString(hr), WsbPtrToUliAsString(pcbSize));
|
||
|
||
return hr;
|
||
}
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::Load(
|
||
IN IStream* pStream)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IPersistStream::Load
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CRmsServer::Load"), OLESTR(""));
|
||
|
||
//
|
||
// Check if the global pointer is already set - if not, update it
|
||
// (Today, Load is the only method that is executed before Initialize)
|
||
//
|
||
if (0 == g_pServer) {
|
||
// Set global variable for quick access (if not set yet)
|
||
WsbAffirmHr(((IUnknown*)(IRmsServer *)this)->QueryInterface(IID_IRmsServer, (void**) &g_pServer));
|
||
|
||
// We don't want the reference count bumped for this global so release it here.
|
||
g_pServer->Release();
|
||
}
|
||
|
||
//
|
||
// Lock down the server while we are loading.
|
||
//
|
||
InterlockedIncrement( &m_LockReference );
|
||
|
||
//
|
||
// The Load reverts the state, which is undesired for the server object.
|
||
// Save away the original status information
|
||
//
|
||
BOOL bTemp = m_IsEnabled;
|
||
LONG lTemp = m_State;
|
||
HRESULT hrTemp = m_StatusCode;
|
||
|
||
try {
|
||
WsbAssertPointer(pStream);
|
||
|
||
CComPtr<IPersistStream> pPersistStream;
|
||
|
||
WsbAffirmHr(CRmsComObject::Load(pStream));
|
||
|
||
// Load the collections
|
||
WsbAffirmHr(m_pMediaSets->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
|
||
WsbAffirmHr(pPersistStream->Load(pStream));
|
||
pPersistStream = 0;
|
||
|
||
WsbAffirmHr(m_pCartridges->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
|
||
WsbAffirmHr(pPersistStream->Load(pStream));
|
||
pPersistStream = 0;
|
||
|
||
WsbAffirmHr(m_pLibraries->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
|
||
WsbAffirmHr(pPersistStream->Load(pStream));
|
||
pPersistStream = 0;
|
||
|
||
WsbAffirmHr(m_pRequests->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
|
||
WsbAffirmHr(pPersistStream->Load(pStream));
|
||
pPersistStream = 0;
|
||
|
||
WsbAffirmHr(m_pClients->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
|
||
WsbAffirmHr(pPersistStream->Load(pStream));
|
||
pPersistStream = 0;
|
||
|
||
// Check that we got everything
|
||
ULONG check_value;
|
||
WsbAffirmHr(WsbLoadFromStream(pStream, &check_value));
|
||
WsbAffirm(check_value == PERSIST_CHECK_VALUE, E_UNEXPECTED);
|
||
|
||
} WsbCatch(hr);
|
||
|
||
|
||
// Reset the object status information to their original settings.
|
||
m_IsEnabled = bTemp;
|
||
m_State = lTemp;
|
||
m_StatusCode = hrTemp;
|
||
|
||
//
|
||
// Unlock the server.
|
||
//
|
||
InterlockedDecrement( &m_LockReference );
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::Save(
|
||
IN IStream* pStream,
|
||
IN BOOL clearDirty)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IPersistStream::Save
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
|
||
WsbTraceIn(OLESTR("CRmsServer::Save"), OLESTR("clearDirty = <%ls>"), WsbBoolAsString(clearDirty));
|
||
|
||
try {
|
||
CComPtr<IPersistStream> pPersistStream;
|
||
|
||
WsbAssertPointer(pStream);
|
||
|
||
WsbAffirmHr(CRmsComObject::Save(pStream, clearDirty));
|
||
|
||
// Save the collections
|
||
WsbAffirmHr(m_pMediaSets->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
|
||
WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
|
||
pPersistStream = 0;
|
||
|
||
WsbAffirmHr(m_pCartridges->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
|
||
WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
|
||
pPersistStream = 0;
|
||
|
||
WsbAffirmHr(m_pLibraries->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
|
||
WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
|
||
pPersistStream = 0;
|
||
|
||
WsbAffirmHr(m_pRequests->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
|
||
WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
|
||
pPersistStream = 0;
|
||
|
||
WsbAffirmHr(m_pClients->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
|
||
WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
|
||
pPersistStream = 0;
|
||
|
||
// Put this at the end as a check during load
|
||
ULONG check_value = PERSIST_CHECK_VALUE;
|
||
WsbAffirmHr(WsbSaveToStream(pStream, check_value));
|
||
|
||
// Do we need to clear the dirty bit?
|
||
if (clearDirty) {
|
||
m_isDirty = FALSE;
|
||
}
|
||
} WsbCatch(hr);
|
||
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// IRmsServer
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::GetServerName(
|
||
OUT BSTR *pName)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::GetServerName
|
||
|
||
--*/
|
||
{
|
||
WsbAssertPointer(pName);
|
||
|
||
m_ServerName.CopyToBstr(pName);
|
||
return S_OK;
|
||
}
|
||
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::GetCartridges(
|
||
OUT IWsbIndexedCollection **ptr)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::GetCartridges
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
try {
|
||
WsbAssertPointer(ptr);
|
||
|
||
*ptr = m_pCartridges;
|
||
m_pCartridges->AddRef();
|
||
|
||
} WsbCatch(hr)
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::GetActiveCartridges(
|
||
OUT IWsbIndexedCollection **ptr)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::GetActiveCartridges
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
try {
|
||
WsbAssertPointer(ptr);
|
||
|
||
*ptr = m_pActiveCartridges;
|
||
m_pActiveCartridges->AddRef();
|
||
|
||
} WsbCatch(hr)
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::GetDataMovers(
|
||
OUT IWsbIndexedCollection **ptr)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::GetDataMovers
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
try {
|
||
WsbAssertPointer(ptr);
|
||
|
||
*ptr = m_pDataMovers;
|
||
m_pDataMovers->AddRef();
|
||
|
||
} WsbCatch(hr)
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::SetActiveCartridge(
|
||
IN IRmsCartridge *ptr)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::SetActiveCartridge
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
try {
|
||
|
||
if (m_pActiveCartridge) {
|
||
m_pActiveCartridge = 0;
|
||
}
|
||
m_pActiveCartridge = ptr;
|
||
|
||
} WsbCatch(hr)
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::GetLibraries(
|
||
OUT IWsbIndexedCollection **ptr)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::GetLibraries
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
try {
|
||
WsbAssertPointer(ptr);
|
||
|
||
*ptr = m_pLibraries;
|
||
m_pLibraries->AddRef();
|
||
|
||
} WsbCatch(hr)
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::GetMediaSets(
|
||
OUT IWsbIndexedCollection **ptr)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::GetMediaSets
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
try {
|
||
WsbAssertPointer(ptr);
|
||
|
||
// We need to reinit NTMS to account for PNP devices.
|
||
(void) m_pNTMS->Initialize();
|
||
|
||
*ptr = m_pMediaSets;
|
||
m_pMediaSets->AddRef();
|
||
|
||
} WsbCatch(hr)
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::GetRequests(
|
||
OUT IWsbIndexedCollection **ptr)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::GetRequests
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
try {
|
||
WsbAssertPointer(ptr);
|
||
|
||
*ptr = m_pRequests;
|
||
m_pRequests->AddRef();
|
||
|
||
} WsbCatch(hr)
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::GetClients(
|
||
OUT IWsbIndexedCollection **ptr)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::GetClients
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
try {
|
||
WsbAssertPointer(ptr);
|
||
|
||
*ptr = m_pClients;
|
||
m_pClients->AddRef();
|
||
|
||
} WsbCatch(hr)
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::GetUnconfiguredDevices(
|
||
OUT IWsbIndexedCollection **ptr)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::GetUnconfiguredDevices
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
try {
|
||
WsbAssertPointer(ptr);
|
||
|
||
*ptr = m_pUnconfiguredDevices;
|
||
m_pUnconfiguredDevices->AddRef();
|
||
|
||
} WsbCatch(hr)
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::ScanForDevices(void)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::ScanForDevices
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CRmsServer::ScanForDevices"), OLESTR(""));
|
||
|
||
HANDLE portHandle = INVALID_HANDLE_VALUE;
|
||
|
||
LONGLONG trace = 0;
|
||
|
||
try {
|
||
|
||
// WsbAssertPointer( g_pTrace );
|
||
|
||
BOOL status;
|
||
DWORD accessMode = GENERIC_READ;
|
||
DWORD shareMode = FILE_SHARE_READ;
|
||
UCHAR portData[2048];
|
||
OLECHAR string[25];
|
||
ULONG returned;
|
||
int portNumber = 0;
|
||
|
||
// BOOL traceTimeStamp;
|
||
// BOOL traceCount;
|
||
// BOOL traceThreadId;
|
||
|
||
// WsbAssertHr( g_pTrace->GetTraceSettings( &trace ));
|
||
// WsbAssertHr( g_pTrace->SetTraceOff( WSB_TRACE_BIT_ALL ));
|
||
// WsbAssertHr( g_pTrace->GetOutputFormat( &traceTimeStamp, &traceCount, &traceThreadId ));
|
||
// WsbAssertHr( g_pTrace->SetOutputFormat( FALSE, FALSE, FALSE ));
|
||
WsbTraceAlways( OLESTR("\n\n----- Begin Device Scan ---------------------------------------------------------------\n\n") );
|
||
|
||
//
|
||
// Go to each SCSI adapter connected to the system and build
|
||
// out the device list.
|
||
//
|
||
|
||
do {
|
||
|
||
swprintf( string, OLESTR("\\\\.\\Scsi%d:"), portNumber );
|
||
|
||
portHandle = CreateFile( string,
|
||
accessMode,
|
||
shareMode,
|
||
NULL,
|
||
OPEN_EXISTING,
|
||
0,
|
||
NULL );
|
||
|
||
if ( portHandle == INVALID_HANDLE_VALUE ) {
|
||
break; // we're done
|
||
}
|
||
|
||
//
|
||
// Get the inquiry data.
|
||
//
|
||
|
||
WsbAffirmStatus( DeviceIoControl( portHandle,
|
||
IOCTL_SCSI_GET_INQUIRY_DATA,
|
||
NULL,
|
||
0,
|
||
portData,
|
||
sizeof(portData),
|
||
&returned,
|
||
FALSE ));
|
||
|
||
status = CloseHandle( portHandle );
|
||
portHandle = INVALID_HANDLE_VALUE;
|
||
WsbAffirmStatus( status );
|
||
|
||
WsbAffirmHrOk( processInquiryData( portNumber, portData ) );
|
||
|
||
portNumber++;
|
||
|
||
} while ( 1 );
|
||
|
||
|
||
WsbTraceAlways( OLESTR("\n\n----- End Device Scan -----------------------------------------------------------------\n\n") );
|
||
// WsbAssertHr( g_pTrace->SetOutputFormat( traceTimeStamp, traceCount, traceThreadId ));
|
||
// WsbAssertHr( g_pTrace->SetTraceOn( trace ));
|
||
|
||
hr = S_OK;
|
||
|
||
}
|
||
WsbCatchAndDo( hr,
|
||
// if (g_pTrace) {
|
||
// WsbAssertHr( g_pTrace->SetTraceOn( trace ));
|
||
WsbTraceAlways( OLESTR("\n\n !!!!! ERROR !!!!! Device Scan Terminated.\n\n") );
|
||
// }
|
||
if ( portHandle != INVALID_HANDLE_VALUE ) {
|
||
CloseHandle( portHandle );
|
||
}
|
||
);
|
||
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::ScanForDevices"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::ScanForDrives(void)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::ScanForDrives
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CRmsServer::ScanForDrives"), OLESTR(""));
|
||
|
||
try {
|
||
|
||
//
|
||
// Build out device objects for various drive types: fixed drives, removables, and CD-ROM.
|
||
// These are all supported by the system, and have drive letters associated with them.
|
||
//
|
||
// Use best effort to dectect drives. If anything fails we just go on to the next one.
|
||
|
||
// Get the unconfigured device list
|
||
CComPtr<IWsbIndexedCollection> pDevices;
|
||
WsbAssertHr( this->GetUnconfiguredDevices( &pDevices ));
|
||
|
||
// Get the drive letters
|
||
const DWORD bufSize = 256; // 26*4 + 1 = 105 is all we really need
|
||
OLECHAR driveLetters[bufSize];
|
||
DWORD len;
|
||
|
||
// See if there are drives for us to support
|
||
if ( getHardDrivesToUseFromRegistry( driveLetters, &len ) != S_OK ) {
|
||
len = GetLogicalDriveStrings( bufSize, driveLetters );
|
||
}
|
||
|
||
UINT type;
|
||
|
||
// For each drive letter see if it is something managed
|
||
// by RMS.
|
||
|
||
m_HardDrivesUsed = 0;
|
||
for ( DWORD i = 0; i < len; i += 4 ) { // drive letters have the form "A:\"
|
||
|
||
try {
|
||
|
||
type = GetDriveType( &driveLetters[i] );
|
||
|
||
switch ( type ) {
|
||
|
||
case DRIVE_REMOVABLE:
|
||
{
|
||
WsbTrace( OLESTR("Removable Drive Detected: %C\n"), driveLetters[i] );
|
||
|
||
CComPtr<IRmsDevice> pDevice;
|
||
WsbAffirmHr( CoCreateInstance( CLSID_CRmsDrive, 0, CLSCTX_SERVER, IID_IRmsDevice, (void **)&pDevice ));
|
||
|
||
CWsbBstrPtr name = &(driveLetters[i]);
|
||
|
||
WsbAffirmHr( pDevice->SetDeviceName( name ));
|
||
WsbAffirmHr( pDevice->SetDeviceType( RmsDeviceRemovableDisk ));
|
||
|
||
//
|
||
// Don't add it if it was already detected in the SCSI device scan
|
||
//
|
||
|
||
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pDevice;
|
||
WsbAssertPointer( pObject );
|
||
WsbAffirmHr( pObject->SetFindBy( RmsFindByDeviceName ));
|
||
|
||
if ( S_OK == pDevices->Contains( pDevice ) ) {
|
||
break;
|
||
}
|
||
|
||
WsbAffirmHr( pDevices->Add( pDevice ));
|
||
pDevice = 0;
|
||
}
|
||
break;
|
||
|
||
case DRIVE_FIXED:
|
||
{
|
||
CWsbBstrPtr name = &(driveLetters[i]);
|
||
WCHAR volumeName[32];
|
||
DWORD volumeSerialNumber;
|
||
DWORD filenameLength;
|
||
DWORD fileSystemFlags;
|
||
WCHAR fileSystemName[32];
|
||
|
||
WsbAffirmStatus(GetVolumeInformation( (WCHAR *)name, volumeName, 32,
|
||
&volumeSerialNumber, &filenameLength, &fileSystemFlags, fileSystemName, 32));
|
||
|
||
WsbTrace( OLESTR("Fixed Drive Detected : %ls <%ls/%d> [len=%d, flags=0x%08x] %ls\n"),
|
||
(WCHAR *)name, volumeName, volumeSerialNumber, filenameLength,
|
||
fileSystemFlags, fileSystemName );
|
||
|
||
//
|
||
// Use any volume with name starting with RStor, Remote Stor, RemoteStor, RS
|
||
//
|
||
if ( (0 == _wcsnicmp(volumeName, L"RS", 2)) ||
|
||
(0 == _wcsnicmp(volumeName, L"Remote Stor", 11)) ||
|
||
(0 == _wcsnicmp(volumeName, L"RemoteStor", 10))) {
|
||
CComPtr<IRmsDevice> pDevice;
|
||
WsbAffirmHr( CoCreateInstance( CLSID_CRmsDrive, 0, CLSCTX_SERVER, IID_IRmsDevice, (void **)&pDevice ));
|
||
|
||
WsbAffirmHr( pDevice->SetDeviceName( name ));
|
||
WsbAffirmHr( pDevice->SetDeviceType( RmsDeviceFixedDisk ));
|
||
WsbAffirmHr( pDevices->Add( pDevice ));
|
||
pDevice = 0;
|
||
m_HardDrivesUsed++;
|
||
WsbTrace( OLESTR(" %ls added to Collection of unconfigured devices.\n"), (WCHAR *)name );
|
||
}
|
||
}
|
||
break;
|
||
|
||
case DRIVE_CDROM:
|
||
{
|
||
WsbTrace( OLESTR("CD-ROM Drive Detected : %C\n"), driveLetters[i] );
|
||
|
||
CComPtr<IRmsDevice> pDevice;
|
||
WsbAffirmHr( CoCreateInstance( CLSID_CRmsDrive, 0, CLSCTX_SERVER, IID_IRmsDevice, (void **)&pDevice ));
|
||
|
||
CWsbBstrPtr name = &(driveLetters[i]);
|
||
|
||
WsbAffirmHr( pDevice->SetDeviceName( name ));
|
||
WsbAffirmHr( pDevice->SetDeviceType( RmsDeviceCDROM ));
|
||
WsbAffirmHr( pDevices->Add( pDevice ));
|
||
pDevice = 0;
|
||
}
|
||
break;
|
||
|
||
case DRIVE_UNKNOWN:
|
||
case DRIVE_REMOTE:
|
||
case DRIVE_RAMDISK:
|
||
default:
|
||
break;
|
||
|
||
} // switch drive types
|
||
|
||
} WsbCatchAndDo(hr,
|
||
hr = S_OK; // Best effort
|
||
);
|
||
|
||
} // for each drive
|
||
|
||
} WsbCatchAndDo( hr,
|
||
WsbTraceAlways( OLESTR("\n\n !!!!! ERROR !!!!! Drive Scan Terminated.\n\n") );
|
||
hr = S_OK; // Best effort
|
||
);
|
||
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::ScanForDrives"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
|
||
HRESULT
|
||
CRmsServer::processInquiryData(
|
||
IN int portNumber,
|
||
IN UCHAR *pDataBuffer)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Builds RMS device objects from adapter port scan data.
|
||
|
||
Arguments:
|
||
|
||
portNumber - The adapter port to be processed.
|
||
|
||
pDataBuffer - The adapter port data.
|
||
|
||
Return Value:
|
||
|
||
S_OK
|
||
|
||
--*/
|
||
|
||
{
|
||
HRESULT hr = E_FAIL;
|
||
|
||
|
||
try {
|
||
|
||
PSCSI_ADAPTER_BUS_INFO adapterInfo;
|
||
PSCSI_INQUIRY_DATA inquiryData;
|
||
OLECHAR deviceString[25];
|
||
|
||
CComPtr<IRmsDevice> pDevice;
|
||
CComPtr<IWsbIndexedCollection> pDevices;
|
||
WsbAffirmHr( this->GetUnconfiguredDevices( &pDevices ));
|
||
|
||
adapterInfo = (PSCSI_ADAPTER_BUS_INFO) pDataBuffer;
|
||
|
||
WsbTraceAlways( OLESTR("Port: %d\n"), portNumber );
|
||
WsbTraceAlways( OLESTR("Bus TID LUN Claimed String Inquiry Header Other\n") );
|
||
WsbTraceAlways( OLESTR("--- --- --- ------- ---------------------------- ----------------------- --------------\n") );
|
||
|
||
for ( UCHAR i = 0; i < adapterInfo->NumberOfBuses; i++) {
|
||
inquiryData = (PSCSI_INQUIRY_DATA) (pDataBuffer +
|
||
adapterInfo->BusData[i].InquiryDataOffset);
|
||
|
||
while (adapterInfo->BusData[i].InquiryDataOffset) {
|
||
WsbTraceAlways( OLESTR(" %d %d %3d %s %.28S "),
|
||
i,
|
||
inquiryData->TargetId,
|
||
inquiryData->Lun,
|
||
(inquiryData->DeviceClaimed) ? "Y" : "N",
|
||
&inquiryData->InquiryData[8] );
|
||
|
||
for ( UCHAR j = 0; j < 8; j++) {
|
||
WsbTraceAlways( OLESTR("%02X "), inquiryData->InquiryData[j] );
|
||
}
|
||
|
||
WsbTraceAlways( OLESTR("%d %3d "), inquiryData->InquiryDataLength, inquiryData->NextInquiryDataOffset );
|
||
|
||
switch ( inquiryData->InquiryData[0] & 0x1f ) {
|
||
|
||
case DIRECT_ACCESS_DEVICE:
|
||
|
||
//
|
||
// Is this a SCSI removable disk? (Fixed drives are dealt with later in the scan)
|
||
//
|
||
|
||
if ( (inquiryData->InquiryData[1] & 0x80) && inquiryData->InquiryData[2] & 0x02) {
|
||
|
||
//
|
||
// The device is a SCSI removable hard drive, So...
|
||
// Create the Drive object and add it to the collection of unconfigured devices.
|
||
//
|
||
|
||
try {
|
||
|
||
if ( inquiryData->DeviceClaimed ) {
|
||
|
||
WsbAffirmHr( CoCreateInstance(CLSID_CRmsDrive, NULL, CLSCTX_SERVER, IID_IRmsDevice, (void**) &pDevice));
|
||
|
||
WsbAffirmHr( pDevice->SetDeviceAddress( (BYTE)portNumber, i, inquiryData->TargetId, inquiryData->Lun ));
|
||
WsbAffirmHr( pDevice->SetDeviceType( RmsDeviceRemovableDisk ));
|
||
WsbAffirmHr( pDevice->SetDeviceInfo( &inquiryData->InquiryData[0], 36 ));
|
||
|
||
|
||
//
|
||
// find drive letter
|
||
//
|
||
|
||
try {
|
||
WsbAffirmHr( findDriveLetter( (UCHAR)portNumber, i, inquiryData->TargetId, inquiryData->Lun, deviceString ))
|
||
WsbTraceAlways( OLESTR("%ls"), deviceString );
|
||
WsbAffirmHr( pDevice->SetDeviceName( deviceString ));
|
||
WsbAffirmHr(pDevices->Add( pDevice ));
|
||
}
|
||
WsbCatch(hr);
|
||
|
||
pDevice = 0;
|
||
|
||
}
|
||
}
|
||
WsbCatch(hr);
|
||
}
|
||
break;
|
||
|
||
case SEQUENTIAL_ACCESS_DEVICE:
|
||
|
||
//
|
||
// Create the Drive object and add it
|
||
// to the collection of unconfigured devices.
|
||
//
|
||
|
||
try {
|
||
|
||
if ( inquiryData->DeviceClaimed ) {
|
||
|
||
WsbAffirmHr( CoCreateInstance(CLSID_CRmsDrive, NULL, CLSCTX_SERVER, IID_IRmsDevice, (void**) &pDevice));
|
||
|
||
WsbAffirmHr( pDevice->SetDeviceAddress( (BYTE)portNumber, i, inquiryData->TargetId, inquiryData->Lun ));
|
||
WsbAffirmHr( pDevice->SetDeviceType( RmsDeviceTape ));
|
||
WsbAffirmHr( pDevice->SetDeviceInfo( &inquiryData->InquiryData[0], 36 ));
|
||
|
||
//
|
||
// Find tape name
|
||
//
|
||
|
||
try {
|
||
WsbAffirmHr( getDeviceName( (UCHAR)portNumber, i, inquiryData->TargetId, inquiryData->Lun, deviceString ));
|
||
WsbTraceAlways( OLESTR("%ls"), deviceString );
|
||
|
||
// Create the name to use when creating a handle
|
||
CWsbBstrPtr name = deviceString;
|
||
name.Prepend( OLESTR("\\\\.\\") );
|
||
WsbAffirmHr( pDevice->SetDeviceName( name ));
|
||
WsbAffirmHr(pDevices->Add( pDevice ));
|
||
}
|
||
WsbCatch(hr);
|
||
|
||
pDevice = 0;
|
||
|
||
}
|
||
}
|
||
WsbCatch(hr);
|
||
break;
|
||
|
||
case WRITE_ONCE_READ_MULTIPLE_DEVICE:
|
||
|
||
//
|
||
// Supported as OPTICAL_DEVICE only
|
||
//
|
||
|
||
break;
|
||
|
||
case READ_ONLY_DIRECT_ACCESS_DEVICE:
|
||
|
||
//
|
||
// we'll deal with CD-ROM later in the scan...
|
||
//
|
||
|
||
break;
|
||
|
||
case OPTICAL_DEVICE:
|
||
|
||
//
|
||
// Create the Drive object and add it
|
||
// to the collection of unconfigured devices.
|
||
//
|
||
|
||
try {
|
||
|
||
if ( inquiryData->DeviceClaimed ) {
|
||
|
||
WsbAffirmHr( CoCreateInstance(CLSID_CRmsDrive, NULL, CLSCTX_SERVER, IID_IRmsDevice, (void**) &pDevice));
|
||
|
||
WsbAffirmHr( pDevice->SetDeviceAddress( (BYTE)portNumber, i, inquiryData->TargetId, inquiryData->Lun ));
|
||
WsbAffirmHr( pDevice->SetDeviceType( RmsDeviceOptical ));
|
||
WsbAffirmHr( pDevice->SetDeviceInfo( &inquiryData->InquiryData[0], 36 ));
|
||
|
||
//
|
||
// Find drive letter
|
||
//
|
||
|
||
try {
|
||
WsbAffirmHr( findDriveLetter( (UCHAR)portNumber, i, inquiryData->TargetId, inquiryData->Lun, deviceString ))
|
||
WsbTraceAlways( OLESTR("%ls"), deviceString );
|
||
WsbAffirmHr( pDevice->SetDeviceName( deviceString ));
|
||
WsbAffirmHr(pDevices->Add( pDevice ));
|
||
}
|
||
WsbCatch(hr);
|
||
|
||
pDevice = 0;
|
||
|
||
}
|
||
}
|
||
WsbCatch(hr);
|
||
break;
|
||
|
||
case MEDIUM_CHANGER:
|
||
|
||
//
|
||
// Create the Medium Changer object and add it
|
||
// to the collection of unconfigured devices.
|
||
//
|
||
|
||
try {
|
||
|
||
if ( inquiryData->DeviceClaimed ) {
|
||
|
||
WsbAffirmHr( CoCreateInstance(CLSID_CRmsMediumChanger, NULL, CLSCTX_SERVER, IID_IRmsDevice, (void**) &pDevice));
|
||
|
||
WsbAffirmHr( pDevice->SetDeviceAddress( (BYTE)portNumber, i, inquiryData->TargetId, inquiryData->Lun ));
|
||
WsbAffirmHr( pDevice->SetDeviceType( RmsDeviceChanger ));
|
||
WsbAffirmHr( pDevice->SetDeviceInfo( &inquiryData->InquiryData[0], 36 ));
|
||
|
||
//
|
||
// Find library name
|
||
//
|
||
|
||
try {
|
||
WsbAffirmHr( getDeviceName( (UCHAR)portNumber, i, inquiryData->TargetId, inquiryData->Lun, deviceString ));
|
||
WsbTraceAlways( OLESTR("%ls"), deviceString );
|
||
|
||
// Create the name to use when creating a handle
|
||
CWsbBstrPtr name = deviceString;
|
||
name.Prepend( OLESTR("\\\\.\\") );
|
||
WsbAffirmHr( pDevice->SetDeviceName( name ));
|
||
WsbAffirmHr(pDevices->Add( pDevice ));
|
||
}
|
||
WsbCatch(hr);
|
||
}
|
||
|
||
pDevice = 0;
|
||
|
||
}
|
||
WsbCatch(hr);
|
||
break;
|
||
|
||
} // switch device type
|
||
|
||
WsbTraceAlways( OLESTR("\n") );
|
||
|
||
if (inquiryData->NextInquiryDataOffset == 0) {
|
||
break;
|
||
}
|
||
|
||
inquiryData = (PSCSI_INQUIRY_DATA) (pDataBuffer +
|
||
inquiryData->NextInquiryDataOffset);
|
||
|
||
} // for each device
|
||
|
||
} // for each bus
|
||
|
||
WsbTraceAlways( OLESTR("\n\n") );
|
||
|
||
hr = S_OK;
|
||
|
||
}
|
||
WsbCatch(hr);
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CRmsServer::findDriveLetter(
|
||
IN UCHAR portNo,
|
||
IN UCHAR pathNo,
|
||
IN UCHAR id,
|
||
IN UCHAR lun,
|
||
OUT OLECHAR *driveString)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Find associated drive letter for defined parameters.
|
||
|
||
Arguments:
|
||
|
||
portNo - input port number.
|
||
pathNo - input path number.
|
||
id - input id.
|
||
lun - input logical unit number.
|
||
driveString - pointer to drive letter string to return.
|
||
|
||
|
||
Return Value:
|
||
|
||
S_OK - Success
|
||
|
||
|
||
--*/
|
||
{
|
||
|
||
HRESULT hr = E_FAIL;
|
||
const DWORD bufSize = 256; // 26*4 + 1 = 105 is all we really need
|
||
OLECHAR driveLetters[bufSize];
|
||
BOOL status;
|
||
DWORD accessMode = 0, // just get some drive properties.
|
||
shareMode = FILE_SHARE_READ;
|
||
HANDLE driveHandle = INVALID_HANDLE_VALUE;
|
||
SCSI_ADDRESS address;
|
||
DWORD returned;
|
||
OLECHAR string[25];
|
||
UINT uiType;
|
||
|
||
try {
|
||
// first find which drives are mapped.
|
||
DWORD len = GetLogicalDriveStrings( bufSize, driveLetters );
|
||
|
||
for ( DWORD i = 0; (i < len) && (hr != S_OK); i += 4 ) { // drive letters have the form "A:\"
|
||
|
||
uiType = GetDriveType( &driveLetters[i] );
|
||
switch ( uiType ) {
|
||
|
||
case DRIVE_REMOVABLE:
|
||
|
||
//
|
||
// get the SCSI address of the device and see if it's a match.
|
||
//
|
||
|
||
swprintf( string, OLESTR("\\\\.\\%C:"), driveLetters[i] );
|
||
|
||
driveHandle = CreateFile( string,
|
||
accessMode,
|
||
shareMode,
|
||
NULL,
|
||
OPEN_EXISTING,
|
||
0,
|
||
NULL);
|
||
|
||
WsbAffirmHandle( driveHandle );
|
||
|
||
//
|
||
// Get the address structure.
|
||
//
|
||
|
||
status = DeviceIoControl( driveHandle,
|
||
IOCTL_SCSI_GET_ADDRESS,
|
||
NULL,
|
||
0,
|
||
&address,
|
||
sizeof(SCSI_ADDRESS),
|
||
&returned,
|
||
FALSE );
|
||
if (!status ) {
|
||
|
||
//
|
||
// asking for the SCSI address is not always a valid request for
|
||
// all types of drives, so getting an error here means we're
|
||
// not talking to a SCSI device... so skip it.
|
||
//
|
||
|
||
break; // out of switch
|
||
}
|
||
|
||
//
|
||
// Let's check the SCSI address and see if we get a match.
|
||
//
|
||
|
||
if ( (address.PortNumber == portNo) &&
|
||
(address.PathId == pathNo) &&
|
||
(address.TargetId == id) &&
|
||
(address.Lun == lun)) {
|
||
|
||
// its a match...
|
||
wcscpy( driveString, &driveLetters[i] );
|
||
hr = S_OK;
|
||
}
|
||
|
||
break; // out of switch
|
||
|
||
} // switch
|
||
|
||
//
|
||
// Cleanup
|
||
//
|
||
|
||
if ( driveHandle != INVALID_HANDLE_VALUE ) {
|
||
status = CloseHandle( driveHandle );
|
||
driveHandle = INVALID_HANDLE_VALUE;
|
||
WsbAffirmStatus( status );
|
||
}
|
||
|
||
} // for each drive letter
|
||
} WsbCatchAndDo( hr,
|
||
if ( driveHandle != INVALID_HANDLE_VALUE ) {
|
||
CloseHandle(driveHandle);
|
||
} );
|
||
|
||
return hr;
|
||
}
|
||
|
||
HRESULT
|
||
CRmsServer::getDeviceName(
|
||
IN UCHAR portNo,
|
||
IN UCHAR pathNo,
|
||
IN UCHAR id,
|
||
IN UCHAR lun,
|
||
OUT OLECHAR *deviceName)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get device name from selected parameters.
|
||
|
||
Arguments:
|
||
|
||
portNo - port number.
|
||
|
||
pathNo - path number.
|
||
|
||
id - id.
|
||
|
||
lun - logical unit number.
|
||
|
||
deviceName - pointer to returned device name.
|
||
|
||
|
||
Return Value:
|
||
|
||
S_OK - Success
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_FALSE;
|
||
OLECHAR string[256];
|
||
DWORD len;
|
||
OLECHAR name[25];
|
||
|
||
// just go to the registry and get the DeviceName
|
||
|
||
swprintf( string,
|
||
OLESTR("HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port %d\\Scsi Bus %d\\Target Id %d\\Logical Unit Id %d"),
|
||
portNo, pathNo, id, lun );
|
||
|
||
|
||
hr = WsbGetRegistryValueString( NULL,
|
||
string,
|
||
OLESTR("DeviceName"),
|
||
name,
|
||
sizeof(name),
|
||
&len );
|
||
|
||
if ( S_OK == hr ) {
|
||
wcscpy( deviceName, name );
|
||
}
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CRmsServer::resolveUnconfiguredDevices(void)
|
||
/*++
|
||
|
||
This method goes through the unconfigured device list, which is created by
|
||
the ScanForDevices() method, and determines if a device has already been configured.
|
||
If a device is already configured, it is removed from the unconfigured device list.
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = E_FAIL;
|
||
WsbTraceIn(OLESTR("CRmsServer::resolveUnconfiguredDevices"), OLESTR(""));
|
||
|
||
BOOL tracingPlatform = 0;
|
||
|
||
try {
|
||
|
||
CComPtr<IWsbIndexedCollection> pDevices;
|
||
CComPtr<IWsbIndexedCollection> pLibs;
|
||
CComPtr<IRmsDevice> pDevice;
|
||
CComPtr<IWsbEnum> pEnumDevices;
|
||
CComPtr<IWsbEnum> pEnumLibs;
|
||
RmsDevice type;
|
||
BOOL deviceIsConfigured = FALSE;
|
||
|
||
// WsbAssertPointer( g_pTrace );
|
||
// WsbAffirmHr( g_pTrace->GetTraceSetting( WSB_TRACE_BIT_PLATFORM, &tracingPlatform ));
|
||
|
||
WsbAssertHr( GetLibraries( &pLibs ) );
|
||
WsbAffirmHr( pLibs->Enum( &pEnumLibs ));
|
||
WsbAssertPointer( pEnumLibs );
|
||
|
||
WsbAssertHr( GetUnconfiguredDevices( &pDevices ));
|
||
WsbAffirmHr( pDevices->Enum( &pEnumDevices ));
|
||
WsbAssertPointer( pEnumDevices );
|
||
|
||
// start off with the first unconfigured device.
|
||
hr = pEnumDevices->First( IID_IRmsDevice, (void **)&pDevice );
|
||
while ( S_OK == hr ) {
|
||
try {
|
||
|
||
CComPtr<IRmsLibrary> pLib;
|
||
|
||
deviceIsConfigured = FALSE;
|
||
|
||
//
|
||
// If a device is already in a library, then it is configured and
|
||
// should be removed from the list of unconfigured devices.
|
||
//
|
||
// To test if a device is in a library we simply go to each library
|
||
// and try to find the device.
|
||
//
|
||
|
||
WsbAffirmHr( pDevice->GetDeviceType( (LONG *) &type ) );
|
||
WsbTrace(OLESTR("CRmsServer::resolveUnconfiguredDevices: external loop: device type = %ld\n"), (LONG)type);
|
||
|
||
CComPtr<IWsbIndexedCollection> pChangers;
|
||
CComPtr<IWsbIndexedCollection> pDrives;
|
||
|
||
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pDevice;
|
||
WsbAssertPointer( pObject );
|
||
|
||
// Set up search method for the changer
|
||
WsbAffirmHr( pObject->SetFindBy( RmsFindByDeviceInfo ));
|
||
|
||
// start off with the first library.
|
||
hr = pEnumLibs->First( IID_IRmsLibrary, (void **)&pLib );
|
||
while ( S_OK == hr ) {
|
||
|
||
try {
|
||
WsbTrace(OLESTR("CRmsServer::resolveUnconfiguredDevices: internal loop: device type = %ld\n"), (LONG)type);
|
||
|
||
switch ( type ) {
|
||
case RmsDeviceChanger:
|
||
{
|
||
CComQIPtr<IRmsMediumChanger, &IID_IRmsMediumChanger> pChanger = pDevice;
|
||
WsbAffirmHr( pLib->GetChangers( &pChangers ) );
|
||
WsbAffirmHrOk( pChangers->Contains( pChanger ));
|
||
deviceIsConfigured = TRUE;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
{
|
||
CComQIPtr<IRmsDrive, &IID_IRmsDrive> pDrive = pDevice;
|
||
WsbAffirmHr( pLib->GetDrives( &pDrives ) );
|
||
WsbAffirmHrOk( pDrives->Contains( pDrive ));
|
||
deviceIsConfigured = TRUE;
|
||
}
|
||
break;
|
||
}
|
||
|
||
}
|
||
WsbCatch(hr);
|
||
|
||
if ( deviceIsConfigured ) {
|
||
WsbAffirmHr( pDevices->RemoveAndRelease( pDevice ));
|
||
break;
|
||
}
|
||
|
||
pLib = 0;
|
||
hr = pEnumLibs->Next( IID_IRmsLibrary, (void **)&pLib );
|
||
}
|
||
|
||
}
|
||
WsbCatch(hr);
|
||
|
||
pDevice = 0;
|
||
if ( deviceIsConfigured )
|
||
hr = pEnumDevices->This( IID_IRmsDevice, (void **)&pDevice );
|
||
else
|
||
hr = pEnumDevices->Next( IID_IRmsDevice, (void **)&pDevice );
|
||
}
|
||
|
||
// if ( !tracingPlatform )
|
||
// WsbAffirmHr( g_pTrace->SetTraceOff( WSB_TRACE_BIT_PLATFORM ) );
|
||
|
||
hr = S_OK;
|
||
|
||
}
|
||
WsbCatch(hr);
|
||
// WsbCatchAndDo( hr,
|
||
// if (g_pTrace) {
|
||
// if ( !tracingPlatform )
|
||
// g_pTrace->SetTraceOff( WSB_TRACE_BIT_PLATFORM );
|
||
// }
|
||
// );
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::resolveUnconfiguredDevices"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CRmsServer::autoConfigureDevices(void)
|
||
/*++
|
||
|
||
This method automatically configures supported devices for RMS.
|
||
|
||
The algorythm simply goes through the list of unconfigured devices and adds them
|
||
to the appropriate library.
|
||
|
||
Eventually, we need to be smart about when to bypass the auto-config step in favor
|
||
of adminstrative overrides, but for now we'll automatically configure everything we
|
||
can.
|
||
|
||
--*/
|
||
{
|
||
|
||
//
|
||
// for each device in the unconfigured list, check if it was previously configured,
|
||
// if it is not add it to a library; otherwise delete it from the list of unconfigured devices.
|
||
//
|
||
HRESULT hr = E_FAIL;
|
||
|
||
WsbTraceIn(OLESTR("CRmsServer::autoConfigureDevices"), OLESTR(""));
|
||
|
||
try {
|
||
|
||
CComPtr<IWsbIndexedCollection> pDevices;
|
||
CComPtr<IWsbIndexedCollection> pLibs;
|
||
CComPtr<IWsbIndexedCollection> pCarts;
|
||
CComPtr<IRmsDevice> pDevice;
|
||
CComPtr<IWsbEnum> pEnumDevices;
|
||
|
||
RmsDevice type;
|
||
BOOL deviceWasConfigured;
|
||
|
||
WsbAssertHr( GetUnconfiguredDevices( &pDevices ));
|
||
WsbAssertHr( GetLibraries( &pLibs ));
|
||
WsbAssertHr( GetCartridges( &pCarts ));
|
||
|
||
WsbAffirmHr( pDevices->Enum( &pEnumDevices ));
|
||
WsbAssertPointer( pEnumDevices );
|
||
|
||
// first find all the changer devices
|
||
hr = pEnumDevices->First( IID_IRmsDevice, (void **)&pDevice );
|
||
while ( S_OK == hr ) {
|
||
try {
|
||
|
||
deviceWasConfigured = FALSE;
|
||
|
||
WsbAffirmHr( pDevice->GetDeviceType( (LONG *) &type ));
|
||
WsbTrace(OLESTR("CRmsServer::autoConfigureDevices: first loop: device type = %ld\n"), (LONG)type);
|
||
|
||
switch ( type ) {
|
||
|
||
case RmsDeviceChanger:
|
||
{
|
||
|
||
CComPtr<IWsbIndexedCollection> pChangers;
|
||
CComPtr<IWsbIndexedCollection> pDrives;
|
||
CComPtr<IWsbIndexedCollection> pMediaSets;
|
||
CComPtr<IRmsLibrary> pLib;
|
||
CComPtr<IRmsMediaSet> pMediaSet;
|
||
|
||
CComQIPtr<IRmsMediumChanger, &IID_IRmsMediumChanger> pChanger = pDevice;
|
||
WsbAssertPointer( pChanger );
|
||
|
||
CComQIPtr<IRmsChangerElement, &IID_IRmsChangerElement> pChangerElmt = pChanger;
|
||
WsbAssertPointer( pChanger );
|
||
|
||
// Create a Library object
|
||
WsbAffirmHr( CoCreateInstance( CLSID_CRmsLibrary, 0, CLSCTX_SERVER,
|
||
IID_IRmsLibrary, (void **)&pLib ));
|
||
|
||
// Fill in library info
|
||
WsbAffirmHr( pLib->SetName( RMS_DEFAULT_OPTICAL_LIBRARY_NAME ));
|
||
WsbAffirmHr( pLib->SetMediaSupported( RmsMedia8mm /*RmsMediaOptical*/ ));
|
||
|
||
// Add the library to the server's collection
|
||
WsbAffirmHr( pLibs->Add( pLib ));
|
||
|
||
// Create a media set
|
||
WsbAffirmHr( CoCreateInstance( CLSID_CRmsMediaSet, 0, CLSCTX_SERVER,
|
||
IID_IRmsMediaSet, (void **)&pMediaSet ));
|
||
|
||
// Fill in media set info
|
||
WsbAffirmHr( pMediaSet->SetName( RMS_DEFAULT_OPTICAL_MEDIASET_NAME ));
|
||
WsbAffirmHr( pMediaSet->SetMediaSupported( RmsMedia8mm /*RmsMediaOptical*/ ));
|
||
WsbAffirmHr( pMediaSet->SetMediaSetType( RmsMediaSetLibrary ) );
|
||
|
||
// Add the media set the libary's collection
|
||
WsbAssertHr( pLib->GetMediaSets( &pMediaSets ));
|
||
WsbAssertPointer( pMediaSets );
|
||
WsbAffirmHr( pMediaSets->Add( pMediaSet ));
|
||
pMediaSets = 0;
|
||
// Add the media set the server's collection
|
||
WsbAssertHr( GetMediaSets( &pMediaSets ) );
|
||
WsbAssertPointer( pMediaSets );
|
||
WsbAffirmHr( pMediaSets->Add( pMediaSet ));
|
||
|
||
// Add the changer device to the library's collection
|
||
WsbAffirmHr( pLib->GetChangers( &pChangers ));
|
||
WsbAssertPointer( pChangers );
|
||
WsbAffirmHr( pChangers->Add( pChanger ));
|
||
|
||
// Set the changer's element information
|
||
GUID libId;
|
||
WsbAffirmHr( pLib->GetLibraryId( &libId ));
|
||
WsbAffirmHr( pChangerElmt->SetLocation( RmsElementChanger, libId, GUID_NULL, 0, 0, 0, 0, FALSE));
|
||
WsbAffirmHr( pChangerElmt->SetMediaSupported( RmsMedia8mm /*RmsMediaOptical*/ ));
|
||
|
||
// Initialize the changer device
|
||
WsbAffirmHr( pChanger->Initialize() );
|
||
|
||
deviceWasConfigured = TRUE;
|
||
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
}
|
||
WsbCatch(hr);
|
||
|
||
pDevice = 0;
|
||
if ( deviceWasConfigured )
|
||
hr = pEnumDevices->This( IID_IRmsDevice, (void **)&pDevice );
|
||
else
|
||
hr = pEnumDevices->Next( IID_IRmsDevice, (void **)&pDevice );
|
||
|
||
}
|
||
|
||
// any remaining devices are stand alone drives.
|
||
hr = pEnumDevices->First( IID_IRmsDevice, (void **)&pDevice );
|
||
while ( S_OK == hr ) {
|
||
try {
|
||
|
||
deviceWasConfigured = FALSE;
|
||
|
||
WsbAffirmHr( hr = pDevice->GetDeviceType( (LONG *) &type ));
|
||
WsbTrace(OLESTR("CRmsServer::autoConfigureDevices: second loop: device type = %ld\n"), (LONG)type);
|
||
|
||
switch ( type ) {
|
||
case RmsDeviceFixedDisk:
|
||
// find the fixed disk library and add this drive.
|
||
{
|
||
|
||
CComPtr<IWsbIndexedCollection> pDrives;
|
||
CComPtr<IWsbIndexedCollection> pMediaSets;
|
||
CComPtr<IRmsLibrary> pFixedLib;
|
||
CComPtr<IRmsMediaSet> pFixedMediaSet;
|
||
CComPtr<IRmsLibrary> pFindLib;
|
||
CComPtr<IRmsCartridge> pCart;
|
||
|
||
GUID libId = GUID_NULL;
|
||
GUID mediaSetId = GUID_NULL;
|
||
ULONG driveNo;
|
||
|
||
CComQIPtr<IRmsChangerElement, &IID_IRmsChangerElement> pDriveElmt = pDevice;
|
||
WsbAssertPointer( pDriveElmt );
|
||
|
||
CComQIPtr<IRmsDrive, &IID_IRmsDrive> pDrive = pDevice;
|
||
WsbAssertPointer( pDrive );
|
||
|
||
WsbAffirmHr( CoCreateInstance( CLSID_CRmsLibrary, 0, CLSCTX_SERVER,
|
||
IID_IRmsLibrary, (void **)&pFindLib ));
|
||
|
||
// Set up the find template
|
||
|
||
WsbAffirmHr( pFindLib->SetMediaSupported( RmsMediaFixed ));
|
||
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pFindLib;
|
||
WsbAffirmHr( pObject->SetFindBy( RmsFindByMediaSupported ));
|
||
|
||
// Find the library
|
||
|
||
hr = pLibs->Find( pFindLib, IID_IRmsLibrary, (void **)&pFixedLib );
|
||
|
||
if ( WSB_E_NOTFOUND == hr ) {
|
||
|
||
// We don't have a fixed drive library yet, so create one...
|
||
|
||
WsbAffirmHr( CoCreateInstance( CLSID_CRmsLibrary, 0, CLSCTX_SERVER,
|
||
IID_IRmsLibrary, (void **)&pFixedLib ));
|
||
WsbAffirmHr( pFixedLib->SetName( RMS_DEFAULT_FIXEDDRIVE_LIBRARY_NAME ));
|
||
WsbAffirmHr( pFixedLib->SetMediaSupported( RmsMediaFixed ));
|
||
|
||
WsbAffirmHr( pLibs->Add( pFixedLib ));
|
||
|
||
CComPtr<IRmsMediaSet> pMediaSet;
|
||
WsbAffirmHr( CoCreateInstance( CLSID_CRmsMediaSet, 0, CLSCTX_SERVER,
|
||
IID_IRmsMediaSet, (void **)&pMediaSet ));
|
||
|
||
|
||
WsbAffirmHr( pMediaSet->SetName( RMS_DEFAULT_FIXEDDRIVE_MEDIASET_NAME ));
|
||
WsbAffirmHr( pMediaSet->SetMediaSupported( RmsMediaFixed ));
|
||
WsbAffirmHr( pMediaSet->SetMediaSetType( RmsMediaSetLibrary ) );
|
||
|
||
// Add the media set the libary's collection
|
||
WsbAssertHr( pFixedLib->GetMediaSets( &pMediaSets ));
|
||
WsbAssertPointer( pMediaSets );
|
||
WsbAffirmHr( pMediaSets->Add( pMediaSet ));
|
||
pMediaSets = 0;
|
||
// Add the media set the server's collection
|
||
WsbAssertHr( GetMediaSets( &pMediaSets ) );
|
||
WsbAssertPointer( pMediaSets );
|
||
WsbAffirmHr( pMediaSets->Add( pMediaSet ));
|
||
DWORD num;
|
||
WsbAffirmHr( pMediaSets->GetEntries( &num ));
|
||
pMediaSets = 0;
|
||
|
||
WsbTrace(OLESTR("CRmsServer::autoConfigureDevices - type %d CRmsMediaSet created.\n"), RmsMediaFixed);
|
||
WsbTrace(OLESTR("CRmsServer::autoConfigureDevices - Number of sets = %d.\n"), num);
|
||
|
||
}
|
||
|
||
// Add the drive to the library
|
||
WsbAssertHr( pFixedLib->GetDrives( &pDrives ));
|
||
WsbAffirmHr( pDrives->Add( pDevice ));
|
||
WsbAffirmHr( pDrives->GetEntries( &driveNo ));
|
||
|
||
// Remove the drive form the unconfigured list
|
||
WsbAffirmHr( pDevices->RemoveAndRelease( pDevice ));
|
||
deviceWasConfigured = TRUE;
|
||
|
||
// Get library information
|
||
WsbAssertHr( pFixedLib->GetMediaSets( &pMediaSets ));
|
||
|
||
WsbAffirmHr( pFixedLib->GetLibraryId( &libId ));
|
||
|
||
WsbAffirmHr( pMediaSets->First( IID_IRmsMediaSet, (void **)&pFixedMediaSet ));
|
||
WsbAffirmHr( pFixedMediaSet->GetMediaSetId( &mediaSetId ));
|
||
|
||
|
||
// Set the location
|
||
WsbAffirmHr( pDriveElmt->SetLocation( RmsElementDrive, libId, mediaSetId,
|
||
driveNo-1, 0, 0, 0, 0 ));
|
||
|
||
// Set the kind of media supported
|
||
WsbAffirmHr( pDriveElmt->SetMediaSupported( RmsMediaFixed ));
|
||
|
||
// Create a cartridge for the media in the drive.
|
||
WsbAffirmHr( CoCreateInstance( CLSID_CRmsCartridge, 0, CLSCTX_SERVER,
|
||
IID_IRmsCartridge, (void **)&pCart ));
|
||
WsbAffirmHr( pCart->SetLocation( RmsElementDrive, libId, mediaSetId,
|
||
driveNo-1, 0, 0, 0, 0 ));
|
||
WsbAffirmHr( pCart->SetHome( RmsElementDrive, libId, mediaSetId,
|
||
driveNo-1, 0, 0, 0, 0 ));
|
||
WsbAffirmHr( pCart->SetStatus( RmsStatusScratch ));
|
||
WsbAffirmHr( pCart->SetType( RmsMediaFixed ));
|
||
|
||
// Add the drive to the Cartridge object.
|
||
WsbAffirmHr( pCart->SetDrive( pDrive ));
|
||
|
||
// Add the cartridge to the cartridge collection
|
||
WsbAffirmHr( pCarts->Add( pCart ));
|
||
|
||
}
|
||
break;
|
||
|
||
case RmsDeviceRemovableDisk:
|
||
// find manual library and add this stand alone drive.
|
||
break;
|
||
|
||
case RmsDeviceTape:
|
||
// find manual tape library and add this stand alone drive.
|
||
{
|
||
|
||
CComPtr<IWsbIndexedCollection> pDrives;
|
||
CComPtr<IWsbIndexedCollection> pMediaSets;
|
||
CComPtr<IRmsLibrary> pTapeLib;
|
||
CComPtr<IRmsMediaSet> pTapeMediaSet;
|
||
CComPtr<IRmsLibrary> pFindLib;
|
||
CComPtr<IRmsCartridge> pCart;
|
||
|
||
GUID libId = GUID_NULL;
|
||
GUID mediaSetId = GUID_NULL;
|
||
ULONG driveNo;
|
||
|
||
CComQIPtr<IRmsChangerElement, &IID_IRmsChangerElement> pDriveElmt = pDevice;
|
||
WsbAssertPointer( pDriveElmt );
|
||
|
||
CComQIPtr<IRmsDrive, &IID_IRmsDrive> pDrive = pDevice;
|
||
WsbAssertPointer( pDrive );
|
||
|
||
WsbAffirmHr( CoCreateInstance( CLSID_CRmsLibrary, 0, CLSCTX_SERVER,
|
||
IID_IRmsLibrary, (void **)&pFindLib ));
|
||
|
||
// Set up the find template
|
||
|
||
WsbAffirmHr( pFindLib->SetMediaSupported( RmsMedia4mm ));
|
||
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pFindLib;
|
||
WsbAffirmHr( pObject->SetFindBy( RmsFindByMediaSupported ));
|
||
|
||
// Find the library
|
||
|
||
hr = pLibs->Find( pFindLib, IID_IRmsLibrary, (void **)&pTapeLib );
|
||
|
||
if ( WSB_E_NOTFOUND == hr ) {
|
||
|
||
// We don't have a manual tape library yet, so create one...
|
||
|
||
WsbAffirmHr( CoCreateInstance( CLSID_CRmsLibrary, 0, CLSCTX_SERVER,
|
||
IID_IRmsLibrary, (void **)&pTapeLib ));
|
||
WsbAffirmHr( pTapeLib->SetName( RMS_DEFAULT_TAPE_LIBRARY_NAME ));
|
||
WsbAffirmHr( pTapeLib->SetMediaSupported( RmsMedia4mm ));
|
||
|
||
WsbAffirmHr( pLibs->Add( pTapeLib ));
|
||
|
||
CComPtr<IRmsMediaSet> pMediaSet;
|
||
WsbAffirmHr( CoCreateInstance( CLSID_CRmsMediaSet, 0, CLSCTX_SERVER,
|
||
IID_IRmsMediaSet, (void **)&pMediaSet ));
|
||
WsbAffirmHr( pMediaSet->SetName( RMS_DEFAULT_TAPE_MEDIASET_NAME ));
|
||
WsbAffirmHr( pMediaSet->SetMediaSupported( RmsMedia4mm ));
|
||
WsbAffirmHr( pMediaSet->SetMediaSetType( RmsMediaSetLibrary ) );
|
||
|
||
// Add the media set the library's collection
|
||
WsbAssertHr( pTapeLib->GetMediaSets( &pMediaSets ));
|
||
WsbAssertPointer( pMediaSets );
|
||
WsbAffirmHr( pMediaSets->Add( pMediaSet ));
|
||
pMediaSets = 0;
|
||
// Add the media set the server's collection
|
||
WsbAssertHr( GetMediaSets( &pMediaSets ) );
|
||
WsbAssertPointer( pMediaSets );
|
||
WsbAffirmHr( pMediaSets->Add( pMediaSet ));
|
||
pMediaSets = 0;
|
||
|
||
WsbTrace(OLESTR("CRmsServer::autoConfigureDevices - type %d CRmsMediaSet created.\n"), RmsMedia4mm);
|
||
|
||
}
|
||
|
||
// Add the drive to the library
|
||
WsbAssertHr( pTapeLib->GetDrives( &pDrives ));
|
||
WsbAffirmHr( pDrives->Add( pDevice ));
|
||
WsbAffirmHr( pDrives->GetEntries( &driveNo ));
|
||
|
||
// Remove the drive form the unconfigured list
|
||
WsbAffirmHr( pDevices->RemoveAndRelease( pDevice ));
|
||
deviceWasConfigured = TRUE;
|
||
|
||
// Get library information
|
||
WsbAssertHr( pTapeLib->GetMediaSets( &pMediaSets ));
|
||
WsbAffirmHr( pTapeLib->GetLibraryId( &libId ));
|
||
|
||
WsbAffirmHr( pMediaSets->First( IID_IRmsMediaSet, (void **)&pTapeMediaSet ));
|
||
WsbAffirmHr( pTapeMediaSet->GetMediaSetId( &mediaSetId ));
|
||
|
||
// Set the location
|
||
WsbAffirmHr( pDriveElmt->SetLocation( RmsElementDrive, libId, mediaSetId,
|
||
driveNo-1, 0, 0, 0, 0 ));
|
||
|
||
// Set the kind of media supported
|
||
WsbAffirmHr( pDriveElmt->SetMediaSupported( RmsMedia4mm ));
|
||
|
||
// Create a cartridge for the media in the drive.
|
||
// TODO: it may be empty.
|
||
WsbAffirmHr( CoCreateInstance( CLSID_CRmsCartridge, 0, CLSCTX_SERVER,
|
||
IID_IRmsCartridge, (void **)&pCart ));
|
||
WsbAffirmHr( pCart->SetLocation( RmsElementDrive, libId, mediaSetId,
|
||
driveNo-1, 0, 0, 0, 0 ));
|
||
WsbAffirmHr( pCart->SetHome( RmsElementDrive, libId, mediaSetId,
|
||
driveNo-1, 0, 0, 0, 0 ));
|
||
WsbAffirmHr( pCart->SetStatus( RmsStatusScratch ));
|
||
WsbAffirmHr( pCart->SetType( RmsMedia4mm ));
|
||
|
||
// Add the drive to the Cartridge object.
|
||
WsbAffirmHr( pCart->SetDrive( pDrive ));
|
||
|
||
// Add the cartridge to the cartridge collection
|
||
WsbAffirmHr( pCarts->Add( pCart ));
|
||
|
||
}
|
||
break;
|
||
|
||
case RmsDeviceCDROM:
|
||
case RmsDeviceWORM:
|
||
case RmsDeviceOptical:
|
||
// find manual library and add this stand alone drive.
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
} WsbCatch(hr);
|
||
|
||
pDevice = 0;
|
||
|
||
if ( deviceWasConfigured )
|
||
hr = pEnumDevices->This( IID_IRmsDevice, (void **)&pDevice );
|
||
else
|
||
hr = pEnumDevices->Next( IID_IRmsDevice, (void **)&pDevice );
|
||
|
||
}
|
||
|
||
hr = S_OK;
|
||
|
||
} WsbCatch(hr);
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::autoConfigureDevices"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
// Maximum number of retries for allocating and mounting a scratch piece of media
|
||
#define MAX_RETRIES 2
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::MountScratchCartridge(
|
||
OUT GUID *pCartId,
|
||
IN REFGUID fromMediaSet,
|
||
IN REFGUID prevSideId,
|
||
IN OUT LONGLONG *pFreeSpace,
|
||
IN LONG blockingFactor,
|
||
IN BSTR displayName,
|
||
IN OUT IRmsDrive **ppDrive,
|
||
OUT IRmsCartridge **ppCartridge,
|
||
OUT IDataMover **ppDataMover,
|
||
IN DWORD dwOptions)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::MountScratchCartridge
|
||
|
||
Notes: The default flag for mounting (in dwOptions) is blocking, i.e. waiting for the Mount
|
||
to finish even if the media is offline, the drive is not ready, etc. Calling with
|
||
flag set to non-blocking indicates performing the Mount only if everything is
|
||
available immediately.
|
||
|
||
--*/
|
||
{
|
||
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CRmsServer::MountScratchCartridge"), OLESTR("<%ls> <%ls> <%ls>"),
|
||
WsbQuickString(WsbGuidAsString(fromMediaSet)),
|
||
WsbQuickString(WsbPtrToLonglongAsString(pFreeSpace)),
|
||
WsbQuickString(WsbPtrToStringAsString((WCHAR **)&displayName)));
|
||
|
||
CWsbBstrPtr cartridgeName = "";
|
||
CWsbBstrPtr cartridgeDesc = "";
|
||
|
||
GUID cartId = GUID_NULL;
|
||
CWsbBstrPtr label;
|
||
|
||
try {
|
||
WsbAssertPointer(pCartId);
|
||
|
||
|
||
WsbAssertPointer(displayName);
|
||
WsbAssert(wcslen((WCHAR *)displayName) > 0, E_INVALIDARG);
|
||
|
||
WsbAffirmHrOk( IsReady() );
|
||
|
||
DWORD retry = 0;
|
||
CComPtr<IRmsDrive> pDrive;
|
||
CComPtr<IRmsCartridge> pCart[MAX_RETRIES];
|
||
CComPtr<IDataMover> pMover;
|
||
|
||
// Decrease max-retries to 1 if short-timeout or non-blocking is specified
|
||
// or if we want to allocate a specific side
|
||
DWORD maxRetries = MAX_RETRIES;
|
||
BOOL bShortTimeout = ( (dwOptions & RMS_SHORT_TIMEOUT) || (dwOptions & RMS_ALLOCATE_NO_BLOCK) ) ? TRUE : FALSE;
|
||
if (bShortTimeout || (GUID_NULL != prevSideId)) {
|
||
maxRetries = 1;
|
||
}
|
||
WsbTrace(OLESTR("Try to allocate and mount a scratch media %lu times\n"), maxRetries);
|
||
|
||
// Get the media set
|
||
CComPtr<IRmsMediaSet> pMediaSet;
|
||
WsbAffirmHr(CreateObject(fromMediaSet, CLSID_CRmsMediaSet, IID_IRmsMediaSet, RmsOpenExisting, (void **) &pMediaSet));
|
||
|
||
try {
|
||
// Allocate from the specified media set
|
||
WsbAffirmHr(pMediaSet->Allocate(prevSideId, pFreeSpace, displayName, dwOptions, &pCart[retry]));
|
||
|
||
// We want to try the scratch mount twice, but do not deallocate the first until we
|
||
// grab the second cartridge so we'll get a different cartridge. If both fail, drop out.
|
||
do {
|
||
//Clear these,in case we're retrying.
|
||
pDrive = NULL;
|
||
pMover = NULL;
|
||
|
||
try {
|
||
|
||
cartId = GUID_NULL;
|
||
cartridgeName = "";
|
||
cartridgeDesc = "";
|
||
|
||
|
||
WsbAffirmHr(pCart[retry]->GetCartridgeId(&cartId)); // for the log message
|
||
|
||
cartridgeName.Free();
|
||
WsbAffirmHr(pCart[retry]->GetName(&cartridgeName)); // for the log message
|
||
|
||
cartridgeDesc.Free();
|
||
WsbAffirmHr(pCart[retry]->GetDescription(&cartridgeDesc)); // for the log message
|
||
|
||
// Mount the cartridge.
|
||
WsbAffirmHr(pCart[retry]->Mount(&pDrive, dwOptions));
|
||
|
||
try {
|
||
|
||
// Set blockingFactor before we create the DataMover (only for a non-fixed block size media)
|
||
if (blockingFactor > 0) {
|
||
HRESULT hrBlock = pCart[retry]->IsFixedBlockSize();
|
||
WsbAffirmHr(hrBlock);
|
||
if (hrBlock == S_FALSE) {
|
||
WsbTrace(OLESTR("MountScratchCartridge: Setting block size on scratch media to %ld\n"), blockingFactor);
|
||
WsbAffirmHr(pCart[retry]->SetBlockSize(blockingFactor));
|
||
}
|
||
}
|
||
|
||
// Create a data mover for the application.
|
||
WsbAffirmHr(pCart[retry]->CreateDataMover(&pMover));
|
||
|
||
// Write out the On Media Label.
|
||
label.Free();
|
||
WsbAffirmHr(pMover->FormatLabel(displayName, &label));
|
||
WsbAffirmHr(pMover->WriteLabel(label));
|
||
|
||
// Mark the media private before returning.
|
||
WsbAffirmHr(pCart[retry]->SetStatus(RmsStatusPrivate));
|
||
|
||
// Since we don't have a DB, we need to persist the current state here.
|
||
WsbAffirmHr(SaveAll());
|
||
|
||
//
|
||
// Fill in the return arguments.
|
||
//
|
||
|
||
WsbAssertHr(pCart[retry]->GetCartridgeId(pCartId));
|
||
|
||
*ppDrive = pDrive;
|
||
pDrive->AddRef();
|
||
*ppCartridge = pCart[retry];
|
||
pCart[retry]->AddRef();
|
||
*ppDataMover = pMover;
|
||
pMover->AddRef();
|
||
|
||
|
||
// We're done, so break out.
|
||
break;
|
||
|
||
|
||
} WsbCatchAndDo(hr,
|
||
|
||
// Best effort dismount...
|
||
DWORD dwDismountOptions = RMS_DISMOUNT_IMMEDIATE;
|
||
pCart[retry]->Dismount(dwDismountOptions);
|
||
WsbThrow(hr);
|
||
|
||
)
|
||
|
||
|
||
|
||
} WsbCatchAndDo(hr,
|
||
|
||
retry++;
|
||
|
||
// Check the exact error code:
|
||
// Alllow another retry only if the error may be media-related
|
||
BOOL bContinue = TRUE;
|
||
switch (hr) {
|
||
case RMS_E_SCRATCH_NOT_FOUND:
|
||
case RMS_E_CANCELLED:
|
||
case RMS_E_REQUEST_REFUSED:
|
||
case RMS_E_CARTRIDGE_UNAVAILABLE: // timeout during Mount
|
||
case HRESULT_FROM_WIN32(ERROR_DEVICE_NOT_AVAILABLE):
|
||
case HRESULT_FROM_WIN32(ERROR_INVALID_DRIVE):
|
||
case HRESULT_FROM_WIN32(ERROR_RESOURCE_DISABLED): // disabled drives
|
||
case HRESULT_FROM_WIN32(ERROR_DATABASE_FULL):
|
||
// Prevent another retry
|
||
bContinue = FALSE;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (bContinue && (retry < maxRetries)) {
|
||
WsbLogEvent(RMS_MESSAGE_SCRATCH_MOUNT_RETRY, sizeof(GUID), (void *) &cartId, (WCHAR *) displayName,
|
||
WsbHrAsString(hr), NULL);
|
||
|
||
// Allocate from the specified media set
|
||
hr = pMediaSet->Allocate(prevSideId, pFreeSpace, displayName, dwOptions, &pCart[retry]);
|
||
|
||
// Deallocate the previous retry media set
|
||
pMediaSet->Deallocate(pCart[(retry-1)]);
|
||
|
||
// Make sure the allocate worked, if not, throw.
|
||
WsbAffirmHr(hr);
|
||
|
||
}
|
||
else {
|
||
// If were on the last retry, deallocate the last media set and E_ABORT
|
||
pMediaSet->Deallocate(pCart[(retry-1)]);
|
||
|
||
WsbThrow(hr);
|
||
|
||
}
|
||
)
|
||
|
||
|
||
} while (retry < maxRetries);
|
||
|
||
} WsbCatch(hr)
|
||
|
||
} WsbCatch(hr)
|
||
|
||
if ( SUCCEEDED(hr) ) {
|
||
WsbLogEvent(RMS_MESSAGE_CARTRIDGE_MOUNTED, sizeof(GUID), (void *) &cartId, (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, NULL);
|
||
}
|
||
else {
|
||
BOOL bShortTimeout = ( (dwOptions & RMS_SHORT_TIMEOUT) || (dwOptions & RMS_ALLOCATE_NO_BLOCK) ) ? TRUE : FALSE;
|
||
// In case of short-timeout or non-blocking mode, log message with low severity
|
||
if (bShortTimeout) {
|
||
WsbLogEvent(RMS_MESSAGE_EXPECTED_SCRATCH_MOUNT_FAILED, sizeof(GUID), (void *) &cartId, (WCHAR *) displayName, WsbHrAsString(hr), NULL);
|
||
} else {
|
||
WsbLogEvent(RMS_MESSAGE_SCRATCH_MOUNT_FAILED, sizeof(GUID), (void *) &cartId, (WCHAR *) displayName, WsbHrAsString(hr), NULL);
|
||
}
|
||
}
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::MountScratchCartridge"), OLESTR("hr = <%ls>, name/desc = <%ls/%ls>, cartId = %ls"), WsbHrAsString(hr), (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, WsbQuickString(WsbGuidAsString(cartId)));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::MountCartridge(
|
||
IN REFGUID cartId,
|
||
IN OUT IRmsDrive **ppDrive,
|
||
OUT IRmsCartridge **ppCartridge,
|
||
OUT IDataMover **ppDataMover,
|
||
IN DWORD dwOptions OPTIONAL,
|
||
IN DWORD threadId OPTIONAL)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::MountCartridge
|
||
|
||
Notes: The default flag for mounting (in dwOptions) is blocking, i.e. waiting for the Mount
|
||
to finish even if the media is offline, the drive is not ready, etc. Calling with
|
||
flag set to non-blocking indicates performing the Mount only if everything is
|
||
available immediately.
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
WsbTraceIn(OLESTR("CRmsServer::MountCartridge"), OLESTR("<%ls>"), WsbGuidAsString(cartId));
|
||
|
||
CWsbBstrPtr cartridgeName = "";
|
||
CWsbBstrPtr cartridgeDesc = "";
|
||
|
||
try {
|
||
WsbAffirmHrOk( IsReady() );
|
||
|
||
CComPtr<IRmsDrive> pDrive;
|
||
CComPtr<IRmsCartridge> pCart;
|
||
CComPtr<IDataMover> pMover;
|
||
|
||
WsbAffirmHr(FindCartridgeById(cartId, &pCart));
|
||
|
||
cartridgeName.Free();
|
||
WsbAffirmHr(pCart->GetName(&cartridgeName)); // for the log message
|
||
|
||
cartridgeDesc.Free();
|
||
WsbAffirmHr(pCart->GetDescription(&cartridgeDesc)); // for the log message
|
||
|
||
WsbAffirmHr(pCart->Mount(&pDrive, dwOptions, threadId));
|
||
|
||
try {
|
||
WsbAffirmHr(pCart->CreateDataMover(&pMover));
|
||
|
||
//
|
||
// Fill in the return arguments.
|
||
//
|
||
|
||
*ppDrive = pDrive;
|
||
pDrive->AddRef();
|
||
*ppCartridge = pCart;
|
||
pCart->AddRef();
|
||
*ppDataMover = pMover;
|
||
pMover->AddRef();
|
||
|
||
} WsbCatchAndDo(hr,
|
||
// Best effort dismount...
|
||
DWORD dwDismountOptions = RMS_DISMOUNT_IMMEDIATE;
|
||
pCart->Dismount(dwDismountOptions);
|
||
WsbThrow(hr);
|
||
)
|
||
|
||
|
||
} WsbCatch(hr)
|
||
|
||
if ( SUCCEEDED(hr) ) {
|
||
WsbLogEvent(RMS_MESSAGE_CARTRIDGE_MOUNTED, sizeof(GUID), (void *) &cartId, (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, NULL);
|
||
}
|
||
else {
|
||
BOOL bShortTimeout = ( dwOptions & RMS_SHORT_TIMEOUT ) ? TRUE : FALSE;
|
||
// In case of short timeout, log message with low severity
|
||
if (bShortTimeout) {
|
||
WsbLogEvent(RMS_MESSAGE_EXPECTED_MOUNT_FAILED, sizeof(GUID), (void *) &cartId, (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, WsbHrAsString(hr), NULL);
|
||
} else {
|
||
WsbLogEvent(RMS_MESSAGE_MOUNT_FAILED, sizeof(GUID), (void *) &cartId, (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, WsbHrAsString(hr), NULL);
|
||
}
|
||
}
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::MountCartridge"), OLESTR("hr = <%ls>, name/desc = <%ls/%ls>, cartId = %ls"), WsbHrAsString(hr), (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, WsbQuickString(WsbGuidAsString(cartId)));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::DismountCartridge(
|
||
IN REFGUID cartId, IN DWORD dwOptions)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::DismountCartridge
|
||
|
||
Notes: The default flag for dismounting (in dwOptions) is not set for immediate dismount,
|
||
i.e. delaying the Dismount for a configurable amount of time. Setting the flag
|
||
for immediate dismount indicates performing Dismount immediately with no delay.
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CRmsServer::DismountCartridge"), OLESTR("<%ls>"), WsbGuidAsString(cartId));
|
||
|
||
CWsbBstrPtr cartridgeName = "";
|
||
CWsbBstrPtr cartridgeDesc = "";
|
||
|
||
try {
|
||
|
||
//
|
||
// Allow dismount when ready or in transition...
|
||
// to handle in-progress duplicate operations.
|
||
//
|
||
HRESULT hrReady = IsReady();
|
||
WsbAffirm((S_OK == hrReady) ||
|
||
(RMS_E_NOT_READY_SERVER_SUSPENDING == hrReady), hrReady);
|
||
|
||
CComPtr<IRmsCartridge> pCart;
|
||
|
||
WsbAffirmHr(FindCartridgeById(cartId, &pCart));
|
||
|
||
cartridgeName.Free();
|
||
WsbAffirmHr(pCart->GetName(&cartridgeName)); // for the log message
|
||
|
||
cartridgeDesc.Free();
|
||
WsbAffirmHr(pCart->GetDescription(&cartridgeDesc)); // for the log message
|
||
|
||
WsbAffirmHr(pCart->Dismount(dwOptions));
|
||
|
||
} WsbCatch(hr)
|
||
|
||
if ( SUCCEEDED(hr) ) {
|
||
WsbLogEvent(RMS_MESSAGE_CARTRIDGE_DISMOUNTED, sizeof(GUID), (void *) &cartId, (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, NULL);
|
||
}
|
||
else {
|
||
WsbLogEvent(RMS_MESSAGE_DISMOUNT_FAILED, sizeof(GUID), (void *) &cartId, (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, WsbHrAsString(hr), NULL);
|
||
}
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::DismountCartridge"), OLESTR("hr = <%ls>, name/desc = <%ls/%ls>, cartId = %ls"), WsbHrAsString(hr), (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, WsbQuickString(WsbGuidAsString(cartId)));
|
||
|
||
return hr;
|
||
|
||
}
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::DuplicateCartridge(
|
||
IN REFGUID originalCartId,
|
||
IN REFGUID firstSideId,
|
||
IN OUT GUID *pCopyCartId,
|
||
IN REFGUID copySetId,
|
||
IN BSTR copyName,
|
||
OUT LONGLONG *pFreeSpace,
|
||
OUT LONGLONG *pCapacity,
|
||
IN DWORD options)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::DuplicateCartridge
|
||
|
||
--*/
|
||
{
|
||
|
||
HRESULT hr = S_OK;
|
||
WsbTraceIn(OLESTR("CRmsServer::DuplicateCartridge"), OLESTR("<%ls> <%ls> <%ls> <%ls> <%d>"),
|
||
WsbQuickString(WsbGuidAsString(originalCartId)),
|
||
WsbQuickString(WsbPtrToGuidAsString(pCopyCartId)),
|
||
WsbQuickString(WsbGuidAsString(copySetId)),
|
||
WsbQuickString(WsbPtrToStringAsString((WCHAR **)©Name)),
|
||
options);
|
||
|
||
CComPtr<IDataMover> pMover1;
|
||
CComPtr<IDataMover> pMover2;
|
||
|
||
GUID newCartId = GUID_NULL;
|
||
|
||
LONGLONG freeSpace = 0;
|
||
LONGLONG capacity = 0;
|
||
|
||
try {
|
||
WsbAffirmHrOk( IsReady() );
|
||
|
||
WsbAssertPointer( pCopyCartId );
|
||
|
||
// Mount the Copy first and then the original
|
||
CComPtr<IRmsDrive> pDrive1;
|
||
CComPtr<IRmsCartridge> pCart1;
|
||
CComPtr<IRmsDrive> pDrive2;
|
||
CComPtr<IRmsCartridge> pCart2;
|
||
|
||
|
||
LONG blockSize1=0, blockSize2=0;
|
||
|
||
// Serialize mounts for media copies
|
||
DWORD dwMountOptions = RMS_SERIALIZE_MOUNT;
|
||
|
||
// mount copy
|
||
if ( *pCopyCartId != GUID_NULL ) {
|
||
WsbAffirmHr(MountCartridge(*pCopyCartId, &pDrive2, &pCart2, &pMover2, dwMountOptions));
|
||
}
|
||
else {
|
||
GUID mediaSetId = copySetId;
|
||
CComPtr<IRmsCartridge> pCart;
|
||
|
||
WsbAffirmHr(FindCartridgeById(originalCartId, &pCart));
|
||
WsbAffirmHr(pCart->GetBlockSize(&blockSize1));
|
||
if ( mediaSetId == GUID_NULL ) {
|
||
WsbAffirmHr(pCart->GetMediaSetId(&mediaSetId));
|
||
}
|
||
|
||
// Get capacity of original media and adjust by fudge factor
|
||
LONGLONG capacity=0;
|
||
CComQIPtr<IRmsStorageInfo, &IID_IRmsStorageInfo> pInfo = pCart;
|
||
WsbAffirmHr(pInfo->GetCapacity(&capacity));
|
||
|
||
LONG fudge = RMS_DEFAULT_MEDIA_COPY_TOLERANCE;
|
||
DWORD size;
|
||
OLECHAR tmpString[256];
|
||
|
||
if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_MEDIA_COPY_TOLERANCE, tmpString, 256, &size))) {
|
||
// Get the value.
|
||
fudge = wcstol(tmpString, NULL, 10);
|
||
}
|
||
capacity -= (capacity * fudge) / 100;
|
||
|
||
WsbAffirmHr(MountScratchCartridge( &newCartId, mediaSetId, firstSideId, &capacity, blockSize1, copyName, &pDrive2, &pCart2, &pMover2, dwMountOptions ));
|
||
}
|
||
|
||
// Mount original (in a non-blocking manner)
|
||
dwMountOptions |= RMS_MOUNT_NO_BLOCK;
|
||
WsbAffirmHr(MountCartridge(originalCartId, &pDrive1, &pCart1, &pMover1, dwMountOptions));
|
||
|
||
// Verify matching block size (only for a non-fixed block size media)
|
||
HRESULT hrBlock = pCart1->IsFixedBlockSize();
|
||
WsbAffirmHr(hrBlock);
|
||
if (hrBlock == S_FALSE) {
|
||
if (blockSize1 == 0) {
|
||
// didn't get it yet...
|
||
WsbAffirmHr(pCart1->GetBlockSize(&blockSize1));
|
||
}
|
||
|
||
WsbAffirmHr(pCart2->GetBlockSize(&blockSize2));
|
||
WsbAssert(blockSize1 == blockSize2, E_UNEXPECTED);
|
||
}
|
||
|
||
WsbAffirmHr(pMover1->Duplicate(pMover2, options, NULL, NULL));
|
||
|
||
// Now get stats to return to caller.
|
||
WsbAffirmHr(pMover2->GetLargestFreeSpace(&freeSpace, &capacity));
|
||
|
||
if (pFreeSpace) {
|
||
*pFreeSpace = freeSpace;
|
||
}
|
||
|
||
if (pCapacity) {
|
||
*pCapacity = capacity;
|
||
}
|
||
|
||
} WsbCatch(hr)
|
||
|
||
if ( pMover1 ) {
|
||
DismountCartridge(originalCartId);
|
||
}
|
||
if ( pMover2 ) {
|
||
// We always perform immediate dismount to the copy media
|
||
// (We may need to recycle a new copy in case of an error + there's no benefit in a deferred
|
||
// dismount for the copy-media - we don't expect the copy-media to be needed again soon)
|
||
DWORD dwDismountOptions = RMS_DISMOUNT_IMMEDIATE;
|
||
|
||
if (newCartId == GUID_NULL) {
|
||
// this is the case of an existing copy
|
||
DismountCartridge(*pCopyCartId, dwDismountOptions);
|
||
} else {
|
||
// this is the case of a scratch copy
|
||
DismountCartridge(newCartId, dwDismountOptions);
|
||
|
||
// if mounting of original failed, we always recycle the scratch copy
|
||
if (((options & RMS_DUPLICATE_RECYCLEONERROR) || (pMover1 == NULL)) && (S_OK != hr)) {
|
||
//
|
||
// If we failed and a scratch mount was performed
|
||
// we need to recycle the cartridge since the calling
|
||
// app can't be depended upon to do this.
|
||
//
|
||
RecycleCartridge(newCartId, 0);
|
||
} else {
|
||
*pCopyCartId = newCartId;
|
||
}
|
||
}
|
||
}
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::DuplicateCartridge"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::RecycleCartridge(
|
||
IN REFGUID cartId,
|
||
IN DWORD options)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::RecycleCartridge
|
||
|
||
--*/
|
||
{
|
||
|
||
HRESULT hr = S_OK;
|
||
WsbTraceIn(OLESTR("CRmsServer::RecycleCartridge"), OLESTR("<%ls> <%d>"), WsbGuidAsString(cartId), options);
|
||
|
||
CWsbBstrPtr cartridgeName = "";
|
||
CWsbBstrPtr cartridgeDesc = "";
|
||
|
||
try {
|
||
//
|
||
// Allow recycle when ready or in transition...
|
||
// to handle in-progress duplicate operations.
|
||
//
|
||
HRESULT hrReady = IsReady();
|
||
WsbAffirm((S_OK == hrReady) ||
|
||
(RMS_E_NOT_READY_SERVER_SUSPENDING == hrReady), hrReady);
|
||
|
||
CComPtr<IRmsCartridge> pCart;
|
||
|
||
GUID mediaSetId;
|
||
CComPtr<IRmsMediaSet> pMediaSet;
|
||
|
||
WsbAffirmHr(FindCartridgeById(cartId, &pCart));
|
||
|
||
cartridgeName.Free();
|
||
WsbAffirmHr(pCart->GetName(&cartridgeName)); // for the log message
|
||
|
||
cartridgeDesc.Free();
|
||
WsbAffirmHr(pCart->GetDescription(&cartridgeDesc)); // for the log message
|
||
|
||
// Now go to the media set to deallocate
|
||
WsbAffirmHr(pCart->GetMediaSetId(&mediaSetId));
|
||
WsbAffirmHr(CreateObject(mediaSetId, CLSID_CRmsMediaSet, IID_IRmsMediaSet, RmsOpenExisting, (void **) &pMediaSet));
|
||
WsbAffirmHr(pMediaSet->Deallocate(pCart));
|
||
|
||
} WsbCatch(hr)
|
||
|
||
if ( SUCCEEDED(hr) ) {
|
||
WsbLogEvent(RMS_MESSAGE_CARTRIDGE_RECYCLED, sizeof(GUID), (void *) &cartId, (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, NULL);
|
||
}
|
||
else {
|
||
WsbLogEvent(RMS_MESSAGE_CARTRIDGE_RECYCLE_FAILED, sizeof(GUID), (void *) &cartId, (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, WsbHrAsString(hr), NULL);
|
||
}
|
||
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::RecycleCartridge"), OLESTR("hr = <%ls>, name/desc = <%ls/%ls>, cartId = %ls"), WsbHrAsString(hr), (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, WsbQuickString(WsbGuidAsString(cartId)));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::FindLibraryById(
|
||
IN REFGUID libId,
|
||
OUT IRmsLibrary **pLib)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::FindLibraryById
|
||
|
||
--*/
|
||
{
|
||
|
||
HRESULT hr = E_FAIL;
|
||
|
||
CComPtr<IRmsCartridge> pFindLib;
|
||
|
||
try {
|
||
|
||
WsbAssertPointer( pLib );
|
||
|
||
// Create a cartridge template
|
||
WsbAffirmHr( CoCreateInstance( CLSID_CRmsLibrary, 0, CLSCTX_SERVER,
|
||
IID_IRmsLibrary, (void **)&pFindLib ));
|
||
|
||
// Fill in the find template
|
||
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pFindLib;
|
||
|
||
WsbAffirmHr( pObject->SetObjectId( libId ));
|
||
WsbAffirmHr( pObject->SetFindBy( RmsFindByObjectId ));
|
||
|
||
// Find the cartridge
|
||
WsbAffirmHr( m_pLibraries->Find( pFindLib, IID_IRmsLibrary, (void **)pLib ));
|
||
|
||
hr = S_OK;
|
||
|
||
} WsbCatchAndDo(hr,
|
||
if ( WSB_E_NOTFOUND == hr) hr = RMS_E_LIBRARY_NOT_FOUND;
|
||
WsbTrace(OLESTR("CRmsServer::FindLibraryById - %ls Not Found. hr = <%ls>\n"),WsbGuidAsString(libId),WsbHrAsString(hr));
|
||
);
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::FindCartridgeById(
|
||
IN REFGUID cartId,
|
||
OUT IRmsCartridge **ppCart)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::FindCartridgeById
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
WsbTraceIn(OLESTR("CRmsServer::FindCartridgeById"), OLESTR("%ls"), WsbGuidAsString(cartId));
|
||
|
||
try {
|
||
WsbAssertPointer(ppCart);
|
||
|
||
//
|
||
// The search algorithms attempts to avoid unnecessary throws that
|
||
// clutter the trace file. Each media management subsystem is tried.
|
||
//
|
||
|
||
// First check the most active cartridge.
|
||
hr = RMS_E_CARTRIDGE_NOT_FOUND;
|
||
|
||
if (m_pActiveCartridge) {
|
||
GUID activeId;
|
||
WsbAffirmHr( m_pActiveCartridge->GetCartridgeId(&activeId));
|
||
if (activeId == cartId) {
|
||
*ppCart = m_pActiveCartridge;
|
||
m_pActiveCartridge->AddRef();
|
||
hr = S_OK;
|
||
}
|
||
}
|
||
|
||
if (hr != S_OK ) {
|
||
|
||
//
|
||
// Try native RMS
|
||
//
|
||
try {
|
||
hr = S_OK;
|
||
|
||
CComPtr<IRmsCartridge> pFindCart;
|
||
|
||
// Create a cartridge template
|
||
WsbAffirmHr(CoCreateInstance(CLSID_CRmsCartridge, 0, CLSCTX_SERVER,
|
||
IID_IRmsCartridge, (void **)&pFindCart));
|
||
|
||
// Fill in the find template
|
||
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pFindCart;
|
||
|
||
WsbAffirmHr( pObject->SetObjectId(cartId));
|
||
WsbAffirmHr( pObject->SetFindBy(RmsFindByObjectId));
|
||
|
||
// Try to find the cartridge in the collection of active cartridges.
|
||
hr = m_pActiveCartridges->Find(pFindCart, IID_IRmsCartridge, (void **)ppCart);
|
||
WsbAffirm(S_OK == hr || WSB_E_NOTFOUND == hr, hr);
|
||
|
||
if (WSB_E_NOTFOUND == hr) {
|
||
|
||
// Find the cartridge in the collection of cartridges
|
||
hr = m_pCartridges->Find(pFindCart, IID_IRmsCartridge, (void **)ppCart);
|
||
WsbAffirm(S_OK == hr || WSB_E_NOTFOUND == hr, hr);
|
||
|
||
if (WSB_E_NOTFOUND == hr) {
|
||
hr = RMS_E_CARTRIDGE_NOT_FOUND;
|
||
}
|
||
|
||
}
|
||
|
||
} WsbCatch(hr);
|
||
|
||
}
|
||
|
||
|
||
if ( hr != S_OK ) {
|
||
|
||
//
|
||
// Try NTMS
|
||
//
|
||
try {
|
||
hr = S_OK;
|
||
|
||
hr = IsNTMSInstalled();
|
||
if ( S_OK == hr ) {
|
||
hr = m_pNTMS->FindCartridge(cartId, ppCart);
|
||
WsbAffirm(S_OK == hr || RMS_E_CARTRIDGE_NOT_FOUND == hr, hr);
|
||
}
|
||
else {
|
||
switch(hr) {
|
||
case RMS_E_NOT_CONFIGURED_FOR_NTMS:
|
||
case RMS_E_NTMS_NOT_REGISTERED:
|
||
// Normal errors
|
||
hr = RMS_E_CARTRIDGE_NOT_FOUND;
|
||
break;
|
||
default:
|
||
// Unexpected Error!
|
||
WsbThrow(hr);
|
||
break;
|
||
}
|
||
}
|
||
|
||
} WsbCatch(hr);
|
||
|
||
}
|
||
|
||
} WsbCatchAndDo(hr,
|
||
CWsbStringPtr idString = cartId;
|
||
WsbLogEvent(RMS_MESSAGE_CARTRIDGE_NOT_FOUND, 0, NULL, (WCHAR *) idString, WsbHrAsString(hr), NULL);
|
||
hr = RMS_E_CARTRIDGE_NOT_FOUND;
|
||
);
|
||
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::FindCartridgeById"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::CreateObject(
|
||
IN REFGUID objectId,
|
||
IN REFCLSID rclsid,
|
||
IN REFIID riid,
|
||
IN DWORD dwCreate,
|
||
OUT void **ppvObj)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::CreateObject
|
||
|
||
--*/
|
||
{
|
||
|
||
HRESULT hr = E_FAIL;
|
||
|
||
|
||
try {
|
||
|
||
WsbAssertPointer( ppvObj );
|
||
WsbAssert( NULL == *ppvObj, E_INVALIDARG );
|
||
|
||
CComPtr<IWsbIndexedCollection> pCollection;
|
||
CComPtr<IWsbCollectable> pCollectable;
|
||
|
||
if ( objectId != GUID_NULL ) {
|
||
|
||
CComPtr<IRmsComObject> pFindObject;
|
||
|
||
// Create an object template
|
||
WsbAffirmHr( CoCreateInstance( rclsid, 0, CLSCTX_SERVER,
|
||
IID_IRmsComObject, (void **)&pFindObject ));
|
||
|
||
WsbAffirmHr( pFindObject->SetObjectId( objectId ));
|
||
WsbAffirmHr( pFindObject->SetFindBy( RmsFindByObjectId ));
|
||
|
||
// The only kinds created must support: IRmsComObject (for the object Id),
|
||
// and IWsbCollectable (to be added to a collection).
|
||
|
||
// See if the object is already in a collection.
|
||
try {
|
||
if ( CLSID_CRmsCartridge == rclsid ) {
|
||
pCollection = m_pCartridges;
|
||
WsbAffirmHrOk( m_pCartridges->Find( pFindObject,
|
||
IID_IWsbCollectable, (void **) &pCollectable ) );
|
||
}
|
||
else if ( CLSID_CRmsLibrary == rclsid ) {
|
||
pCollection = m_pLibraries;
|
||
WsbAffirmHrOk( m_pLibraries->Find( pFindObject,
|
||
IID_IWsbCollectable, (void **) &pCollectable ) );
|
||
}
|
||
else if ( CLSID_CRmsMediaSet == rclsid ) {
|
||
pCollection = m_pMediaSets;
|
||
WsbAffirmHrOk( m_pMediaSets->Find( pFindObject,
|
||
IID_IWsbCollectable, (void **) &pCollectable ) );
|
||
}
|
||
else if ( CLSID_CRmsRequest == rclsid ) {
|
||
pCollection = m_pRequests;
|
||
WsbAffirmHrOk( m_pRequests->Find( pFindObject,
|
||
IID_IWsbCollectable, (void **) &pCollectable ) );
|
||
}
|
||
else if ( CLSID_CRmsClient == rclsid ) {
|
||
pCollection = m_pClients;
|
||
WsbAffirmHrOk( m_pClients->Find( pFindObject,
|
||
IID_IWsbCollectable, (void **) &pCollectable ) );
|
||
}
|
||
else {
|
||
WsbThrow( E_UNEXPECTED );
|
||
}
|
||
|
||
hr = S_OK;
|
||
} WsbCatch(hr);
|
||
|
||
}
|
||
else if ( RmsOpenExisting == dwCreate ) {
|
||
|
||
// If we get GUID_NULL, we must going after a default object, and we only support this
|
||
// with existing objects. This is only legal if the default media set registry key exists.
|
||
|
||
if ( CLSID_CRmsMediaSet == rclsid ) {
|
||
|
||
CWsbBstrPtr defaultMediaSetName = RMS_DEFAULT_MEDIASET;
|
||
|
||
DWORD size;
|
||
OLECHAR tmpString[256];
|
||
if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_DEFAULT_MEDIASET, tmpString, 256, &size))) {
|
||
// Get the value.
|
||
defaultMediaSetName = tmpString;
|
||
}
|
||
else {
|
||
WsbAssert( objectId != GUID_NULL, E_INVALIDARG );
|
||
}
|
||
|
||
CComPtr<IRmsComObject> pFindObject;
|
||
|
||
// Create an object template
|
||
WsbAffirmHr( CoCreateInstance( rclsid, 0, CLSCTX_SERVER,
|
||
IID_IRmsComObject, (void **)&pFindObject ));
|
||
|
||
WsbAffirmHr( pFindObject->SetName( defaultMediaSetName ));
|
||
WsbAffirmHr( pFindObject->SetFindBy( RmsFindByName ));
|
||
|
||
pCollection = m_pMediaSets;
|
||
WsbAffirmHrOk( m_pMediaSets->Find( pFindObject,
|
||
IID_IWsbCollectable, (void **) &pCollectable ) );
|
||
|
||
WsbTrace(OLESTR("Using Default MediaSet <%ls>.\n"), (WCHAR *) defaultMediaSetName);
|
||
|
||
hr = S_OK;
|
||
}
|
||
else {
|
||
WsbThrow( E_INVALIDARG );
|
||
}
|
||
}
|
||
else {
|
||
WsbThrow( E_UNEXPECTED );
|
||
}
|
||
|
||
// If the object wasn't found we create it here, and add it to the appropriate collection.
|
||
switch ( (RmsCreate)dwCreate ) {
|
||
case RmsOpenExisting:
|
||
if ( S_OK == hr ) {
|
||
WsbAffirmHr( pCollectable->QueryInterface( riid, ppvObj ) );
|
||
}
|
||
else {
|
||
WsbThrow( hr );
|
||
}
|
||
break;
|
||
|
||
case RmsOpenAlways:
|
||
if ( WSB_E_NOTFOUND == hr ) {
|
||
// Create the object
|
||
WsbAffirmHr( CoCreateInstance( rclsid, 0, CLSCTX_SERVER,
|
||
IID_IWsbCollectable, (void **) &pCollectable ));
|
||
|
||
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pCollectable;
|
||
WsbAffirmPointer( pObject );
|
||
WsbAffirmHr( pObject->SetObjectId( objectId ) );
|
||
|
||
// Before we add the collection, make sure the interface is supported.
|
||
WsbAffirmHr( pCollectable->QueryInterface( riid, ppvObj ));
|
||
WsbAffirmPointer( pCollection );
|
||
WsbAffirmHr( pCollection->Add( pCollectable ) );
|
||
}
|
||
else if ( S_OK == hr ) {
|
||
WsbAffirmHr( pCollectable->QueryInterface( riid, ppvObj ) );
|
||
}
|
||
else {
|
||
WsbThrow( hr );
|
||
}
|
||
break;
|
||
|
||
case RmsCreateNew:
|
||
if ( WSB_E_NOTFOUND == hr ) {
|
||
// Create the object
|
||
WsbAffirmHr( CoCreateInstance( rclsid, 0, CLSCTX_SERVER,
|
||
IID_IWsbCollectable, (void **) &pCollectable ));
|
||
|
||
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pCollectable;
|
||
WsbAffirmPointer( pObject );
|
||
WsbAffirmHr( pObject->SetObjectId( objectId ) );
|
||
|
||
// Before we add the collection, make sure the interface is supported.
|
||
WsbAffirmHr( pCollectable->QueryInterface( riid, ppvObj ) );
|
||
WsbAffirmPointer( pCollection );
|
||
WsbAffirmHr( pCollection->Add( pCollectable ) );
|
||
}
|
||
else if ( S_OK == hr ) {
|
||
WsbThrow( RMS_E_ALREADY_EXISTS );
|
||
}
|
||
else {
|
||
WsbThrow( hr );
|
||
}
|
||
break;
|
||
|
||
default:
|
||
WsbThrow( E_UNEXPECTED );
|
||
break;
|
||
|
||
}
|
||
|
||
hr = S_OK;
|
||
|
||
}
|
||
WsbCatchAndDo( hr,
|
||
if ( WSB_E_NOTFOUND == hr) hr = RMS_E_NOT_FOUND;
|
||
WsbTrace(OLESTR("!!!!! ERROR !!!!! CRmsServer::CreateObject: %ls; hr = <%ls>\n"),WsbGuidAsString(objectId),WsbHrAsString(hr));
|
||
);
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CRmsServer::getHardDrivesToUseFromRegistry(
|
||
OUT OLECHAR *pDrivesToUse,
|
||
OUT DWORD *pLen)
|
||
/*++
|
||
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
WsbTraceIn(OLESTR("CRmsServer::GetHardpDrivesToUseFromRegistry"),OLESTR(""));
|
||
|
||
try {
|
||
WsbAssert(0 != pDrivesToUse, E_POINTER);
|
||
WsbAssert(0 != pLen, E_POINTER);
|
||
|
||
DWORD sizeGot;
|
||
OLECHAR tmpString[1000];
|
||
|
||
*pLen = 0;
|
||
pDrivesToUse[0] = OLECHAR('\0');
|
||
pDrivesToUse[1] = OLECHAR('\0');
|
||
|
||
//
|
||
// Get the default value
|
||
//
|
||
WsbAffirmHr(WsbEnsureRegistryKeyExists (NULL, RMS_REGISTRY_STRING));
|
||
WsbAffirmHr(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_HARD_DRIVES_TO_USE,
|
||
tmpString, RMS_DIR_LEN, &sizeGot));
|
||
// We are doing some string manipulation here to match the Win32 call
|
||
// GetLogicalDriveStrings. It returns a string of drives separated by
|
||
// Nulls with a double NULL at the end. For example: if we want to use
|
||
// the C and E drives the string should be: C:\<null>E:\<null><null>
|
||
// and len would be 8.
|
||
DWORD myCharCount = 0;
|
||
sizeGot = wcslen(tmpString);
|
||
for (DWORD i = 0; i < sizeGot; i++) {
|
||
swprintf((OLECHAR *)&pDrivesToUse[myCharCount], OLESTR("%c:\\"), tmpString[i]);
|
||
myCharCount = ((i + 1)* 4);
|
||
}
|
||
pDrivesToUse[myCharCount] = OLECHAR('\0');
|
||
if (myCharCount != 0) {
|
||
*pLen = myCharCount + 1;
|
||
}
|
||
|
||
} WsbCatch(hr);
|
||
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::GetHardpDrivesToUseFromRegistry"), OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
|
||
HRESULT
|
||
CRmsServer::enableAsBackupOperator(void)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine enables backup operator privilege for the process. This is required
|
||
to insure that RMS has full access to all resources on the system, primarily with
|
||
regard to the data mover.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Values:
|
||
|
||
S_OK - Success.
|
||
|
||
--*/
|
||
{
|
||
|
||
HRESULT hr = E_FAIL;
|
||
|
||
try {
|
||
|
||
HANDLE pHandle;
|
||
LUID backupValue;
|
||
HANDLE tokenHandle;
|
||
TOKEN_PRIVILEGES newState;
|
||
DWORD lErr;
|
||
|
||
pHandle = GetCurrentProcess();
|
||
WsbAffirmStatus(OpenProcessToken(pHandle, MAXIMUM_ALLOWED, &tokenHandle));
|
||
//
|
||
// adjust backup token privileges
|
||
//
|
||
WsbAffirmStatus(LookupPrivilegeValueW(NULL, L"SeBackupPrivilege", &backupValue));
|
||
newState.PrivilegeCount = 1;
|
||
newState.Privileges[0].Luid = backupValue;
|
||
newState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||
WsbAffirmStatus(AdjustTokenPrivileges(tokenHandle, FALSE, &newState, (DWORD)0, NULL, NULL));
|
||
//
|
||
// Note that AdjustTokenPrivileges may return success even if it did not assign all privileges.
|
||
// We check last error here to insure everything was set.
|
||
//
|
||
if ( (lErr = GetLastError()) != ERROR_SUCCESS ) {
|
||
// Not backup user or some other error
|
||
//
|
||
// TODO: Should we fail here or just log something?
|
||
//
|
||
WsbLogEvent( RMS_MESSAGE_SERVICE_UNABLE_TO_SET_BACKUP_PRIVILEGE, 0, NULL,
|
||
WsbHrAsString(HRESULT_FROM_WIN32(lErr)), NULL );
|
||
}
|
||
|
||
WsbAffirmStatus(LookupPrivilegeValueW(NULL, L"SeRestorePrivilege", &backupValue));
|
||
newState.PrivilegeCount = 1;
|
||
newState.Privileges[0].Luid = backupValue;
|
||
newState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||
WsbAffirmStatus(AdjustTokenPrivileges(tokenHandle, FALSE, &newState, (DWORD)0, NULL, NULL));
|
||
//
|
||
// Note that AdjustTokenPrivileges may return success even if it did not assign all privileges.
|
||
// We check last error here to insure everything was set.
|
||
//
|
||
if ( (lErr = GetLastError()) != ERROR_SUCCESS ) {
|
||
// Not backup user or some other error
|
||
//
|
||
// TODO: Should we fail here or just log something?
|
||
//
|
||
WsbLogEvent( RMS_MESSAGE_SERVICE_UNABLE_TO_SET_RESTORE_PRIVILEGE, 0, NULL,
|
||
WsbHrAsString(HRESULT_FROM_WIN32(lErr)), NULL );
|
||
|
||
}
|
||
CloseHandle( tokenHandle );
|
||
|
||
hr = S_OK;
|
||
|
||
}
|
||
WsbCatch( hr );
|
||
|
||
return hr;
|
||
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CRmsServer::ChangeState(
|
||
IN LONG newState)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::CreateObject
|
||
|
||
--*/
|
||
{
|
||
|
||
HRESULT hr = S_OK;
|
||
WsbTraceIn(OLESTR("CRmsServer::ChangeState"), OLESTR("<%d>"), newState);
|
||
|
||
try {
|
||
|
||
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
|
||
WsbAssertPointer( pObject );
|
||
|
||
switch ((RmsServerState) newState) {
|
||
case RmsServerStateStarting:
|
||
case RmsServerStateStarted:
|
||
case RmsServerStateInitializing:
|
||
case RmsServerStateReady:
|
||
case RmsServerStateStopping:
|
||
case RmsServerStateStopped:
|
||
case RmsServerStateSuspending:
|
||
case RmsServerStateSuspended:
|
||
case RmsServerStateResuming:
|
||
WsbAffirmHr(pObject->SetState(newState));
|
||
break;
|
||
default:
|
||
WsbAssert(0, E_UNEXPECTED);
|
||
break;
|
||
}
|
||
|
||
} WsbCatch(hr);
|
||
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::ChangeState"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CRmsServer::IsReady(void)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::IsReady
|
||
|
||
--*/
|
||
{
|
||
|
||
HRESULT hr = S_OK;
|
||
|
||
try {
|
||
|
||
BOOL isEnabled;
|
||
HRESULT status;
|
||
RmsServerState state;
|
||
|
||
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
|
||
WsbAssertPointer( pObject );
|
||
|
||
WsbAffirm(m_LockReference == 0, RMS_E_NOT_READY_SERVER_LOCKED);
|
||
|
||
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 ) {
|
||
switch ( state ) {
|
||
case RmsServerStateStarting:
|
||
WsbThrow(RMS_E_NOT_READY_SERVER_STARTING);
|
||
break;
|
||
case RmsServerStateStarted:
|
||
WsbThrow(RMS_E_NOT_READY_SERVER_STARTED);
|
||
break;
|
||
case RmsServerStateInitializing:
|
||
WsbThrow(RMS_E_NOT_READY_SERVER_INITIALIZING);
|
||
break;
|
||
case RmsServerStateStopping:
|
||
WsbThrow(RMS_E_NOT_READY_SERVER_STOPPING);
|
||
break;
|
||
case RmsServerStateStopped:
|
||
WsbThrow(RMS_E_NOT_READY_SERVER_STOPPED);
|
||
break;
|
||
case RmsServerStateSuspending:
|
||
WsbThrow(RMS_E_NOT_READY_SERVER_SUSPENDING);
|
||
break;
|
||
case RmsServerStateSuspended:
|
||
WsbThrow(RMS_E_NOT_READY_SERVER_SUSPENDED);
|
||
break;
|
||
case RmsServerStateResuming:
|
||
WsbThrow(RMS_E_NOT_READY_SERVER_RESUMING);
|
||
break;
|
||
default:
|
||
WsbThrow(E_UNEXPECTED);
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
WsbThrow(status);
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
if ( S_OK == status ) {
|
||
WsbThrow(RMS_E_NOT_READY_SERVER_DISABLED);
|
||
}
|
||
else {
|
||
WsbThrow(status);
|
||
}
|
||
}
|
||
|
||
} WsbCatch(hr);
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CRmsServer::ChangeSysState(
|
||
IN OUT HSM_SYSTEM_STATE* pSysState
|
||
)
|
||
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IHsmSystemState::ChangeSysState().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CRmsServer::ChangeSysState"), OLESTR("State = %lx"),
|
||
pSysState->State);
|
||
|
||
try {
|
||
if ((pSysState->State & HSM_STATE_SHUTDOWN) ||
|
||
(pSysState->State & HSM_STATE_SUSPEND)) {
|
||
//
|
||
// Shutdown or Suspend operations
|
||
//
|
||
// For power mangement support we need to release
|
||
// all device handles, and the NTMS (RSM) session handle.
|
||
//
|
||
// To accomplish this we simply disable each cartridge,
|
||
// then disable NTMS.
|
||
//
|
||
// The fallout from this gets everything in the power ready state.
|
||
//
|
||
|
||
WsbAffirmHr(ChangeState(RmsServerStateSuspending));
|
||
|
||
//
|
||
// Suspend operations with NMTS. This will cancel any in-progress mounts.
|
||
//
|
||
WsbAffirmHr(m_pNTMS->Suspend());
|
||
|
||
//
|
||
// Disable each of the active cartridges
|
||
//
|
||
CComPtr<IWsbEnum> pEnumCartridges;
|
||
CComPtr<IWsbEnum> pEnumDataMovers;
|
||
CComPtr<IRmsComObject> pObject;
|
||
CComPtr<IRmsCartridge> pCart;
|
||
CComPtr<IDataMover> pMover;
|
||
CComPtr<IRmsDrive> pDrive;
|
||
|
||
WsbAffirmHr( m_pActiveCartridges->Enum( &pEnumCartridges ));
|
||
WsbAssertPointer( pEnumCartridges );
|
||
|
||
//
|
||
// Disable each cartridge.
|
||
//
|
||
|
||
hr = pEnumCartridges->First( IID_IRmsComObject, (void **)&pObject );
|
||
while (S_OK == hr) {
|
||
try {
|
||
WsbAffirmHr(pObject->Disable(RMS_E_NOT_READY_SERVER_SUSPENDING));
|
||
} WsbCatch(hr);
|
||
|
||
pObject = 0;
|
||
hr = pEnumCartridges->Next( IID_IRmsComObject, (void **)&pObject );
|
||
}
|
||
hr = S_OK;
|
||
|
||
|
||
/*
|
||
Tracking DataMovers is only partially implemented.
|
||
|
||
|
||
//
|
||
// Cancel I/O requests.
|
||
//
|
||
|
||
WsbAffirmHr( m_pDataMovers->Enum( &pEnumDataMovers ));
|
||
WsbAssertPointer( pEnumDataMovers );
|
||
hr = pEnumDataMovers->First( IID_IDataMover, (void **)&pMover );
|
||
while (S_OK == hr) {
|
||
try {
|
||
WsbAffirmHr(pMover->Cancel());
|
||
} WsbCatch(hr);
|
||
|
||
pMover = 0;
|
||
hr = pEnumDataMovers->Next( IID_IDataMover, (void **)&pMover );
|
||
}
|
||
hr = S_OK;
|
||
|
||
*/
|
||
|
||
//
|
||
// Unload all drives.
|
||
//
|
||
|
||
hr = pEnumCartridges->First( IID_IRmsCartridge, (void **)&pCart );
|
||
while (S_OK == hr) {
|
||
try {
|
||
WsbAffirmHr(pCart->GetDrive(&pDrive));
|
||
WsbAffirmHr(pDrive->UnloadNow());
|
||
} WsbCatch(hr);
|
||
|
||
pDrive = 0;
|
||
pCart = 0;
|
||
|
||
//
|
||
// We use "->This" since the UnloadNow() method will wait
|
||
// until the active cartridge is dismount, and removed
|
||
// from the active cartridge list.
|
||
//
|
||
hr = pEnumCartridges->This( IID_IRmsCartridge, (void **)&pCart );
|
||
}
|
||
hr = S_OK;
|
||
|
||
//
|
||
// Suspend operations with NMTS. This will close the NTMS handle in
|
||
// case it was reopend for dismounts during shutdown.
|
||
//
|
||
WsbAffirmHr(m_pNTMS->Suspend());
|
||
|
||
WsbAffirmHr(ChangeState(RmsServerStateSuspended));
|
||
|
||
} else if (pSysState->State & HSM_STATE_RESUME) {
|
||
//
|
||
// Resume operations
|
||
//
|
||
WsbAffirmHr(ChangeState(RmsServerStateResuming));
|
||
|
||
WsbAffirmHr(m_pNTMS->Resume());
|
||
|
||
CComPtr<IWsbEnum> pEnumCartridges;
|
||
CComPtr<IRmsComObject> pObject;
|
||
|
||
WsbAffirmHr( m_pActiveCartridges->Enum( &pEnumCartridges ));
|
||
WsbAssertPointer( pEnumCartridges );
|
||
|
||
//
|
||
// Enable each of the active cartridges
|
||
//
|
||
hr = pEnumCartridges->First( IID_IRmsComObject, (void **)&pObject );
|
||
while (S_OK == hr) {
|
||
try {
|
||
WsbAffirmHr(pObject->Enable());
|
||
} WsbCatch(hr);
|
||
|
||
pObject = 0;
|
||
hr = pEnumCartridges->Next( IID_IRmsComObject, (void **)&pObject );
|
||
}
|
||
hr = S_OK;
|
||
|
||
WsbAffirmHr(ChangeState(RmsServerStateReady));
|
||
|
||
}
|
||
|
||
} WsbCatch(hr);
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::ChangeSysState"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
HRESULT
|
||
CRmsServer::GetNofAvailableDrives(
|
||
IN REFGUID fromMediaSet,
|
||
OUT DWORD* pdwNofDrives
|
||
)
|
||
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::GetNofAvailableDrives().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CRmsServer::GetNofAvailableDrives"), OLESTR(""));
|
||
|
||
try {
|
||
WsbAssertPointer(pdwNofDrives);
|
||
*pdwNofDrives = 0;
|
||
|
||
// Get the media set
|
||
CComPtr<IRmsMediaSet> pMediaSet;
|
||
WsbAffirmHr(CreateObject(fromMediaSet, CLSID_CRmsMediaSet, IID_IRmsMediaSet, RmsOpenExisting, (void **) &pMediaSet));
|
||
|
||
// Check if the media set is of fixed drives
|
||
LONG mediaType;
|
||
WsbAffirmHr(pMediaSet->GetMediaSupported(&mediaType));
|
||
|
||
if (RmsMediaFixed == mediaType) {
|
||
// Count fixed drives
|
||
// We take a shortcut here and just use number of drives that were counted
|
||
// during initialization. (FindCartridgeStatusById can give current state)
|
||
*pdwNofDrives = m_HardDrivesUsed;
|
||
} else {
|
||
// Just use NTMS
|
||
// TEMPORARY - We might want RmsNtms to use media-set info as well,
|
||
// in order not to count both tape and optical drives on a system that has both
|
||
WsbAffirmHr(m_pNTMS->GetNofAvailableDrives(pdwNofDrives));
|
||
}
|
||
|
||
} WsbCatch(hr);
|
||
|
||
WsbTrace(OLESTR("CRmsServer::GetNofAvailableDrives: Number of enabled drives is %lu\n"), *pdwNofDrives);
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::GetNofAvailableDrives"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
HRESULT
|
||
CRmsServer::FindCartridgeStatusById(
|
||
IN REFGUID cartId,
|
||
OUT DWORD* pdwStatus
|
||
)
|
||
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::FindCartridgeStatusById().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
CComPtr<IRmsCartridge> pCart;
|
||
CComPtr<IRmsCartridge> pFindCart;
|
||
|
||
WsbTraceIn(OLESTR("CRmsServer::FindCartridgeStatusById"), OLESTR("cartId = %ls"), WsbGuidAsString(cartId));
|
||
|
||
try {
|
||
WsbAssertPointer(pdwStatus);
|
||
*pdwStatus = 0;
|
||
|
||
// Try native RMS, Currently this should succeed only if media is a fixed drive
|
||
WsbAffirmHr(CoCreateInstance(CLSID_CRmsCartridge, 0, CLSCTX_SERVER,
|
||
IID_IRmsCartridge, (void **)&pFindCart));
|
||
|
||
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pFindCart;
|
||
|
||
WsbAffirmHr(pObject->SetObjectId(cartId));
|
||
WsbAffirmHr(pObject->SetFindBy(RmsFindByObjectId));
|
||
|
||
hr = m_pCartridges->Find(pFindCart, IID_IRmsCartridge, (void **)&pCart);
|
||
WsbAffirm(S_OK == hr || WSB_E_NOTFOUND == hr, hr);
|
||
if (WSB_E_NOTFOUND == hr) {
|
||
hr = RMS_E_CARTRIDGE_NOT_FOUND;
|
||
}
|
||
|
||
// Search in RSM
|
||
if (S_OK != hr) {
|
||
hr = IsNTMSInstalled();
|
||
if (S_OK == hr) {
|
||
hr = m_pNTMS->FindCartridge(cartId, &pCart);
|
||
WsbAffirm(S_OK == hr || RMS_E_CARTRIDGE_NOT_FOUND == hr, hr);
|
||
} else {
|
||
switch(hr) {
|
||
case RMS_E_NOT_CONFIGURED_FOR_NTMS:
|
||
case RMS_E_NTMS_NOT_REGISTERED:
|
||
// Normal errors
|
||
hr = RMS_E_CARTRIDGE_NOT_FOUND;
|
||
break;
|
||
default:
|
||
// Unexpected Error!
|
||
WsbThrow(hr);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// if media found...
|
||
if (S_OK == hr) {
|
||
// Check media type
|
||
LONG mediaType;
|
||
WsbAffirmHr(pCart->GetType(&mediaType));
|
||
|
||
if (RmsMediaFixed != mediaType) {
|
||
// RSM media
|
||
|
||
// set flags
|
||
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pCart;
|
||
WsbAffirmPointer(pObject);
|
||
if (S_OK == pObject->IsEnabled()) {
|
||
(*pdwStatus) |= RMS_MEDIA_ENABLED;
|
||
}
|
||
|
||
if (S_OK == pCart->IsAvailable()) {
|
||
(*pdwStatus) |= RMS_MEDIA_AVAILABLE;
|
||
}
|
||
|
||
LONG lLocationType;
|
||
GUID Dum1,Dum2;
|
||
LONG lDum3, lDum4, lDum5, lDum6;
|
||
BOOL bDum7;
|
||
WsbAffirmHr(pCart->GetLocation(&lLocationType, &Dum1, &Dum2, &lDum3, &lDum4,
|
||
&lDum5, &lDum6, &bDum7));
|
||
switch (lLocationType) {
|
||
case RmsElementUnknown:
|
||
case RmsElementShelf:
|
||
case RmsElementOffSite:
|
||
// media is offline...
|
||
break;
|
||
|
||
default:
|
||
(*pdwStatus) |= RMS_MEDIA_ONLINE;
|
||
break;
|
||
}
|
||
|
||
} else {
|
||
// Fixed drive - just try to access the volume and see if it's still valid
|
||
// If so, set all flags, otherwise, set none
|
||
CComPtr<IRmsDrive> pDrive;
|
||
CWsbBstrPtr driveName;
|
||
WCHAR fileSystemType[MAX_PATH];
|
||
|
||
// Get drive name (volume name for fixed drives) to check
|
||
WsbAffirmHr(pCart->GetDrive(&pDrive));
|
||
CComQIPtr<IRmsDevice, &IID_IRmsDevice> pDevice = pDrive;
|
||
WsbAssertPointer(pDevice);
|
||
WsbAffirmHr(pDevice->GetDeviceName(&driveName));
|
||
|
||
if (GetVolumeInformation((WCHAR *)driveName, NULL, 0,
|
||
NULL, NULL, NULL, fileSystemType, MAX_PATH) ) {
|
||
if (0 == wcscmp(L"NTFS", fileSystemType)) {
|
||
// Volume is ready for migration - set all flags
|
||
(*pdwStatus) |= (RMS_MEDIA_ENABLED | RMS_MEDIA_ONLINE | RMS_MEDIA_AVAILABLE);
|
||
} else {
|
||
// Not NTFS - don't use that volume
|
||
WsbTrace(OLESTR("CRmsServer::FindCartridgeStatusById: Fixed volume %ls is formatted to %ls\n"),
|
||
(WCHAR *)driveName, fileSystemType);
|
||
}
|
||
} else {
|
||
// Volume is not available - don't use it
|
||
WsbTrace(OLESTR("CRmsServer::FindCartridgeStatusById: GetVolumeInformation returned %lu for Fixed volume %ls\n"),
|
||
GetLastError(), (WCHAR *)driveName);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
} WsbCatch(hr);
|
||
|
||
WsbTrace(OLESTR("CRmsServer::FindCartridgeStatusById: Status bits are %lX\n"), *pdwStatus);
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::FindCartridgeStatusById"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
HRESULT
|
||
CRmsServer::IsMultipleSidedMedia(
|
||
IN REFGUID mediaSetId
|
||
)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::IsMultipleSidedMedia
|
||
|
||
Notes:
|
||
|
||
Currently, optical & DVD media types are reported as multiple sided media
|
||
Tapes and fixed disks would fall in the default - one side media
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_FALSE;
|
||
WsbTraceIn(OLESTR("CRmsServer::IsMultipleSidedMedia"), OLESTR(""));
|
||
|
||
try {
|
||
// Multiple sided is currently determined if the media set is optical or not
|
||
// This may change to include other media types of according two other characteristics
|
||
CComPtr<IRmsMediaSet> pMediaSet;
|
||
LONG mediaType;
|
||
|
||
if (mediaSetId != GUID_NULL) {
|
||
// if input media set is non-null, check this data-set.
|
||
WsbAffirmHr(CreateObject(mediaSetId, CLSID_CRmsMediaSet, IID_IRmsMediaSet, RmsOpenAlways, (void **)&pMediaSet));
|
||
WsbAffirmHr(pMediaSet->GetMediaSupported(&mediaType));
|
||
if ((RmsMediaOptical == mediaType) || (RmsMediaDVD == mediaType)) {
|
||
hr = S_OK;
|
||
}
|
||
|
||
} else {
|
||
// Otherwise, enumerate the collection seeking for any media set that might have two sides
|
||
CComPtr<IWsbEnum> pEnumSets;
|
||
|
||
WsbAffirmHr(m_pMediaSets->Enum(&pEnumSets));
|
||
WsbAssertPointer(pEnumSets);
|
||
hr = pEnumSets->First(IID_IRmsMediaSet, (void **)&pMediaSet);
|
||
while (S_OK == hr) {
|
||
WsbAffirmHr(pMediaSet->GetMediaSupported(&mediaType));
|
||
if ((RmsMediaOptical == mediaType) || (RmsMediaDVD == mediaType)) {
|
||
hr = S_OK;
|
||
break;
|
||
}
|
||
|
||
hr = pEnumSets->Next(IID_IRmsMediaSet, (void **)&pMediaSet);
|
||
if (hr == WSB_E_NOTFOUND) {
|
||
hr = S_FALSE;
|
||
} else {
|
||
WsbAffirmHr(hr);
|
||
}
|
||
}
|
||
}
|
||
|
||
} WsbCatch(hr);
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::IsMultipleSidedMedia"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
return hr;
|
||
}
|
||
|
||
HRESULT
|
||
CRmsServer::CheckSecondSide(
|
||
IN REFGUID firstSideId,
|
||
OUT BOOL *pbValid,
|
||
OUT GUID *pSecondSideId
|
||
)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IRmsServer::CheckSecondSide().
|
||
|
||
Notes:
|
||
|
||
It is not expected that this utility is called on a single sided media.
|
||
If it does, it would return invalid second side for tape and would fail on fixed disks.
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
WsbTraceIn(OLESTR("CRmsServer::CheckSecondSide"), OLESTR(""));
|
||
|
||
try {
|
||
// just use NTMS (RmsServer collections are not used today!)
|
||
WsbAffirmHr(m_pNTMS->CheckSecondSide(firstSideId, pbValid, pSecondSideId));
|
||
|
||
} WsbCatch(hr);
|
||
|
||
WsbTrace(OLESTR("CRmsServer::CheckSecondSide: Valid second side: %ls, id=<%ls>\n"),
|
||
WsbBoolAsString(*pbValid), WsbGuidAsString(*pSecondSideId));
|
||
|
||
WsbTraceOut(OLESTR("CRmsServer::CheckSecondSide"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|