Leaked source code of windows server 2003
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.

4022 lines
130 KiB

  1. /*++
  2. 1998 Seagate Software, Inc. All rights reserved
  3. Module Name:
  4. RmsServr.cpp
  5. Abstract:
  6. Implementation of CRmsServer
  7. Author:
  8. Brian Dodd [brian] 15-Nov-1996
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. //#include <stl.h>
  13. //using namespace std ;
  14. //#pragma warning (disable : 4786)
  15. //using namespace std ;
  16. #include <devioctl.h>
  17. #include <ntddscsi.h>
  18. #include "RmsServr.h"
  19. #include "rsbuild.h"
  20. #include "wsb.h"
  21. #include "ntverp.h"
  22. #define PERSIST_CHECK_VALUE 0x526f6e57
  23. #if 0
  24. #define DebugPrint(a) { \
  25. CWsbStringPtr out = a; \
  26. out.Prepend(L": "); \
  27. out.Prepend(WsbLongAsString(GetCurrentThreadId())); \
  28. OutputDebugString((WCHAR *) out); \
  29. }
  30. #else
  31. #define DebugPrint(a)
  32. #endif // DBG
  33. // This is made global so that anybody in the context of the server has
  34. // quick access to it
  35. IRmsServer *g_pServer = 0;
  36. /////////////////////////////////////////////////////////////////////////////
  37. // CComObjectRoot
  38. HRESULT
  39. CRmsServer::FinalConstruct(void)
  40. /*++
  41. Routine Description:
  42. This method does some initialization of the object that is necessary
  43. after construction.
  44. Arguments:
  45. None.
  46. Return Value:
  47. S_OK
  48. Anything returned by CWsbPersistStream::FinalConstruct().
  49. --*/
  50. {
  51. HRESULT hr = S_OK;
  52. WsbTraceIn(OLESTR("CRmsServer::FinalConstruct"), OLESTR(""));
  53. // Zeroing global variable
  54. g_pServer = 0;
  55. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
  56. try {
  57. WsbAssertPointer( pObject );
  58. CWsbBstrPtr tmpString;
  59. WsbAssertHr( CWsbPersistStream::FinalConstruct() );
  60. WsbAffirmHr( ChangeState( RmsServerStateStarting ));
  61. // Figure out where to store information and initialize trace.
  62. // Setup the collections
  63. WsbAssertHr(CoCreateInstance( CLSID_CWsbOrderedCollection,
  64. 0,
  65. CLSCTX_SERVER,
  66. IID_IWsbIndexedCollection,
  67. (void **)&m_pCartridges ));
  68. WsbAssertHr(CoCreateInstance( CLSID_CWsbOrderedCollection,
  69. 0,
  70. CLSCTX_SERVER,
  71. IID_IWsbIndexedCollection,
  72. (void **)&m_pActiveCartridges ));
  73. WsbAssertHr(CoCreateInstance( CLSID_CWsbOrderedCollection,
  74. 0,
  75. CLSCTX_SERVER,
  76. IID_IWsbIndexedCollection,
  77. (void **)&m_pDataMovers ));
  78. WsbAssertHr(CoCreateInstance( CLSID_CWsbOrderedCollection,
  79. 0,
  80. CLSCTX_SERVER,
  81. IID_IWsbIndexedCollection,
  82. (void **)&m_pLibraries ));
  83. WsbAssertHr(CoCreateInstance( CLSID_CWsbOrderedCollection,
  84. 0,
  85. CLSCTX_SERVER,
  86. IID_IWsbIndexedCollection,
  87. (void **)&m_pMediaSets ));
  88. WsbAssertHr(CoCreateInstance( CLSID_CWsbOrderedCollection,
  89. 0,
  90. CLSCTX_SERVER,
  91. IID_IWsbIndexedCollection,
  92. (void **)&m_pRequests ));
  93. WsbAssertHr(CoCreateInstance( CLSID_CWsbOrderedCollection,
  94. 0,
  95. CLSCTX_SERVER,
  96. IID_IWsbIndexedCollection,
  97. (void **)&m_pClients ));
  98. WsbAssertHr(CoCreateInstance( CLSID_CWsbOrderedCollection,
  99. 0,
  100. CLSCTX_SERVER,
  101. IID_IWsbIndexedCollection,
  102. (void **)&m_pUnconfiguredDevices ));
  103. // Create NTMS object
  104. WsbAssertHr(CoCreateInstance( CLSID_CRmsNTMS,
  105. 0,
  106. CLSCTX_SERVER,
  107. IID_IRmsNTMS,
  108. (void **)&m_pNTMS ));
  109. // Get the name of the computer on which we running.
  110. CWsbStringPtr serverNameString;
  111. WsbAffirmHr( WsbGetComputerName( serverNameString ));
  112. m_ServerName = serverNameString;
  113. m_HardDrivesUsed = 0;
  114. m_LockReference = 0;
  115. WsbAffirmHr( ChangeState( RmsServerStateStarted ));
  116. } WsbCatchAndDo(hr,
  117. pObject->Disable( hr );
  118. );
  119. WsbTraceOut(OLESTR("CRmsServer::FinalConstruct"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  120. return hr;
  121. }
  122. HRESULT
  123. CRmsServer::FinalRelease(void)
  124. /*++
  125. Routine Description:
  126. This method does some uninitialization of the object that is necessary
  127. before destrucruction.
  128. Arguments:
  129. None.
  130. Return Value:
  131. S_OK
  132. --*/
  133. {
  134. HRESULT hr = S_OK;
  135. WsbTraceIn(OLESTR("CRmsServer::FinalRelease"), OLESTR(""));
  136. try {
  137. WsbAffirmHr( ChangeState( RmsServerStateStopping ));
  138. CWsbPersistStream::FinalRelease();
  139. WsbAffirmHr( ChangeState( RmsServerStateStopped ));
  140. #ifdef WSB_TRACK_MEMORY
  141. (void) WsbObjectTracePointers(WSB_OTP_SEQUENCE | WSB_OTP_STATISTICS | WSB_OTP_ALLOCATED);
  142. (void) WsbObjectTraceTypes();
  143. #endif
  144. } WsbCatch(hr);
  145. WsbTraceOut(OLESTR("CRmsServer::FinalRelease"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  146. return hr;
  147. }
  148. STDMETHODIMP
  149. CRmsServer::InitializeInAnotherThread(void)
  150. {
  151. HRESULT hr = S_OK;
  152. WsbTraceIn(OLESTR("CRmsServer::InitializeInAnotherThread"), OLESTR(""));
  153. try {
  154. DWORD threadId;
  155. HANDLE hThread;
  156. WsbAffirmHandle(hThread = CreateThread(NULL, 1024, CRmsServer::InitializationThread, this, 0, &threadId));
  157. CloseHandle(hThread);
  158. } WsbCatch(hr);
  159. WsbTraceOut(OLESTR("CRmsServer::InitializeInAnotherThread"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  160. return hr;
  161. }
  162. DWORD WINAPI
  163. CRmsServer::InitializationThread(
  164. IN LPVOID pv)
  165. {
  166. HRESULT hr = S_OK;
  167. WsbTraceIn(OLESTR("CRmsServer::InitializationThread"), OLESTR(""));
  168. HRESULT hrCom = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  169. try {
  170. WsbAssertPointer(pv);
  171. CRmsServer *pServer = (CRmsServer*)pv;
  172. WsbAffirmHr(pServer->Initialize());
  173. } WsbCatch(hr);
  174. if (SUCCEEDED(hrCom)) {
  175. CoUninitialize();
  176. }
  177. WsbTraceOut(OLESTR("CRmsServer::InitializationThread"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  178. return hr;
  179. }
  180. STDMETHODIMP
  181. CRmsServer::Initialize(void)
  182. {
  183. HRESULT hr = S_OK;
  184. WsbTraceIn(OLESTR("CRmsServer::Initialize"), OLESTR(""));
  185. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
  186. DWORD fixedDriveEnabled = RMS_DEFAULT_FIXED_DRIVE;
  187. DWORD size;
  188. OLECHAR tmpString[256];
  189. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_FIXED_DRIVE, tmpString, 256, &size))) {
  190. // Get the value.
  191. fixedDriveEnabled = wcstol(tmpString, NULL, 10);
  192. }
  193. DWORD opticalEnabled = RMS_DEFAULT_OPTICAL;
  194. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_OPTICAL, tmpString, 256, &size))) {
  195. // Get the value.
  196. opticalEnabled = wcstol(tmpString, NULL, 10);
  197. }
  198. DWORD tapeEnabled = RMS_DEFAULT_TAPE;
  199. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_TAPE, tmpString, 256, &size))) {
  200. // Get the value.
  201. tapeEnabled = wcstol(tmpString, NULL, 10);
  202. }
  203. DWORD dvdEnabled = RMS_DEFAULT_DVD;
  204. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_DVD, tmpString, 256, &size))) {
  205. // Get the value.
  206. dvdEnabled = wcstol(tmpString, NULL, 10);
  207. }
  208. WsbTraceAlways(OLESTR("Fixed Drive Media Enabled: %ls\n"), WsbBoolAsString((BOOL)fixedDriveEnabled));
  209. WsbTraceAlways(OLESTR("Optical Media Enabled: %ls\n"), WsbBoolAsString((BOOL)opticalEnabled));
  210. WsbTraceAlways(OLESTR("Tape Media Enabled: %ls\n"), WsbBoolAsString((BOOL)tapeEnabled));
  211. WsbTraceAlways(OLESTR("DVD Media Enabled: %ls\n"), WsbBoolAsString((BOOL)dvdEnabled));
  212. try {
  213. if (0 == g_pServer) {
  214. // Set global variable for quick access (if not set yet)
  215. WsbAffirmHr(((IUnknown*)(IRmsServer *)this)->QueryInterface(IID_IRmsServer, (void**) &g_pServer));
  216. // We don't want the reference count bumped for this global so release it here.
  217. g_pServer->Release();
  218. }
  219. // initializing
  220. WsbAssertPointer( pObject );
  221. CWsbStringPtr tmpString;
  222. WsbAffirmHr( ChangeState( RmsServerStateInitializing ));
  223. hr = IsNTMSInstalled();
  224. if ( S_OK == hr ) {
  225. try {
  226. // Perform any initialization required for using NTMS subsystem.
  227. WsbAffirmHr( m_pNTMS->Initialize() );
  228. } WsbCatch (hr);
  229. hr = S_OK;
  230. if (fixedDriveEnabled) {
  231. // Scan for drives.
  232. WsbAffirmHr( ScanForDrives() );
  233. }
  234. // Resolve the devices detected by the scan.
  235. WsbAffirmHr( resolveUnconfiguredDevices() );
  236. // Auto configure the remaining devices.
  237. WsbAffirmHr( autoConfigureDevices() );
  238. // Try to dismount all of our medias, ignore errors
  239. HRESULT hrDismountAll = S_OK;
  240. try {
  241. CComPtr<IWsbEnum> pEnumSets;
  242. CComPtr<IRmsMediaSet> pMediaSet;
  243. CComPtr<IRmsComObject> pObject;
  244. GUID mediaSetId;
  245. WsbAffirmHr(m_pMediaSets->Enum(&pEnumSets));
  246. WsbAssertPointer(pEnumSets);
  247. hrDismountAll = pEnumSets->First(IID_IRmsMediaSet, (void **)&pMediaSet);
  248. while (S_OK == hrDismountAll) {
  249. WsbAffirmHr(pMediaSet->QueryInterface(IID_IRmsComObject, (void**) &pObject));
  250. WsbAffirmHr(pObject->GetObjectId(&mediaSetId));
  251. WsbAffirmHr(m_pNTMS->DismountAll(mediaSetId));
  252. hrDismountAll = pEnumSets->Next(IID_IRmsMediaSet, (void **)&pMediaSet);
  253. }
  254. if (hrDismountAll == WSB_E_NOTFOUND) {
  255. hrDismountAll = S_OK;
  256. } else {
  257. WsbAffirmHr(hrDismountAll);
  258. }
  259. } WsbCatch(hrDismountAll);
  260. }
  261. else if ( RMS_E_NOT_CONFIGURED_FOR_NTMS == hr ) {
  262. hr = S_OK;
  263. // Scan for devices.
  264. WsbAffirmHr( ScanForDevices() );
  265. if (fixedDriveEnabled) {
  266. // Scan for drives.
  267. WsbAffirmHr( ScanForDrives() );
  268. }
  269. // Resolve the devices detected by the scan.
  270. WsbAffirmHr( resolveUnconfiguredDevices() );
  271. // Auto configure the remaining devices.
  272. WsbAffirmHr( autoConfigureDevices() );
  273. }
  274. else { // Some other NTMS connection failure (NTMS not installed, configured, or running)
  275. hr = S_OK;
  276. if (fixedDriveEnabled) {
  277. // Scan for drives.
  278. WsbAffirmHr( ScanForDrives() );
  279. // Resolve the devices detected by the scan.
  280. WsbAffirmHr( resolveUnconfiguredDevices() );
  281. // Auto configure the remaining devices.
  282. WsbAffirmHr( autoConfigureDevices() );
  283. }
  284. }
  285. // Enable RMS process for backup operations.
  286. WsbAffirmHr( enableAsBackupOperator() );
  287. // Save the configuration information.
  288. WsbAffirmHr( SaveAll() );
  289. WsbAffirmHr( ChangeState( RmsServerStateReady ));
  290. WsbTraceAlways(OLESTR("RMS is ready.\n"));
  291. } WsbCatchAndDo(hr,
  292. pObject->Disable( hr );
  293. );
  294. WsbTraceOut(OLESTR("CRmsServer::Initialize"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  295. return hr;
  296. }
  297. STDMETHODIMP
  298. CRmsServer::IsNTMSInstalled(void)
  299. {
  300. return m_pNTMS->IsInstalled();
  301. }
  302. STDMETHODIMP
  303. CRmsServer::GetNTMS(
  304. OUT IRmsNTMS **ptr)
  305. /*++
  306. Implements:
  307. IRmsServer::GetNTMS
  308. --*/
  309. {
  310. HRESULT hr = E_FAIL;
  311. try {
  312. WsbAssertPointer( ptr );
  313. *ptr = m_pNTMS;
  314. m_pNTMS.p->AddRef();
  315. hr = S_OK;
  316. } WsbCatch( hr );
  317. return hr;
  318. }
  319. //
  320. // Rms no longer save independently its own .col file, but only the NTMS database
  321. //
  322. STDMETHODIMP
  323. CRmsServer::SaveAll(void)
  324. {
  325. HRESULT hr = S_OK;
  326. WsbTraceIn(OLESTR("CRmsServer::SaveAll"), OLESTR(""));
  327. static BOOL saving = FALSE;
  328. try {
  329. WsbAffirm(!saving, S_FALSE);
  330. saving = TRUE;
  331. hr = m_pNTMS->ExportDatabase();
  332. saving = FALSE;
  333. } WsbCatch(hr);
  334. WsbTraceOut(OLESTR("CRmsServer::SaveAll"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  335. return hr;
  336. }
  337. STDMETHODIMP
  338. CRmsServer::Unload(void)
  339. {
  340. HRESULT hr = S_OK;
  341. WsbTraceIn(OLESTR("CRmsServer::Unload"), OLESTR(""));
  342. try {
  343. // We only need to release what may have gotten set/created by
  344. // a failed Load attempt.
  345. if (m_pCartridges) {
  346. WsbAffirmHr(m_pCartridges->RemoveAllAndRelease());
  347. }
  348. if (m_pLibraries) {
  349. WsbAffirmHr(m_pLibraries->RemoveAllAndRelease());
  350. }
  351. if (m_pMediaSets) {
  352. WsbAffirmHr(m_pMediaSets->RemoveAllAndRelease());
  353. }
  354. if (m_pRequests) {
  355. WsbAffirmHr(m_pRequests->RemoveAllAndRelease());
  356. }
  357. if (m_pClients) {
  358. WsbAffirmHr(m_pClients->RemoveAllAndRelease());
  359. }
  360. } WsbCatch(hr);
  361. WsbTraceOut(OLESTR("CRmsServer::Unload"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  362. return hr;
  363. }
  364. STDMETHODIMP
  365. CRmsServer::GetClassID(
  366. OUT CLSID* pClsid)
  367. /*++
  368. Implements:
  369. IPersist::GetClassId
  370. --*/
  371. {
  372. HRESULT hr = S_OK;
  373. WsbTraceIn(OLESTR("CRmsServer::GetClassID"), OLESTR(""));
  374. try {
  375. WsbAssert(0 != pClsid, E_POINTER);
  376. *pClsid = CLSID_CRmsServer;
  377. } WsbCatch(hr);
  378. WsbTraceOut(OLESTR("CRmsServer::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid));
  379. return hr;
  380. }
  381. STDMETHODIMP
  382. CRmsServer::GetSizeMax(
  383. OUT ULARGE_INTEGER* /*pcbSize*/)
  384. /*++
  385. Implements:
  386. IPersistStream::GetSizeMax
  387. --*/
  388. {
  389. HRESULT hr = E_NOTIMPL;
  390. // ULONG serverNameLen;
  391. // ULARGE_INTEGER cartridgesLen;
  392. // ULARGE_INTEGER librariesLen;
  393. // ULARGE_INTEGER mediaSetsLen;
  394. // ULARGE_INTEGER requestsLen;
  395. // ULARGE_INTEGER clientsLen;
  396. // ULARGE_INTEGER unconfiguredDevicesLen;
  397. // WsbTraceIn(OLESTR("CRmsServer::GetSizeMax"), OLESTR(""));
  398. // try {
  399. // WsbAssert(0 != pcbSize, E_POINTER);
  400. // m_pCartridges-> GetSizeMax (&cartridgesLen);
  401. // set up size of CRmsServer
  402. // pcbSize->QuadPart = WsbPersistSizeOf(ULONG) + // length of serverName
  403. // cartridgesLen.QuadPart; // m_pCartridges
  404. // } WsbCatch(hr);
  405. // WsbTraceOut(OLESTR("CRmsServer::GetSizeMax"), OLESTR("hr = <%ls>, Size = <%ls>"), WsbHrAsString(hr), WsbPtrToUliAsString(pcbSize));
  406. return hr;
  407. }
  408. STDMETHODIMP
  409. CRmsServer::Load(
  410. IN IStream* pStream)
  411. /*++
  412. Implements:
  413. IPersistStream::Load
  414. --*/
  415. {
  416. HRESULT hr = S_OK;
  417. WsbTraceIn(OLESTR("CRmsServer::Load"), OLESTR(""));
  418. //
  419. // Check if the global pointer is already set - if not, update it
  420. // (Today, Load is the only method that is executed before Initialize)
  421. //
  422. if (0 == g_pServer) {
  423. // Set global variable for quick access (if not set yet)
  424. WsbAffirmHr(((IUnknown*)(IRmsServer *)this)->QueryInterface(IID_IRmsServer, (void**) &g_pServer));
  425. // We don't want the reference count bumped for this global so release it here.
  426. g_pServer->Release();
  427. }
  428. //
  429. // Lock down the server while we are loading.
  430. //
  431. InterlockedIncrement( &m_LockReference );
  432. //
  433. // The Load reverts the state, which is undesired for the server object.
  434. // Save away the original status information
  435. //
  436. BOOL bTemp = m_IsEnabled;
  437. LONG lTemp = m_State;
  438. HRESULT hrTemp = m_StatusCode;
  439. try {
  440. WsbAssertPointer(pStream);
  441. CComPtr<IPersistStream> pPersistStream;
  442. WsbAffirmHr(CRmsComObject::Load(pStream));
  443. // Load the collections
  444. WsbAffirmHr(m_pMediaSets->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  445. WsbAffirmHr(pPersistStream->Load(pStream));
  446. pPersistStream = 0;
  447. WsbAffirmHr(m_pCartridges->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  448. WsbAffirmHr(pPersistStream->Load(pStream));
  449. pPersistStream = 0;
  450. WsbAffirmHr(m_pLibraries->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  451. WsbAffirmHr(pPersistStream->Load(pStream));
  452. pPersistStream = 0;
  453. WsbAffirmHr(m_pRequests->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  454. WsbAffirmHr(pPersistStream->Load(pStream));
  455. pPersistStream = 0;
  456. WsbAffirmHr(m_pClients->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  457. WsbAffirmHr(pPersistStream->Load(pStream));
  458. pPersistStream = 0;
  459. // Check that we got everything
  460. ULONG check_value;
  461. WsbAffirmHr(WsbLoadFromStream(pStream, &check_value));
  462. WsbAffirm(check_value == PERSIST_CHECK_VALUE, E_UNEXPECTED);
  463. } WsbCatch(hr);
  464. // Reset the object status information to their original settings.
  465. m_IsEnabled = bTemp;
  466. m_State = lTemp;
  467. m_StatusCode = hrTemp;
  468. //
  469. // Unlock the server.
  470. //
  471. InterlockedDecrement( &m_LockReference );
  472. WsbTraceOut(OLESTR("CRmsServer::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  473. return hr;
  474. }
  475. STDMETHODIMP
  476. CRmsServer::Save(
  477. IN IStream* pStream,
  478. IN BOOL clearDirty)
  479. /*++
  480. Implements:
  481. IPersistStream::Save
  482. --*/
  483. {
  484. HRESULT hr = S_OK;
  485. WsbTraceIn(OLESTR("CRmsServer::Save"), OLESTR("clearDirty = <%ls>"), WsbBoolAsString(clearDirty));
  486. try {
  487. CComPtr<IPersistStream> pPersistStream;
  488. WsbAssertPointer(pStream);
  489. WsbAffirmHr(CRmsComObject::Save(pStream, clearDirty));
  490. // Save the collections
  491. WsbAffirmHr(m_pMediaSets->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  492. WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
  493. pPersistStream = 0;
  494. WsbAffirmHr(m_pCartridges->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  495. WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
  496. pPersistStream = 0;
  497. WsbAffirmHr(m_pLibraries->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  498. WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
  499. pPersistStream = 0;
  500. WsbAffirmHr(m_pRequests->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  501. WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
  502. pPersistStream = 0;
  503. WsbAffirmHr(m_pClients->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  504. WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
  505. pPersistStream = 0;
  506. // Put this at the end as a check during load
  507. ULONG check_value = PERSIST_CHECK_VALUE;
  508. WsbAffirmHr(WsbSaveToStream(pStream, check_value));
  509. // Do we need to clear the dirty bit?
  510. if (clearDirty) {
  511. m_isDirty = FALSE;
  512. }
  513. } WsbCatch(hr);
  514. WsbTraceOut(OLESTR("CRmsServer::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  515. return hr;
  516. }
  517. /////////////////////////////////////////////////////////////////////////////
  518. // IRmsServer
  519. STDMETHODIMP
  520. CRmsServer::GetServerName(
  521. OUT BSTR *pName)
  522. /*++
  523. Implements:
  524. IRmsServer::GetServerName
  525. --*/
  526. {
  527. WsbAssertPointer(pName);
  528. m_ServerName.CopyToBstr(pName);
  529. return S_OK;
  530. }
  531. STDMETHODIMP
  532. CRmsServer::GetCartridges(
  533. OUT IWsbIndexedCollection **ptr)
  534. /*++
  535. Implements:
  536. IRmsServer::GetCartridges
  537. --*/
  538. {
  539. HRESULT hr = S_OK;
  540. try {
  541. WsbAssertPointer(ptr);
  542. *ptr = m_pCartridges;
  543. m_pCartridges.p->AddRef();
  544. } WsbCatch(hr)
  545. return hr;
  546. }
  547. STDMETHODIMP
  548. CRmsServer::GetActiveCartridges(
  549. OUT IWsbIndexedCollection **ptr)
  550. /*++
  551. Implements:
  552. IRmsServer::GetActiveCartridges
  553. --*/
  554. {
  555. HRESULT hr = S_OK;
  556. try {
  557. WsbAssertPointer(ptr);
  558. *ptr = m_pActiveCartridges;
  559. m_pActiveCartridges.p->AddRef();
  560. } WsbCatch(hr)
  561. return hr;
  562. }
  563. STDMETHODIMP
  564. CRmsServer::GetDataMovers(
  565. OUT IWsbIndexedCollection **ptr)
  566. /*++
  567. Implements:
  568. IRmsServer::GetDataMovers
  569. --*/
  570. {
  571. HRESULT hr = S_OK;
  572. try {
  573. WsbAssertPointer(ptr);
  574. *ptr = m_pDataMovers;
  575. m_pDataMovers.p->AddRef();
  576. } WsbCatch(hr)
  577. return hr;
  578. }
  579. STDMETHODIMP
  580. CRmsServer::SetActiveCartridge(
  581. IN IRmsCartridge *ptr)
  582. /*++
  583. Implements:
  584. IRmsServer::SetActiveCartridge
  585. --*/
  586. {
  587. HRESULT hr = S_OK;
  588. try {
  589. if (m_pActiveCartridge) {
  590. m_pActiveCartridge = 0;
  591. }
  592. m_pActiveCartridge = ptr;
  593. } WsbCatch(hr)
  594. return hr;
  595. }
  596. STDMETHODIMP
  597. CRmsServer::GetLibraries(
  598. OUT IWsbIndexedCollection **ptr)
  599. /*++
  600. Implements:
  601. IRmsServer::GetLibraries
  602. --*/
  603. {
  604. HRESULT hr = S_OK;
  605. try {
  606. WsbAssertPointer(ptr);
  607. *ptr = m_pLibraries;
  608. m_pLibraries.p->AddRef();
  609. } WsbCatch(hr)
  610. return hr;
  611. }
  612. STDMETHODIMP
  613. CRmsServer::GetMediaSets(
  614. OUT IWsbIndexedCollection **ptr)
  615. /*++
  616. Implements:
  617. IRmsServer::GetMediaSets
  618. --*/
  619. {
  620. HRESULT hr = S_OK;
  621. try {
  622. WsbAssertPointer(ptr);
  623. // We need to reinit NTMS to account for PNP devices.
  624. (void) m_pNTMS->Initialize();
  625. *ptr = m_pMediaSets;
  626. m_pMediaSets.p->AddRef();
  627. } WsbCatch(hr)
  628. return hr;
  629. }
  630. STDMETHODIMP
  631. CRmsServer::GetRequests(
  632. OUT IWsbIndexedCollection **ptr)
  633. /*++
  634. Implements:
  635. IRmsServer::GetRequests
  636. --*/
  637. {
  638. HRESULT hr = S_OK;
  639. try {
  640. WsbAssertPointer(ptr);
  641. *ptr = m_pRequests;
  642. m_pRequests.p->AddRef();
  643. } WsbCatch(hr)
  644. return hr;
  645. }
  646. STDMETHODIMP
  647. CRmsServer::GetClients(
  648. OUT IWsbIndexedCollection **ptr)
  649. /*++
  650. Implements:
  651. IRmsServer::GetClients
  652. --*/
  653. {
  654. HRESULT hr = S_OK;
  655. try {
  656. WsbAssertPointer(ptr);
  657. *ptr = m_pClients;
  658. m_pClients.p->AddRef();
  659. } WsbCatch(hr)
  660. return hr;
  661. }
  662. STDMETHODIMP
  663. CRmsServer::GetUnconfiguredDevices(
  664. OUT IWsbIndexedCollection **ptr)
  665. /*++
  666. Implements:
  667. IRmsServer::GetUnconfiguredDevices
  668. --*/
  669. {
  670. HRESULT hr = S_OK;
  671. try {
  672. WsbAssertPointer(ptr);
  673. *ptr = m_pUnconfiguredDevices;
  674. m_pUnconfiguredDevices.p->AddRef();
  675. } WsbCatch(hr)
  676. return hr;
  677. }
  678. STDMETHODIMP
  679. CRmsServer::ScanForDevices(void)
  680. /*++
  681. Implements:
  682. IRmsServer::ScanForDevices
  683. --*/
  684. {
  685. HRESULT hr = S_OK;
  686. WsbTraceIn(OLESTR("CRmsServer::ScanForDevices"), OLESTR(""));
  687. HANDLE portHandle = INVALID_HANDLE_VALUE;
  688. LONGLONG trace = 0;
  689. try {
  690. // WsbAssertPointer( g_pTrace );
  691. BOOL status;
  692. DWORD accessMode = GENERIC_READ;
  693. DWORD shareMode = FILE_SHARE_READ;
  694. UCHAR portData[2048];
  695. OLECHAR string[25];
  696. ULONG returned;
  697. int portNumber = 0;
  698. // BOOL traceTimeStamp;
  699. // BOOL traceCount;
  700. // BOOL traceThreadId;
  701. // WsbAssertHr( g_pTrace->GetTraceSettings( &trace ));
  702. // WsbAssertHr( g_pTrace->SetTraceOff( WSB_TRACE_BIT_ALL ));
  703. // WsbAssertHr( g_pTrace->GetOutputFormat( &traceTimeStamp, &traceCount, &traceThreadId ));
  704. // WsbAssertHr( g_pTrace->SetOutputFormat( FALSE, FALSE, FALSE ));
  705. WsbTraceAlways( OLESTR("\n\n----- Begin Device Scan ---------------------------------------------------------------\n\n") );
  706. //
  707. // Go to each SCSI adapter connected to the system and build
  708. // out the device list.
  709. //
  710. do {
  711. swprintf( string, OLESTR("\\\\.\\Scsi%d:"), portNumber );
  712. portHandle = CreateFile( string,
  713. accessMode,
  714. shareMode,
  715. NULL,
  716. OPEN_EXISTING,
  717. 0,
  718. NULL );
  719. if ( portHandle == INVALID_HANDLE_VALUE ) {
  720. break; // we're done
  721. }
  722. //
  723. // Get the inquiry data.
  724. //
  725. WsbAffirmStatus( DeviceIoControl( portHandle,
  726. IOCTL_SCSI_GET_INQUIRY_DATA,
  727. NULL,
  728. 0,
  729. portData,
  730. sizeof(portData),
  731. &returned,
  732. FALSE ));
  733. status = CloseHandle( portHandle );
  734. portHandle = INVALID_HANDLE_VALUE;
  735. WsbAffirmStatus( status );
  736. WsbAffirmHrOk( processInquiryData( portNumber, portData ) );
  737. portNumber++;
  738. } while ( 1 );
  739. WsbTraceAlways( OLESTR("\n\n----- End Device Scan -----------------------------------------------------------------\n\n") );
  740. // WsbAssertHr( g_pTrace->SetOutputFormat( traceTimeStamp, traceCount, traceThreadId ));
  741. // WsbAssertHr( g_pTrace->SetTraceOn( trace ));
  742. hr = S_OK;
  743. }
  744. WsbCatchAndDo( hr,
  745. // if (g_pTrace) {
  746. // WsbAssertHr( g_pTrace->SetTraceOn( trace ));
  747. WsbTraceAlways( OLESTR("\n\n !!!!! ERROR !!!!! Device Scan Terminated.\n\n") );
  748. // }
  749. if ( portHandle != INVALID_HANDLE_VALUE ) {
  750. CloseHandle( portHandle );
  751. }
  752. );
  753. WsbTraceOut(OLESTR("CRmsServer::ScanForDevices"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  754. return hr;
  755. }
  756. STDMETHODIMP
  757. CRmsServer::ScanForDrives(void)
  758. /*++
  759. Implements:
  760. IRmsServer::ScanForDrives
  761. --*/
  762. {
  763. HRESULT hr = S_OK;
  764. WsbTraceIn(OLESTR("CRmsServer::ScanForDrives"), OLESTR(""));
  765. try {
  766. //
  767. // Build out device objects for various drive types: fixed drives, removables, and CD-ROM.
  768. // These are all supported by the system, and have drive letters associated with them.
  769. //
  770. // Use best effort to dectect drives. If anything fails we just go on to the next one.
  771. // Get the unconfigured device list
  772. CComPtr<IWsbIndexedCollection> pDevices;
  773. WsbAssertHr( this->GetUnconfiguredDevices( &pDevices ));
  774. // Get the drive letters
  775. const DWORD bufSize = 256; // 26*4 + 1 = 105 is all we really need
  776. OLECHAR driveLetters[bufSize];
  777. DWORD len;
  778. // See if there are drives for us to support
  779. if ( getHardDrivesToUseFromRegistry( driveLetters, &len ) != S_OK ) {
  780. len = GetLogicalDriveStrings( bufSize, driveLetters );
  781. }
  782. UINT type;
  783. // For each drive letter see if it is something managed
  784. // by RMS.
  785. m_HardDrivesUsed = 0;
  786. for ( DWORD i = 0; i < len; i += 4 ) { // drive letters have the form "A:\"
  787. try {
  788. type = GetDriveType( &driveLetters[i] );
  789. switch ( type ) {
  790. case DRIVE_REMOVABLE:
  791. {
  792. WsbTrace( OLESTR("Removable Drive Detected: %C\n"), driveLetters[i] );
  793. CComPtr<IRmsDevice> pDevice;
  794. WsbAffirmHr( CoCreateInstance( CLSID_CRmsDrive, 0, CLSCTX_SERVER, IID_IRmsDevice, (void **)&pDevice ));
  795. CWsbBstrPtr name = &(driveLetters[i]);
  796. WsbAffirmHr( pDevice->SetDeviceName( name ));
  797. WsbAffirmHr( pDevice->SetDeviceType( RmsDeviceRemovableDisk ));
  798. //
  799. // Don't add it if it was already detected in the SCSI device scan
  800. //
  801. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pDevice;
  802. WsbAssertPointer( pObject );
  803. WsbAffirmHr( pObject->SetFindBy( RmsFindByDeviceName ));
  804. if ( S_OK == pDevices->Contains( pDevice ) ) {
  805. break;
  806. }
  807. WsbAffirmHr( pDevices->Add( pDevice ));
  808. pDevice = 0;
  809. }
  810. break;
  811. case DRIVE_FIXED:
  812. {
  813. CWsbBstrPtr name = &(driveLetters[i]);
  814. WCHAR volumeName[32];
  815. DWORD volumeSerialNumber;
  816. DWORD filenameLength;
  817. DWORD fileSystemFlags;
  818. WCHAR fileSystemName[32];
  819. WsbAffirmStatus(GetVolumeInformation( (WCHAR *)name, volumeName, 32,
  820. &volumeSerialNumber, &filenameLength, &fileSystemFlags, fileSystemName, 32));
  821. WsbTrace( OLESTR("Fixed Drive Detected : %ls <%ls/%d> [len=%d, flags=0x%08x] %ls\n"),
  822. (WCHAR *)name, volumeName, volumeSerialNumber, filenameLength,
  823. fileSystemFlags, fileSystemName );
  824. //
  825. // Use any volume with name starting with RStor, Remote Stor, RemoteStor, RS
  826. //
  827. if ( (0 == _wcsnicmp(volumeName, L"RS", 2)) ||
  828. (0 == _wcsnicmp(volumeName, L"Remote Stor", 11)) ||
  829. (0 == _wcsnicmp(volumeName, L"RemoteStor", 10))) {
  830. CComPtr<IRmsDevice> pDevice;
  831. WsbAffirmHr( CoCreateInstance( CLSID_CRmsDrive, 0, CLSCTX_SERVER, IID_IRmsDevice, (void **)&pDevice ));
  832. WsbAffirmHr( pDevice->SetDeviceName( name ));
  833. WsbAffirmHr( pDevice->SetDeviceType( RmsDeviceFixedDisk ));
  834. WsbAffirmHr( pDevices->Add( pDevice ));
  835. pDevice = 0;
  836. m_HardDrivesUsed++;
  837. WsbTrace( OLESTR(" %ls added to Collection of unconfigured devices.\n"), (WCHAR *)name );
  838. }
  839. }
  840. break;
  841. case DRIVE_CDROM:
  842. {
  843. WsbTrace( OLESTR("CD-ROM Drive Detected : %C\n"), driveLetters[i] );
  844. CComPtr<IRmsDevice> pDevice;
  845. WsbAffirmHr( CoCreateInstance( CLSID_CRmsDrive, 0, CLSCTX_SERVER, IID_IRmsDevice, (void **)&pDevice ));
  846. CWsbBstrPtr name = &(driveLetters[i]);
  847. WsbAffirmHr( pDevice->SetDeviceName( name ));
  848. WsbAffirmHr( pDevice->SetDeviceType( RmsDeviceCDROM ));
  849. WsbAffirmHr( pDevices->Add( pDevice ));
  850. pDevice = 0;
  851. }
  852. break;
  853. case DRIVE_UNKNOWN:
  854. case DRIVE_REMOTE:
  855. case DRIVE_RAMDISK:
  856. default:
  857. break;
  858. } // switch drive types
  859. } WsbCatchAndDo(hr,
  860. hr = S_OK; // Best effort
  861. );
  862. } // for each drive
  863. } WsbCatchAndDo( hr,
  864. WsbTraceAlways( OLESTR("\n\n !!!!! ERROR !!!!! Drive Scan Terminated.\n\n") );
  865. hr = S_OK; // Best effort
  866. );
  867. WsbTraceOut(OLESTR("CRmsServer::ScanForDrives"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  868. return hr;
  869. }
  870. HRESULT
  871. CRmsServer::processInquiryData(
  872. IN int portNumber,
  873. IN UCHAR *pDataBuffer)
  874. /*++
  875. Routine Description:
  876. Builds RMS device objects from adapter port scan data.
  877. Arguments:
  878. portNumber - The adapter port to be processed.
  879. pDataBuffer - The adapter port data.
  880. Return Value:
  881. S_OK
  882. --*/
  883. {
  884. HRESULT hr = E_FAIL;
  885. try {
  886. PSCSI_ADAPTER_BUS_INFO adapterInfo;
  887. PSCSI_INQUIRY_DATA inquiryData;
  888. OLECHAR deviceString[25];
  889. CComPtr<IRmsDevice> pDevice;
  890. CComPtr<IWsbIndexedCollection> pDevices;
  891. WsbAffirmHr( this->GetUnconfiguredDevices( &pDevices ));
  892. adapterInfo = (PSCSI_ADAPTER_BUS_INFO) pDataBuffer;
  893. WsbTraceAlways( OLESTR("Port: %d\n"), portNumber );
  894. WsbTraceAlways( OLESTR("Bus TID LUN Claimed String Inquiry Header Other\n") );
  895. WsbTraceAlways( OLESTR("--- --- --- ------- ---------------------------- ----------------------- --------------\n") );
  896. for ( UCHAR i = 0; i < adapterInfo->NumberOfBuses; i++) {
  897. inquiryData = (PSCSI_INQUIRY_DATA) (pDataBuffer +
  898. adapterInfo->BusData[i].InquiryDataOffset);
  899. while (adapterInfo->BusData[i].InquiryDataOffset) {
  900. WsbTraceAlways( OLESTR(" %d %d %3d %s %.28S "),
  901. i,
  902. inquiryData->TargetId,
  903. inquiryData->Lun,
  904. (inquiryData->DeviceClaimed) ? "Y" : "N",
  905. &inquiryData->InquiryData[8] );
  906. for ( UCHAR j = 0; j < 8; j++) {
  907. WsbTraceAlways( OLESTR("%02X "), inquiryData->InquiryData[j] );
  908. }
  909. WsbTraceAlways( OLESTR("%d %3d "), inquiryData->InquiryDataLength, inquiryData->NextInquiryDataOffset );
  910. switch ( inquiryData->InquiryData[0] & 0x1f ) {
  911. case DIRECT_ACCESS_DEVICE:
  912. //
  913. // Is this a SCSI removable disk? (Fixed drives are dealt with later in the scan)
  914. //
  915. if ( (inquiryData->InquiryData[1] & 0x80) && inquiryData->InquiryData[2] & 0x02) {
  916. //
  917. // The device is a SCSI removable hard drive, So...
  918. // Create the Drive object and add it to the collection of unconfigured devices.
  919. //
  920. try {
  921. if ( inquiryData->DeviceClaimed ) {
  922. WsbAffirmHr( CoCreateInstance(CLSID_CRmsDrive, NULL, CLSCTX_SERVER, IID_IRmsDevice, (void**) &pDevice));
  923. WsbAffirmHr( pDevice->SetDeviceAddress( (BYTE)portNumber, i, inquiryData->TargetId, inquiryData->Lun ));
  924. WsbAffirmHr( pDevice->SetDeviceType( RmsDeviceRemovableDisk ));
  925. WsbAffirmHr( pDevice->SetDeviceInfo( &inquiryData->InquiryData[0], 36 ));
  926. //
  927. // find drive letter
  928. //
  929. try {
  930. WsbAffirmHr( findDriveLetter( (UCHAR)portNumber, i, inquiryData->TargetId, inquiryData->Lun, deviceString ))
  931. WsbTraceAlways( OLESTR("%ls"), deviceString );
  932. WsbAffirmHr( pDevice->SetDeviceName( deviceString ));
  933. WsbAffirmHr(pDevices->Add( pDevice ));
  934. }
  935. WsbCatch(hr);
  936. pDevice = 0;
  937. }
  938. }
  939. WsbCatch(hr);
  940. }
  941. break;
  942. case SEQUENTIAL_ACCESS_DEVICE:
  943. //
  944. // Create the Drive object and add it
  945. // to the collection of unconfigured devices.
  946. //
  947. try {
  948. if ( inquiryData->DeviceClaimed ) {
  949. WsbAffirmHr( CoCreateInstance(CLSID_CRmsDrive, NULL, CLSCTX_SERVER, IID_IRmsDevice, (void**) &pDevice));
  950. WsbAffirmHr( pDevice->SetDeviceAddress( (BYTE)portNumber, i, inquiryData->TargetId, inquiryData->Lun ));
  951. WsbAffirmHr( pDevice->SetDeviceType( RmsDeviceTape ));
  952. WsbAffirmHr( pDevice->SetDeviceInfo( &inquiryData->InquiryData[0], 36 ));
  953. //
  954. // Find tape name
  955. //
  956. try {
  957. WsbAffirmHr( getDeviceName( (UCHAR)portNumber, i, inquiryData->TargetId, inquiryData->Lun, deviceString ));
  958. WsbTraceAlways( OLESTR("%ls"), deviceString );
  959. // Create the name to use when creating a handle
  960. CWsbBstrPtr name = deviceString;
  961. name.Prepend( OLESTR("\\\\.\\") );
  962. WsbAffirmHr( pDevice->SetDeviceName( name ));
  963. WsbAffirmHr(pDevices->Add( pDevice ));
  964. }
  965. WsbCatch(hr);
  966. pDevice = 0;
  967. }
  968. }
  969. WsbCatch(hr);
  970. break;
  971. case WRITE_ONCE_READ_MULTIPLE_DEVICE:
  972. //
  973. // Supported as OPTICAL_DEVICE only
  974. //
  975. break;
  976. case READ_ONLY_DIRECT_ACCESS_DEVICE:
  977. //
  978. // we'll deal with CD-ROM later in the scan...
  979. //
  980. break;
  981. case OPTICAL_DEVICE:
  982. //
  983. // Create the Drive object and add it
  984. // to the collection of unconfigured devices.
  985. //
  986. try {
  987. if ( inquiryData->DeviceClaimed ) {
  988. WsbAffirmHr( CoCreateInstance(CLSID_CRmsDrive, NULL, CLSCTX_SERVER, IID_IRmsDevice, (void**) &pDevice));
  989. WsbAffirmHr( pDevice->SetDeviceAddress( (BYTE)portNumber, i, inquiryData->TargetId, inquiryData->Lun ));
  990. WsbAffirmHr( pDevice->SetDeviceType( RmsDeviceOptical ));
  991. WsbAffirmHr( pDevice->SetDeviceInfo( &inquiryData->InquiryData[0], 36 ));
  992. //
  993. // Find drive letter
  994. //
  995. try {
  996. WsbAffirmHr( findDriveLetter( (UCHAR)portNumber, i, inquiryData->TargetId, inquiryData->Lun, deviceString ))
  997. WsbTraceAlways( OLESTR("%ls"), deviceString );
  998. WsbAffirmHr( pDevice->SetDeviceName( deviceString ));
  999. WsbAffirmHr(pDevices->Add( pDevice ));
  1000. }
  1001. WsbCatch(hr);
  1002. pDevice = 0;
  1003. }
  1004. }
  1005. WsbCatch(hr);
  1006. break;
  1007. case MEDIUM_CHANGER:
  1008. //
  1009. // Create the Medium Changer object and add it
  1010. // to the collection of unconfigured devices.
  1011. //
  1012. try {
  1013. if ( inquiryData->DeviceClaimed ) {
  1014. WsbAffirmHr( CoCreateInstance(CLSID_CRmsMediumChanger, NULL, CLSCTX_SERVER, IID_IRmsDevice, (void**) &pDevice));
  1015. WsbAffirmHr( pDevice->SetDeviceAddress( (BYTE)portNumber, i, inquiryData->TargetId, inquiryData->Lun ));
  1016. WsbAffirmHr( pDevice->SetDeviceType( RmsDeviceChanger ));
  1017. WsbAffirmHr( pDevice->SetDeviceInfo( &inquiryData->InquiryData[0], 36 ));
  1018. //
  1019. // Find library name
  1020. //
  1021. try {
  1022. WsbAffirmHr( getDeviceName( (UCHAR)portNumber, i, inquiryData->TargetId, inquiryData->Lun, deviceString ));
  1023. WsbTraceAlways( OLESTR("%ls"), deviceString );
  1024. // Create the name to use when creating a handle
  1025. CWsbBstrPtr name = deviceString;
  1026. name.Prepend( OLESTR("\\\\.\\") );
  1027. WsbAffirmHr( pDevice->SetDeviceName( name ));
  1028. WsbAffirmHr(pDevices->Add( pDevice ));
  1029. }
  1030. WsbCatch(hr);
  1031. }
  1032. pDevice = 0;
  1033. }
  1034. WsbCatch(hr);
  1035. break;
  1036. } // switch device type
  1037. WsbTraceAlways( OLESTR("\n") );
  1038. if (inquiryData->NextInquiryDataOffset == 0) {
  1039. break;
  1040. }
  1041. inquiryData = (PSCSI_INQUIRY_DATA) (pDataBuffer +
  1042. inquiryData->NextInquiryDataOffset);
  1043. } // for each device
  1044. } // for each bus
  1045. WsbTraceAlways( OLESTR("\n\n") );
  1046. hr = S_OK;
  1047. }
  1048. WsbCatch(hr);
  1049. return hr;
  1050. }
  1051. HRESULT
  1052. CRmsServer::findDriveLetter(
  1053. IN UCHAR portNo,
  1054. IN UCHAR pathNo,
  1055. IN UCHAR id,
  1056. IN UCHAR lun,
  1057. OUT OLECHAR *driveString)
  1058. /*++
  1059. Routine Description:
  1060. Find associated drive letter for defined parameters.
  1061. Arguments:
  1062. portNo - input port number.
  1063. pathNo - input path number.
  1064. id - input id.
  1065. lun - input logical unit number.
  1066. driveString - pointer to drive letter string to return.
  1067. Return Value:
  1068. S_OK - Success
  1069. --*/
  1070. {
  1071. HRESULT hr = E_FAIL;
  1072. const DWORD bufSize = 256; // 26*4 + 1 = 105 is all we really need
  1073. OLECHAR driveLetters[bufSize];
  1074. BOOL status;
  1075. DWORD accessMode = 0, // just get some drive properties.
  1076. shareMode = FILE_SHARE_READ;
  1077. HANDLE driveHandle = INVALID_HANDLE_VALUE;
  1078. SCSI_ADDRESS address;
  1079. DWORD returned;
  1080. OLECHAR string[25];
  1081. UINT uiType;
  1082. try {
  1083. // first find which drives are mapped.
  1084. DWORD len = GetLogicalDriveStrings( bufSize, driveLetters );
  1085. for ( DWORD i = 0; (i < len) && (hr != S_OK); i += 4 ) { // drive letters have the form "A:\"
  1086. uiType = GetDriveType( &driveLetters[i] );
  1087. switch ( uiType ) {
  1088. case DRIVE_REMOVABLE:
  1089. //
  1090. // get the SCSI address of the device and see if it's a match.
  1091. //
  1092. swprintf( string, OLESTR("\\\\.\\%C:"), driveLetters[i] );
  1093. driveHandle = CreateFile( string,
  1094. accessMode,
  1095. shareMode,
  1096. NULL,
  1097. OPEN_EXISTING,
  1098. 0,
  1099. NULL);
  1100. WsbAffirmHandle( driveHandle );
  1101. //
  1102. // Get the address structure.
  1103. //
  1104. status = DeviceIoControl( driveHandle,
  1105. IOCTL_SCSI_GET_ADDRESS,
  1106. NULL,
  1107. 0,
  1108. &address,
  1109. sizeof(SCSI_ADDRESS),
  1110. &returned,
  1111. FALSE );
  1112. if (!status ) {
  1113. //
  1114. // asking for the SCSI address is not always a valid request for
  1115. // all types of drives, so getting an error here means we're
  1116. // not talking to a SCSI device... so skip it.
  1117. //
  1118. break; // out of switch
  1119. }
  1120. //
  1121. // Let's check the SCSI address and see if we get a match.
  1122. //
  1123. if ( (address.PortNumber == portNo) &&
  1124. (address.PathId == pathNo) &&
  1125. (address.TargetId == id) &&
  1126. (address.Lun == lun)) {
  1127. // its a match...
  1128. wcscpy( driveString, &driveLetters[i] );
  1129. hr = S_OK;
  1130. }
  1131. break; // out of switch
  1132. } // switch
  1133. //
  1134. // Cleanup
  1135. //
  1136. if ( driveHandle != INVALID_HANDLE_VALUE ) {
  1137. status = CloseHandle( driveHandle );
  1138. driveHandle = INVALID_HANDLE_VALUE;
  1139. WsbAffirmStatus( status );
  1140. }
  1141. } // for each drive letter
  1142. } WsbCatchAndDo( hr,
  1143. if ( driveHandle != INVALID_HANDLE_VALUE ) {
  1144. CloseHandle(driveHandle);
  1145. } );
  1146. return hr;
  1147. }
  1148. HRESULT
  1149. CRmsServer::getDeviceName(
  1150. IN UCHAR portNo,
  1151. IN UCHAR pathNo,
  1152. IN UCHAR id,
  1153. IN UCHAR lun,
  1154. OUT OLECHAR *deviceName)
  1155. /*++
  1156. Routine Description:
  1157. Get device name from selected parameters.
  1158. Arguments:
  1159. portNo - port number.
  1160. pathNo - path number.
  1161. id - id.
  1162. lun - logical unit number.
  1163. deviceName - pointer to returned device name.
  1164. Return Value:
  1165. S_OK - Success
  1166. --*/
  1167. {
  1168. HRESULT hr = S_FALSE;
  1169. OLECHAR string[256];
  1170. DWORD len;
  1171. OLECHAR name[25];
  1172. // just go to the registry and get the DeviceName
  1173. swprintf( string,
  1174. OLESTR("HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port %d\\Scsi Bus %d\\Target Id %d\\Logical Unit Id %d"),
  1175. portNo, pathNo, id, lun );
  1176. hr = WsbGetRegistryValueString( NULL,
  1177. string,
  1178. OLESTR("DeviceName"),
  1179. name,
  1180. 25,
  1181. &len );
  1182. if ( S_OK == hr ) {
  1183. wcscpy( deviceName, name );
  1184. }
  1185. return hr;
  1186. }
  1187. HRESULT
  1188. CRmsServer::resolveUnconfiguredDevices(void)
  1189. /*++
  1190. This method goes through the unconfigured device list, which is created by
  1191. the ScanForDevices() method, and determines if a device has already been configured.
  1192. If a device is already configured, it is removed from the unconfigured device list.
  1193. --*/
  1194. {
  1195. HRESULT hr = E_FAIL;
  1196. WsbTraceIn(OLESTR("CRmsServer::resolveUnconfiguredDevices"), OLESTR(""));
  1197. BOOL tracingPlatform = 0;
  1198. try {
  1199. CComPtr<IWsbIndexedCollection> pDevices;
  1200. CComPtr<IWsbIndexedCollection> pLibs;
  1201. CComPtr<IRmsDevice> pDevice;
  1202. CComPtr<IWsbEnum> pEnumDevices;
  1203. CComPtr<IWsbEnum> pEnumLibs;
  1204. RmsDevice type;
  1205. BOOL deviceIsConfigured = FALSE;
  1206. // WsbAssertPointer( g_pTrace );
  1207. // WsbAffirmHr( g_pTrace->GetTraceSetting( WSB_TRACE_BIT_PLATFORM, &tracingPlatform ));
  1208. WsbAssertHr( GetLibraries( &pLibs ) );
  1209. WsbAffirmHr( pLibs->Enum( &pEnumLibs ));
  1210. WsbAssertPointer( pEnumLibs );
  1211. WsbAssertHr( GetUnconfiguredDevices( &pDevices ));
  1212. WsbAffirmHr( pDevices->Enum( &pEnumDevices ));
  1213. WsbAssertPointer( pEnumDevices );
  1214. // start off with the first unconfigured device.
  1215. hr = pEnumDevices->First( IID_IRmsDevice, (void **)&pDevice );
  1216. while ( S_OK == hr ) {
  1217. try {
  1218. CComPtr<IRmsLibrary> pLib;
  1219. deviceIsConfigured = FALSE;
  1220. //
  1221. // If a device is already in a library, then it is configured and
  1222. // should be removed from the list of unconfigured devices.
  1223. //
  1224. // To test if a device is in a library we simply go to each library
  1225. // and try to find the device.
  1226. //
  1227. WsbAffirmHr( pDevice->GetDeviceType( (LONG *) &type ) );
  1228. WsbTrace(OLESTR("CRmsServer::resolveUnconfiguredDevices: external loop: device type = %ld\n"), (LONG)type);
  1229. CComPtr<IWsbIndexedCollection> pChangers;
  1230. CComPtr<IWsbIndexedCollection> pDrives;
  1231. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pDevice;
  1232. WsbAssertPointer( pObject );
  1233. // Set up search method for the changer
  1234. WsbAffirmHr( pObject->SetFindBy( RmsFindByDeviceInfo ));
  1235. // start off with the first library.
  1236. hr = pEnumLibs->First( IID_IRmsLibrary, (void **)&pLib );
  1237. while ( S_OK == hr ) {
  1238. try {
  1239. WsbTrace(OLESTR("CRmsServer::resolveUnconfiguredDevices: internal loop: device type = %ld\n"), (LONG)type);
  1240. switch ( type ) {
  1241. case RmsDeviceChanger:
  1242. {
  1243. CComQIPtr<IRmsMediumChanger, &IID_IRmsMediumChanger> pChanger = pDevice;
  1244. WsbAffirmHr( pLib->GetChangers( &pChangers ) );
  1245. WsbAffirmHrOk( pChangers->Contains( pChanger ));
  1246. deviceIsConfigured = TRUE;
  1247. }
  1248. break;
  1249. default:
  1250. {
  1251. CComQIPtr<IRmsDrive, &IID_IRmsDrive> pDrive = pDevice;
  1252. WsbAffirmHr( pLib->GetDrives( &pDrives ) );
  1253. WsbAffirmHrOk( pDrives->Contains( pDrive ));
  1254. deviceIsConfigured = TRUE;
  1255. }
  1256. break;
  1257. }
  1258. }
  1259. WsbCatch(hr);
  1260. if ( deviceIsConfigured ) {
  1261. WsbAffirmHr( pDevices->RemoveAndRelease( pDevice ));
  1262. break;
  1263. }
  1264. pLib = 0;
  1265. hr = pEnumLibs->Next( IID_IRmsLibrary, (void **)&pLib );
  1266. }
  1267. }
  1268. WsbCatch(hr);
  1269. pDevice = 0;
  1270. if ( deviceIsConfigured )
  1271. hr = pEnumDevices->This( IID_IRmsDevice, (void **)&pDevice );
  1272. else
  1273. hr = pEnumDevices->Next( IID_IRmsDevice, (void **)&pDevice );
  1274. }
  1275. // if ( !tracingPlatform )
  1276. // WsbAffirmHr( g_pTrace->SetTraceOff( WSB_TRACE_BIT_PLATFORM ) );
  1277. hr = S_OK;
  1278. }
  1279. WsbCatch(hr);
  1280. // WsbCatchAndDo( hr,
  1281. // if (g_pTrace) {
  1282. // if ( !tracingPlatform )
  1283. // g_pTrace->SetTraceOff( WSB_TRACE_BIT_PLATFORM );
  1284. // }
  1285. // );
  1286. WsbTraceOut(OLESTR("CRmsServer::resolveUnconfiguredDevices"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1287. return hr;
  1288. }
  1289. HRESULT
  1290. CRmsServer::autoConfigureDevices(void)
  1291. /*++
  1292. This method automatically configures supported devices for RMS.
  1293. The algorythm simply goes through the list of unconfigured devices and adds them
  1294. to the appropriate library.
  1295. Eventually, we need to be smart about when to bypass the auto-config step in favor
  1296. of adminstrative overrides, but for now we'll automatically configure everything we
  1297. can.
  1298. --*/
  1299. {
  1300. //
  1301. // for each device in the unconfigured list, check if it was previously configured,
  1302. // if it is not add it to a library; otherwise delete it from the list of unconfigured devices.
  1303. //
  1304. HRESULT hr = E_FAIL;
  1305. WsbTraceIn(OLESTR("CRmsServer::autoConfigureDevices"), OLESTR(""));
  1306. try {
  1307. CComPtr<IWsbIndexedCollection> pDevices;
  1308. CComPtr<IWsbIndexedCollection> pLibs;
  1309. CComPtr<IWsbIndexedCollection> pCarts;
  1310. CComPtr<IRmsDevice> pDevice;
  1311. CComPtr<IWsbEnum> pEnumDevices;
  1312. RmsDevice type;
  1313. BOOL deviceWasConfigured;
  1314. WsbAssertHr( GetUnconfiguredDevices( &pDevices ));
  1315. WsbAssertHr( GetLibraries( &pLibs ));
  1316. WsbAssertHr( GetCartridges( &pCarts ));
  1317. WsbAffirmHr( pDevices->Enum( &pEnumDevices ));
  1318. WsbAssertPointer( pEnumDevices );
  1319. // first find all the changer devices
  1320. hr = pEnumDevices->First( IID_IRmsDevice, (void **)&pDevice );
  1321. while ( S_OK == hr ) {
  1322. try {
  1323. deviceWasConfigured = FALSE;
  1324. WsbAffirmHr( pDevice->GetDeviceType( (LONG *) &type ));
  1325. WsbTrace(OLESTR("CRmsServer::autoConfigureDevices: first loop: device type = %ld\n"), (LONG)type);
  1326. switch ( type ) {
  1327. case RmsDeviceChanger:
  1328. {
  1329. CComPtr<IWsbIndexedCollection> pChangers;
  1330. CComPtr<IWsbIndexedCollection> pDrives;
  1331. CComPtr<IWsbIndexedCollection> pMediaSets;
  1332. CComPtr<IRmsLibrary> pLib;
  1333. CComPtr<IRmsMediaSet> pMediaSet;
  1334. CComQIPtr<IRmsMediumChanger, &IID_IRmsMediumChanger> pChanger = pDevice;
  1335. WsbAssertPointer( pChanger );
  1336. CComQIPtr<IRmsChangerElement, &IID_IRmsChangerElement> pChangerElmt = pChanger;
  1337. WsbAssertPointer( pChanger );
  1338. // Create a Library object
  1339. WsbAffirmHr( CoCreateInstance( CLSID_CRmsLibrary, 0, CLSCTX_SERVER,
  1340. IID_IRmsLibrary, (void **)&pLib ));
  1341. // Fill in library info
  1342. WsbAffirmHr( pLib->SetName( RMS_DEFAULT_OPTICAL_LIBRARY_NAME ));
  1343. WsbAffirmHr( pLib->SetMediaSupported( RmsMedia8mm /*RmsMediaOptical*/ ));
  1344. // Add the library to the server's collection
  1345. WsbAffirmHr( pLibs->Add( pLib ));
  1346. // Create a media set
  1347. WsbAffirmHr( CoCreateInstance( CLSID_CRmsMediaSet, 0, CLSCTX_SERVER,
  1348. IID_IRmsMediaSet, (void **)&pMediaSet ));
  1349. // Fill in media set info
  1350. WsbAffirmHr( pMediaSet->SetName( RMS_DEFAULT_OPTICAL_MEDIASET_NAME ));
  1351. WsbAffirmHr( pMediaSet->SetMediaSupported( RmsMedia8mm /*RmsMediaOptical*/ ));
  1352. WsbAffirmHr( pMediaSet->SetMediaSetType( RmsMediaSetLibrary ) );
  1353. // Add the media set the libary's collection
  1354. WsbAssertHr( pLib->GetMediaSets( &pMediaSets ));
  1355. WsbAssertPointer( pMediaSets );
  1356. WsbAffirmHr( pMediaSets->Add( pMediaSet ));
  1357. pMediaSets = 0;
  1358. // Add the media set the server's collection
  1359. WsbAssertHr( GetMediaSets( &pMediaSets ) );
  1360. WsbAssertPointer( pMediaSets );
  1361. WsbAffirmHr( pMediaSets->Add( pMediaSet ));
  1362. // Add the changer device to the library's collection
  1363. WsbAffirmHr( pLib->GetChangers( &pChangers ));
  1364. WsbAssertPointer( pChangers );
  1365. WsbAffirmHr( pChangers->Add( pChanger ));
  1366. // Set the changer's element information
  1367. GUID libId;
  1368. WsbAffirmHr( pLib->GetLibraryId( &libId ));
  1369. WsbAffirmHr( pChangerElmt->SetLocation( RmsElementChanger, libId, GUID_NULL, 0, 0, 0, 0, FALSE));
  1370. WsbAffirmHr( pChangerElmt->SetMediaSupported( RmsMedia8mm /*RmsMediaOptical*/ ));
  1371. // Initialize the changer device
  1372. WsbAffirmHr( pChanger->Initialize() );
  1373. deviceWasConfigured = TRUE;
  1374. }
  1375. break;
  1376. default:
  1377. break;
  1378. }
  1379. }
  1380. WsbCatch(hr);
  1381. pDevice = 0;
  1382. if ( deviceWasConfigured )
  1383. hr = pEnumDevices->This( IID_IRmsDevice, (void **)&pDevice );
  1384. else
  1385. hr = pEnumDevices->Next( IID_IRmsDevice, (void **)&pDevice );
  1386. }
  1387. // any remaining devices are stand alone drives.
  1388. hr = pEnumDevices->First( IID_IRmsDevice, (void **)&pDevice );
  1389. while ( S_OK == hr ) {
  1390. try {
  1391. deviceWasConfigured = FALSE;
  1392. WsbAffirmHr( hr = pDevice->GetDeviceType( (LONG *) &type ));
  1393. WsbTrace(OLESTR("CRmsServer::autoConfigureDevices: second loop: device type = %ld\n"), (LONG)type);
  1394. switch ( type ) {
  1395. case RmsDeviceFixedDisk:
  1396. // find the fixed disk library and add this drive.
  1397. {
  1398. CComPtr<IWsbIndexedCollection> pDrives;
  1399. CComPtr<IWsbIndexedCollection> pMediaSets;
  1400. CComPtr<IRmsLibrary> pFixedLib;
  1401. CComPtr<IRmsMediaSet> pFixedMediaSet;
  1402. CComPtr<IRmsLibrary> pFindLib;
  1403. CComPtr<IRmsCartridge> pCart;
  1404. GUID libId = GUID_NULL;
  1405. GUID mediaSetId = GUID_NULL;
  1406. ULONG driveNo;
  1407. CComQIPtr<IRmsChangerElement, &IID_IRmsChangerElement> pDriveElmt = pDevice;
  1408. WsbAssertPointer( pDriveElmt );
  1409. CComQIPtr<IRmsDrive, &IID_IRmsDrive> pDrive = pDevice;
  1410. WsbAssertPointer( pDrive );
  1411. WsbAffirmHr( CoCreateInstance( CLSID_CRmsLibrary, 0, CLSCTX_SERVER,
  1412. IID_IRmsLibrary, (void **)&pFindLib ));
  1413. // Set up the find template
  1414. WsbAffirmHr( pFindLib->SetMediaSupported( RmsMediaFixed ));
  1415. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pFindLib;
  1416. WsbAffirmHr( pObject->SetFindBy( RmsFindByMediaSupported ));
  1417. // Find the library
  1418. hr = pLibs->Find( pFindLib, IID_IRmsLibrary, (void **)&pFixedLib );
  1419. if ( WSB_E_NOTFOUND == hr ) {
  1420. // We don't have a fixed drive library yet, so create one...
  1421. WsbAffirmHr( CoCreateInstance( CLSID_CRmsLibrary, 0, CLSCTX_SERVER,
  1422. IID_IRmsLibrary, (void **)&pFixedLib ));
  1423. WsbAffirmHr( pFixedLib->SetName( RMS_DEFAULT_FIXEDDRIVE_LIBRARY_NAME ));
  1424. WsbAffirmHr( pFixedLib->SetMediaSupported( RmsMediaFixed ));
  1425. WsbAffirmHr( pLibs->Add( pFixedLib ));
  1426. CComPtr<IRmsMediaSet> pMediaSet;
  1427. WsbAffirmHr( CoCreateInstance( CLSID_CRmsMediaSet, 0, CLSCTX_SERVER,
  1428. IID_IRmsMediaSet, (void **)&pMediaSet ));
  1429. WsbAffirmHr( pMediaSet->SetName( RMS_DEFAULT_FIXEDDRIVE_MEDIASET_NAME ));
  1430. WsbAffirmHr( pMediaSet->SetMediaSupported( RmsMediaFixed ));
  1431. WsbAffirmHr( pMediaSet->SetMediaSetType( RmsMediaSetLibrary ) );
  1432. // Add the media set the libary's collection
  1433. WsbAssertHr( pFixedLib->GetMediaSets( &pMediaSets ));
  1434. WsbAssertPointer( pMediaSets );
  1435. WsbAffirmHr( pMediaSets->Add( pMediaSet ));
  1436. pMediaSets = 0;
  1437. // Add the media set the server's collection
  1438. WsbAssertHr( GetMediaSets( &pMediaSets ) );
  1439. WsbAssertPointer( pMediaSets );
  1440. WsbAffirmHr( pMediaSets->Add( pMediaSet ));
  1441. DWORD num;
  1442. WsbAffirmHr( pMediaSets->GetEntries( &num ));
  1443. pMediaSets = 0;
  1444. WsbTrace(OLESTR("CRmsServer::autoConfigureDevices - type %d CRmsMediaSet created.\n"), RmsMediaFixed);
  1445. WsbTrace(OLESTR("CRmsServer::autoConfigureDevices - Number of sets = %d.\n"), num);
  1446. }
  1447. // Add the drive to the library
  1448. WsbAssertHr( pFixedLib->GetDrives( &pDrives ));
  1449. WsbAffirmHr( pDrives->Add( pDevice ));
  1450. WsbAffirmHr( pDrives->GetEntries( &driveNo ));
  1451. // Remove the drive form the unconfigured list
  1452. WsbAffirmHr( pDevices->RemoveAndRelease( pDevice ));
  1453. deviceWasConfigured = TRUE;
  1454. // Get library information
  1455. WsbAssertHr( pFixedLib->GetMediaSets( &pMediaSets ));
  1456. WsbAffirmHr( pFixedLib->GetLibraryId( &libId ));
  1457. WsbAffirmHr( pMediaSets->First( IID_IRmsMediaSet, (void **)&pFixedMediaSet ));
  1458. WsbAffirmHr( pFixedMediaSet->GetMediaSetId( &mediaSetId ));
  1459. // Set the location
  1460. WsbAffirmHr( pDriveElmt->SetLocation( RmsElementDrive, libId, mediaSetId,
  1461. driveNo-1, 0, 0, 0, 0 ));
  1462. // Set the kind of media supported
  1463. WsbAffirmHr( pDriveElmt->SetMediaSupported( RmsMediaFixed ));
  1464. // Create a cartridge for the media in the drive.
  1465. WsbAffirmHr( CoCreateInstance( CLSID_CRmsCartridge, 0, CLSCTX_SERVER,
  1466. IID_IRmsCartridge, (void **)&pCart ));
  1467. WsbAffirmHr( pCart->SetLocation( RmsElementDrive, libId, mediaSetId,
  1468. driveNo-1, 0, 0, 0, 0 ));
  1469. WsbAffirmHr( pCart->SetHome( RmsElementDrive, libId, mediaSetId,
  1470. driveNo-1, 0, 0, 0, 0 ));
  1471. WsbAffirmHr( pCart->SetStatus( RmsStatusScratch ));
  1472. WsbAffirmHr( pCart->SetType( RmsMediaFixed ));
  1473. // Add the drive to the Cartridge object.
  1474. WsbAffirmHr( pCart->SetDrive( pDrive ));
  1475. // Add the cartridge to the cartridge collection
  1476. WsbAffirmHr( pCarts->Add( pCart ));
  1477. }
  1478. break;
  1479. case RmsDeviceRemovableDisk:
  1480. // find manual library and add this stand alone drive.
  1481. break;
  1482. case RmsDeviceTape:
  1483. // find manual tape library and add this stand alone drive.
  1484. {
  1485. CComPtr<IWsbIndexedCollection> pDrives;
  1486. CComPtr<IWsbIndexedCollection> pMediaSets;
  1487. CComPtr<IRmsLibrary> pTapeLib;
  1488. CComPtr<IRmsMediaSet> pTapeMediaSet;
  1489. CComPtr<IRmsLibrary> pFindLib;
  1490. CComPtr<IRmsCartridge> pCart;
  1491. GUID libId = GUID_NULL;
  1492. GUID mediaSetId = GUID_NULL;
  1493. ULONG driveNo;
  1494. CComQIPtr<IRmsChangerElement, &IID_IRmsChangerElement> pDriveElmt = pDevice;
  1495. WsbAssertPointer( pDriveElmt );
  1496. CComQIPtr<IRmsDrive, &IID_IRmsDrive> pDrive = pDevice;
  1497. WsbAssertPointer( pDrive );
  1498. WsbAffirmHr( CoCreateInstance( CLSID_CRmsLibrary, 0, CLSCTX_SERVER,
  1499. IID_IRmsLibrary, (void **)&pFindLib ));
  1500. // Set up the find template
  1501. WsbAffirmHr( pFindLib->SetMediaSupported( RmsMedia4mm ));
  1502. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pFindLib;
  1503. WsbAffirmHr( pObject->SetFindBy( RmsFindByMediaSupported ));
  1504. // Find the library
  1505. hr = pLibs->Find( pFindLib, IID_IRmsLibrary, (void **)&pTapeLib );
  1506. if ( WSB_E_NOTFOUND == hr ) {
  1507. // We don't have a manual tape library yet, so create one...
  1508. WsbAffirmHr( CoCreateInstance( CLSID_CRmsLibrary, 0, CLSCTX_SERVER,
  1509. IID_IRmsLibrary, (void **)&pTapeLib ));
  1510. WsbAffirmHr( pTapeLib->SetName( RMS_DEFAULT_TAPE_LIBRARY_NAME ));
  1511. WsbAffirmHr( pTapeLib->SetMediaSupported( RmsMedia4mm ));
  1512. WsbAffirmHr( pLibs->Add( pTapeLib ));
  1513. CComPtr<IRmsMediaSet> pMediaSet;
  1514. WsbAffirmHr( CoCreateInstance( CLSID_CRmsMediaSet, 0, CLSCTX_SERVER,
  1515. IID_IRmsMediaSet, (void **)&pMediaSet ));
  1516. WsbAffirmHr( pMediaSet->SetName( RMS_DEFAULT_TAPE_MEDIASET_NAME ));
  1517. WsbAffirmHr( pMediaSet->SetMediaSupported( RmsMedia4mm ));
  1518. WsbAffirmHr( pMediaSet->SetMediaSetType( RmsMediaSetLibrary ) );
  1519. // Add the media set the library's collection
  1520. WsbAssertHr( pTapeLib->GetMediaSets( &pMediaSets ));
  1521. WsbAssertPointer( pMediaSets );
  1522. WsbAffirmHr( pMediaSets->Add( pMediaSet ));
  1523. pMediaSets = 0;
  1524. // Add the media set the server's collection
  1525. WsbAssertHr( GetMediaSets( &pMediaSets ) );
  1526. WsbAssertPointer( pMediaSets );
  1527. WsbAffirmHr( pMediaSets->Add( pMediaSet ));
  1528. pMediaSets = 0;
  1529. WsbTrace(OLESTR("CRmsServer::autoConfigureDevices - type %d CRmsMediaSet created.\n"), RmsMedia4mm);
  1530. }
  1531. // Add the drive to the library
  1532. WsbAssertHr( pTapeLib->GetDrives( &pDrives ));
  1533. WsbAffirmHr( pDrives->Add( pDevice ));
  1534. WsbAffirmHr( pDrives->GetEntries( &driveNo ));
  1535. // Remove the drive form the unconfigured list
  1536. WsbAffirmHr( pDevices->RemoveAndRelease( pDevice ));
  1537. deviceWasConfigured = TRUE;
  1538. // Get library information
  1539. WsbAssertHr( pTapeLib->GetMediaSets( &pMediaSets ));
  1540. WsbAffirmHr( pTapeLib->GetLibraryId( &libId ));
  1541. WsbAffirmHr( pMediaSets->First( IID_IRmsMediaSet, (void **)&pTapeMediaSet ));
  1542. WsbAffirmHr( pTapeMediaSet->GetMediaSetId( &mediaSetId ));
  1543. // Set the location
  1544. WsbAffirmHr( pDriveElmt->SetLocation( RmsElementDrive, libId, mediaSetId,
  1545. driveNo-1, 0, 0, 0, 0 ));
  1546. // Set the kind of media supported
  1547. WsbAffirmHr( pDriveElmt->SetMediaSupported( RmsMedia4mm ));
  1548. // Create a cartridge for the media in the drive.
  1549. // TODO: it may be empty.
  1550. WsbAffirmHr( CoCreateInstance( CLSID_CRmsCartridge, 0, CLSCTX_SERVER,
  1551. IID_IRmsCartridge, (void **)&pCart ));
  1552. WsbAffirmHr( pCart->SetLocation( RmsElementDrive, libId, mediaSetId,
  1553. driveNo-1, 0, 0, 0, 0 ));
  1554. WsbAffirmHr( pCart->SetHome( RmsElementDrive, libId, mediaSetId,
  1555. driveNo-1, 0, 0, 0, 0 ));
  1556. WsbAffirmHr( pCart->SetStatus( RmsStatusScratch ));
  1557. WsbAffirmHr( pCart->SetType( RmsMedia4mm ));
  1558. // Add the drive to the Cartridge object.
  1559. WsbAffirmHr( pCart->SetDrive( pDrive ));
  1560. // Add the cartridge to the cartridge collection
  1561. WsbAffirmHr( pCarts->Add( pCart ));
  1562. }
  1563. break;
  1564. case RmsDeviceCDROM:
  1565. case RmsDeviceWORM:
  1566. case RmsDeviceOptical:
  1567. // find manual library and add this stand alone drive.
  1568. break;
  1569. default:
  1570. break;
  1571. }
  1572. } WsbCatch(hr);
  1573. pDevice = 0;
  1574. if ( deviceWasConfigured )
  1575. hr = pEnumDevices->This( IID_IRmsDevice, (void **)&pDevice );
  1576. else
  1577. hr = pEnumDevices->Next( IID_IRmsDevice, (void **)&pDevice );
  1578. }
  1579. hr = S_OK;
  1580. } WsbCatch(hr);
  1581. WsbTraceOut(OLESTR("CRmsServer::autoConfigureDevices"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1582. return hr;
  1583. }
  1584. // Maximum number of retries for allocating and mounting a scratch piece of media
  1585. #define MAX_RETRIES 2
  1586. STDMETHODIMP
  1587. CRmsServer::MountScratchCartridge(
  1588. OUT GUID *pCartId,
  1589. IN REFGUID fromMediaSet,
  1590. IN REFGUID prevSideId,
  1591. IN OUT LONGLONG *pFreeSpace,
  1592. IN LONG blockingFactor,
  1593. IN BSTR displayName,
  1594. IN OUT IRmsDrive **ppDrive,
  1595. OUT IRmsCartridge **ppCartridge,
  1596. OUT IDataMover **ppDataMover,
  1597. IN DWORD dwOptions)
  1598. /*++
  1599. Implements:
  1600. IRmsServer::MountScratchCartridge
  1601. Notes: The default flag for mounting (in dwOptions) is blocking, i.e. waiting for the Mount
  1602. to finish even if the media is offline, the drive is not ready, etc. Calling with
  1603. flag set to non-blocking indicates performing the Mount only if everything is
  1604. available immediately.
  1605. --*/
  1606. {
  1607. HRESULT hr = S_OK;
  1608. WsbTraceIn(OLESTR("CRmsServer::MountScratchCartridge"), OLESTR("<%ls> <%ls> <%ls>"),
  1609. WsbQuickString(WsbGuidAsString(fromMediaSet)),
  1610. WsbQuickString(WsbPtrToLonglongAsString(pFreeSpace)),
  1611. WsbQuickString(WsbPtrToStringAsString((WCHAR **)&displayName)));
  1612. CWsbBstrPtr cartridgeName = "";
  1613. CWsbBstrPtr cartridgeDesc = "";
  1614. GUID cartId = GUID_NULL;
  1615. CWsbBstrPtr label;
  1616. try {
  1617. WsbAssertPointer(pCartId);
  1618. WsbAssertPointer(displayName);
  1619. WsbAssert(wcslen((WCHAR *)displayName) > 0, E_INVALIDARG);
  1620. WsbAffirmHrOk( IsReady() );
  1621. DWORD retry = 0;
  1622. CComPtr<IRmsDrive> pDrive;
  1623. CComPtr<IRmsCartridge> pCart[MAX_RETRIES];
  1624. CComPtr<IDataMover> pMover;
  1625. // Decrease max-retries to 1 if short-timeout or non-blocking is specified
  1626. // or if we want to allocate a specific side
  1627. DWORD maxRetries = MAX_RETRIES;
  1628. BOOL bShortTimeout = ( (dwOptions & RMS_SHORT_TIMEOUT) || (dwOptions & RMS_ALLOCATE_NO_BLOCK) ) ? TRUE : FALSE;
  1629. if (bShortTimeout || (GUID_NULL != prevSideId)) {
  1630. maxRetries = 1;
  1631. }
  1632. WsbTrace(OLESTR("Try to allocate and mount a scratch media %lu times\n"), maxRetries);
  1633. // Get the media set
  1634. CComPtr<IRmsMediaSet> pMediaSet;
  1635. WsbAffirmHr(CreateObject(fromMediaSet, CLSID_CRmsMediaSet, IID_IRmsMediaSet, RmsOpenExisting, (void **) &pMediaSet));
  1636. try {
  1637. // Allocate from the specified media set
  1638. WsbAffirmHr(pMediaSet->Allocate(prevSideId, pFreeSpace, displayName, dwOptions, &pCart[retry]));
  1639. // We want to try the scratch mount twice, but do not deallocate the first until we
  1640. // grab the second cartridge so we'll get a different cartridge. If both fail, drop out.
  1641. do {
  1642. //Clear these,in case we're retrying.
  1643. pDrive = NULL;
  1644. pMover = NULL;
  1645. try {
  1646. cartId = GUID_NULL;
  1647. cartridgeName = "";
  1648. cartridgeDesc = "";
  1649. WsbAffirmHr(pCart[retry]->GetCartridgeId(&cartId)); // for the log message
  1650. cartridgeName.Free();
  1651. WsbAffirmHr(pCart[retry]->GetName(&cartridgeName)); // for the log message
  1652. cartridgeDesc.Free();
  1653. WsbAffirmHr(pCart[retry]->GetDescription(&cartridgeDesc)); // for the log message
  1654. // Mount the cartridge.
  1655. WsbAffirmHr(pCart[retry]->Mount(&pDrive, dwOptions));
  1656. try {
  1657. // Set blockingFactor before we create the DataMover (only for a non-fixed block size media)
  1658. if (blockingFactor > 0) {
  1659. HRESULT hrBlock = pCart[retry]->IsFixedBlockSize();
  1660. WsbAffirmHr(hrBlock);
  1661. if (hrBlock == S_FALSE) {
  1662. WsbTrace(OLESTR("MountScratchCartridge: Setting block size on scratch media to %ld\n"), blockingFactor);
  1663. WsbAffirmHr(pCart[retry]->SetBlockSize(blockingFactor));
  1664. }
  1665. }
  1666. // Create a data mover for the application.
  1667. WsbAffirmHr(pCart[retry]->CreateDataMover(&pMover));
  1668. // Write out the On Media Label.
  1669. label.Free();
  1670. WsbAffirmHr(pMover->FormatLabel(displayName, &label));
  1671. WsbAffirmHr(pMover->WriteLabel(label));
  1672. // Mark the media private before returning.
  1673. WsbAffirmHr(pCart[retry]->SetStatus(RmsStatusPrivate));
  1674. // Since we don't have a DB, we need to persist the current state here.
  1675. WsbAffirmHr(SaveAll());
  1676. //
  1677. // Fill in the return arguments.
  1678. //
  1679. WsbAssertHr(pCart[retry]->GetCartridgeId(pCartId));
  1680. *ppDrive = pDrive;
  1681. pDrive.p->AddRef();
  1682. *ppCartridge = pCart[retry];
  1683. pCart[retry].p->AddRef();
  1684. *ppDataMover = pMover;
  1685. pMover.p->AddRef();
  1686. // We're done, so break out.
  1687. break;
  1688. } WsbCatchAndDo(hr,
  1689. // Best effort dismount...
  1690. DWORD dwDismountOptions = RMS_DISMOUNT_IMMEDIATE;
  1691. pCart[retry]->Dismount(dwDismountOptions);
  1692. WsbThrow(hr);
  1693. )
  1694. } WsbCatchAndDo(hr,
  1695. retry++;
  1696. // Check the exact error code:
  1697. // Alllow another retry only if the error may be media-related
  1698. BOOL bContinue = TRUE;
  1699. switch (hr) {
  1700. case RMS_E_SCRATCH_NOT_FOUND:
  1701. case RMS_E_CANCELLED:
  1702. case RMS_E_REQUEST_REFUSED:
  1703. case RMS_E_CARTRIDGE_UNAVAILABLE: // timeout during Mount
  1704. case HRESULT_FROM_WIN32(ERROR_DEVICE_NOT_AVAILABLE):
  1705. case HRESULT_FROM_WIN32(ERROR_INVALID_DRIVE):
  1706. case HRESULT_FROM_WIN32(ERROR_RESOURCE_DISABLED): // disabled drives
  1707. case HRESULT_FROM_WIN32(ERROR_DATABASE_FULL):
  1708. // Prevent another retry
  1709. bContinue = FALSE;
  1710. break;
  1711. default:
  1712. break;
  1713. }
  1714. // Persist original failure code
  1715. HRESULT hrFailure = hr;
  1716. if (bContinue && (retry < maxRetries)) {
  1717. WsbLogEvent(RMS_MESSAGE_SCRATCH_MOUNT_RETRY, sizeof(GUID), (void *) &cartId, (WCHAR *) displayName,
  1718. WsbHrAsString(hr), NULL);
  1719. // Allocate from the specified media set
  1720. hr = pMediaSet->Allocate(prevSideId, pFreeSpace, displayName, dwOptions, &pCart[retry]);
  1721. //Check media failures (ignore return value)
  1722. CheckForMediaFailures(hrFailure, pCart[(retry-1)], prevSideId);
  1723. // Deallocate the previous retry media set
  1724. pMediaSet->Deallocate(pCart[(retry-1)]);
  1725. // Make sure the allocate worked, if not, throw.
  1726. WsbAffirmHr(hr);
  1727. }
  1728. else {
  1729. //Check media failures (ignore return value)
  1730. CheckForMediaFailures(hrFailure, pCart[(retry-1)], prevSideId);
  1731. // If were on the last retry, deallocate the last media set and E_ABORT
  1732. pMediaSet->Deallocate(pCart[(retry-1)]);
  1733. // Abort
  1734. WsbThrow(hr);
  1735. }
  1736. )
  1737. } while (retry < maxRetries);
  1738. } WsbCatch(hr)
  1739. } WsbCatch(hr)
  1740. if ( SUCCEEDED(hr) ) {
  1741. WsbLogEvent(RMS_MESSAGE_CARTRIDGE_MOUNTED, sizeof(GUID), (void *) &cartId, (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, NULL);
  1742. }
  1743. else {
  1744. BOOL bShortTimeout = ( (dwOptions & RMS_SHORT_TIMEOUT) || (dwOptions & RMS_ALLOCATE_NO_BLOCK) ) ? TRUE : FALSE;
  1745. // In case of short-timeout or non-blocking mode or size-too-big error, log message with low severity
  1746. if (bShortTimeout || (RMS_E_SCRATCH_NOT_FOUND_TOO_SMALL == hr)) {
  1747. WsbLogEvent(RMS_MESSAGE_EXPECTED_SCRATCH_MOUNT_FAILED, sizeof(GUID), (void *) &cartId, (WCHAR *) displayName, WsbHrAsString(hr), NULL);
  1748. } else {
  1749. WsbLogEvent(RMS_MESSAGE_SCRATCH_MOUNT_FAILED, sizeof(GUID), (void *) &cartId, (WCHAR *) displayName, WsbHrAsString(hr), NULL);
  1750. }
  1751. }
  1752. WsbTraceOut(OLESTR("CRmsServer::MountScratchCartridge"), OLESTR("hr = <%ls>, name/desc = <%ls/%ls>, cartId = %ls"), WsbHrAsString(hr), (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, WsbQuickString(WsbGuidAsString(cartId)));
  1753. return hr;
  1754. }
  1755. STDMETHODIMP
  1756. CRmsServer::MountCartridge(
  1757. IN REFGUID cartId,
  1758. IN OUT IRmsDrive **ppDrive,
  1759. OUT IRmsCartridge **ppCartridge,
  1760. OUT IDataMover **ppDataMover,
  1761. IN DWORD dwOptions OPTIONAL,
  1762. IN DWORD threadId OPTIONAL)
  1763. /*++
  1764. Implements:
  1765. IRmsServer::MountCartridge
  1766. Notes: The default flag for mounting (in dwOptions) is blocking, i.e. waiting for the Mount
  1767. to finish even if the media is offline, the drive is not ready, etc. Calling with
  1768. flag set to non-blocking indicates performing the Mount only if everything is
  1769. available immediately.
  1770. --*/
  1771. {
  1772. HRESULT hr = S_OK;
  1773. WsbTraceIn(OLESTR("CRmsServer::MountCartridge"), OLESTR("<%ls>"), WsbGuidAsString(cartId));
  1774. CWsbBstrPtr cartridgeName = "";
  1775. CWsbBstrPtr cartridgeDesc = "";
  1776. try {
  1777. WsbAffirmHrOk( IsReady() );
  1778. CComPtr<IRmsDrive> pDrive;
  1779. CComPtr<IRmsCartridge> pCart;
  1780. CComPtr<IDataMover> pMover;
  1781. WsbAffirmHr(FindCartridgeById(cartId, &pCart));
  1782. cartridgeName.Free();
  1783. WsbAffirmHr(pCart->GetName(&cartridgeName)); // for the log message
  1784. cartridgeDesc.Free();
  1785. WsbAffirmHr(pCart->GetDescription(&cartridgeDesc)); // for the log message
  1786. WsbAffirmHr(pCart->Mount(&pDrive, dwOptions, threadId));
  1787. try {
  1788. WsbAffirmHr(pCart->CreateDataMover(&pMover));
  1789. //
  1790. // Fill in the return arguments.
  1791. //
  1792. *ppDrive = pDrive;
  1793. pDrive.p->AddRef();
  1794. *ppCartridge = pCart;
  1795. pCart.p->AddRef();
  1796. *ppDataMover = pMover;
  1797. pMover.p->AddRef();
  1798. } WsbCatchAndDo(hr,
  1799. // Best effort dismount...
  1800. DWORD dwDismountOptions = RMS_DISMOUNT_IMMEDIATE;
  1801. pCart->Dismount(dwDismountOptions);
  1802. WsbThrow(hr);
  1803. )
  1804. } WsbCatch(hr)
  1805. if ( SUCCEEDED(hr) ) {
  1806. WsbLogEvent(RMS_MESSAGE_CARTRIDGE_MOUNTED, sizeof(GUID), (void *) &cartId, (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, NULL);
  1807. }
  1808. else {
  1809. BOOL bShortTimeout = ( dwOptions & RMS_SHORT_TIMEOUT ) ? TRUE : FALSE;
  1810. // In case of short timeout, log message with low severity
  1811. if (bShortTimeout) {
  1812. WsbLogEvent(RMS_MESSAGE_EXPECTED_MOUNT_FAILED, sizeof(GUID), (void *) &cartId, (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, WsbHrAsString(hr), NULL);
  1813. } else {
  1814. WsbLogEvent(RMS_MESSAGE_MOUNT_FAILED, sizeof(GUID), (void *) &cartId, (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, WsbHrAsString(hr), NULL);
  1815. }
  1816. }
  1817. WsbTraceOut(OLESTR("CRmsServer::MountCartridge"), OLESTR("hr = <%ls>, name/desc = <%ls/%ls>, cartId = %ls"), WsbHrAsString(hr), (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, WsbQuickString(WsbGuidAsString(cartId)));
  1818. return hr;
  1819. }
  1820. STDMETHODIMP
  1821. CRmsServer::DismountCartridge(
  1822. IN REFGUID cartId, IN DWORD dwOptions)
  1823. /*++
  1824. Implements:
  1825. IRmsServer::DismountCartridge
  1826. Notes: The default flag for dismounting (in dwOptions) is not set for immediate dismount,
  1827. i.e. delaying the Dismount for a configurable amount of time. Setting the flag
  1828. for immediate dismount indicates performing Dismount immediately with no delay.
  1829. --*/
  1830. {
  1831. HRESULT hr = S_OK;
  1832. WsbTraceIn(OLESTR("CRmsServer::DismountCartridge"), OLESTR("<%ls>"), WsbGuidAsString(cartId));
  1833. CWsbBstrPtr cartridgeName = "";
  1834. CWsbBstrPtr cartridgeDesc = "";
  1835. try {
  1836. //
  1837. // Allow dismount when ready or in transition...
  1838. // to handle in-progress duplicate operations.
  1839. //
  1840. HRESULT hrReady = IsReady();
  1841. WsbAffirm((S_OK == hrReady) ||
  1842. (RMS_E_NOT_READY_SERVER_SUSPENDING == hrReady), hrReady);
  1843. CComPtr<IRmsCartridge> pCart;
  1844. WsbAffirmHr(FindCartridgeById(cartId, &pCart));
  1845. cartridgeName.Free();
  1846. WsbAffirmHr(pCart->GetName(&cartridgeName)); // for the log message
  1847. cartridgeDesc.Free();
  1848. WsbAffirmHr(pCart->GetDescription(&cartridgeDesc)); // for the log message
  1849. WsbAffirmHr(pCart->Dismount(dwOptions));
  1850. } WsbCatch(hr)
  1851. if ( SUCCEEDED(hr) ) {
  1852. WsbLogEvent(RMS_MESSAGE_CARTRIDGE_DISMOUNTED, sizeof(GUID), (void *) &cartId, (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, NULL);
  1853. }
  1854. else {
  1855. WsbLogEvent(RMS_MESSAGE_DISMOUNT_FAILED, sizeof(GUID), (void *) &cartId, (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, WsbHrAsString(hr), NULL);
  1856. }
  1857. WsbTraceOut(OLESTR("CRmsServer::DismountCartridge"), OLESTR("hr = <%ls>, name/desc = <%ls/%ls>, cartId = %ls"), WsbHrAsString(hr), (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, WsbQuickString(WsbGuidAsString(cartId)));
  1858. return hr;
  1859. }
  1860. STDMETHODIMP
  1861. CRmsServer::DuplicateCartridge(
  1862. IN REFGUID originalCartId,
  1863. IN REFGUID firstSideId,
  1864. IN OUT GUID *pCopyCartId,
  1865. IN REFGUID copySetId,
  1866. IN BSTR copyName,
  1867. OUT LONGLONG *pFreeSpace,
  1868. OUT LONGLONG *pCapacity,
  1869. IN DWORD options)
  1870. /*++
  1871. Implements:
  1872. IRmsServer::DuplicateCartridge
  1873. --*/
  1874. {
  1875. HRESULT hr = S_OK;
  1876. WsbTraceIn(OLESTR("CRmsServer::DuplicateCartridge"), OLESTR("<%ls> <%ls> <%ls> <%ls> <%d>"),
  1877. WsbQuickString(WsbGuidAsString(originalCartId)),
  1878. WsbQuickString(WsbPtrToGuidAsString(pCopyCartId)),
  1879. WsbQuickString(WsbGuidAsString(copySetId)),
  1880. WsbQuickString(WsbPtrToStringAsString((WCHAR **)&copyName)),
  1881. options);
  1882. CComPtr<IDataMover> pMover1;
  1883. CComPtr<IDataMover> pMover2;
  1884. GUID newCartId = GUID_NULL;
  1885. LONGLONG freeSpace = 0;
  1886. LONGLONG capacity = 0;
  1887. try {
  1888. WsbAffirmHrOk( IsReady() );
  1889. WsbAssertPointer( pCopyCartId );
  1890. // Mount the Copy first and then the original
  1891. CComPtr<IRmsDrive> pDrive1;
  1892. CComPtr<IRmsCartridge> pCart1;
  1893. CComPtr<IRmsDrive> pDrive2;
  1894. CComPtr<IRmsCartridge> pCart2;
  1895. LONG blockSize1=0, blockSize2=0;
  1896. // Serialize mounts for media copies
  1897. DWORD dwMountOptions = RMS_SERIALIZE_MOUNT;
  1898. // mount copy
  1899. if ( *pCopyCartId != GUID_NULL ) {
  1900. WsbAffirmHr(MountCartridge(*pCopyCartId, &pDrive2, &pCart2, &pMover2, dwMountOptions));
  1901. }
  1902. else {
  1903. GUID mediaSetId = copySetId;
  1904. CComPtr<IRmsCartridge> pCart;
  1905. WsbAffirmHr(FindCartridgeById(originalCartId, &pCart));
  1906. WsbAffirmHr(pCart->GetBlockSize(&blockSize1));
  1907. if ( mediaSetId == GUID_NULL ) {
  1908. WsbAffirmHr(pCart->GetMediaSetId(&mediaSetId));
  1909. }
  1910. // Get capacity of original media and adjust by fudge factor
  1911. LONGLONG capacity=0;
  1912. CComQIPtr<IRmsStorageInfo, &IID_IRmsStorageInfo> pInfo = pCart;
  1913. WsbAffirmHr(pInfo->GetCapacity(&capacity));
  1914. LONG fudge = RMS_DEFAULT_MEDIA_COPY_TOLERANCE;
  1915. DWORD size;
  1916. OLECHAR tmpString[256];
  1917. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_MEDIA_COPY_TOLERANCE, tmpString, 256, &size))) {
  1918. // Get the value.
  1919. fudge = wcstol(tmpString, NULL, 10);
  1920. }
  1921. capacity -= (capacity * fudge) / 100;
  1922. WsbAffirmHr(MountScratchCartridge( &newCartId, mediaSetId, firstSideId, &capacity, blockSize1, copyName, &pDrive2, &pCart2, &pMover2, dwMountOptions ));
  1923. }
  1924. // Mount original (in a non-blocking manner)
  1925. dwMountOptions |= RMS_MOUNT_NO_BLOCK;
  1926. WsbAffirmHr(MountCartridge(originalCartId, &pDrive1, &pCart1, &pMover1, dwMountOptions));
  1927. // Verify matching block size (only for a non-fixed block size media)
  1928. HRESULT hrBlock = pCart1->IsFixedBlockSize();
  1929. WsbAffirmHr(hrBlock);
  1930. if (hrBlock == S_FALSE) {
  1931. if (blockSize1 == 0) {
  1932. // didn't get it yet...
  1933. WsbAffirmHr(pCart1->GetBlockSize(&blockSize1));
  1934. }
  1935. WsbAffirmHr(pCart2->GetBlockSize(&blockSize2));
  1936. WsbAssert(blockSize1 == blockSize2, E_UNEXPECTED);
  1937. }
  1938. WsbAffirmHr(pMover1->Duplicate(pMover2, options, NULL, NULL));
  1939. // Now get stats to return to caller.
  1940. WsbAffirmHr(pMover2->GetLargestFreeSpace(&freeSpace, &capacity));
  1941. if (pFreeSpace) {
  1942. *pFreeSpace = freeSpace;
  1943. }
  1944. if (pCapacity) {
  1945. *pCapacity = capacity;
  1946. }
  1947. } WsbCatch(hr)
  1948. if ( pMover1 ) {
  1949. DismountCartridge(originalCartId);
  1950. }
  1951. if ( pMover2 ) {
  1952. // We always perform immediate dismount to the copy media
  1953. // (We may need to recycle a new copy in case of an error + there's no benefit in a deferred
  1954. // dismount for the copy-media - we don't expect the copy-media to be needed again soon)
  1955. DWORD dwDismountOptions = RMS_DISMOUNT_IMMEDIATE;
  1956. if (newCartId == GUID_NULL) {
  1957. // this is the case of an existing copy
  1958. DismountCartridge(*pCopyCartId, dwDismountOptions);
  1959. } else {
  1960. // this is the case of a scratch copy
  1961. DismountCartridge(newCartId, dwDismountOptions);
  1962. // if mounting of original failed, we always recycle the scratch copy
  1963. if (((options & RMS_DUPLICATE_RECYCLEONERROR) || (pMover1 == NULL)) && (S_OK != hr)) {
  1964. //
  1965. // If we failed and a scratch mount was performed
  1966. // we need to recycle the cartridge since the calling
  1967. // app can't be depended upon to do this.
  1968. //
  1969. RecycleCartridge(newCartId, 0);
  1970. } else {
  1971. *pCopyCartId = newCartId;
  1972. }
  1973. }
  1974. }
  1975. WsbTraceOut(OLESTR("CRmsServer::DuplicateCartridge"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1976. return hr;
  1977. }
  1978. STDMETHODIMP
  1979. CRmsServer::RecycleCartridge(
  1980. IN REFGUID cartId,
  1981. IN DWORD options)
  1982. /*++
  1983. Implements:
  1984. IRmsServer::RecycleCartridge
  1985. --*/
  1986. {
  1987. HRESULT hr = S_OK;
  1988. WsbTraceIn(OLESTR("CRmsServer::RecycleCartridge"), OLESTR("<%ls> <%d>"), WsbGuidAsString(cartId), options);
  1989. CWsbBstrPtr cartridgeName = "";
  1990. CWsbBstrPtr cartridgeDesc = "";
  1991. try {
  1992. //
  1993. // Allow recycle when ready or in transition...
  1994. // to handle in-progress duplicate operations.
  1995. //
  1996. HRESULT hrReady = IsReady();
  1997. WsbAffirm((S_OK == hrReady) ||
  1998. (RMS_E_NOT_READY_SERVER_SUSPENDING == hrReady), hrReady);
  1999. CComPtr<IRmsCartridge> pCart;
  2000. GUID mediaSetId;
  2001. CComPtr<IRmsMediaSet> pMediaSet;
  2002. WsbAffirmHr(FindCartridgeById(cartId, &pCart));
  2003. cartridgeName.Free();
  2004. WsbAffirmHr(pCart->GetName(&cartridgeName)); // for the log message
  2005. cartridgeDesc.Free();
  2006. WsbAffirmHr(pCart->GetDescription(&cartridgeDesc)); // for the log message
  2007. // Now go to the media set to deallocate
  2008. WsbAffirmHr(pCart->GetMediaSetId(&mediaSetId));
  2009. WsbAffirmHr(CreateObject(mediaSetId, CLSID_CRmsMediaSet, IID_IRmsMediaSet, RmsOpenExisting, (void **) &pMediaSet));
  2010. WsbAffirmHr(pMediaSet->Deallocate(pCart));
  2011. } WsbCatch(hr)
  2012. if ( SUCCEEDED(hr) ) {
  2013. WsbLogEvent(RMS_MESSAGE_CARTRIDGE_RECYCLED, sizeof(GUID), (void *) &cartId, (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, NULL);
  2014. }
  2015. else {
  2016. WsbLogEvent(RMS_MESSAGE_CARTRIDGE_RECYCLE_FAILED, sizeof(GUID), (void *) &cartId, (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, WsbHrAsString(hr), NULL);
  2017. }
  2018. WsbTraceOut(OLESTR("CRmsServer::RecycleCartridge"), OLESTR("hr = <%ls>, name/desc = <%ls/%ls>, cartId = %ls"), WsbHrAsString(hr), (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, WsbQuickString(WsbGuidAsString(cartId)));
  2019. return hr;
  2020. }
  2021. STDMETHODIMP
  2022. CRmsServer::FindLibraryById(
  2023. IN REFGUID libId,
  2024. OUT IRmsLibrary **pLib)
  2025. /*++
  2026. Implements:
  2027. IRmsServer::FindLibraryById
  2028. --*/
  2029. {
  2030. HRESULT hr = E_FAIL;
  2031. CComPtr<IRmsCartridge> pFindLib;
  2032. try {
  2033. WsbAssertPointer( pLib );
  2034. // Create a cartridge template
  2035. WsbAffirmHr( CoCreateInstance( CLSID_CRmsLibrary, 0, CLSCTX_SERVER,
  2036. IID_IRmsLibrary, (void **)&pFindLib ));
  2037. // Fill in the find template
  2038. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pFindLib;
  2039. WsbAffirmHr( pObject->SetObjectId( libId ));
  2040. WsbAffirmHr( pObject->SetFindBy( RmsFindByObjectId ));
  2041. // Find the cartridge
  2042. WsbAffirmHr( m_pLibraries->Find( pFindLib, IID_IRmsLibrary, (void **)pLib ));
  2043. hr = S_OK;
  2044. } WsbCatchAndDo(hr,
  2045. if ( WSB_E_NOTFOUND == hr) hr = RMS_E_LIBRARY_NOT_FOUND;
  2046. WsbTrace(OLESTR("CRmsServer::FindLibraryById - %ls Not Found. hr = <%ls>\n"),WsbGuidAsString(libId),WsbHrAsString(hr));
  2047. );
  2048. return hr;
  2049. }
  2050. STDMETHODIMP
  2051. CRmsServer::FindCartridgeById(
  2052. IN REFGUID cartId,
  2053. OUT IRmsCartridge **ppCart)
  2054. /*++
  2055. Implements:
  2056. IRmsServer::FindCartridgeById
  2057. --*/
  2058. {
  2059. HRESULT hr = S_OK;
  2060. WsbTraceIn(OLESTR("CRmsServer::FindCartridgeById"), OLESTR("%ls"), WsbGuidAsString(cartId));
  2061. try {
  2062. WsbAssertPointer(ppCart);
  2063. //
  2064. // The search algorithms attempts to avoid unnecessary throws that
  2065. // clutter the trace file. Each media management subsystem is tried.
  2066. //
  2067. // First check the most active cartridge.
  2068. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  2069. if (m_pActiveCartridge) {
  2070. GUID activeId;
  2071. WsbAffirmHr( m_pActiveCartridge->GetCartridgeId(&activeId));
  2072. if (activeId == cartId) {
  2073. *ppCart = m_pActiveCartridge;
  2074. m_pActiveCartridge.p->AddRef();
  2075. hr = S_OK;
  2076. }
  2077. }
  2078. if (hr != S_OK ) {
  2079. //
  2080. // Try native RMS
  2081. //
  2082. try {
  2083. hr = S_OK;
  2084. CComPtr<IRmsCartridge> pFindCart;
  2085. // Create a cartridge template
  2086. WsbAffirmHr(CoCreateInstance(CLSID_CRmsCartridge, 0, CLSCTX_SERVER,
  2087. IID_IRmsCartridge, (void **)&pFindCart));
  2088. // Fill in the find template
  2089. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pFindCart;
  2090. WsbAffirmHr( pObject->SetObjectId(cartId));
  2091. WsbAffirmHr( pObject->SetFindBy(RmsFindByObjectId));
  2092. // Try to find the cartridge in the collection of active cartridges.
  2093. hr = m_pActiveCartridges->Find(pFindCart, IID_IRmsCartridge, (void **)ppCart);
  2094. WsbAffirm(S_OK == hr || WSB_E_NOTFOUND == hr, hr);
  2095. if (WSB_E_NOTFOUND == hr) {
  2096. // Find the cartridge in the collection of cartridges
  2097. hr = m_pCartridges->Find(pFindCart, IID_IRmsCartridge, (void **)ppCart);
  2098. WsbAffirm(S_OK == hr || WSB_E_NOTFOUND == hr, hr);
  2099. if (WSB_E_NOTFOUND == hr) {
  2100. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  2101. }
  2102. }
  2103. } WsbCatch(hr);
  2104. }
  2105. if ( hr != S_OK ) {
  2106. //
  2107. // Try NTMS
  2108. //
  2109. try {
  2110. hr = S_OK;
  2111. hr = IsNTMSInstalled();
  2112. if ( S_OK == hr ) {
  2113. hr = m_pNTMS->FindCartridge(cartId, ppCart);
  2114. WsbAffirm(S_OK == hr || RMS_E_CARTRIDGE_NOT_FOUND == hr, hr);
  2115. }
  2116. else {
  2117. switch(hr) {
  2118. case RMS_E_NOT_CONFIGURED_FOR_NTMS:
  2119. case RMS_E_NTMS_NOT_REGISTERED:
  2120. // Normal errors
  2121. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  2122. break;
  2123. default:
  2124. // Unexpected Error!
  2125. WsbThrow(hr);
  2126. break;
  2127. }
  2128. }
  2129. } WsbCatch(hr);
  2130. }
  2131. } WsbCatchAndDo(hr,
  2132. CWsbStringPtr idString = cartId;
  2133. WsbLogEvent(RMS_MESSAGE_CARTRIDGE_NOT_FOUND, 0, NULL, (WCHAR *) idString, WsbHrAsString(hr), NULL);
  2134. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  2135. );
  2136. WsbTraceOut(OLESTR("CRmsServer::FindCartridgeById"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2137. return hr;
  2138. }
  2139. STDMETHODIMP
  2140. CRmsServer::CreateObject(
  2141. IN REFGUID objectId,
  2142. IN REFCLSID rclsid,
  2143. IN REFIID riid,
  2144. IN DWORD dwCreate,
  2145. OUT void **ppvObj)
  2146. /*++
  2147. Implements:
  2148. IRmsServer::CreateObject
  2149. --*/
  2150. {
  2151. HRESULT hr = E_FAIL;
  2152. try {
  2153. WsbAssertPointer( ppvObj );
  2154. WsbAssert( NULL == *ppvObj, E_INVALIDARG );
  2155. CComPtr<IWsbIndexedCollection> pCollection;
  2156. CComPtr<IWsbCollectable> pCollectable;
  2157. if ( objectId != GUID_NULL ) {
  2158. CComPtr<IRmsComObject> pFindObject;
  2159. // Create an object template
  2160. WsbAffirmHr( CoCreateInstance( rclsid, 0, CLSCTX_SERVER,
  2161. IID_IRmsComObject, (void **)&pFindObject ));
  2162. WsbAffirmHr( pFindObject->SetObjectId( objectId ));
  2163. WsbAffirmHr( pFindObject->SetFindBy( RmsFindByObjectId ));
  2164. // The only kinds created must support: IRmsComObject (for the object Id),
  2165. // and IWsbCollectable (to be added to a collection).
  2166. // See if the object is already in a collection.
  2167. try {
  2168. if ( CLSID_CRmsCartridge == rclsid ) {
  2169. pCollection = m_pCartridges;
  2170. WsbAffirmHrOk( m_pCartridges->Find( pFindObject,
  2171. IID_IWsbCollectable, (void **) &pCollectable ) );
  2172. }
  2173. else if ( CLSID_CRmsLibrary == rclsid ) {
  2174. pCollection = m_pLibraries;
  2175. WsbAffirmHrOk( m_pLibraries->Find( pFindObject,
  2176. IID_IWsbCollectable, (void **) &pCollectable ) );
  2177. }
  2178. else if ( CLSID_CRmsMediaSet == rclsid ) {
  2179. pCollection = m_pMediaSets;
  2180. WsbAffirmHrOk( m_pMediaSets->Find( pFindObject,
  2181. IID_IWsbCollectable, (void **) &pCollectable ) );
  2182. }
  2183. else if ( CLSID_CRmsRequest == rclsid ) {
  2184. pCollection = m_pRequests;
  2185. WsbAffirmHrOk( m_pRequests->Find( pFindObject,
  2186. IID_IWsbCollectable, (void **) &pCollectable ) );
  2187. }
  2188. else if ( CLSID_CRmsClient == rclsid ) {
  2189. pCollection = m_pClients;
  2190. WsbAffirmHrOk( m_pClients->Find( pFindObject,
  2191. IID_IWsbCollectable, (void **) &pCollectable ) );
  2192. }
  2193. else {
  2194. WsbThrow( E_UNEXPECTED );
  2195. }
  2196. hr = S_OK;
  2197. } WsbCatch(hr);
  2198. }
  2199. else if ( RmsOpenExisting == dwCreate ) {
  2200. // If we get GUID_NULL, we must going after a default object, and we only support this
  2201. // with existing objects. This is only legal if the default media set registry key exists.
  2202. if ( CLSID_CRmsMediaSet == rclsid ) {
  2203. CWsbBstrPtr defaultMediaSetName = RMS_DEFAULT_MEDIASET;
  2204. DWORD size;
  2205. OLECHAR tmpString[256];
  2206. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_DEFAULT_MEDIASET, tmpString, 256, &size))) {
  2207. // Get the value.
  2208. defaultMediaSetName = tmpString;
  2209. }
  2210. else {
  2211. WsbAssert( objectId != GUID_NULL, E_INVALIDARG );
  2212. }
  2213. CComPtr<IRmsComObject> pFindObject;
  2214. // Create an object template
  2215. WsbAffirmHr( CoCreateInstance( rclsid, 0, CLSCTX_SERVER,
  2216. IID_IRmsComObject, (void **)&pFindObject ));
  2217. WsbAffirmHr( pFindObject->SetName( defaultMediaSetName ));
  2218. WsbAffirmHr( pFindObject->SetFindBy( RmsFindByName ));
  2219. pCollection = m_pMediaSets;
  2220. WsbAffirmHrOk( m_pMediaSets->Find( pFindObject,
  2221. IID_IWsbCollectable, (void **) &pCollectable ) );
  2222. WsbTrace(OLESTR("Using Default MediaSet <%ls>.\n"), (WCHAR *) defaultMediaSetName);
  2223. hr = S_OK;
  2224. }
  2225. else {
  2226. WsbThrow( E_INVALIDARG );
  2227. }
  2228. }
  2229. else {
  2230. WsbThrow( E_UNEXPECTED );
  2231. }
  2232. // If the object wasn't found we create it here, and add it to the appropriate collection.
  2233. switch ( (RmsCreate)dwCreate ) {
  2234. case RmsOpenExisting:
  2235. if ( S_OK == hr ) {
  2236. WsbAffirmHr( pCollectable->QueryInterface( riid, ppvObj ) );
  2237. }
  2238. else {
  2239. WsbThrow( hr );
  2240. }
  2241. break;
  2242. case RmsOpenAlways:
  2243. if ( WSB_E_NOTFOUND == hr ) {
  2244. // Create the object
  2245. WsbAffirmHr( CoCreateInstance( rclsid, 0, CLSCTX_SERVER,
  2246. IID_IWsbCollectable, (void **) &pCollectable ));
  2247. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pCollectable;
  2248. WsbAffirmPointer( pObject );
  2249. WsbAffirmHr( pObject->SetObjectId( objectId ) );
  2250. // Before we add the collection, make sure the interface is supported.
  2251. WsbAffirmHr( pCollectable->QueryInterface( riid, ppvObj ));
  2252. WsbAffirmPointer( pCollection );
  2253. WsbAffirmHr( pCollection->Add( pCollectable ) );
  2254. }
  2255. else if ( S_OK == hr ) {
  2256. WsbAffirmHr( pCollectable->QueryInterface( riid, ppvObj ) );
  2257. }
  2258. else {
  2259. WsbThrow( hr );
  2260. }
  2261. break;
  2262. case RmsCreateNew:
  2263. if ( WSB_E_NOTFOUND == hr ) {
  2264. // Create the object
  2265. WsbAffirmHr( CoCreateInstance( rclsid, 0, CLSCTX_SERVER,
  2266. IID_IWsbCollectable, (void **) &pCollectable ));
  2267. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pCollectable;
  2268. WsbAffirmPointer( pObject );
  2269. WsbAffirmHr( pObject->SetObjectId( objectId ) );
  2270. // Before we add the collection, make sure the interface is supported.
  2271. WsbAffirmHr( pCollectable->QueryInterface( riid, ppvObj ) );
  2272. WsbAffirmPointer( pCollection );
  2273. WsbAffirmHr( pCollection->Add( pCollectable ) );
  2274. }
  2275. else if ( S_OK == hr ) {
  2276. WsbThrow( RMS_E_ALREADY_EXISTS );
  2277. }
  2278. else {
  2279. WsbThrow( hr );
  2280. }
  2281. break;
  2282. default:
  2283. WsbThrow( E_UNEXPECTED );
  2284. break;
  2285. }
  2286. hr = S_OK;
  2287. }
  2288. WsbCatchAndDo( hr,
  2289. if ( WSB_E_NOTFOUND == hr) hr = RMS_E_NOT_FOUND;
  2290. WsbTrace(OLESTR("!!!!! ERROR !!!!! CRmsServer::CreateObject: %ls; hr = <%ls>\n"),WsbGuidAsString(objectId),WsbHrAsString(hr));
  2291. );
  2292. return hr;
  2293. }
  2294. HRESULT
  2295. CRmsServer::getHardDrivesToUseFromRegistry(
  2296. OUT OLECHAR *pDrivesToUse,
  2297. OUT DWORD *pLen)
  2298. /*++
  2299. --*/
  2300. {
  2301. HRESULT hr = S_OK;
  2302. WsbTraceIn(OLESTR("CRmsServer::GetHardpDrivesToUseFromRegistry"),OLESTR(""));
  2303. try {
  2304. WsbAssert(0 != pDrivesToUse, E_POINTER);
  2305. WsbAssert(0 != pLen, E_POINTER);
  2306. DWORD sizeGot;
  2307. OLECHAR tmpString[1000];
  2308. *pLen = 0;
  2309. pDrivesToUse[0] = OLECHAR('\0');
  2310. pDrivesToUse[1] = OLECHAR('\0');
  2311. //
  2312. // Get the default value
  2313. //
  2314. WsbAffirmHr(WsbEnsureRegistryKeyExists (NULL, RMS_REGISTRY_STRING));
  2315. WsbAffirmHr(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_HARD_DRIVES_TO_USE,
  2316. tmpString, RMS_DIR_LEN, &sizeGot));
  2317. // We are doing some string manipulation here to match the Win32 call
  2318. // GetLogicalDriveStrings. It returns a string of drives separated by
  2319. // Nulls with a double NULL at the end. For example: if we want to use
  2320. // the C and E drives the string should be: C:\<null>E:\<null><null>
  2321. // and len would be 8.
  2322. DWORD myCharCount = 0;
  2323. sizeGot = wcslen(tmpString);
  2324. for (DWORD i = 0; i < sizeGot; i++) {
  2325. swprintf((OLECHAR *)&pDrivesToUse[myCharCount], OLESTR("%c:\\"), tmpString[i]);
  2326. myCharCount = ((i + 1)* 4);
  2327. }
  2328. pDrivesToUse[myCharCount] = OLECHAR('\0');
  2329. if (myCharCount != 0) {
  2330. *pLen = myCharCount + 1;
  2331. }
  2332. } WsbCatch(hr);
  2333. WsbTraceOut(OLESTR("CRmsServer::GetHardpDrivesToUseFromRegistry"), OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  2334. return hr;
  2335. }
  2336. HRESULT
  2337. CRmsServer::enableAsBackupOperator(void)
  2338. /*++
  2339. Routine Description:
  2340. This routine enables backup operator privilege for the process. This is required
  2341. to insure that RMS has full access to all resources on the system, primarily with
  2342. regard to the data mover.
  2343. Arguments:
  2344. None.
  2345. Return Values:
  2346. S_OK - Success.
  2347. --*/
  2348. {
  2349. HRESULT hr = E_FAIL;
  2350. try {
  2351. HANDLE pHandle;
  2352. LUID backupValue;
  2353. HANDLE tokenHandle;
  2354. TOKEN_PRIVILEGES newState;
  2355. DWORD lErr;
  2356. pHandle = GetCurrentProcess();
  2357. WsbAffirmStatus(OpenProcessToken(pHandle, MAXIMUM_ALLOWED, &tokenHandle));
  2358. //
  2359. // adjust backup token privileges
  2360. //
  2361. WsbAffirmStatus(LookupPrivilegeValueW(NULL, L"SeBackupPrivilege", &backupValue));
  2362. newState.PrivilegeCount = 1;
  2363. newState.Privileges[0].Luid = backupValue;
  2364. newState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  2365. WsbAffirmStatus(AdjustTokenPrivileges(tokenHandle, FALSE, &newState, (DWORD)0, NULL, NULL));
  2366. //
  2367. // Note that AdjustTokenPrivileges may return success even if it did not assign all privileges.
  2368. // We check last error here to insure everything was set.
  2369. //
  2370. if ( (lErr = GetLastError()) != ERROR_SUCCESS ) {
  2371. // Not backup user or some other error
  2372. //
  2373. // TODO: Should we fail here or just log something?
  2374. //
  2375. WsbLogEvent( RMS_MESSAGE_SERVICE_UNABLE_TO_SET_BACKUP_PRIVILEGE, 0, NULL,
  2376. WsbHrAsString(HRESULT_FROM_WIN32(lErr)), NULL );
  2377. }
  2378. WsbAffirmStatus(LookupPrivilegeValueW(NULL, L"SeRestorePrivilege", &backupValue));
  2379. newState.PrivilegeCount = 1;
  2380. newState.Privileges[0].Luid = backupValue;
  2381. newState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  2382. WsbAffirmStatus(AdjustTokenPrivileges(tokenHandle, FALSE, &newState, (DWORD)0, NULL, NULL));
  2383. //
  2384. // Note that AdjustTokenPrivileges may return success even if it did not assign all privileges.
  2385. // We check last error here to insure everything was set.
  2386. //
  2387. if ( (lErr = GetLastError()) != ERROR_SUCCESS ) {
  2388. // Not backup user or some other error
  2389. //
  2390. // TODO: Should we fail here or just log something?
  2391. //
  2392. WsbLogEvent( RMS_MESSAGE_SERVICE_UNABLE_TO_SET_RESTORE_PRIVILEGE, 0, NULL,
  2393. WsbHrAsString(HRESULT_FROM_WIN32(lErr)), NULL );
  2394. }
  2395. CloseHandle( tokenHandle );
  2396. hr = S_OK;
  2397. }
  2398. WsbCatch( hr );
  2399. return hr;
  2400. }
  2401. STDMETHODIMP
  2402. CRmsServer::ChangeState(
  2403. IN LONG newState)
  2404. /*++
  2405. Implements:
  2406. IRmsServer::CreateObject
  2407. --*/
  2408. {
  2409. HRESULT hr = S_OK;
  2410. WsbTraceIn(OLESTR("CRmsServer::ChangeState"), OLESTR("<%d>"), newState);
  2411. try {
  2412. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
  2413. WsbAssertPointer( pObject );
  2414. switch ((RmsServerState) newState) {
  2415. case RmsServerStateStarting:
  2416. case RmsServerStateStarted:
  2417. case RmsServerStateInitializing:
  2418. case RmsServerStateReady:
  2419. case RmsServerStateStopping:
  2420. case RmsServerStateStopped:
  2421. case RmsServerStateSuspending:
  2422. case RmsServerStateSuspended:
  2423. case RmsServerStateResuming:
  2424. WsbAffirmHr(pObject->SetState(newState));
  2425. break;
  2426. default:
  2427. WsbAssert(0, E_UNEXPECTED);
  2428. break;
  2429. }
  2430. } WsbCatch(hr);
  2431. WsbTraceOut(OLESTR("CRmsServer::ChangeState"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2432. return hr;
  2433. }
  2434. HRESULT
  2435. CRmsServer::IsReady(void)
  2436. /*++
  2437. Implements:
  2438. IRmsServer::IsReady
  2439. --*/
  2440. {
  2441. HRESULT hr = S_OK;
  2442. try {
  2443. BOOL isEnabled;
  2444. HRESULT status;
  2445. RmsServerState state;
  2446. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
  2447. WsbAssertPointer( pObject );
  2448. WsbAffirm(m_LockReference == 0, RMS_E_NOT_READY_SERVER_LOCKED);
  2449. WsbAffirmHr( isEnabled = pObject->IsEnabled());
  2450. WsbAffirmHr( pObject->GetState( (LONG *)&state ));
  2451. WsbAffirmHr( pObject->GetStatusCode( &status ));
  2452. if ( S_OK == isEnabled ) {
  2453. if ( RmsServerStateReady == state ) {
  2454. hr = S_OK;
  2455. }
  2456. else {
  2457. if ( S_OK == status ) {
  2458. switch ( state ) {
  2459. case RmsServerStateStarting:
  2460. WsbThrow(RMS_E_NOT_READY_SERVER_STARTING);
  2461. break;
  2462. case RmsServerStateStarted:
  2463. WsbThrow(RMS_E_NOT_READY_SERVER_STARTED);
  2464. break;
  2465. case RmsServerStateInitializing:
  2466. WsbThrow(RMS_E_NOT_READY_SERVER_INITIALIZING);
  2467. break;
  2468. case RmsServerStateStopping:
  2469. WsbThrow(RMS_E_NOT_READY_SERVER_STOPPING);
  2470. break;
  2471. case RmsServerStateStopped:
  2472. WsbThrow(RMS_E_NOT_READY_SERVER_STOPPED);
  2473. break;
  2474. case RmsServerStateSuspending:
  2475. WsbThrow(RMS_E_NOT_READY_SERVER_SUSPENDING);
  2476. break;
  2477. case RmsServerStateSuspended:
  2478. WsbThrow(RMS_E_NOT_READY_SERVER_SUSPENDED);
  2479. break;
  2480. case RmsServerStateResuming:
  2481. WsbThrow(RMS_E_NOT_READY_SERVER_RESUMING);
  2482. break;
  2483. default:
  2484. WsbThrow(E_UNEXPECTED);
  2485. break;
  2486. }
  2487. }
  2488. else {
  2489. WsbThrow(status);
  2490. }
  2491. }
  2492. }
  2493. else {
  2494. if ( S_OK == status ) {
  2495. WsbThrow(RMS_E_NOT_READY_SERVER_DISABLED);
  2496. }
  2497. else {
  2498. WsbThrow(status);
  2499. }
  2500. }
  2501. } WsbCatch(hr);
  2502. return hr;
  2503. }
  2504. HRESULT
  2505. CRmsServer::ChangeSysState(
  2506. IN OUT HSM_SYSTEM_STATE* pSysState
  2507. )
  2508. /*++
  2509. Implements:
  2510. IHsmSystemState::ChangeSysState().
  2511. --*/
  2512. {
  2513. HRESULT hr = S_OK;
  2514. WsbTraceIn(OLESTR("CRmsServer::ChangeSysState"), OLESTR("State = %lx"),
  2515. pSysState->State);
  2516. try {
  2517. if ((pSysState->State & HSM_STATE_SHUTDOWN) ||
  2518. (pSysState->State & HSM_STATE_SUSPEND)) {
  2519. //
  2520. // Shutdown or Suspend operations
  2521. //
  2522. // For power mangement support we need to release
  2523. // all device handles, and the NTMS (RSM) session handle.
  2524. //
  2525. // To accomplish this we simply disable each cartridge,
  2526. // then disable NTMS.
  2527. //
  2528. // The fallout from this gets everything in the power ready state.
  2529. //
  2530. WsbAffirmHr(ChangeState(RmsServerStateSuspending));
  2531. //
  2532. // Suspend operations with NMTS. This will cancel any in-progress mounts.
  2533. //
  2534. WsbAffirmHr(m_pNTMS->Suspend());
  2535. //
  2536. // Disable each of the active cartridges
  2537. //
  2538. CComPtr<IWsbEnum> pEnumCartridges;
  2539. CComPtr<IWsbEnum> pEnumDataMovers;
  2540. CComPtr<IRmsComObject> pObject;
  2541. CComPtr<IRmsCartridge> pCart;
  2542. CComPtr<IDataMover> pMover;
  2543. CComPtr<IRmsDrive> pDrive;
  2544. WsbAffirmHr( m_pActiveCartridges->Enum( &pEnumCartridges ));
  2545. WsbAssertPointer( pEnumCartridges );
  2546. //
  2547. // Disable each cartridge.
  2548. //
  2549. hr = pEnumCartridges->First( IID_IRmsComObject, (void **)&pObject );
  2550. while (S_OK == hr) {
  2551. try {
  2552. WsbAffirmHr(pObject->Disable(RMS_E_NOT_READY_SERVER_SUSPENDING));
  2553. } WsbCatch(hr);
  2554. pObject = 0;
  2555. hr = pEnumCartridges->Next( IID_IRmsComObject, (void **)&pObject );
  2556. }
  2557. hr = S_OK;
  2558. /*
  2559. Tracking DataMovers is only partially implemented.
  2560. //
  2561. // Cancel I/O requests.
  2562. //
  2563. WsbAffirmHr( m_pDataMovers->Enum( &pEnumDataMovers ));
  2564. WsbAssertPointer( pEnumDataMovers );
  2565. hr = pEnumDataMovers->First( IID_IDataMover, (void **)&pMover );
  2566. while (S_OK == hr) {
  2567. try {
  2568. WsbAffirmHr(pMover->Cancel());
  2569. } WsbCatch(hr);
  2570. pMover = 0;
  2571. hr = pEnumDataMovers->Next( IID_IDataMover, (void **)&pMover );
  2572. }
  2573. hr = S_OK;
  2574. */
  2575. //
  2576. // Unload all drives.
  2577. //
  2578. hr = pEnumCartridges->First( IID_IRmsCartridge, (void **)&pCart );
  2579. while (S_OK == hr) {
  2580. try {
  2581. WsbAffirmHr(pCart->GetDrive(&pDrive));
  2582. WsbAffirmHr(pDrive->UnloadNow());
  2583. } WsbCatch(hr);
  2584. pDrive = 0;
  2585. pCart = 0;
  2586. //
  2587. // We use "->This" since the UnloadNow() method will wait
  2588. // until the active cartridge is dismount, and removed
  2589. // from the active cartridge list.
  2590. //
  2591. hr = pEnumCartridges->This( IID_IRmsCartridge, (void **)&pCart );
  2592. }
  2593. hr = S_OK;
  2594. //
  2595. // Suspend operations with NMTS. This will close the NTMS handle in
  2596. // case it was reopend for dismounts during shutdown.
  2597. //
  2598. WsbAffirmHr(m_pNTMS->Suspend());
  2599. WsbAffirmHr(ChangeState(RmsServerStateSuspended));
  2600. } else if (pSysState->State & HSM_STATE_RESUME) {
  2601. //
  2602. // Resume operations
  2603. //
  2604. WsbAffirmHr(ChangeState(RmsServerStateResuming));
  2605. WsbAffirmHr(m_pNTMS->Resume());
  2606. CComPtr<IWsbEnum> pEnumCartridges;
  2607. CComPtr<IRmsComObject> pObject;
  2608. WsbAffirmHr( m_pActiveCartridges->Enum( &pEnumCartridges ));
  2609. WsbAssertPointer( pEnumCartridges );
  2610. //
  2611. // Enable each of the active cartridges
  2612. //
  2613. hr = pEnumCartridges->First( IID_IRmsComObject, (void **)&pObject );
  2614. while (S_OK == hr) {
  2615. try {
  2616. WsbAffirmHr(pObject->Enable());
  2617. } WsbCatch(hr);
  2618. pObject = 0;
  2619. hr = pEnumCartridges->Next( IID_IRmsComObject, (void **)&pObject );
  2620. }
  2621. hr = S_OK;
  2622. WsbAffirmHr(ChangeState(RmsServerStateReady));
  2623. }
  2624. } WsbCatch(hr);
  2625. WsbTraceOut(OLESTR("CRmsServer::ChangeSysState"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2626. return(hr);
  2627. }
  2628. HRESULT
  2629. CRmsServer::GetNofAvailableDrives(
  2630. IN REFGUID fromMediaSet,
  2631. OUT DWORD* pdwNofDrives
  2632. )
  2633. /*++
  2634. Implements:
  2635. IRmsServer::GetNofAvailableDrives().
  2636. --*/
  2637. {
  2638. HRESULT hr = S_OK;
  2639. WsbTraceIn(OLESTR("CRmsServer::GetNofAvailableDrives"), OLESTR(""));
  2640. try {
  2641. WsbAssertPointer(pdwNofDrives);
  2642. *pdwNofDrives = 0;
  2643. // Get the media set
  2644. CComPtr<IRmsMediaSet> pMediaSet;
  2645. WsbAffirmHr(CreateObject(fromMediaSet, CLSID_CRmsMediaSet, IID_IRmsMediaSet, RmsOpenExisting, (void **) &pMediaSet));
  2646. // Check if the media set is of fixed drives
  2647. LONG mediaType;
  2648. WsbAffirmHr(pMediaSet->GetMediaSupported(&mediaType));
  2649. if (RmsMediaFixed == mediaType) {
  2650. // Count fixed drives
  2651. // We take a shortcut here and just use number of drives that were counted
  2652. // during initialization. (FindCartridgeStatusById can give current state)
  2653. *pdwNofDrives = m_HardDrivesUsed;
  2654. } else {
  2655. // Just use NTMS
  2656. // TEMPORARY - We might want RmsNtms to use media-set info as well,
  2657. // in order not to count both tape and optical drives on a system that has both
  2658. WsbAffirmHr(m_pNTMS->GetNofAvailableDrives(pdwNofDrives));
  2659. }
  2660. } WsbCatch(hr);
  2661. WsbTrace(OLESTR("CRmsServer::GetNofAvailableDrives: Number of enabled drives is %lu\n"), *pdwNofDrives);
  2662. WsbTraceOut(OLESTR("CRmsServer::GetNofAvailableDrives"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2663. return(hr);
  2664. }
  2665. HRESULT
  2666. CRmsServer::FindCartridgeStatusById(
  2667. IN REFGUID cartId,
  2668. OUT DWORD* pdwStatus
  2669. )
  2670. /*++
  2671. Implements:
  2672. IRmsServer::FindCartridgeStatusById().
  2673. --*/
  2674. {
  2675. HRESULT hr = S_OK;
  2676. CComPtr<IRmsCartridge> pCart;
  2677. CComPtr<IRmsCartridge> pFindCart;
  2678. WsbTraceIn(OLESTR("CRmsServer::FindCartridgeStatusById"), OLESTR("cartId = %ls"), WsbGuidAsString(cartId));
  2679. try {
  2680. WsbAssertPointer(pdwStatus);
  2681. *pdwStatus = 0;
  2682. // Try native RMS, Currently this should succeed only if media is a fixed drive
  2683. WsbAffirmHr(CoCreateInstance(CLSID_CRmsCartridge, 0, CLSCTX_SERVER,
  2684. IID_IRmsCartridge, (void **)&pFindCart));
  2685. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pFindCart;
  2686. WsbAffirmHr(pObject->SetObjectId(cartId));
  2687. WsbAffirmHr(pObject->SetFindBy(RmsFindByObjectId));
  2688. hr = m_pCartridges->Find(pFindCart, IID_IRmsCartridge, (void **)&pCart);
  2689. WsbAffirm(S_OK == hr || WSB_E_NOTFOUND == hr, hr);
  2690. if (WSB_E_NOTFOUND == hr) {
  2691. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  2692. }
  2693. // Search in RSM
  2694. if (S_OK != hr) {
  2695. hr = IsNTMSInstalled();
  2696. if (S_OK == hr) {
  2697. hr = m_pNTMS->FindCartridge(cartId, &pCart);
  2698. WsbAffirm(S_OK == hr || RMS_E_CARTRIDGE_NOT_FOUND == hr, hr);
  2699. } else {
  2700. switch(hr) {
  2701. case RMS_E_NOT_CONFIGURED_FOR_NTMS:
  2702. case RMS_E_NTMS_NOT_REGISTERED:
  2703. // Normal errors
  2704. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  2705. break;
  2706. default:
  2707. // Unexpected Error!
  2708. WsbThrow(hr);
  2709. break;
  2710. }
  2711. }
  2712. }
  2713. // if media found...
  2714. if (S_OK == hr) {
  2715. // Check media type
  2716. LONG mediaType;
  2717. WsbAffirmHr(pCart->GetType(&mediaType));
  2718. if (RmsMediaFixed != mediaType) {
  2719. // RSM media
  2720. // set flags
  2721. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pCart;
  2722. WsbAffirmPointer(pObject);
  2723. if (S_OK == pObject->IsEnabled()) {
  2724. (*pdwStatus) |= RMS_MEDIA_ENABLED;
  2725. }
  2726. if (S_OK == pCart->IsAvailable()) {
  2727. (*pdwStatus) |= RMS_MEDIA_AVAILABLE;
  2728. }
  2729. LONG lLocationType;
  2730. GUID Dum1,Dum2;
  2731. LONG lDum3, lDum4, lDum5, lDum6;
  2732. BOOL bDum7;
  2733. WsbAffirmHr(pCart->GetLocation(&lLocationType, &Dum1, &Dum2, &lDum3, &lDum4,
  2734. &lDum5, &lDum6, &bDum7));
  2735. switch (lLocationType) {
  2736. case RmsElementUnknown:
  2737. case RmsElementShelf:
  2738. case RmsElementOffSite:
  2739. // media is offline...
  2740. break;
  2741. default:
  2742. (*pdwStatus) |= RMS_MEDIA_ONLINE;
  2743. break;
  2744. }
  2745. } else {
  2746. // Fixed drive - just try to access the volume and see if it's still valid
  2747. // If so, set all flags, otherwise, set none
  2748. CComPtr<IRmsDrive> pDrive;
  2749. CWsbBstrPtr driveName;
  2750. WCHAR fileSystemType[MAX_PATH];
  2751. // Get drive name (volume name for fixed drives) to check
  2752. WsbAffirmHr(pCart->GetDrive(&pDrive));
  2753. CComQIPtr<IRmsDevice, &IID_IRmsDevice> pDevice = pDrive;
  2754. WsbAssertPointer(pDevice);
  2755. WsbAffirmHr(pDevice->GetDeviceName(&driveName));
  2756. if (GetVolumeInformation((WCHAR *)driveName, NULL, 0,
  2757. NULL, NULL, NULL, fileSystemType, MAX_PATH) ) {
  2758. if (0 == wcscmp(L"NTFS", fileSystemType)) {
  2759. // Volume is ready for migration - set all flags
  2760. (*pdwStatus) |= (RMS_MEDIA_ENABLED | RMS_MEDIA_ONLINE | RMS_MEDIA_AVAILABLE);
  2761. } else {
  2762. // Not NTFS - don't use that volume
  2763. WsbTrace(OLESTR("CRmsServer::FindCartridgeStatusById: Fixed volume %ls is formatted to %ls\n"),
  2764. (WCHAR *)driveName, fileSystemType);
  2765. }
  2766. } else {
  2767. // Volume is not available - don't use it
  2768. WsbTrace(OLESTR("CRmsServer::FindCartridgeStatusById: GetVolumeInformation returned %lu for Fixed volume %ls\n"),
  2769. GetLastError(), (WCHAR *)driveName);
  2770. }
  2771. }
  2772. }
  2773. } WsbCatch(hr);
  2774. WsbTrace(OLESTR("CRmsServer::FindCartridgeStatusById: Status bits are %lX\n"), *pdwStatus);
  2775. WsbTraceOut(OLESTR("CRmsServer::FindCartridgeStatusById"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2776. return(hr);
  2777. }
  2778. HRESULT
  2779. CRmsServer::IsMultipleSidedMedia(
  2780. IN REFGUID mediaSetId
  2781. )
  2782. /*++
  2783. Implements:
  2784. IRmsServer::IsMultipleSidedMedia
  2785. Notes:
  2786. Currently, optical & DVD media types are reported as multiple sided media
  2787. Tapes and fixed disks would fall in the default - one side media
  2788. --*/
  2789. {
  2790. HRESULT hr = S_FALSE;
  2791. WsbTraceIn(OLESTR("CRmsServer::IsMultipleSidedMedia"), OLESTR(""));
  2792. try {
  2793. // Multiple sided is currently determined if the media set is optical or not
  2794. // This may change to include other media types of according two other characteristics
  2795. CComPtr<IRmsMediaSet> pMediaSet;
  2796. LONG mediaType;
  2797. if (mediaSetId != GUID_NULL) {
  2798. // if input media set is non-null, check this data-set.
  2799. WsbAffirmHr(CreateObject(mediaSetId, CLSID_CRmsMediaSet, IID_IRmsMediaSet, RmsOpenAlways, (void **)&pMediaSet));
  2800. WsbAffirmHr(pMediaSet->GetMediaSupported(&mediaType));
  2801. if ((RmsMediaOptical == mediaType) || (RmsMediaDVD == mediaType)) {
  2802. hr = S_OK;
  2803. }
  2804. } else {
  2805. // Otherwise, enumerate the collection seeking for any media set that might have two sides
  2806. CComPtr<IWsbEnum> pEnumSets;
  2807. WsbAffirmHr(m_pMediaSets->Enum(&pEnumSets));
  2808. WsbAssertPointer(pEnumSets);
  2809. hr = pEnumSets->First(IID_IRmsMediaSet, (void **)&pMediaSet);
  2810. while (S_OK == hr) {
  2811. WsbAffirmHr(pMediaSet->GetMediaSupported(&mediaType));
  2812. if ((RmsMediaOptical == mediaType) || (RmsMediaDVD == mediaType)) {
  2813. hr = S_OK;
  2814. break;
  2815. }
  2816. hr = pEnumSets->Next(IID_IRmsMediaSet, (void **)&pMediaSet);
  2817. if (hr == WSB_E_NOTFOUND) {
  2818. hr = S_FALSE;
  2819. } else {
  2820. WsbAffirmHr(hr);
  2821. }
  2822. }
  2823. }
  2824. } WsbCatch(hr);
  2825. WsbTraceOut(OLESTR("CRmsServer::IsMultipleSidedMedia"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2826. return hr;
  2827. }
  2828. HRESULT
  2829. CRmsServer::CheckSecondSide(
  2830. IN REFGUID firstSideId,
  2831. OUT BOOL *pbValid,
  2832. OUT GUID *pSecondSideId
  2833. )
  2834. /*++
  2835. Implements:
  2836. IRmsServer::CheckSecondSide().
  2837. Notes:
  2838. It is not expected that this utility is called on a single sided media.
  2839. If it does, it would return invalid second side for tape and would fail on fixed disks.
  2840. --*/
  2841. {
  2842. HRESULT hr = S_OK;
  2843. WsbTraceIn(OLESTR("CRmsServer::CheckSecondSide"), OLESTR(""));
  2844. try {
  2845. // just use NTMS (RmsServer collections are not used today!)
  2846. WsbAffirmHr(m_pNTMS->CheckSecondSide(firstSideId, pbValid, pSecondSideId));
  2847. } WsbCatch(hr);
  2848. WsbTrace(OLESTR("CRmsServer::CheckSecondSide: Valid second side: %ls, id=<%ls>\n"),
  2849. WsbBoolAsString(*pbValid), WsbGuidAsString(*pSecondSideId));
  2850. WsbTraceOut(OLESTR("CRmsServer::CheckSecondSide"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2851. return(hr);
  2852. }
  2853. HRESULT
  2854. CRmsServer::GetMaxMediaCapacity(
  2855. IN REFGUID fromMediaSet,
  2856. OUT LONGLONG *pMaxCapacity
  2857. )
  2858. /*++
  2859. Implements:
  2860. IRmsServer::GetMaxMediaCapacity().
  2861. --*/
  2862. {
  2863. HRESULT hr = S_OK;
  2864. WsbTraceIn(OLESTR("CRmsServer::GetMaxMediaCapacity"), OLESTR(""));
  2865. try {
  2866. // just use NTMS
  2867. WsbAffirmHr(m_pNTMS->GetMaxMediaCapacity(fromMediaSet, pMaxCapacity));
  2868. } WsbCatch(hr);
  2869. WsbTraceOut(OLESTR("CRmsServer::GetMaxMediaCapacity"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2870. return(hr);
  2871. }
  2872. HRESULT
  2873. CRmsServer::CheckForMediaFailures(
  2874. IN HRESULT hrFailure,
  2875. IN IRmsCartridge *pCart,
  2876. IN REFGUID prevSideId
  2877. )
  2878. /*++
  2879. Implements:
  2880. CRmsServer::CheckForMediaFailures().
  2881. Notes:
  2882. This method is inetneded to check for media-related errors.
  2883. If such an error is detected, the method calls an NTMS utility function
  2884. to disbale and eject the media.
  2885. Currently, the method handles only format (of optical media) failure codes,
  2886. which are suspected as indicating a bad media.
  2887. --*/
  2888. {
  2889. HRESULT hr = S_OK;
  2890. WsbTraceIn(OLESTR("CRmsServer::CheckForMediaFailures"), OLESTR(""));
  2891. try {
  2892. BOOL bSecondSide = (prevSideId != GUID_NULL) ? TRUE : FALSE;
  2893. switch (hrFailure) {
  2894. case WSB_E_BAD_MEDIA:
  2895. case WSB_E_IO_ERROR:
  2896. case WSB_E_FORMAT_FAILED:
  2897. if (! bSecondSide) {
  2898. // Log an appropriate message in Event Viewer
  2899. CWsbBstrPtr cartridgeName;
  2900. WsbAffirmHr(pCart->GetName(&cartridgeName));
  2901. WsbLogEvent(RMS_MESSAGE_FORMAT_BAD_MEDIA, 0, NULL, (WCHAR *)cartridgeName, NULL);
  2902. // Call NTMS to disbale and eject
  2903. WsbAffirmHr(m_pNTMS->DisableAndEject(pCart));
  2904. } else {
  2905. // Cannot disbale & eject the media if the first side is already allocated
  2906. // Instead, log a message that advises the user what can be done
  2907. CComPtr<IRmsCartridge> pFirstSideCart;
  2908. CWsbBstrPtr firstSideName;
  2909. WsbAffirmHr(FindCartridgeById(prevSideId, &pFirstSideCart));
  2910. WsbAffirmHr(pFirstSideCart->GetName(&firstSideName));
  2911. WsbLogEvent(RMS_MESSAGE_FORMAT_BAD_SECOND_SIDE_MEDIA, 0, NULL, (WCHAR *)firstSideName, NULL);
  2912. }
  2913. break;
  2914. default:
  2915. // Do nothing
  2916. break;
  2917. }
  2918. } WsbCatch(hr);
  2919. WsbTraceOut(OLESTR("CRmsServer::CheckForMediaFailures"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2920. return(hr);
  2921. }