Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2033 lines
47 KiB

  1. /*++
  2. 1998 Seagate Software, Inc. All rights reserved
  3. Module Name:
  4. RmsChngr.cpp
  5. Abstract:
  6. Implementation of CRmsMediumChanger
  7. Author:
  8. Brian Dodd [brian] 15-Nov-1996
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #include "RmsChngr.h"
  13. #include "RmsServr.h"
  14. ////////////////////////////////////////////////////////////////////////////////
  15. //
  16. HRESULT
  17. CRmsMediumChanger::FinalConstruct(
  18. void
  19. )
  20. /*++
  21. Implements:
  22. CComObjectRoot::FinalConstruct
  23. --*/
  24. {
  25. HRESULT hr = S_OK;
  26. try {
  27. WsbAssertHr(CWsbObject::FinalConstruct());
  28. // Initialize fields
  29. m_isAutomatic = FALSE;
  30. m_canRotate = FALSE;
  31. m_operation = RMS_UNDEFINED_STRING;
  32. m_percentComplete = 0;
  33. m_handle = INVALID_HANDLE_VALUE;
  34. } WsbCatch(hr);
  35. return(hr);
  36. }
  37. HRESULT
  38. CRmsMediumChanger::FinalRelease(
  39. void
  40. )
  41. /*++
  42. Implements:
  43. CComObjectRoot::FinalRelease
  44. --*/
  45. {
  46. HRESULT hr = S_OK;
  47. try {
  48. WsbAssertHr( ReleaseDevice() );
  49. } WsbCatch(hr);
  50. return(hr);
  51. }
  52. STDMETHODIMP
  53. CRmsMediumChanger::CompareTo(
  54. IN IUnknown *pCollectable,
  55. OUT SHORT *pResult
  56. )
  57. /*++
  58. Implements:
  59. IWsbCollectable::CompareTo
  60. --*/
  61. {
  62. HRESULT hr = E_FAIL;
  63. SHORT result = 1;
  64. WsbTraceIn( OLESTR("CRmsMediumChanger::CompareTo"), OLESTR("") );
  65. try {
  66. // Validate arguments - Okay if pResult is NULL
  67. WsbAssertPointer( pCollectable );
  68. // !!!!!
  69. //
  70. // IMPORTANT: The collectable coming in may not be a CRmsDrive if the collection
  71. // is the unconfigured device list.
  72. //
  73. // !!!!!
  74. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pCollectable;
  75. WsbAssertPointer( pObject );
  76. switch ( m_findBy ) {
  77. case RmsFindByDeviceInfo:
  78. case RmsFindByDeviceAddress:
  79. case RmsFindByDeviceName:
  80. case RmsFindByDeviceType:
  81. // Do CompareTo for device
  82. hr = CRmsDevice::CompareTo( pCollectable, &result );
  83. break;
  84. case RmsFindByElementNumber:
  85. case RmsFindByMediaSupported:
  86. // Do CompareTo for changer element
  87. hr = CRmsChangerElement::CompareTo( pCollectable, &result );
  88. break;
  89. case RmsFindByObjectId:
  90. default:
  91. // Do CompareTo for object
  92. hr = CRmsComObject::CompareTo( pCollectable, &result );
  93. break;
  94. }
  95. }
  96. WsbCatch( hr );
  97. if ( SUCCEEDED(hr) && (0 != pResult) ){
  98. *pResult = result;
  99. }
  100. WsbTraceOut( OLESTR("CRmsMediumChanger::CompareTo"),
  101. OLESTR("hr = <%ls>, result = <%ls>"),
  102. WsbHrAsString( hr ), WsbPtrToShortAsString( pResult ) );
  103. return hr;
  104. }
  105. STDMETHODIMP
  106. CRmsMediumChanger::GetClassID(
  107. OUT CLSID* pClsid
  108. )
  109. /*++
  110. Implements:
  111. IPersist::GetClassID
  112. --*/
  113. {
  114. HRESULT hr = S_OK;
  115. WsbTraceIn(OLESTR("CRmsMediumChanger::GetClassID"), OLESTR(""));
  116. try {
  117. WsbAssert(0 != pClsid, E_POINTER);
  118. *pClsid = CLSID_CRmsMediumChanger;
  119. } WsbCatch(hr);
  120. WsbTraceOut(OLESTR("CRmsMediumChanger::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid));
  121. return(hr);
  122. }
  123. STDMETHODIMP
  124. CRmsMediumChanger::GetSizeMax(
  125. OUT ULARGE_INTEGER* pcbSize
  126. )
  127. /*++
  128. Implements:
  129. IPersistStream::GetSizeMax
  130. --*/
  131. {
  132. HRESULT hr = E_NOTIMPL;
  133. // ULONG inProcessOperation;
  134. WsbTraceIn(OLESTR("CRmsMediumChanger::GetSizeMax"), OLESTR(""));
  135. // try {
  136. // WsbAssert(0 != pcbSize, E_POINTER);
  137. // inProcessOperation = SysStringByteLen(m_operation);
  138. // // Get size
  139. // pcbSize->QuadPart = WsbPersistSizeOf(LONG) + // m_isAutomatic
  140. // WsbPersistSizeOf(LONG) + // m_canRotate
  141. // WsbPersistSizeOf(LONG) + // m_operation length
  142. // inProcessOperation; // m_operation
  143. //// inProcessOperation + // m_operation
  144. //// WsbPersistSizeOf(BYTE); // m_percentComplete
  145. // } WsbCatch(hr);
  146. WsbTraceOut(OLESTR("CRmsMediumChanger::GetSizeMax"), OLESTR("hr = <%ls>, Size = <%ls>"), WsbHrAsString(hr), WsbPtrToUliAsString(pcbSize));
  147. return(hr);
  148. }
  149. STDMETHODIMP
  150. CRmsMediumChanger::Load(
  151. IN IStream* pStream
  152. )
  153. /*++
  154. Implements:
  155. IPersistStream::Load
  156. --*/
  157. {
  158. HRESULT hr = S_OK;
  159. ULONG ulBytes = 0;
  160. WsbTraceIn(OLESTR("CRmsMediumChanger::Load"), OLESTR(""));
  161. try {
  162. WsbAssert(0 != pStream, E_POINTER);
  163. WsbAffirmHr(CRmsDevice::Load(pStream));
  164. // Load value
  165. WsbAffirmHr(WsbLoadFromStream(pStream, &m_isAutomatic));
  166. WsbAffirmHr(WsbLoadFromStream(pStream, &m_canRotate));
  167. WsbAffirmHr(WsbBstrFromStream(pStream, &m_operation));
  168. WsbAffirmHr(WsbLoadFromStream(pStream, &m_percentComplete));
  169. if ( INVALID_HANDLE_VALUE == m_handle ) {
  170. WsbAffirmHr( AcquireDevice() );
  171. }
  172. } WsbCatch(hr);
  173. WsbTraceOut(OLESTR("CRmsMediumChanger::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  174. return(hr);
  175. }
  176. STDMETHODIMP
  177. CRmsMediumChanger::Save(
  178. IN IStream *pStream,
  179. IN BOOL clearDirty
  180. )
  181. /*++
  182. Implements:
  183. IPersistStream::Save
  184. --*/
  185. {
  186. HRESULT hr = S_OK;
  187. ULONG ulBytes = 0;
  188. WsbTraceIn(OLESTR("CRmsMediumChanger::Save"), OLESTR("clearDirty = <%ls>"), WsbBoolAsString(clearDirty));
  189. try {
  190. WsbAssert(0 != pStream, E_POINTER);
  191. WsbAffirmHr(CRmsDevice::Save(pStream, clearDirty));
  192. // Save value
  193. WsbAffirmHr(WsbSaveToStream(pStream, m_isAutomatic));
  194. WsbAffirmHr(WsbSaveToStream(pStream, m_canRotate));
  195. WsbAffirmHr(WsbBstrToStream(pStream, m_operation));
  196. WsbAffirmHr(WsbSaveToStream(pStream, m_percentComplete));
  197. // Do we need to clear the dirty bit?
  198. if (clearDirty) {
  199. m_isDirty = FALSE;
  200. }
  201. } WsbCatch(hr);
  202. WsbTraceOut(OLESTR("CRmsMediumChanger::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  203. return(hr);
  204. }
  205. STDMETHODIMP
  206. CRmsMediumChanger::Test(
  207. OUT USHORT *pPassed,
  208. OUT USHORT *pFailed
  209. )
  210. /*++
  211. Implements:
  212. IWsbTestable::Test
  213. --*/
  214. {
  215. HRESULT hr = S_OK;
  216. CComPtr<IRmsMediumChanger> pChanger1;
  217. CComPtr<IRmsMediumChanger> pChanger2;
  218. CComPtr<IPersistFile> pFile1;
  219. CComPtr<IPersistFile> pFile2;
  220. // CRmsLocator locWork1;
  221. // CRmsLocator locWork2;
  222. CWsbBstrPtr bstrVal1 = OLESTR("5A5A5A");
  223. CWsbBstrPtr bstrWork1;
  224. CWsbBstrPtr bstrWork2;
  225. WsbTraceIn(OLESTR("CRmsMediumChanger::Test"), OLESTR(""));
  226. try {
  227. // Get the Changer interface.
  228. hr = S_OK;
  229. try {
  230. WsbAssertHr(((IUnknown*) (IRmsMediumChanger*) this)->QueryInterface(IID_IRmsMediumChanger, (void**) &pChanger1));
  231. // Test SetHome & GetHome
  232. // Test SetAutomatic & IsAutomatic to TRUE
  233. hr = S_OK;
  234. try{
  235. WsbAffirmHr(SetAutomatic (TRUE));
  236. WsbAffirmHr(IsAutomatic ());
  237. } WsbCatch (hr);
  238. if (hr == S_OK){
  239. (*pPassed)++;
  240. } else {
  241. (*pFailed)++;
  242. }
  243. // Test SetAutomatic & IsAutomatic to FALSE
  244. hr = S_OK;
  245. try{
  246. WsbAffirmHr(SetAutomatic (FALSE));
  247. WsbAffirmHr(IsAutomatic ());
  248. } WsbCatch (hr);
  249. if (hr == S_OK){
  250. (*pFailed)++;
  251. } else {
  252. (*pPassed)++;
  253. }
  254. // Test SetCanRotate & IsCanRotate to TRUE
  255. hr = S_OK;
  256. try{
  257. WsbAffirmHr(SetCanRotate (TRUE));
  258. WsbAffirmHr(CanRotate ());
  259. } WsbCatch (hr);
  260. if (hr == S_OK){
  261. (*pPassed)++;
  262. } else {
  263. (*pFailed)++;
  264. }
  265. // Test SetCanRotate & IsCanRotate to FALSE
  266. hr = S_OK;
  267. try{
  268. WsbAffirmHr(SetCanRotate (FALSE));
  269. WsbAffirmHr(CanRotate ());
  270. } WsbCatch (hr);
  271. if (hr == S_OK){
  272. (*pFailed)++;
  273. } else {
  274. (*pPassed)++;
  275. }
  276. // Test SetOperation & GetOperation interface
  277. bstrWork1 = bstrVal1;
  278. SetOperation(bstrWork1);
  279. GetOperation(&bstrWork2);
  280. if (bstrWork1 == bstrWork2){
  281. (*pPassed)++;
  282. } else {
  283. (*pFailed)++;
  284. }
  285. // Test SetPercentComplete & GetPercentComplete
  286. // Test ExportCartridge & ImportCartridge
  287. // Test DismountCartridge & MountCartridge
  288. // Test TestReady
  289. // Test Home
  290. } WsbCatch(hr);
  291. // Tally up the results
  292. hr = S_OK;
  293. if (*pFailed) {
  294. hr = S_FALSE;
  295. }
  296. } WsbCatch(hr);
  297. WsbTraceOut(OLESTR("CRmsMediumChanger::Test"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  298. return(hr);
  299. }
  300. /////////////////////////////////////////////////////////////////////////////
  301. //
  302. // IRmsMediumChanger implementation
  303. //
  304. STDMETHODIMP
  305. CRmsMediumChanger::GetHome(
  306. LONG *pType,
  307. LONG *pPos,
  308. BOOL *pInvert
  309. )
  310. /*++
  311. Implements:
  312. IRmsMediumChanger::GetHome
  313. --*/
  314. {
  315. GUID zero = {0,0,0,0,0,0,0,0,0,0,0};
  316. LONG junk;
  317. return m_home.GetLocation( pType,
  318. &zero,
  319. &zero,
  320. pPos,
  321. &junk,
  322. &junk,
  323. &junk,
  324. pInvert );
  325. }
  326. STDMETHODIMP
  327. CRmsMediumChanger::SetHome(
  328. LONG type,
  329. LONG pos,
  330. BOOL invert
  331. )
  332. /*++
  333. Implements:
  334. IRmsMediumChanger::SetHome
  335. --*/
  336. {
  337. GUID zero = {0,0,0,0,0,0,0,0,0,0,0};
  338. LONG junk = 0;
  339. m_isDirty = TRUE;
  340. return m_home.SetLocation( type, zero, zero, pos, junk, junk, junk, invert );
  341. }
  342. STDMETHODIMP
  343. CRmsMediumChanger::SetAutomatic(
  344. BOOL flag
  345. )
  346. /*++
  347. Implements:
  348. IRmsMediumChanger::SetAutomatic
  349. --*/
  350. {
  351. m_isAutomatic = flag;
  352. m_isDirty = TRUE;
  353. return S_OK;
  354. }
  355. STDMETHODIMP
  356. CRmsMediumChanger::IsAutomatic(
  357. void
  358. )
  359. /*++
  360. Implements:
  361. IRmsMediumChanger::IsAutomatic
  362. --*/
  363. {
  364. HRESULT hr = S_FALSE;
  365. if (m_isAutomatic){
  366. hr = S_OK;
  367. }
  368. return (hr);
  369. }
  370. STDMETHODIMP
  371. CRmsMediumChanger::SetCanRotate(
  372. BOOL flag
  373. )
  374. /*++
  375. Implements:
  376. IRmsMediumChanger::SetCanRotate
  377. --*/
  378. {
  379. m_canRotate = flag;
  380. m_isDirty = TRUE;
  381. return S_OK;
  382. }
  383. STDMETHODIMP
  384. CRmsMediumChanger::CanRotate(
  385. void
  386. )
  387. /*++
  388. Implements:
  389. IRmsMediumChanger::CanRotate
  390. --*/
  391. {
  392. HRESULT hr = S_FALSE;
  393. if (m_canRotate){
  394. hr = S_OK;
  395. }
  396. return (hr);
  397. }
  398. STDMETHODIMP
  399. CRmsMediumChanger::GetOperation(
  400. BSTR *pOperation
  401. )
  402. /*++
  403. Implements:
  404. IRmsMediumChanger::GetOperation
  405. --*/
  406. {
  407. WsbAssertPointer ( pOperation );
  408. m_operation.CopyToBstr( pOperation );
  409. return S_OK;
  410. }
  411. STDMETHODIMP
  412. CRmsMediumChanger::SetOperation(
  413. BSTR pOperation
  414. )
  415. /*++
  416. Implements:
  417. IRmsMediumChanger::SetOperation
  418. --*/
  419. {
  420. m_operation = pOperation;
  421. m_isDirty = TRUE;
  422. return S_OK;
  423. }
  424. STDMETHODIMP
  425. CRmsMediumChanger::GetPercentComplete(
  426. BYTE *pPercent
  427. )
  428. /*++
  429. Implements:
  430. IRmsMediumChanger::GetPercentComplete
  431. --*/
  432. {
  433. *pPercent = m_percentComplete;
  434. return S_OK;
  435. }
  436. STDMETHODIMP
  437. CRmsMediumChanger::SetPercentComplete(
  438. BYTE percent
  439. )
  440. /*++
  441. Implements:
  442. IRmsMediumChanger::SetPercentComplete
  443. --*/
  444. {
  445. m_percentComplete = percent;
  446. m_isDirty = TRUE;
  447. return S_OK;
  448. }
  449. STDMETHODIMP
  450. CRmsMediumChanger::TestReady(
  451. void
  452. )
  453. /*++
  454. Implements:
  455. IRmsMediumChanger::TestReady
  456. --*/
  457. {
  458. return E_NOTIMPL;
  459. }
  460. STDMETHODIMP
  461. CRmsMediumChanger::ImportCartridge(
  462. IRmsCartridge** /*pCart*/
  463. )
  464. /*++
  465. Implements:
  466. IRmsMediumChanger::ImportCartridge
  467. --*/
  468. {
  469. return E_NOTIMPL;
  470. }
  471. STDMETHODIMP
  472. CRmsMediumChanger::ExportCartridge(
  473. IRmsCartridge** /*pCart*/
  474. )
  475. /*++
  476. Implements:
  477. IRmsMediumChanger::ExportCartridge
  478. --*/
  479. {
  480. return E_NOTIMPL;
  481. }
  482. STDMETHODIMP
  483. CRmsMediumChanger::MoveCartridge(
  484. IN IRmsCartridge *pSrcCart,
  485. IN IUnknown *pDestElmt
  486. )
  487. /*++
  488. Implements:
  489. IRmsMediumChanger::MountCartridge
  490. --*/
  491. {
  492. HRESULT hr = E_FAIL;
  493. try {
  494. CComPtr<IRmsCartridge> pCart2;
  495. CComPtr<IRmsDrive> pDrive2;
  496. GUID libId=GUID_NULL, mediaSetId=GUID_NULL;
  497. LONG type=0, pos=0, alt1=0, alt2=0, alt3=0;
  498. BOOL invert=0;
  499. GUID destLibId=GUID_NULL, destMediaSetId=GUID_NULL;
  500. LONG destType=0, destPos=0, destAlt1=0, destAlt2=0, destAlt3=0;
  501. BOOL destInvert=0;
  502. GUID dest2LibId=GUID_NULL, dest2MediaSetId=GUID_NULL;
  503. LONG dest2Type=0, dest2Pos=0, dest2Alt1=0, dest2Alt2=0, dest2Alt3=0;
  504. BOOL dest2Invert=0;
  505. CHANGER_ELEMENT src, dest, dest2;
  506. CComQIPtr<IRmsChangerElement, &IID_IRmsChangerElement> pElmt = pDestElmt;
  507. WsbAssertPointer( pElmt );
  508. // TODO: assert cartridge has same libId as changer
  509. // Set up for SOURCE
  510. WsbAffirmHr( pSrcCart->GetLocation( &type, &libId, &mediaSetId,
  511. &pos, &alt1, &alt2, &alt3, &invert ));
  512. src.ElementAddress = pos;
  513. // Translate the RmsElement type to something the drive understands.
  514. // TODO: make this a local method
  515. switch ( (RmsElement) type ) {
  516. case RmsElementUnknown:
  517. WsbAssertHr( E_UNEXPECTED );
  518. break;
  519. case RmsElementStage:
  520. case RmsElementStorage:
  521. src.ElementType = ChangerSlot;
  522. break;
  523. case RmsElementShelf:
  524. case RmsElementOffSite:
  525. // not supported here!
  526. WsbAssertHr( E_UNEXPECTED );
  527. break;
  528. case RmsElementDrive:
  529. src.ElementType = ChangerDrive;
  530. break;
  531. case RmsElementChanger:
  532. src.ElementType = ChangerTransport;
  533. break;
  534. case RmsElementIEPort:
  535. src.ElementType = ChangerIEPort;
  536. break;
  537. default:
  538. WsbAssertHr( E_UNEXPECTED );
  539. break;
  540. }
  541. //
  542. // Set up for DESTINATION
  543. //
  544. WsbAffirmHr( pElmt->GetLocation( &destType, &destLibId, &destMediaSetId,
  545. &destPos, &destAlt1, &destAlt2, &destAlt3, &destInvert ));
  546. dest.ElementAddress = destPos;
  547. // Translate the Rms type to something the drive understands.
  548. switch ( (RmsElement) destType) {
  549. case RmsElementUnknown:
  550. WsbAssertHr( E_UNEXPECTED );
  551. break;
  552. case RmsElementStage:
  553. case RmsElementStorage:
  554. dest.ElementType = ChangerSlot;
  555. break;
  556. case RmsElementShelf:
  557. case RmsElementOffSite:
  558. // not supported here!
  559. WsbAssertHr( E_UNEXPECTED );
  560. break;
  561. case RmsElementDrive:
  562. dest.ElementType = ChangerDrive;
  563. break;
  564. case RmsElementChanger:
  565. dest.ElementType = ChangerTransport;
  566. break;
  567. case RmsElementIEPort:
  568. dest.ElementType = ChangerIEPort;
  569. break;
  570. default:
  571. WsbAssertHr( E_UNEXPECTED );
  572. break;
  573. }
  574. //
  575. // Do we need to do an exchange or a simple move?
  576. //
  577. BOOL destFull;
  578. hr = pElmt->IsOccupied();
  579. destFull = ( S_OK == hr ) ? TRUE : FALSE;
  580. if ( destFull ) {
  581. //
  582. // Set up for second destination
  583. //
  584. pElmt->GetCartridge( &pCart2 );
  585. pCart2->GetDrive( &pDrive2 );
  586. if ( pDrive2 && ( m_parameters.Features0 & CHANGER_PREDISMOUNT_EJECT_REQUIRED ) ) {
  587. pDrive2->Eject();
  588. }
  589. WsbAffirmHr( pCart2->GetHome( &dest2Type, &dest2LibId, &dest2MediaSetId,
  590. &dest2Pos, &dest2Alt1, &dest2Alt2, &dest2Alt3, &dest2Invert ));
  591. dest2.ElementAddress = dest2Pos;
  592. // Translate the Rms type to something the drive understands.
  593. switch ( (RmsElement) dest2Type) {
  594. case RmsElementUnknown:
  595. WsbAssertHr( E_UNEXPECTED );
  596. break;
  597. case RmsElementStage:
  598. case RmsElementStorage:
  599. dest2.ElementType = ChangerSlot;
  600. break;
  601. case RmsElementShelf:
  602. case RmsElementOffSite:
  603. // not supported here!
  604. WsbAssertHr( E_UNEXPECTED );
  605. break;
  606. case RmsElementDrive:
  607. WsbAssertHr( E_UNEXPECTED );
  608. break;
  609. case RmsElementChanger:
  610. WsbAssertHr( E_UNEXPECTED );
  611. break;
  612. case RmsElementIEPort:
  613. dest2.ElementType = ChangerIEPort;
  614. break;
  615. default:
  616. WsbAssertHr( E_UNEXPECTED );
  617. break;
  618. }
  619. WsbAffirmHr( ExchangeMedium( src, dest, dest2, FALSE, FALSE ));
  620. // Update the Cartridge's Locator
  621. WsbAffirmHr( pSrcCart->SetLocation( destType, libId, mediaSetId,
  622. destPos, alt1, alt2, alt3, invert ));
  623. WsbAffirmHr( pCart2->SetLocation( dest2Type, dest2LibId, dest2MediaSetId,
  624. dest2Pos, dest2Alt1, dest2Alt2, dest2Alt3, dest2Invert ));
  625. }
  626. else {
  627. // Call through to the medium changer driver to move the cartridge
  628. // TODO: handle two sided media.
  629. WsbAffirmHr( MoveMedium( src, dest, FALSE ));
  630. // Update the Cartridge's Locator
  631. WsbAffirmHr( pSrcCart->SetLocation( destType, libId, mediaSetId,
  632. destPos, alt1, alt2, alt3, invert ));
  633. }
  634. hr = S_OK;
  635. }
  636. WsbCatch(hr);
  637. return hr;
  638. }
  639. STDMETHODIMP
  640. CRmsMediumChanger::HomeCartridge(
  641. IN IRmsCartridge *pCart
  642. )
  643. /*++
  644. Implements:
  645. IRmsMediumChanger::HomeCartridge
  646. --*/
  647. {
  648. HRESULT hr = E_FAIL;
  649. try {
  650. WsbAssertPointer( pCart );
  651. GUID libId=GUID_NULL, mediaSetId=GUID_NULL;
  652. LONG type=0, pos=0, alt1=0, alt2=0, alt3=0;
  653. BOOL invert=0;
  654. GUID destLibId=GUID_NULL, destMediaSetId=GUID_NULL;
  655. LONG destType=0, destPos=0, destAlt1=0, destAlt2=0, destAlt3=0;
  656. BOOL destInvert=0;
  657. CHANGER_ELEMENT src, dest;
  658. // TODO: assert cartridge has same libId as changer
  659. // Set up for SOURCE
  660. WsbAffirmHr( pCart->GetLocation( &type, &libId, &mediaSetId,
  661. &pos, &alt1, &alt2, &alt3, &invert ));
  662. src.ElementAddress = pos;
  663. // Translate the RmsElement type to something the drive understands.
  664. // TODO: make this a local method
  665. switch ( (RmsElement) type ) {
  666. case RmsElementUnknown:
  667. WsbAssertHr( E_UNEXPECTED );
  668. break;
  669. case RmsElementStage:
  670. case RmsElementStorage:
  671. src.ElementType = ChangerSlot;
  672. break;
  673. case RmsElementShelf:
  674. case RmsElementOffSite:
  675. // not supported here!
  676. WsbAssertHr( E_UNEXPECTED );
  677. break;
  678. case RmsElementDrive:
  679. src.ElementType = ChangerDrive;
  680. break;
  681. case RmsElementChanger:
  682. src.ElementType = ChangerTransport;
  683. break;
  684. case RmsElementIEPort:
  685. src.ElementType = ChangerIEPort;
  686. break;
  687. default:
  688. WsbAssertHr( E_UNEXPECTED );
  689. break;
  690. }
  691. //
  692. // Set up for DESTINATION
  693. //
  694. WsbAffirmHr( pCart->GetHome( &destType, &destLibId, &destMediaSetId,
  695. &destPos, &destAlt1, &destAlt2, &destAlt3, &destInvert ));
  696. dest.ElementAddress = destPos;
  697. // Translate the Rms type to something the drive understands.
  698. switch ( (RmsElement) destType) {
  699. case RmsElementUnknown:
  700. WsbAssertHr( E_UNEXPECTED );
  701. break;
  702. case RmsElementStage:
  703. case RmsElementStorage:
  704. dest.ElementType = ChangerSlot;
  705. break;
  706. case RmsElementShelf:
  707. case RmsElementOffSite:
  708. // not supported here!
  709. WsbAssertHr( E_UNEXPECTED );
  710. break;
  711. case RmsElementDrive:
  712. dest.ElementType = ChangerDrive;
  713. break;
  714. case RmsElementChanger:
  715. dest.ElementType = ChangerTransport;
  716. break;
  717. case RmsElementIEPort:
  718. dest.ElementType = ChangerIEPort;
  719. break;
  720. default:
  721. WsbAssertHr( E_UNEXPECTED );
  722. break;
  723. }
  724. WsbAffirmHr( MoveMedium( src, dest, FALSE ));
  725. // Update the Cartridge's Locator
  726. WsbAffirmHr( pCart->SetLocation( destType, libId, mediaSetId,
  727. destPos, alt1, alt2, alt3, invert ));
  728. hr = S_OK;
  729. }
  730. WsbCatch(hr);
  731. return hr;
  732. }
  733. STDMETHODIMP
  734. CRmsMediumChanger::Initialize(
  735. void
  736. )
  737. /*++
  738. Implements:
  739. IRmsMediumChanger::Initialize
  740. --*/
  741. {
  742. // TODO: Break this into some smaller methods for initializing slot, drives, ports, etc.
  743. HRESULT hr = E_FAIL;
  744. PREAD_ELEMENT_ADDRESS_INFO pElementInformation = 0;
  745. try {
  746. DWORD size;
  747. WsbAffirmHr(AcquireDevice());
  748. WsbAffirmHr(Status());
  749. size = sizeof( CHANGER_PRODUCT_DATA );
  750. CHANGER_PRODUCT_DATA productData;
  751. WsbAffirmHr(GetProductData( &size, &productData ));
  752. // Get device specific parameters.
  753. size = sizeof( GET_CHANGER_PARAMETERS );
  754. WsbAffirmHr(GetParameters(&size, &m_parameters));
  755. // save some of the more common parameters
  756. m_isAutomatic = TRUE;
  757. if ( m_parameters.Features0 & CHANGER_MEDIUM_FLIP ) m_canRotate = TRUE;
  758. // Initialize the changer elements
  759. BOOL scan = TRUE;
  760. CHANGER_ELEMENT_LIST list;
  761. if ( m_parameters.Features0 & CHANGER_BAR_CODE_SCANNER_INSTALLED ) scan = TRUE;
  762. list.NumberOfElements = 1;
  763. list.Element.ElementType = AllElements;
  764. list.Element.ElementAddress = 0;
  765. WsbAffirmHr( InitializeElementStatus( list, scan ) );
  766. list.NumberOfElements = m_parameters.NumberStorageElements;
  767. list.Element.ElementType = ChangerSlot;
  768. list.Element.ElementAddress = 0;
  769. BOOL tag = ( m_parameters.Features0 & CHANGER_VOLUME_IDENTIFICATION ) ? TRUE : FALSE;
  770. size = sizeof(READ_ELEMENT_ADDRESS_INFO) + (list.NumberOfElements - 1) * sizeof(CHANGER_ELEMENT_STATUS);
  771. pElementInformation = (PREAD_ELEMENT_ADDRESS_INFO)WsbAlloc( size );
  772. WsbAffirmPointer(pElementInformation);
  773. memset(pElementInformation, 0, size);
  774. WsbAffirmHr( GetElementStatus( list, tag, &size, pElementInformation ));
  775. // Create storage slot objects for this changer, if required.
  776. LONG type;
  777. GUID libId, mediaSetId;
  778. LONG pos, alt1, alt2, alt3;
  779. BOOL invert;
  780. m_location.GetLocation( &type, &libId, &mediaSetId, &pos, &alt1, &alt2, &alt3, &invert );
  781. CComQIPtr<IRmsServer, &IID_IRmsServer> pServer = g_pServer;
  782. CComPtr<IWsbIndexedCollection> pCarts;
  783. CComPtr<IWsbIndexedCollection> pSlots;
  784. CComPtr<IRmsLibrary> pLib;
  785. CComPtr<IRmsStorageSlot> pSlot;
  786. WsbAffirmHr( pServer->FindLibraryById( libId, &pLib ));
  787. WsbAffirmHr( pLib->GetStorageSlots( &pSlots ));
  788. WsbAffirmHr( pServer->GetCartridges( &pCarts ));
  789. ULONG count = 0;
  790. WsbAffirmHr( pSlots->GetEntries( &count ));
  791. while ( count < pElementInformation->NumberOfElements ) {
  792. // Add more slots objects to the library
  793. WsbAffirmHr( hr = CoCreateInstance( CLSID_CRmsStorageSlot, 0, CLSCTX_SERVER,
  794. IID_IRmsStorageSlot, (void **)&pSlot ));
  795. WsbAffirmHr( pSlots->Add( pSlot ));
  796. pSlot = 0;
  797. count++;
  798. }
  799. // Populate the storage slot objects with information reported by the device
  800. // TODO: We need to add lots more asserts of various conditions where the
  801. // previous slot information is not consistant with what has been detected.
  802. PCHANGER_ELEMENT_STATUS pElementStatus;
  803. CComPtr<IWsbEnum> pEnumSlots;
  804. WsbAffirmHr( pSlots->Enum( &pEnumSlots ));
  805. WsbAssertPointer( pEnumSlots );
  806. hr = pEnumSlots->First( IID_IRmsStorageSlot, (void **)&pSlot );
  807. for ( ULONG i = 0; i < pElementInformation->NumberOfElements; i++ ) {
  808. pElementStatus = &pElementInformation->ElementStatus[i];
  809. WsbAssert( ChangerSlot == pElementStatus->Element.ElementType, E_UNEXPECTED );
  810. WsbAssert( i == pElementStatus->Element.ElementAddress, E_UNEXPECTED );
  811. CComQIPtr<IRmsChangerElement, &IID_IRmsChangerElement> pSlotElmt = pSlot;
  812. // Is the unit of media inverted?
  813. invert = ( ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_SVALID ) &&
  814. ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_INVERT ) ) ? TRUE : FALSE;
  815. WsbAffirmHr( pSlotElmt->SetLocation( RmsElementStorage, libId, GUID_NULL, i, 0, 0, 0, invert ));
  816. // Is the slot Full or Empty?
  817. BOOL occupied = ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_FULL ) ? TRUE : FALSE;
  818. WsbAffirmHr( pSlotElmt->SetIsOccupied( occupied ));
  819. // Set the media type supported
  820. WsbAffirmHr( pSlotElmt->SetMediaSupported( m_mediaSupported ));
  821. // Set the storage flag
  822. WsbAffirmHr( pSlotElmt->SetIsStorage( TRUE ));
  823. // If there is a cartridge present fill in cartridge information
  824. if ( occupied ) {
  825. CComPtr<IRmsCartridge> pCart;
  826. WsbAffirmHr( hr = CoCreateInstance( CLSID_CRmsCartridge, 0, CLSCTX_SERVER,
  827. IID_IRmsCartridge, (void **)&pCart ));
  828. WsbAffirmHr( pCart->SetLocation( RmsElementStorage, libId, GUID_NULL, i, 0, 0, 0, invert ));
  829. WsbAffirmHr( pCart->SetLocation( RmsElementStorage, libId, GUID_NULL, i, 0, 0, 0, invert ));
  830. WsbAffirmHr( pCart->SetHome( RmsElementStorage, libId, GUID_NULL, i, 0, 0, 0, invert ));
  831. WsbAffirmHr( pCart->SetStatus( RmsStatusScratch ));
  832. WsbAffirmHr( pCart->SetType( m_mediaSupported ));
  833. WsbAffirmHr( pSlotElmt->SetCartridge( pCart ));
  834. // Add cartridge to drive
  835. WsbAffirmHr( pCarts->Add( pCart ));
  836. if ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_PVOLTAG ) {
  837. pElementStatus->PrimaryVolumeID[32] = '\0'; // This nulls the reserved byte
  838. pElementStatus->PrimaryVolumeID[33] = '\0'; // This nulls the reserved byte
  839. CWsbBstrPtr label( (char *)pElementStatus->PrimaryVolumeID );
  840. // Fill in external label information
  841. WsbAffirmHr( pCart->SetTagAndNumber( label, 0 ));
  842. }
  843. }
  844. // Get the next slot
  845. hr = pEnumSlots->Next( IID_IRmsStorageSlot, (void **)&pSlot );
  846. }
  847. // Now process drives.
  848. // Read element status
  849. list.NumberOfElements = m_parameters.NumberDataTransferElements;
  850. list.Element.ElementType = ChangerDrive;
  851. list.Element.ElementAddress = 0;
  852. if ( m_parameters.Features0 & CHANGER_VOLUME_IDENTIFICATION ) tag = TRUE;
  853. size = sizeof(READ_ELEMENT_ADDRESS_INFO) + (list.NumberOfElements - 1) * sizeof(CHANGER_ELEMENT_STATUS);
  854. WsbFree( pElementInformation );
  855. pElementInformation = (PREAD_ELEMENT_ADDRESS_INFO)WsbAlloc( size );
  856. WsbAffirmPointer(pElementInformation);
  857. memset(pElementInformation, 0, size);
  858. WsbAffirmHr( GetElementStatus( list, tag, &size, pElementInformation ));
  859. CComPtr<IWsbIndexedCollection> pDevices;
  860. CComPtr<IWsbIndexedCollection> pDrives;
  861. CComPtr<IRmsDrive> pDrive;
  862. CComPtr<IRmsDrive> pFindDrive;
  863. CComPtr<IRmsDevice> pFindDevice;
  864. WsbAffirmHr( pServer->GetUnconfiguredDevices( &pDevices ));
  865. WsbAffirmHr( pLib->GetDrives( &pDrives ));
  866. // For each drive in the element status page, find the drive in the
  867. // unconfigured list of devices.
  868. for ( i = 0; i < pElementInformation->NumberOfElements; i++ ) {
  869. pElementStatus = &pElementInformation->ElementStatus[i];
  870. WsbAssert( ChangerDrive == pElementStatus->Element.ElementType, E_UNEXPECTED );
  871. WsbAssert( i == pElementStatus->Element.ElementAddress, E_UNEXPECTED );
  872. // set up a find template
  873. WsbAffirmHr( CoCreateInstance( CLSID_CRmsDrive, 0, CLSCTX_SERVER,
  874. IID_IRmsDrive, (void **)&pFindDrive ));
  875. CComQIPtr<IRmsDevice, &IID_IRmsDevice> pFindDevice = pFindDrive;
  876. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pFindObject = pFindDrive;
  877. BYTE port=0xff, bus=0xff, id=0xff, lun=0xff;
  878. if ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_LUN_VALID )
  879. lun = pElementStatus->Lun;
  880. if ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_ID_VALID )
  881. id = pElementStatus->TargetId;
  882. if ( !(pElementStatus->Flags & (ULONG)ELEMENT_STATUS_NOT_BUS) ) {
  883. bus = m_bus;
  884. port = m_port;
  885. }
  886. WsbAffirmHr( pFindDevice->SetDeviceAddress( port, bus, id, lun ));
  887. WsbAffirmHr( pFindObject->SetFindBy( RmsFindByDeviceAddress ));
  888. // Find the drive
  889. hr = pDevices->Find( pFindDrive, IID_IRmsDrive, (void **)&pDrive );
  890. if ( S_OK == hr ) {
  891. // Add the drive to the library
  892. WsbAffirmHr( pDrives->Add( pDrive ));
  893. // Remove the drive form the unconfigured list
  894. WsbAffirmHr( pDevices->RemoveAndRelease( pDrive ));
  895. // Fill in more drive information
  896. CComQIPtr<IRmsChangerElement, &IID_IRmsChangerElement> pDriveElmt = pDrive;
  897. // Is the unit of media inverted?
  898. invert = ( ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_SVALID ) &&
  899. ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_INVERT ) ) ? TRUE : FALSE;
  900. WsbAffirmHr( pDriveElmt->SetLocation( RmsElementDrive, libId, GUID_NULL, i, 0, 0, 0, invert ));
  901. // Is the slot Full or Empty?
  902. BOOL occupied = ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_FULL ) ? TRUE : FALSE;
  903. WsbAffirmHr( pDriveElmt->SetIsOccupied( occupied ));
  904. // Set the media type supported
  905. WsbAffirmHr( pDriveElmt->SetMediaSupported( m_mediaSupported ));
  906. // Set the storage flag
  907. WsbAffirmHr( pDriveElmt->SetIsStorage( TRUE ));
  908. // If there is a cartridge present fill in cartridge information
  909. if ( occupied ) {
  910. CComPtr<IRmsCartridge> pCart;
  911. WsbAffirmHr( hr = CoCreateInstance( CLSID_CRmsCartridge, 0, CLSCTX_SERVER,
  912. IID_IRmsCartridge, (void **)&pCart ));
  913. WsbAffirmHr( pCart->SetLocation( RmsElementStorage, libId, GUID_NULL, i, 0, 0, 0, invert ));
  914. if ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_SVALID ) {
  915. try {
  916. ULONG pos;
  917. // pos = pElementStatus->SourceElementAddress[1];
  918. // pos |= (pElementStatus->SourceElementAddress[0] << 8);
  919. pos = pElementStatus->SrcElementAddress.ElementAddress;
  920. //
  921. // TODO: FIX THIS - This code incorrectly assumes source is a slot!!!
  922. //
  923. // I'll work on trying to get chuck to return element type and position
  924. // in element status page.
  925. //
  926. WsbAffirm( pos >= m_parameters.FirstSlotNumber, E_UNEXPECTED );
  927. pos = pos - m_parameters.FirstSlotNumber;
  928. BOOL invert = ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_INVERT ) ? TRUE : FALSE;
  929. WsbAffirmHr( pCart->SetHome( RmsElementStorage, libId, GUID_NULL, pos, 0, 0, 0, invert ));
  930. }
  931. WsbCatch(hr);
  932. }
  933. // TODO: if not ELEMENT_STATUS_SVALID we should set the home location to
  934. // some empty slot. This handles the case where we we come up with
  935. // unknown media in a drive.
  936. WsbAffirmHr( pCart->SetStatus( RmsStatusScratch ));
  937. WsbAffirmHr( pCart->SetType( m_mediaSupported ));
  938. WsbAffirmHr( pCart->SetDrive( pDrive ));
  939. // Add cartridge to drive
  940. WsbAffirmHr( pCarts->Add( pCart ));
  941. if ( pElementStatus->Flags & (ULONG)ELEMENT_STATUS_PVOLTAG ) {
  942. pElementStatus->PrimaryVolumeID[32] = '\0'; // This nulls the reserved byte
  943. pElementStatus->PrimaryVolumeID[33] = '\0'; // This nulls the reserved byte
  944. CWsbBstrPtr label( (char *)pElementStatus->PrimaryVolumeID );
  945. // Fill in external label information
  946. WsbAffirmHr( pCart->SetTagAndNumber( label, 0 ));
  947. }
  948. }
  949. }
  950. }
  951. // All done
  952. hr = S_OK;
  953. }
  954. WsbCatch(hr);
  955. if ( pElementInformation ) {
  956. WsbFree( pElementInformation );
  957. }
  958. return hr;
  959. }
  960. STDMETHODIMP
  961. CRmsMediumChanger::AcquireDevice(
  962. void
  963. )
  964. /*++
  965. Implements:
  966. IRmsMediumChanger::AcquireDevice
  967. --*/
  968. {
  969. HRESULT hr = E_FAIL;
  970. HANDLE hChanger = INVALID_HANDLE_VALUE;
  971. CWsbBstrPtr name;
  972. try {
  973. // Get the device name for this changer
  974. GetDeviceName( &name );
  975. // Create a handle
  976. hChanger = CreateFile( name,
  977. GENERIC_READ | GENERIC_WRITE,
  978. 0,
  979. 0,
  980. OPEN_EXISTING,
  981. 0,
  982. NULL
  983. );
  984. WsbAffirmHandle( hChanger );
  985. // Save the handle
  986. m_handle = hChanger;
  987. // Do any other initialization here
  988. hr = S_OK;
  989. }
  990. WsbCatchAndDo( hr,
  991. WsbTrace( OLESTR("\n\n !!!!! ERROR !!!!! Acquire() failed. name=<%ls>\n\n"), name );
  992. if ( hChanger != INVALID_HANDLE_VALUE ) {
  993. CloseHandle( hChanger );
  994. } );
  995. return hr;
  996. }
  997. STDMETHODIMP
  998. CRmsMediumChanger::ReleaseDevice(
  999. void
  1000. )
  1001. /*++
  1002. Implements:
  1003. IRmsMediumChanger::ReleaseDevice
  1004. --*/
  1005. {
  1006. HRESULT hr = E_FAIL;
  1007. try {
  1008. if ( INVALID_HANDLE_VALUE != m_handle ) {
  1009. WsbAffirmStatus( CloseHandle( m_handle ));
  1010. m_handle = INVALID_HANDLE_VALUE;
  1011. }
  1012. hr = S_OK;
  1013. }
  1014. WsbCatch( hr );
  1015. return hr;
  1016. }
  1017. ////////////////////////////////////////////////////////////////////////////////
  1018. //
  1019. // IRmsMoveMedia Interface
  1020. //
  1021. STDMETHODIMP
  1022. CRmsMediumChanger::GetParameters(
  1023. IN OUT PDWORD pSize,
  1024. OUT PGET_CHANGER_PARAMETERS pParms
  1025. )
  1026. /*++
  1027. Implements:
  1028. IRmsMoveMedia::GetParameters
  1029. --*/
  1030. {
  1031. HRESULT hr = E_FAIL;
  1032. try
  1033. {
  1034. DWORD dwReturn;
  1035. WsbAssertPointer( pSize );
  1036. WsbAssertPointer( pParms );
  1037. WsbAssertHandle( m_handle );
  1038. pParms->Size = sizeof(GET_CHANGER_PARAMETERS);
  1039. WsbAssertStatus( DeviceIoControl( m_handle,
  1040. IOCTL_CHANGER_GET_PARAMETERS,
  1041. pParms,
  1042. sizeof(GET_CHANGER_PARAMETERS),
  1043. pParms,
  1044. sizeof(GET_CHANGER_PARAMETERS),
  1045. &dwReturn,
  1046. NULL ));
  1047. hr = S_OK;
  1048. }
  1049. WsbCatch( hr );
  1050. return hr;
  1051. }
  1052. STDMETHODIMP
  1053. CRmsMediumChanger::GetProductData(
  1054. IN OUT PDWORD pSize,
  1055. OUT PCHANGER_PRODUCT_DATA pData
  1056. )
  1057. /*++
  1058. Implements:
  1059. IRmsMoveMedia::GetProductData
  1060. --*/
  1061. {
  1062. HRESULT hr = E_FAIL;
  1063. try
  1064. {
  1065. DWORD dwReturn;
  1066. WsbAssertPointer( pSize );
  1067. WsbAssertPointer( pData );
  1068. WsbAssertHandle( m_handle );
  1069. WsbAssertStatus( DeviceIoControl( m_handle,
  1070. IOCTL_CHANGER_GET_PRODUCT_DATA,
  1071. NULL,
  1072. 0,
  1073. pData,
  1074. sizeof(CHANGER_PRODUCT_DATA),
  1075. &dwReturn,
  1076. NULL ));
  1077. hr = S_OK;
  1078. }
  1079. WsbCatch( hr );
  1080. return hr;
  1081. }
  1082. STDMETHODIMP
  1083. CRmsMediumChanger::Status(
  1084. void
  1085. )
  1086. /*++
  1087. Implements:
  1088. IRmsMoveMedia::Status
  1089. --*/
  1090. {
  1091. HRESULT hr = E_FAIL;
  1092. try
  1093. {
  1094. DWORD dwReturn;
  1095. WsbAssertStatus( DeviceIoControl( m_handle,
  1096. IOCTL_CHANGER_GET_STATUS,
  1097. NULL,
  1098. 0,
  1099. NULL,
  1100. 0,
  1101. &dwReturn,
  1102. NULL) );
  1103. hr = S_OK;
  1104. }
  1105. WsbCatch( hr );
  1106. return hr;
  1107. }
  1108. STDMETHODIMP
  1109. CRmsMediumChanger::SetAccess(
  1110. IN CHANGER_ELEMENT element,
  1111. IN DWORD control
  1112. )
  1113. /*++
  1114. Implements:
  1115. IRmsMoveMedia::SetAccess
  1116. --*/
  1117. {
  1118. HRESULT hr = E_FAIL;
  1119. try
  1120. {
  1121. DWORD dwReturn;
  1122. CHANGER_SET_ACCESS setAccess;
  1123. setAccess.Element = element;
  1124. setAccess.Control = control;
  1125. WsbAssertStatus( DeviceIoControl( m_handle,
  1126. IOCTL_CHANGER_SET_ACCESS,
  1127. &setAccess,
  1128. sizeof(CHANGER_SET_ACCESS),
  1129. NULL,
  1130. 0,
  1131. &dwReturn,
  1132. NULL ));
  1133. hr = S_OK;
  1134. }
  1135. WsbCatch( hr );
  1136. return hr;
  1137. }
  1138. STDMETHODIMP
  1139. CRmsMediumChanger::GetElementStatus(
  1140. IN CHANGER_ELEMENT_LIST elementList,
  1141. IN BOOL volumeTagInfo,
  1142. IN OUT PDWORD pSize,
  1143. OUT PREAD_ELEMENT_ADDRESS_INFO pElementInformation
  1144. )
  1145. /*++
  1146. Implements:
  1147. IRmsMoveMedia::GetElementStatus
  1148. --*/
  1149. {
  1150. HRESULT hr = E_FAIL;
  1151. try
  1152. {
  1153. DWORD dwReturn;
  1154. DWORD requiredSize;
  1155. CHANGER_READ_ELEMENT_STATUS readElementStatus;
  1156. PCHANGER_ELEMENT_STATUS pElementStatus = pElementInformation->ElementStatus;
  1157. WsbAssertPointer( pSize );
  1158. WsbAssertPointer( pElementInformation );
  1159. requiredSize = elementList.NumberOfElements * sizeof( CHANGER_ELEMENT_STATUS );
  1160. WsbAssert( *pSize >= requiredSize, E_INVALIDARG );
  1161. readElementStatus.ElementList = elementList;
  1162. readElementStatus.VolumeTagInfo = (BOOLEAN)( volumeTagInfo ? TRUE : FALSE );
  1163. WsbAssertStatus( DeviceIoControl( m_handle,
  1164. IOCTL_CHANGER_GET_ELEMENT_STATUS,
  1165. &readElementStatus,
  1166. sizeof(CHANGER_READ_ELEMENT_STATUS),
  1167. pElementStatus,
  1168. requiredSize,
  1169. &dwReturn,
  1170. NULL ));
  1171. pElementInformation->NumberOfElements = dwReturn / sizeof( CHANGER_ELEMENT_STATUS );
  1172. hr = S_OK;
  1173. }
  1174. WsbCatch( hr );
  1175. return hr;
  1176. }
  1177. STDMETHODIMP
  1178. CRmsMediumChanger::InitializeElementStatus(
  1179. IN CHANGER_ELEMENT_LIST elementList,
  1180. IN BOOL barCodeScan
  1181. )
  1182. /*++
  1183. Implements:
  1184. IRmsMoveMedia::InitializeElementStatus
  1185. --*/
  1186. {
  1187. HRESULT hr = E_FAIL;
  1188. try
  1189. {
  1190. DWORD dwReturn;
  1191. CHANGER_INITIALIZE_ELEMENT_STATUS initElementStatus;
  1192. initElementStatus.ElementList = elementList;
  1193. initElementStatus.BarCodeScan = (BOOLEAN)( barCodeScan ? TRUE : FALSE );
  1194. WsbAssertStatus( DeviceIoControl( m_handle,
  1195. IOCTL_CHANGER_INITIALIZE_ELEMENT_STATUS,
  1196. &initElementStatus,
  1197. sizeof(CHANGER_INITIALIZE_ELEMENT_STATUS),
  1198. NULL,
  1199. 0,
  1200. &dwReturn,
  1201. NULL) );
  1202. hr = S_OK;
  1203. }
  1204. WsbCatch( hr );
  1205. return hr;
  1206. }
  1207. STDMETHODIMP
  1208. CRmsMediumChanger::ExchangeMedium(
  1209. IN CHANGER_ELEMENT source,
  1210. IN CHANGER_ELEMENT destination1,
  1211. IN CHANGER_ELEMENT destination2,
  1212. IN BOOL flip1,
  1213. IN BOOL flip2
  1214. )
  1215. /*++
  1216. Implements:
  1217. IRmsMoveMedia::ExchangeMedium
  1218. --*/
  1219. {
  1220. HRESULT hr = E_FAIL;
  1221. try
  1222. {
  1223. DWORD dwReturn;
  1224. CHANGER_EXCHANGE_MEDIUM exchangeMedium;
  1225. exchangeMedium.Transport.ElementType = ChangerTransport;
  1226. exchangeMedium.Transport.ElementAddress = 0; // default arm or thumb
  1227. exchangeMedium.Source = source;
  1228. exchangeMedium.Destination1 = destination1;
  1229. exchangeMedium.Destination2 = destination2;
  1230. exchangeMedium.Flip1 = (BOOLEAN)( flip1 ? TRUE : FALSE );
  1231. exchangeMedium.Flip2 = (BOOLEAN)( flip2 ? TRUE : FALSE );
  1232. WsbAssertStatus( DeviceIoControl( m_handle,
  1233. IOCTL_CHANGER_EXCHANGE_MEDIUM,
  1234. &exchangeMedium,
  1235. sizeof(CHANGER_EXCHANGE_MEDIUM),
  1236. NULL,
  1237. 0,
  1238. &dwReturn,
  1239. NULL ));
  1240. hr = S_OK;
  1241. }
  1242. WsbCatch( hr );
  1243. return hr;
  1244. }
  1245. STDMETHODIMP
  1246. CRmsMediumChanger::MoveMedium(
  1247. IN CHANGER_ELEMENT source,
  1248. IN CHANGER_ELEMENT destination,
  1249. IN BOOL flip
  1250. )
  1251. /*++
  1252. Implements:
  1253. IRmsMoveMedia::MoveMedium
  1254. --*/
  1255. {
  1256. HRESULT hr = E_FAIL;
  1257. try
  1258. {
  1259. DWORD dwReturn;
  1260. CHANGER_MOVE_MEDIUM moveMedium;
  1261. moveMedium.Transport.ElementType = ChangerTransport;
  1262. moveMedium.Transport.ElementAddress = 0; // default arm or thumb
  1263. moveMedium.Source = source;
  1264. moveMedium.Destination = destination;
  1265. moveMedium.Flip = (BOOLEAN)( flip ? TRUE : FALSE );
  1266. WsbAssertStatus( DeviceIoControl( m_handle,
  1267. IOCTL_CHANGER_MOVE_MEDIUM,
  1268. &moveMedium,
  1269. sizeof(CHANGER_MOVE_MEDIUM),
  1270. NULL,
  1271. 0,
  1272. &dwReturn,
  1273. NULL ));
  1274. hr = S_OK;
  1275. }
  1276. WsbCatch( hr );
  1277. return hr;
  1278. }
  1279. STDMETHODIMP
  1280. CRmsMediumChanger::Position(
  1281. IN CHANGER_ELEMENT destination,
  1282. IN BOOL flip
  1283. )
  1284. /*++
  1285. Implements:
  1286. IRmsMoveMedia::Position
  1287. --*/
  1288. {
  1289. HRESULT hr = E_FAIL;
  1290. try
  1291. {
  1292. DWORD dwReturn;
  1293. CHANGER_SET_POSITION positon;
  1294. positon.Transport.ElementType = ChangerTransport;
  1295. positon.Transport.ElementAddress = 0; // default arm or thumb
  1296. positon.Destination = destination;
  1297. positon.Flip = (BOOLEAN)( flip ? TRUE : FALSE );
  1298. WsbAssertStatus( DeviceIoControl( m_handle,
  1299. IOCTL_CHANGER_SET_POSITION,
  1300. &positon,
  1301. sizeof(CHANGER_SET_POSITION),
  1302. NULL,
  1303. 0,
  1304. &dwReturn,
  1305. NULL ));
  1306. hr = S_OK;
  1307. }
  1308. WsbCatch( hr );
  1309. return hr;
  1310. }
  1311. STDMETHODIMP
  1312. CRmsMediumChanger::RezeroUnit(
  1313. void
  1314. )
  1315. /*++
  1316. Implements:
  1317. IRmsMoveMedia::RezeroUnit
  1318. --*/
  1319. {
  1320. HRESULT hr = E_FAIL;
  1321. try
  1322. {
  1323. DWORD dwReturn;
  1324. WsbAssertStatus( DeviceIoControl( m_handle,
  1325. IOCTL_CHANGER_REINITIALIZE_TRANSPORT,
  1326. NULL,
  1327. 0,
  1328. NULL,
  1329. 0,
  1330. &dwReturn,
  1331. NULL ));
  1332. hr = S_OK;
  1333. }
  1334. WsbCatch( hr );
  1335. return hr;
  1336. }
  1337. /*
  1338. HRESULT
  1339. CRmsMediumChanger::getDisplay(
  1340. OUT PCHANGER_DISPLAY pDisplay
  1341. )
  1342. {
  1343. HRESULT hr = E_FAIL;
  1344. try
  1345. {
  1346. DWORD dwReturn;
  1347. WsbAssertStatus( DeviceIoControl( m_handle,
  1348. IOCTL_CHANGER_GET_DISPLAY,
  1349. pDisplay,
  1350. sizeof(CHANGER_DISPLAY) + (pDisplay->LineCount - 1) * sizeof(SET_CHANGER_DISPLAY),
  1351. pDisplay,
  1352. sizeof(CHANGER_DISPLAY) + (pDisplay->LineCount - 1) * sizeof(SET_CHANGER_DISPLAY),
  1353. &dwReturn,
  1354. NULL ));
  1355. hr = S_OK;
  1356. }
  1357. WsbCatch( hr );
  1358. return hr;
  1359. }
  1360. HRESULT
  1361. CRmsMediumChanger::setDisplay(
  1362. IN PCHANGER_DISPLAY pDisplay
  1363. )
  1364. {
  1365. HRESULT hr = E_FAIL;
  1366. try
  1367. {
  1368. DWORD dwReturn;
  1369. WsbAssertStatus( DeviceIoControl( m_handle,
  1370. IOCTL_CHANGER_SET_DISPLAY,
  1371. pDisplay,
  1372. sizeof(CHANGER_DISPLAY) + (pDisplay->LineCount - 1) * sizeof(SET_CHANGER_DISPLAY),
  1373. NULL,
  1374. 0,
  1375. &dwReturn,
  1376. NULL ));
  1377. hr = S_OK;
  1378. }
  1379. WsbCatch( hr );
  1380. return hr;
  1381. }
  1382. */
  1383. STDMETHODIMP
  1384. CRmsMediumChanger::QueryVolumeTag(
  1385. IN CHANGER_ELEMENT startingElement,
  1386. IN DWORD actionCode,
  1387. IN PUCHAR pVolumeIDTemplate,
  1388. OUT PDWORD pNumberOfElementsReturned,
  1389. OUT PREAD_ELEMENT_ADDRESS_INFO pElementInformation
  1390. )
  1391. /*++
  1392. Implements:
  1393. IRmsMoveMedia::QueryVolumeTag
  1394. --*/
  1395. {
  1396. HRESULT hr = E_FAIL;
  1397. try
  1398. {
  1399. DWORD dwReturn;
  1400. CHANGER_SEND_VOLUME_TAG_INFORMATION tagInfo;
  1401. tagInfo.StartingElement = startingElement;
  1402. tagInfo.ActionCode = actionCode;
  1403. memcpy( &tagInfo.VolumeIDTemplate, pVolumeIDTemplate, sizeof(MAX_VOLUME_TEMPLATE_SIZE) );
  1404. WsbAssertStatus( DeviceIoControl( m_handle,
  1405. IOCTL_CHANGER_QUERY_VOLUME_TAGS,
  1406. &tagInfo,
  1407. sizeof(CHANGER_SEND_VOLUME_TAG_INFORMATION),
  1408. pElementInformation,
  1409. sizeof(READ_ELEMENT_ADDRESS_INFO) + (pElementInformation->NumberOfElements - 1) * sizeof(CHANGER_ELEMENT_STATUS),
  1410. &dwReturn,
  1411. NULL ));
  1412. *pNumberOfElementsReturned = pElementInformation->NumberOfElements;
  1413. hr = S_OK;
  1414. }
  1415. WsbCatch( hr );
  1416. return hr;
  1417. }