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

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