mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2033 lines
47 KiB
2033 lines
47 KiB
/*++
|
|
|
|
© 1998 Seagate Software, Inc. All rights reserved
|
|
|
|
Module Name:
|
|
|
|
RmsChngr.cpp
|
|
|
|
Abstract:
|
|
|
|
Implementation of CRmsMediumChanger
|
|
|
|
Author:
|
|
|
|
Brian Dodd [brian] 15-Nov-1996
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "RmsChngr.h"
|
|
#include "RmsServr.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
|
|
HRESULT
|
|
CRmsMediumChanger::FinalConstruct(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
CComObjectRoot::FinalConstruct
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
WsbAssertHr(CWsbObject::FinalConstruct());
|
|
|
|
// Initialize fields
|
|
m_isAutomatic = FALSE;
|
|
|
|
m_canRotate = FALSE;
|
|
|
|
m_operation = RMS_UNDEFINED_STRING;
|
|
|
|
m_percentComplete = 0;
|
|
|
|
m_handle = INVALID_HANDLE_VALUE;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CRmsMediumChanger::FinalRelease(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
CComObjectRoot::FinalRelease
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssertHr( ReleaseDevice() );
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::CompareTo(
|
|
IN IUnknown *pCollectable,
|
|
OUT SHORT *pResult
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IWsbCollectable::CompareTo
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
SHORT result = 1;
|
|
|
|
WsbTraceIn( OLESTR("CRmsMediumChanger::CompareTo"), OLESTR("") );
|
|
|
|
try {
|
|
|
|
// Validate arguments - Okay if pResult is NULL
|
|
WsbAssertPointer( pCollectable );
|
|
|
|
// !!!!!
|
|
//
|
|
// IMPORTANT: The collectable coming in may not be a CRmsDrive if the collection
|
|
// is the unconfigured device list.
|
|
//
|
|
// !!!!!
|
|
|
|
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pCollectable;
|
|
WsbAssertPointer( pObject );
|
|
|
|
switch ( m_findBy ) {
|
|
|
|
case RmsFindByDeviceInfo:
|
|
case RmsFindByDeviceAddress:
|
|
case RmsFindByDeviceName:
|
|
case RmsFindByDeviceType:
|
|
|
|
// Do CompareTo for device
|
|
hr = CRmsDevice::CompareTo( pCollectable, &result );
|
|
break;
|
|
|
|
case RmsFindByElementNumber:
|
|
case RmsFindByMediaSupported:
|
|
|
|
// Do CompareTo for changer element
|
|
hr = CRmsChangerElement::CompareTo( pCollectable, &result );
|
|
break;
|
|
|
|
case RmsFindByObjectId:
|
|
default:
|
|
|
|
// Do CompareTo for object
|
|
hr = CRmsComObject::CompareTo( pCollectable, &result );
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
WsbCatch( hr );
|
|
|
|
if ( SUCCEEDED(hr) && (0 != pResult) ){
|
|
*pResult = result;
|
|
}
|
|
|
|
WsbTraceOut( OLESTR("CRmsMediumChanger::CompareTo"),
|
|
OLESTR("hr = <%ls>, result = <%ls>"),
|
|
WsbHrAsString( hr ), WsbPtrToShortAsString( pResult ) );
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::GetClassID(
|
|
OUT CLSID* pClsid
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IPersist::GetClassID
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CRmsMediumChanger::GetClassID"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pClsid, E_POINTER);
|
|
|
|
*pClsid = CLSID_CRmsMediumChanger;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CRmsMediumChanger::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::GetSizeMax(
|
|
OUT ULARGE_INTEGER* pcbSize
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IPersistStream::GetSizeMax
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = E_NOTIMPL;
|
|
|
|
// ULONG inProcessOperation;
|
|
|
|
|
|
WsbTraceIn(OLESTR("CRmsMediumChanger::GetSizeMax"), OLESTR(""));
|
|
|
|
// try {
|
|
// WsbAssert(0 != pcbSize, E_POINTER);
|
|
|
|
// inProcessOperation = SysStringByteLen(m_operation);
|
|
|
|
// // Get size
|
|
// pcbSize->QuadPart = WsbPersistSizeOf(LONG) + // m_isAutomatic
|
|
// WsbPersistSizeOf(LONG) + // m_canRotate
|
|
// WsbPersistSizeOf(LONG) + // m_operation length
|
|
// inProcessOperation; // m_operation
|
|
|
|
//// inProcessOperation + // m_operation
|
|
//// WsbPersistSizeOf(BYTE); // m_percentComplete
|
|
|
|
|
|
// } WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CRmsMediumChanger::GetSizeMax"), OLESTR("hr = <%ls>, Size = <%ls>"), WsbHrAsString(hr), WsbPtrToUliAsString(pcbSize));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::Load(
|
|
IN IStream* pStream
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IPersistStream::Load
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG ulBytes = 0;
|
|
|
|
WsbTraceIn(OLESTR("CRmsMediumChanger::Load"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pStream, E_POINTER);
|
|
|
|
WsbAffirmHr(CRmsDevice::Load(pStream));
|
|
|
|
// Load value
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_isAutomatic));
|
|
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_canRotate));
|
|
|
|
WsbAffirmHr(WsbBstrFromStream(pStream, &m_operation));
|
|
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_percentComplete));
|
|
|
|
if ( INVALID_HANDLE_VALUE == m_handle ) {
|
|
|
|
WsbAffirmHr( AcquireDevice() );
|
|
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CRmsMediumChanger::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::Save(
|
|
IN IStream *pStream,
|
|
IN BOOL clearDirty
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IPersistStream::Save
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG ulBytes = 0;
|
|
|
|
WsbTraceIn(OLESTR("CRmsMediumChanger::Save"), OLESTR("clearDirty = <%ls>"), WsbBoolAsString(clearDirty));
|
|
|
|
try {
|
|
WsbAssert(0 != pStream, E_POINTER);
|
|
|
|
WsbAffirmHr(CRmsDevice::Save(pStream, clearDirty));
|
|
|
|
// Save value
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_isAutomatic));
|
|
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_canRotate));
|
|
|
|
WsbAffirmHr(WsbBstrToStream(pStream, m_operation));
|
|
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_percentComplete));
|
|
|
|
// Do we need to clear the dirty bit?
|
|
if (clearDirty) {
|
|
m_isDirty = FALSE;
|
|
}
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CRmsMediumChanger::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::Test(
|
|
OUT USHORT *pPassed,
|
|
OUT USHORT *pFailed
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IWsbTestable::Test
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CComPtr<IRmsMediumChanger> pChanger1;
|
|
CComPtr<IRmsMediumChanger> pChanger2;
|
|
|
|
CComPtr<IPersistFile> pFile1;
|
|
CComPtr<IPersistFile> pFile2;
|
|
|
|
// CRmsLocator locWork1;
|
|
// CRmsLocator locWork2;
|
|
|
|
CWsbBstrPtr bstrVal1 = OLESTR("5A5A5A");
|
|
CWsbBstrPtr bstrWork1;
|
|
CWsbBstrPtr bstrWork2;
|
|
|
|
|
|
WsbTraceIn(OLESTR("CRmsMediumChanger::Test"), OLESTR(""));
|
|
|
|
try {
|
|
// Get the Changer interface.
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssertHr(((IUnknown*) (IRmsMediumChanger*) this)->QueryInterface(IID_IRmsMediumChanger, (void**) &pChanger1));
|
|
|
|
// Test SetHome & GetHome
|
|
|
|
// Test SetAutomatic & IsAutomatic to TRUE
|
|
hr = S_OK;
|
|
|
|
try{
|
|
WsbAffirmHr(SetAutomatic (TRUE));
|
|
WsbAffirmHr(IsAutomatic ());
|
|
} WsbCatch (hr);
|
|
|
|
if (hr == S_OK){
|
|
(*pPassed)++;
|
|
} else {
|
|
(*pFailed)++;
|
|
}
|
|
|
|
// Test SetAutomatic & IsAutomatic to FALSE
|
|
hr = S_OK;
|
|
|
|
try{
|
|
WsbAffirmHr(SetAutomatic (FALSE));
|
|
WsbAffirmHr(IsAutomatic ());
|
|
} WsbCatch (hr);
|
|
|
|
if (hr == S_OK){
|
|
(*pFailed)++;
|
|
} else {
|
|
(*pPassed)++;
|
|
}
|
|
|
|
// Test SetCanRotate & IsCanRotate to TRUE
|
|
hr = S_OK;
|
|
|
|
try{
|
|
WsbAffirmHr(SetCanRotate (TRUE));
|
|
WsbAffirmHr(CanRotate ());
|
|
} WsbCatch (hr);
|
|
|
|
if (hr == S_OK){
|
|
(*pPassed)++;
|
|
} else {
|
|
(*pFailed)++;
|
|
}
|
|
|
|
// Test SetCanRotate & IsCanRotate to FALSE
|
|
hr = S_OK;
|
|
|
|
try{
|
|
WsbAffirmHr(SetCanRotate (FALSE));
|
|
WsbAffirmHr(CanRotate ());
|
|
} WsbCatch (hr);
|
|
|
|
if (hr == S_OK){
|
|
(*pFailed)++;
|
|
} else {
|
|
(*pPassed)++;
|
|
}
|
|
|
|
// Test SetOperation & GetOperation interface
|
|
bstrWork1 = bstrVal1;
|
|
|
|
SetOperation(bstrWork1);
|
|
|
|
GetOperation(&bstrWork2);
|
|
|
|
if (bstrWork1 == bstrWork2){
|
|
(*pPassed)++;
|
|
} else {
|
|
(*pFailed)++;
|
|
}
|
|
|
|
// Test SetPercentComplete & GetPercentComplete
|
|
|
|
// Test ExportCartridge & ImportCartridge
|
|
|
|
// Test DismountCartridge & MountCartridge
|
|
|
|
// Test TestReady
|
|
|
|
// Test Home
|
|
|
|
} WsbCatch(hr);
|
|
|
|
// Tally up the results
|
|
|
|
hr = S_OK;
|
|
if (*pFailed) {
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CRmsMediumChanger::Test"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IRmsMediumChanger implementation
|
|
//
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::GetHome(
|
|
LONG *pType,
|
|
LONG *pPos,
|
|
BOOL *pInvert
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::GetHome
|
|
|
|
--*/
|
|
{
|
|
GUID zero = {0,0,0,0,0,0,0,0,0,0,0};
|
|
LONG junk;
|
|
|
|
return m_home.GetLocation( pType,
|
|
&zero,
|
|
&zero,
|
|
pPos,
|
|
&junk,
|
|
&junk,
|
|
&junk,
|
|
pInvert );
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::SetHome(
|
|
LONG type,
|
|
LONG pos,
|
|
BOOL invert
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::SetHome
|
|
|
|
--*/
|
|
{
|
|
GUID zero = {0,0,0,0,0,0,0,0,0,0,0};
|
|
LONG junk = 0;
|
|
|
|
m_isDirty = TRUE;
|
|
return m_home.SetLocation( type, zero, zero, pos, junk, junk, junk, invert );
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::SetAutomatic(
|
|
BOOL flag
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::SetAutomatic
|
|
|
|
--*/
|
|
{
|
|
m_isAutomatic = flag;
|
|
m_isDirty = TRUE;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::IsAutomatic(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::IsAutomatic
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
|
|
if (m_isAutomatic){
|
|
hr = S_OK;
|
|
}
|
|
|
|
return (hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::SetCanRotate(
|
|
BOOL flag
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::SetCanRotate
|
|
|
|
--*/
|
|
{
|
|
m_canRotate = flag;
|
|
m_isDirty = TRUE;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::CanRotate(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::CanRotate
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
|
|
if (m_canRotate){
|
|
hr = S_OK;
|
|
}
|
|
|
|
return (hr);
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::GetOperation(
|
|
BSTR *pOperation
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::GetOperation
|
|
|
|
--*/
|
|
{
|
|
WsbAssertPointer ( pOperation );
|
|
|
|
m_operation.CopyToBstr( pOperation );
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::SetOperation(
|
|
BSTR pOperation
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::SetOperation
|
|
|
|
--*/
|
|
{
|
|
m_operation = pOperation;
|
|
m_isDirty = TRUE;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::GetPercentComplete(
|
|
BYTE *pPercent
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::GetPercentComplete
|
|
|
|
--*/
|
|
{
|
|
*pPercent = m_percentComplete;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::SetPercentComplete(
|
|
BYTE percent
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::SetPercentComplete
|
|
|
|
--*/
|
|
{
|
|
m_percentComplete = percent;
|
|
m_isDirty = TRUE;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::TestReady(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::TestReady
|
|
|
|
--*/
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::ImportCartridge(
|
|
IRmsCartridge** /*pCart*/
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::ImportCartridge
|
|
|
|
--*/
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::ExportCartridge(
|
|
IRmsCartridge** /*pCart*/
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::ExportCartridge
|
|
|
|
--*/
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::MoveCartridge(
|
|
IN IRmsCartridge *pSrcCart,
|
|
IN IUnknown *pDestElmt
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::MountCartridge
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
try {
|
|
|
|
CComPtr<IRmsCartridge> pCart2;
|
|
CComPtr<IRmsDrive> pDrive2;
|
|
|
|
GUID libId=GUID_NULL, mediaSetId=GUID_NULL;
|
|
LONG type=0, pos=0, alt1=0, alt2=0, alt3=0;
|
|
BOOL invert=0;
|
|
|
|
GUID destLibId=GUID_NULL, destMediaSetId=GUID_NULL;
|
|
LONG destType=0, destPos=0, destAlt1=0, destAlt2=0, destAlt3=0;
|
|
BOOL destInvert=0;
|
|
|
|
GUID dest2LibId=GUID_NULL, dest2MediaSetId=GUID_NULL;
|
|
LONG dest2Type=0, dest2Pos=0, dest2Alt1=0, dest2Alt2=0, dest2Alt3=0;
|
|
BOOL dest2Invert=0;
|
|
|
|
CHANGER_ELEMENT src, dest, dest2;
|
|
|
|
CComQIPtr<IRmsChangerElement, &IID_IRmsChangerElement> pElmt = pDestElmt;
|
|
WsbAssertPointer( pElmt );
|
|
|
|
// TODO: assert cartridge has same libId as changer
|
|
|
|
// Set up for SOURCE
|
|
|
|
WsbAffirmHr( pSrcCart->GetLocation( &type, &libId, &mediaSetId,
|
|
&pos, &alt1, &alt2, &alt3, &invert ));
|
|
|
|
src.ElementAddress = pos;
|
|
|
|
// Translate the RmsElement type to something the drive understands.
|
|
|
|
// TODO: make this a local method
|
|
|
|
switch ( (RmsElement) type ) {
|
|
case RmsElementUnknown:
|
|
WsbAssertHr( E_UNEXPECTED );
|
|
break;
|
|
|
|
case RmsElementStage:
|
|
case RmsElementStorage:
|
|
src.ElementType = ChangerSlot;
|
|
break;
|
|
|
|
case RmsElementShelf:
|
|
case RmsElementOffSite:
|
|
// not supported here!
|
|
WsbAssertHr( E_UNEXPECTED );
|
|
break;
|
|
|
|
case RmsElementDrive:
|
|
src.ElementType = ChangerDrive;
|
|
break;
|
|
|
|
case RmsElementChanger:
|
|
src.ElementType = ChangerTransport;
|
|
break;
|
|
|
|
case RmsElementIEPort:
|
|
src.ElementType = ChangerIEPort;
|
|
break;
|
|
|
|
default:
|
|
WsbAssertHr( E_UNEXPECTED );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Set up for DESTINATION
|
|
//
|
|
|
|
WsbAffirmHr( pElmt->GetLocation( &destType, &destLibId, &destMediaSetId,
|
|
&destPos, &destAlt1, &destAlt2, &destAlt3, &destInvert ));
|
|
|
|
dest.ElementAddress = destPos;
|
|
|
|
// Translate the Rms type to something the drive understands.
|
|
switch ( (RmsElement) destType) {
|
|
case RmsElementUnknown:
|
|
WsbAssertHr( E_UNEXPECTED );
|
|
break;
|
|
|
|
case RmsElementStage:
|
|
case RmsElementStorage:
|
|
dest.ElementType = ChangerSlot;
|
|
break;
|
|
|
|
case RmsElementShelf:
|
|
case RmsElementOffSite:
|
|
// not supported here!
|
|
WsbAssertHr( E_UNEXPECTED );
|
|
break;
|
|
|
|
case RmsElementDrive:
|
|
dest.ElementType = ChangerDrive;
|
|
break;
|
|
|
|
case RmsElementChanger:
|
|
dest.ElementType = ChangerTransport;
|
|
break;
|
|
|
|
case RmsElementIEPort:
|
|
dest.ElementType = ChangerIEPort;
|
|
break;
|
|
|
|
default:
|
|
WsbAssertHr( E_UNEXPECTED );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Do we need to do an exchange or a simple move?
|
|
//
|
|
|
|
BOOL destFull;
|
|
|
|
hr = pElmt->IsOccupied();
|
|
|
|
destFull = ( S_OK == hr ) ? TRUE : FALSE;
|
|
|
|
if ( destFull ) {
|
|
|
|
//
|
|
// Set up for second destination
|
|
//
|
|
|
|
pElmt->GetCartridge( &pCart2 );
|
|
|
|
pCart2->GetDrive( &pDrive2 );
|
|
|
|
if ( pDrive2 && ( m_parameters.Features0 & CHANGER_PREDISMOUNT_EJECT_REQUIRED ) ) {
|
|
pDrive2->Eject();
|
|
}
|
|
|
|
WsbAffirmHr( pCart2->GetHome( &dest2Type, &dest2LibId, &dest2MediaSetId,
|
|
&dest2Pos, &dest2Alt1, &dest2Alt2, &dest2Alt3, &dest2Invert ));
|
|
|
|
|
|
dest2.ElementAddress = dest2Pos;
|
|
|
|
// Translate the Rms type to something the drive understands.
|
|
switch ( (RmsElement) dest2Type) {
|
|
case RmsElementUnknown:
|
|
WsbAssertHr( E_UNEXPECTED );
|
|
break;
|
|
|
|
case RmsElementStage:
|
|
case RmsElementStorage:
|
|
dest2.ElementType = ChangerSlot;
|
|
break;
|
|
|
|
case RmsElementShelf:
|
|
case RmsElementOffSite:
|
|
// not supported here!
|
|
WsbAssertHr( E_UNEXPECTED );
|
|
break;
|
|
|
|
case RmsElementDrive:
|
|
WsbAssertHr( E_UNEXPECTED );
|
|
break;
|
|
|
|
case RmsElementChanger:
|
|
WsbAssertHr( E_UNEXPECTED );
|
|
break;
|
|
|
|
case RmsElementIEPort:
|
|
dest2.ElementType = ChangerIEPort;
|
|
break;
|
|
|
|
default:
|
|
WsbAssertHr( E_UNEXPECTED );
|
|
break;
|
|
}
|
|
|
|
|
|
WsbAffirmHr( ExchangeMedium( src, dest, dest2, FALSE, FALSE ));
|
|
|
|
// Update the Cartridge's Locator
|
|
WsbAffirmHr( pSrcCart->SetLocation( destType, libId, mediaSetId,
|
|
destPos, alt1, alt2, alt3, invert ));
|
|
|
|
WsbAffirmHr( pCart2->SetLocation( dest2Type, dest2LibId, dest2MediaSetId,
|
|
dest2Pos, dest2Alt1, dest2Alt2, dest2Alt3, dest2Invert ));
|
|
|
|
}
|
|
else {
|
|
|
|
// Call through to the medium changer driver to move the cartridge
|
|
|
|
// TODO: handle two sided media.
|
|
|
|
WsbAffirmHr( MoveMedium( src, dest, FALSE ));
|
|
|
|
// Update the Cartridge's Locator
|
|
WsbAffirmHr( pSrcCart->SetLocation( destType, libId, mediaSetId,
|
|
destPos, alt1, alt2, alt3, invert ));
|
|
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
}
|
|
WsbCatch(hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::HomeCartridge(
|
|
IN IRmsCartridge *pCart
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::HomeCartridge
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
try {
|
|
|
|
WsbAssertPointer( pCart );
|
|
|
|
GUID libId=GUID_NULL, mediaSetId=GUID_NULL;
|
|
LONG type=0, pos=0, alt1=0, alt2=0, alt3=0;
|
|
BOOL invert=0;
|
|
|
|
GUID destLibId=GUID_NULL, destMediaSetId=GUID_NULL;
|
|
LONG destType=0, destPos=0, destAlt1=0, destAlt2=0, destAlt3=0;
|
|
BOOL destInvert=0;
|
|
|
|
CHANGER_ELEMENT src, dest;
|
|
|
|
// TODO: assert cartridge has same libId as changer
|
|
|
|
// Set up for SOURCE
|
|
|
|
WsbAffirmHr( pCart->GetLocation( &type, &libId, &mediaSetId,
|
|
&pos, &alt1, &alt2, &alt3, &invert ));
|
|
|
|
src.ElementAddress = pos;
|
|
|
|
// Translate the RmsElement type to something the drive understands.
|
|
|
|
// TODO: make this a local method
|
|
|
|
switch ( (RmsElement) type ) {
|
|
case RmsElementUnknown:
|
|
WsbAssertHr( E_UNEXPECTED );
|
|
break;
|
|
|
|
case RmsElementStage:
|
|
case RmsElementStorage:
|
|
src.ElementType = ChangerSlot;
|
|
break;
|
|
|
|
case RmsElementShelf:
|
|
case RmsElementOffSite:
|
|
// not supported here!
|
|
WsbAssertHr( E_UNEXPECTED );
|
|
break;
|
|
|
|
case RmsElementDrive:
|
|
src.ElementType = ChangerDrive;
|
|
break;
|
|
|
|
case RmsElementChanger:
|
|
src.ElementType = ChangerTransport;
|
|
break;
|
|
|
|
case RmsElementIEPort:
|
|
src.ElementType = ChangerIEPort;
|
|
break;
|
|
|
|
default:
|
|
WsbAssertHr( E_UNEXPECTED );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Set up for DESTINATION
|
|
//
|
|
|
|
WsbAffirmHr( pCart->GetHome( &destType, &destLibId, &destMediaSetId,
|
|
&destPos, &destAlt1, &destAlt2, &destAlt3, &destInvert ));
|
|
|
|
dest.ElementAddress = destPos;
|
|
|
|
// Translate the Rms type to something the drive understands.
|
|
switch ( (RmsElement) destType) {
|
|
case RmsElementUnknown:
|
|
WsbAssertHr( E_UNEXPECTED );
|
|
break;
|
|
|
|
case RmsElementStage:
|
|
case RmsElementStorage:
|
|
dest.ElementType = ChangerSlot;
|
|
break;
|
|
|
|
case RmsElementShelf:
|
|
case RmsElementOffSite:
|
|
// not supported here!
|
|
WsbAssertHr( E_UNEXPECTED );
|
|
break;
|
|
|
|
case RmsElementDrive:
|
|
dest.ElementType = ChangerDrive;
|
|
break;
|
|
|
|
case RmsElementChanger:
|
|
dest.ElementType = ChangerTransport;
|
|
break;
|
|
|
|
case RmsElementIEPort:
|
|
dest.ElementType = ChangerIEPort;
|
|
break;
|
|
|
|
default:
|
|
WsbAssertHr( E_UNEXPECTED );
|
|
break;
|
|
}
|
|
|
|
WsbAffirmHr( MoveMedium( src, dest, FALSE ));
|
|
|
|
// Update the Cartridge's Locator
|
|
WsbAffirmHr( pCart->SetLocation( destType, libId, mediaSetId,
|
|
destPos, alt1, alt2, alt3, invert ));
|
|
|
|
hr = S_OK;
|
|
|
|
}
|
|
WsbCatch(hr);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::Initialize(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::Initialize
|
|
|
|
--*/
|
|
{
|
|
|
|
// TODO: Break this into some smaller methods for initializing slot, drives, ports, etc.
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
PREAD_ELEMENT_ADDRESS_INFO pElementInformation = 0;
|
|
|
|
try {
|
|
DWORD size;
|
|
|
|
WsbAffirmHr(AcquireDevice());
|
|
|
|
WsbAffirmHr(Status());
|
|
|
|
size = sizeof( CHANGER_PRODUCT_DATA );
|
|
CHANGER_PRODUCT_DATA productData;
|
|
WsbAffirmHr(GetProductData( &size, &productData ));
|
|
|
|
// Get device specific parameters.
|
|
size = sizeof( GET_CHANGER_PARAMETERS );
|
|
WsbAffirmHr(GetParameters(&size, &m_parameters));
|
|
|
|
// save some of the more common parameters
|
|
m_isAutomatic = TRUE;
|
|
if ( m_parameters.Features0 & CHANGER_MEDIUM_FLIP ) m_canRotate = TRUE;
|
|
|
|
// Initialize the changer elements
|
|
BOOL scan = TRUE;
|
|
CHANGER_ELEMENT_LIST list;
|
|
|
|
if ( m_parameters.Features0 & CHANGER_BAR_CODE_SCANNER_INSTALLED ) scan = TRUE;
|
|
|
|
list.NumberOfElements = 1;
|
|
list.Element.ElementType = AllElements;
|
|
list.Element.ElementAddress = 0;
|
|
|
|
WsbAffirmHr( InitializeElementStatus( list, scan ) );
|
|
|
|
list.NumberOfElements = m_parameters.NumberStorageElements;
|
|
list.Element.ElementType = ChangerSlot;
|
|
list.Element.ElementAddress = 0;
|
|
|
|
BOOL tag = ( m_parameters.Features0 & CHANGER_VOLUME_IDENTIFICATION ) ? TRUE : FALSE;
|
|
|
|
size = sizeof(READ_ELEMENT_ADDRESS_INFO) + (list.NumberOfElements - 1) * sizeof(CHANGER_ELEMENT_STATUS);
|
|
pElementInformation = (PREAD_ELEMENT_ADDRESS_INFO)WsbAlloc( size );
|
|
WsbAffirmPointer(pElementInformation);
|
|
memset(pElementInformation, 0, size);
|
|
|
|
WsbAffirmHr( GetElementStatus( list, tag, &size, pElementInformation ));
|
|
|
|
// Create storage slot objects for this changer, if required.
|
|
LONG type;
|
|
GUID libId, mediaSetId;
|
|
LONG pos, alt1, alt2, alt3;
|
|
BOOL invert;
|
|
|
|
m_location.GetLocation( &type, &libId, &mediaSetId, &pos, &alt1, &alt2, &alt3, &invert );
|
|
|
|
CComQIPtr<IRmsServer, &IID_IRmsServer> pServer = g_pServer;
|
|
|
|
CComPtr<IWsbIndexedCollection> pCarts;
|
|
CComPtr<IWsbIndexedCollection> pSlots;
|
|
|
|
CComPtr<IRmsLibrary> pLib;
|
|
CComPtr<IRmsStorageSlot> pSlot;
|
|
|
|
WsbAffirmHr( pServer->FindLibraryById( libId, &pLib ));
|
|
|
|
WsbAffirmHr( pLib->GetStorageSlots( &pSlots ));
|
|
WsbAffirmHr( pServer->GetCartridges( &pCarts ));
|
|
|
|
ULONG count = 0;
|
|
WsbAffirmHr( pSlots->GetEntries( &count ));
|
|
|
|
while ( count < pElementInformation->NumberOfElements ) {
|
|
|
|
// Add more slots objects to the library
|
|
WsbAffirmHr( hr = CoCreateInstance( CLSID_CRmsStorageSlot, 0, CLSCTX_SERVER,
|
|
IID_IRmsStorageSlot, (void **)&pSlot ));
|
|
|
|
WsbAffirmHr( pSlots->Add( pSlot ));
|
|
|
|
pSlot = 0;
|
|
|
|
count++;
|
|
}
|
|
|
|
// Populate the storage slot objects with information reported by the device
|
|
|
|
// TODO: We need to add lots more asserts of various conditions where the
|
|
// previous slot information is not consistant with what has been detected.
|
|
|
|
PCHANGER_ELEMENT_STATUS pElementStatus;
|
|
CComPtr<IWsbEnum> pEnumSlots;
|
|
|
|
WsbAffirmHr( pSlots->Enum( &pEnumSlots ));
|
|
WsbAssertPointer( pEnumSlots );
|
|
|
|
hr = pEnumSlots->First( IID_IRmsStorageSlot, (void **)&pSlot );
|
|
|
|
for ( ULONG i = 0; i < pElementInformation->NumberOfElements; i++ ) {
|
|
|
|
pElementStatus = &pElementInformation->ElementStatus[i];
|
|
|
|
WsbAssert( ChangerSlot == pElementStatus->Element.ElementType, E_UNEXPECTED );
|
|
WsbAssert( i == pElementStatus->Element.ElementAddress, E_UNEXPECTED );
|
|
|
|
CComQIPtr<IRmsChangerElement, &IID_IRmsChangerElement> pSlotElmt = pSlot;
|
|
|
|
// Is the unit of media inverted?
|
|
invert = ( ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_SVALID ) &&
|
|
( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_INVERT ) ) ? TRUE : FALSE;
|
|
WsbAffirmHr( pSlotElmt->SetLocation( RmsElementStorage, libId, GUID_NULL, i, 0, 0, 0, invert ));
|
|
|
|
// Is the slot Full or Empty?
|
|
BOOL occupied = ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_FULL ) ? TRUE : FALSE;
|
|
WsbAffirmHr( pSlotElmt->SetIsOccupied( occupied ));
|
|
|
|
// Set the media type supported
|
|
WsbAffirmHr( pSlotElmt->SetMediaSupported( m_mediaSupported ));
|
|
|
|
// Set the storage flag
|
|
WsbAffirmHr( pSlotElmt->SetIsStorage( TRUE ));
|
|
|
|
// If there is a cartridge present fill in cartridge information
|
|
if ( occupied ) {
|
|
|
|
CComPtr<IRmsCartridge> pCart;
|
|
|
|
WsbAffirmHr( hr = CoCreateInstance( CLSID_CRmsCartridge, 0, CLSCTX_SERVER,
|
|
IID_IRmsCartridge, (void **)&pCart ));
|
|
|
|
|
|
WsbAffirmHr( pCart->SetLocation( RmsElementStorage, libId, GUID_NULL, i, 0, 0, 0, invert ));
|
|
WsbAffirmHr( pCart->SetLocation( RmsElementStorage, libId, GUID_NULL, i, 0, 0, 0, invert ));
|
|
WsbAffirmHr( pCart->SetHome( RmsElementStorage, libId, GUID_NULL, i, 0, 0, 0, invert ));
|
|
WsbAffirmHr( pCart->SetStatus( RmsStatusScratch ));
|
|
WsbAffirmHr( pCart->SetType( m_mediaSupported ));
|
|
WsbAffirmHr( pSlotElmt->SetCartridge( pCart ));
|
|
|
|
// Add cartridge to drive
|
|
WsbAffirmHr( pCarts->Add( pCart ));
|
|
|
|
if ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_PVOLTAG ) {
|
|
|
|
pElementStatus->PrimaryVolumeID[32] = '\0'; // This nulls the reserved byte
|
|
pElementStatus->PrimaryVolumeID[33] = '\0'; // This nulls the reserved byte
|
|
CWsbBstrPtr label( (char *)pElementStatus->PrimaryVolumeID );
|
|
|
|
// Fill in external label information
|
|
WsbAffirmHr( pCart->SetTagAndNumber( label, 0 ));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Get the next slot
|
|
hr = pEnumSlots->Next( IID_IRmsStorageSlot, (void **)&pSlot );
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now process drives.
|
|
|
|
|
|
|
|
// Read element status
|
|
|
|
list.NumberOfElements = m_parameters.NumberDataTransferElements;
|
|
list.Element.ElementType = ChangerDrive;
|
|
list.Element.ElementAddress = 0;
|
|
|
|
if ( m_parameters.Features0 & CHANGER_VOLUME_IDENTIFICATION ) tag = TRUE;
|
|
|
|
size = sizeof(READ_ELEMENT_ADDRESS_INFO) + (list.NumberOfElements - 1) * sizeof(CHANGER_ELEMENT_STATUS);
|
|
|
|
WsbFree( pElementInformation );
|
|
pElementInformation = (PREAD_ELEMENT_ADDRESS_INFO)WsbAlloc( size );
|
|
WsbAffirmPointer(pElementInformation);
|
|
memset(pElementInformation, 0, size);
|
|
|
|
WsbAffirmHr( GetElementStatus( list, tag, &size, pElementInformation ));
|
|
|
|
CComPtr<IWsbIndexedCollection> pDevices;
|
|
CComPtr<IWsbIndexedCollection> pDrives;
|
|
CComPtr<IRmsDrive> pDrive;
|
|
CComPtr<IRmsDrive> pFindDrive;
|
|
CComPtr<IRmsDevice> pFindDevice;
|
|
|
|
WsbAffirmHr( pServer->GetUnconfiguredDevices( &pDevices ));
|
|
WsbAffirmHr( pLib->GetDrives( &pDrives ));
|
|
|
|
// For each drive in the element status page, find the drive in the
|
|
// unconfigured list of devices.
|
|
|
|
for ( i = 0; i < pElementInformation->NumberOfElements; i++ ) {
|
|
|
|
pElementStatus = &pElementInformation->ElementStatus[i];
|
|
|
|
WsbAssert( ChangerDrive == pElementStatus->Element.ElementType, E_UNEXPECTED );
|
|
WsbAssert( i == pElementStatus->Element.ElementAddress, E_UNEXPECTED );
|
|
|
|
// set up a find template
|
|
WsbAffirmHr( CoCreateInstance( CLSID_CRmsDrive, 0, CLSCTX_SERVER,
|
|
IID_IRmsDrive, (void **)&pFindDrive ));
|
|
|
|
CComQIPtr<IRmsDevice, &IID_IRmsDevice> pFindDevice = pFindDrive;
|
|
CComQIPtr<IRmsComObject, &IID_IRmsComObject> pFindObject = pFindDrive;
|
|
|
|
BYTE port=0xff, bus=0xff, id=0xff, lun=0xff;
|
|
|
|
if ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_LUN_VALID )
|
|
lun = pElementStatus->Lun;
|
|
|
|
if ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_ID_VALID )
|
|
id = pElementStatus->TargetId;
|
|
|
|
if ( !(pElementStatus->Flags & (ULONG)ELEMENT_STATUS_NOT_BUS) ) {
|
|
bus = m_bus;
|
|
port = m_port;
|
|
}
|
|
|
|
WsbAffirmHr( pFindDevice->SetDeviceAddress( port, bus, id, lun ));
|
|
|
|
WsbAffirmHr( pFindObject->SetFindBy( RmsFindByDeviceAddress ));
|
|
|
|
// Find the drive
|
|
|
|
hr = pDevices->Find( pFindDrive, IID_IRmsDrive, (void **)&pDrive );
|
|
|
|
if ( S_OK == hr ) {
|
|
|
|
// Add the drive to the library
|
|
WsbAffirmHr( pDrives->Add( pDrive ));
|
|
|
|
// Remove the drive form the unconfigured list
|
|
WsbAffirmHr( pDevices->RemoveAndRelease( pDrive ));
|
|
|
|
// Fill in more drive information
|
|
CComQIPtr<IRmsChangerElement, &IID_IRmsChangerElement> pDriveElmt = pDrive;
|
|
|
|
// Is the unit of media inverted?
|
|
invert = ( ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_SVALID ) &&
|
|
( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_INVERT ) ) ? TRUE : FALSE;
|
|
WsbAffirmHr( pDriveElmt->SetLocation( RmsElementDrive, libId, GUID_NULL, i, 0, 0, 0, invert ));
|
|
|
|
// Is the slot Full or Empty?
|
|
BOOL occupied = ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_FULL ) ? TRUE : FALSE;
|
|
WsbAffirmHr( pDriveElmt->SetIsOccupied( occupied ));
|
|
|
|
// Set the media type supported
|
|
WsbAffirmHr( pDriveElmt->SetMediaSupported( m_mediaSupported ));
|
|
|
|
// Set the storage flag
|
|
WsbAffirmHr( pDriveElmt->SetIsStorage( TRUE ));
|
|
|
|
// If there is a cartridge present fill in cartridge information
|
|
if ( occupied ) {
|
|
|
|
CComPtr<IRmsCartridge> pCart;
|
|
|
|
WsbAffirmHr( hr = CoCreateInstance( CLSID_CRmsCartridge, 0, CLSCTX_SERVER,
|
|
IID_IRmsCartridge, (void **)&pCart ));
|
|
|
|
WsbAffirmHr( pCart->SetLocation( RmsElementStorage, libId, GUID_NULL, i, 0, 0, 0, invert ));
|
|
|
|
if ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_SVALID ) {
|
|
|
|
|
|
try {
|
|
ULONG pos;
|
|
|
|
// pos = pElementStatus->SourceElementAddress[1];
|
|
// pos |= (pElementStatus->SourceElementAddress[0] << 8);
|
|
pos = pElementStatus->SrcElementAddress.ElementAddress;
|
|
|
|
|
|
//
|
|
// TODO: FIX THIS - This code incorrectly assumes source is a slot!!!
|
|
//
|
|
// I'll work on trying to get chuck to return element type and position
|
|
// in element status page.
|
|
//
|
|
|
|
WsbAffirm( pos >= m_parameters.FirstSlotNumber, E_UNEXPECTED );
|
|
|
|
pos = pos - m_parameters.FirstSlotNumber;
|
|
|
|
BOOL invert = ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_INVERT ) ? TRUE : FALSE;
|
|
|
|
WsbAffirmHr( pCart->SetHome( RmsElementStorage, libId, GUID_NULL, pos, 0, 0, 0, invert ));
|
|
}
|
|
WsbCatch(hr);
|
|
|
|
}
|
|
|
|
// TODO: if not ELEMENT_STATUS_SVALID we should set the home location to
|
|
// some empty slot. This handles the case where we we come up with
|
|
// unknown media in a drive.
|
|
|
|
|
|
WsbAffirmHr( pCart->SetStatus( RmsStatusScratch ));
|
|
WsbAffirmHr( pCart->SetType( m_mediaSupported ));
|
|
WsbAffirmHr( pCart->SetDrive( pDrive ));
|
|
|
|
// Add cartridge to drive
|
|
WsbAffirmHr( pCarts->Add( pCart ));
|
|
|
|
if ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_PVOLTAG ) {
|
|
|
|
pElementStatus->PrimaryVolumeID[32] = '\0'; // This nulls the reserved byte
|
|
pElementStatus->PrimaryVolumeID[33] = '\0'; // This nulls the reserved byte
|
|
CWsbBstrPtr label( (char *)pElementStatus->PrimaryVolumeID );
|
|
|
|
// Fill in external label information
|
|
WsbAffirmHr( pCart->SetTagAndNumber( label, 0 ));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// All done
|
|
hr = S_OK;
|
|
|
|
}
|
|
WsbCatch(hr);
|
|
|
|
if ( pElementInformation ) {
|
|
WsbFree( pElementInformation );
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::AcquireDevice(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::AcquireDevice
|
|
|
|
--*/
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
HANDLE hChanger = INVALID_HANDLE_VALUE;
|
|
CWsbBstrPtr name;
|
|
|
|
try {
|
|
// Get the device name for this changer
|
|
GetDeviceName( &name );
|
|
|
|
// Create a handle
|
|
hChanger = CreateFile( name,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
0,
|
|
0,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL
|
|
);
|
|
|
|
WsbAffirmHandle( hChanger );
|
|
|
|
// Save the handle
|
|
m_handle = hChanger;
|
|
|
|
// Do any other initialization here
|
|
|
|
hr = S_OK;
|
|
}
|
|
WsbCatchAndDo( hr,
|
|
WsbTrace( OLESTR("\n\n !!!!! ERROR !!!!! Acquire() failed. name=<%ls>\n\n"), name );
|
|
if ( hChanger != INVALID_HANDLE_VALUE ) {
|
|
CloseHandle( hChanger );
|
|
} );
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::ReleaseDevice(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMediumChanger::ReleaseDevice
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
try {
|
|
|
|
if ( INVALID_HANDLE_VALUE != m_handle ) {
|
|
|
|
WsbAffirmStatus( CloseHandle( m_handle ));
|
|
m_handle = INVALID_HANDLE_VALUE;
|
|
|
|
}
|
|
hr = S_OK;
|
|
|
|
}
|
|
WsbCatch( hr );
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IRmsMoveMedia Interface
|
|
//
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::GetParameters(
|
|
IN OUT PDWORD pSize,
|
|
OUT PGET_CHANGER_PARAMETERS pParms
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMoveMedia::GetParameters
|
|
|
|
--*/
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
try
|
|
{
|
|
DWORD dwReturn;
|
|
|
|
WsbAssertPointer( pSize );
|
|
WsbAssertPointer( pParms );
|
|
WsbAssertHandle( m_handle );
|
|
|
|
pParms->Size = sizeof(GET_CHANGER_PARAMETERS);
|
|
|
|
WsbAssertStatus( DeviceIoControl( m_handle,
|
|
IOCTL_CHANGER_GET_PARAMETERS,
|
|
pParms,
|
|
sizeof(GET_CHANGER_PARAMETERS),
|
|
pParms,
|
|
sizeof(GET_CHANGER_PARAMETERS),
|
|
&dwReturn,
|
|
NULL ));
|
|
hr = S_OK;
|
|
}
|
|
WsbCatch( hr );
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::GetProductData(
|
|
IN OUT PDWORD pSize,
|
|
OUT PCHANGER_PRODUCT_DATA pData
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMoveMedia::GetProductData
|
|
|
|
--*/
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
try
|
|
{
|
|
DWORD dwReturn;
|
|
|
|
WsbAssertPointer( pSize );
|
|
WsbAssertPointer( pData );
|
|
WsbAssertHandle( m_handle );
|
|
|
|
WsbAssertStatus( DeviceIoControl( m_handle,
|
|
IOCTL_CHANGER_GET_PRODUCT_DATA,
|
|
NULL,
|
|
0,
|
|
pData,
|
|
sizeof(CHANGER_PRODUCT_DATA),
|
|
&dwReturn,
|
|
NULL ));
|
|
hr = S_OK;
|
|
}
|
|
WsbCatch( hr );
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::Status(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMoveMedia::Status
|
|
|
|
--*/
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
try
|
|
{
|
|
DWORD dwReturn;
|
|
|
|
WsbAssertStatus( DeviceIoControl( m_handle,
|
|
IOCTL_CHANGER_GET_STATUS,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0,
|
|
&dwReturn,
|
|
NULL) );
|
|
hr = S_OK;
|
|
}
|
|
WsbCatch( hr );
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::SetAccess(
|
|
IN CHANGER_ELEMENT element,
|
|
IN DWORD control
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMoveMedia::SetAccess
|
|
|
|
--*/
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
try
|
|
{
|
|
DWORD dwReturn;
|
|
CHANGER_SET_ACCESS setAccess;
|
|
|
|
setAccess.Element = element;
|
|
setAccess.Control = control;
|
|
|
|
WsbAssertStatus( DeviceIoControl( m_handle,
|
|
IOCTL_CHANGER_SET_ACCESS,
|
|
&setAccess,
|
|
sizeof(CHANGER_SET_ACCESS),
|
|
NULL,
|
|
0,
|
|
&dwReturn,
|
|
NULL ));
|
|
hr = S_OK;
|
|
}
|
|
WsbCatch( hr );
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::GetElementStatus(
|
|
IN CHANGER_ELEMENT_LIST elementList,
|
|
IN BOOL volumeTagInfo,
|
|
IN OUT PDWORD pSize,
|
|
OUT PREAD_ELEMENT_ADDRESS_INFO pElementInformation
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMoveMedia::GetElementStatus
|
|
|
|
--*/
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
try
|
|
{
|
|
DWORD dwReturn;
|
|
DWORD requiredSize;
|
|
CHANGER_READ_ELEMENT_STATUS readElementStatus;
|
|
PCHANGER_ELEMENT_STATUS pElementStatus = pElementInformation->ElementStatus;
|
|
|
|
WsbAssertPointer( pSize );
|
|
WsbAssertPointer( pElementInformation );
|
|
|
|
requiredSize = elementList.NumberOfElements * sizeof( CHANGER_ELEMENT_STATUS );
|
|
WsbAssert( *pSize >= requiredSize, E_INVALIDARG );
|
|
|
|
readElementStatus.ElementList = elementList;
|
|
readElementStatus.VolumeTagInfo = (BOOLEAN)( volumeTagInfo ? TRUE : FALSE );
|
|
|
|
WsbAssertStatus( DeviceIoControl( m_handle,
|
|
IOCTL_CHANGER_GET_ELEMENT_STATUS,
|
|
&readElementStatus,
|
|
sizeof(CHANGER_READ_ELEMENT_STATUS),
|
|
pElementStatus,
|
|
requiredSize,
|
|
&dwReturn,
|
|
NULL ));
|
|
|
|
pElementInformation->NumberOfElements = dwReturn / sizeof( CHANGER_ELEMENT_STATUS );
|
|
|
|
hr = S_OK;
|
|
|
|
}
|
|
WsbCatch( hr );
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::InitializeElementStatus(
|
|
IN CHANGER_ELEMENT_LIST elementList,
|
|
IN BOOL barCodeScan
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMoveMedia::InitializeElementStatus
|
|
|
|
--*/
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
try
|
|
{
|
|
DWORD dwReturn;
|
|
CHANGER_INITIALIZE_ELEMENT_STATUS initElementStatus;
|
|
|
|
initElementStatus.ElementList = elementList;
|
|
initElementStatus.BarCodeScan = (BOOLEAN)( barCodeScan ? TRUE : FALSE );
|
|
|
|
WsbAssertStatus( DeviceIoControl( m_handle,
|
|
IOCTL_CHANGER_INITIALIZE_ELEMENT_STATUS,
|
|
&initElementStatus,
|
|
sizeof(CHANGER_INITIALIZE_ELEMENT_STATUS),
|
|
NULL,
|
|
0,
|
|
&dwReturn,
|
|
NULL) );
|
|
hr = S_OK;
|
|
}
|
|
WsbCatch( hr );
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::ExchangeMedium(
|
|
IN CHANGER_ELEMENT source,
|
|
IN CHANGER_ELEMENT destination1,
|
|
IN CHANGER_ELEMENT destination2,
|
|
IN BOOL flip1,
|
|
IN BOOL flip2
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMoveMedia::ExchangeMedium
|
|
|
|
--*/
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
try
|
|
{
|
|
DWORD dwReturn;
|
|
CHANGER_EXCHANGE_MEDIUM exchangeMedium;
|
|
|
|
exchangeMedium.Transport.ElementType = ChangerTransport;
|
|
exchangeMedium.Transport.ElementAddress = 0; // default arm or thumb
|
|
exchangeMedium.Source = source;
|
|
exchangeMedium.Destination1 = destination1;
|
|
exchangeMedium.Destination2 = destination2;
|
|
exchangeMedium.Flip1 = (BOOLEAN)( flip1 ? TRUE : FALSE );
|
|
exchangeMedium.Flip2 = (BOOLEAN)( flip2 ? TRUE : FALSE );
|
|
|
|
WsbAssertStatus( DeviceIoControl( m_handle,
|
|
IOCTL_CHANGER_EXCHANGE_MEDIUM,
|
|
&exchangeMedium,
|
|
sizeof(CHANGER_EXCHANGE_MEDIUM),
|
|
NULL,
|
|
0,
|
|
&dwReturn,
|
|
NULL ));
|
|
hr = S_OK;
|
|
}
|
|
WsbCatch( hr );
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::MoveMedium(
|
|
IN CHANGER_ELEMENT source,
|
|
IN CHANGER_ELEMENT destination,
|
|
IN BOOL flip
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMoveMedia::MoveMedium
|
|
|
|
--*/
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
try
|
|
{
|
|
DWORD dwReturn;
|
|
CHANGER_MOVE_MEDIUM moveMedium;
|
|
|
|
moveMedium.Transport.ElementType = ChangerTransport;
|
|
moveMedium.Transport.ElementAddress = 0; // default arm or thumb
|
|
moveMedium.Source = source;
|
|
moveMedium.Destination = destination;
|
|
moveMedium.Flip = (BOOLEAN)( flip ? TRUE : FALSE );
|
|
|
|
WsbAssertStatus( DeviceIoControl( m_handle,
|
|
IOCTL_CHANGER_MOVE_MEDIUM,
|
|
&moveMedium,
|
|
sizeof(CHANGER_MOVE_MEDIUM),
|
|
NULL,
|
|
0,
|
|
&dwReturn,
|
|
NULL ));
|
|
hr = S_OK;
|
|
}
|
|
WsbCatch( hr );
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::Position(
|
|
IN CHANGER_ELEMENT destination,
|
|
IN BOOL flip
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMoveMedia::Position
|
|
|
|
--*/
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
try
|
|
{
|
|
DWORD dwReturn;
|
|
CHANGER_SET_POSITION positon;
|
|
|
|
positon.Transport.ElementType = ChangerTransport;
|
|
positon.Transport.ElementAddress = 0; // default arm or thumb
|
|
positon.Destination = destination;
|
|
positon.Flip = (BOOLEAN)( flip ? TRUE : FALSE );
|
|
|
|
WsbAssertStatus( DeviceIoControl( m_handle,
|
|
IOCTL_CHANGER_SET_POSITION,
|
|
&positon,
|
|
sizeof(CHANGER_SET_POSITION),
|
|
NULL,
|
|
0,
|
|
&dwReturn,
|
|
NULL ));
|
|
hr = S_OK;
|
|
}
|
|
WsbCatch( hr );
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::RezeroUnit(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMoveMedia::RezeroUnit
|
|
|
|
--*/
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
try
|
|
{
|
|
DWORD dwReturn;
|
|
|
|
WsbAssertStatus( DeviceIoControl( m_handle,
|
|
IOCTL_CHANGER_REINITIALIZE_TRANSPORT,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0,
|
|
&dwReturn,
|
|
NULL ));
|
|
hr = S_OK;
|
|
}
|
|
WsbCatch( hr );
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*
|
|
|
|
HRESULT
|
|
CRmsMediumChanger::getDisplay(
|
|
OUT PCHANGER_DISPLAY pDisplay
|
|
)
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
try
|
|
{
|
|
DWORD dwReturn;
|
|
|
|
WsbAssertStatus( DeviceIoControl( m_handle,
|
|
IOCTL_CHANGER_GET_DISPLAY,
|
|
pDisplay,
|
|
sizeof(CHANGER_DISPLAY) + (pDisplay->LineCount - 1) * sizeof(SET_CHANGER_DISPLAY),
|
|
pDisplay,
|
|
sizeof(CHANGER_DISPLAY) + (pDisplay->LineCount - 1) * sizeof(SET_CHANGER_DISPLAY),
|
|
&dwReturn,
|
|
NULL ));
|
|
hr = S_OK;
|
|
}
|
|
WsbCatch( hr );
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CRmsMediumChanger::setDisplay(
|
|
IN PCHANGER_DISPLAY pDisplay
|
|
)
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
try
|
|
{
|
|
DWORD dwReturn;
|
|
|
|
WsbAssertStatus( DeviceIoControl( m_handle,
|
|
IOCTL_CHANGER_SET_DISPLAY,
|
|
pDisplay,
|
|
sizeof(CHANGER_DISPLAY) + (pDisplay->LineCount - 1) * sizeof(SET_CHANGER_DISPLAY),
|
|
NULL,
|
|
0,
|
|
&dwReturn,
|
|
NULL ));
|
|
hr = S_OK;
|
|
}
|
|
WsbCatch( hr );
|
|
|
|
return hr;
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CRmsMediumChanger::QueryVolumeTag(
|
|
IN CHANGER_ELEMENT startingElement,
|
|
IN DWORD actionCode,
|
|
IN PUCHAR pVolumeIDTemplate,
|
|
OUT PDWORD pNumberOfElementsReturned,
|
|
OUT PREAD_ELEMENT_ADDRESS_INFO pElementInformation
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IRmsMoveMedia::QueryVolumeTag
|
|
|
|
--*/
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
try
|
|
{
|
|
DWORD dwReturn;
|
|
CHANGER_SEND_VOLUME_TAG_INFORMATION tagInfo;
|
|
|
|
tagInfo.StartingElement = startingElement;
|
|
tagInfo.ActionCode = actionCode;
|
|
memcpy( &tagInfo.VolumeIDTemplate, pVolumeIDTemplate, sizeof(MAX_VOLUME_TEMPLATE_SIZE) );
|
|
|
|
WsbAssertStatus( DeviceIoControl( m_handle,
|
|
IOCTL_CHANGER_QUERY_VOLUME_TAGS,
|
|
&tagInfo,
|
|
sizeof(CHANGER_SEND_VOLUME_TAG_INFORMATION),
|
|
pElementInformation,
|
|
sizeof(READ_ELEMENT_ADDRESS_INFO) + (pElementInformation->NumberOfElements - 1) * sizeof(CHANGER_ELEMENT_STATUS),
|
|
&dwReturn,
|
|
NULL ));
|
|
|
|
*pNumberOfElementsReturned = pElementInformation->NumberOfElements;
|
|
|
|
hr = S_OK;
|
|
}
|
|
WsbCatch( hr );
|
|
|
|
return hr;
|
|
}
|