Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5294 lines
207 KiB

  1. /*++
  2. 1998 Seagate Software, Inc. All rights reserved
  3. Module Name:
  4. RmsNTMS.cpp
  5. Abstract:
  6. Implementation of CRmsNTMS
  7. Author:
  8. Brian Dodd [brian] 14-May-1997
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #include "RmsServr.h"
  13. #include "RmsNTMS.h"
  14. typedef struct RmsNTMSSearchHandle {
  15. WCHAR FindName[NTMS_OBJECTNAME_LENGTH];
  16. NTMS_GUID FindId;
  17. DWORD FindType;
  18. LPNTMS_GUID Objects;
  19. DWORD NumberOfObjects;
  20. DWORD MaxObjects;
  21. DWORD Next;
  22. DWORD LastError;
  23. } RMS_NTMS_SEARCH_HANDLE, *LPRMS_NTMS_SEARCH_HANDLE;
  24. #define ADD_ACE_MASK_BITS 1
  25. #define REMOVE_ACE_MASK_BITS 2
  26. //
  27. // We use application name in RSM interface for media pool name.
  28. // Media pool name is an identifier of the media pool in RSM, therefore, we cannot allow
  29. // this string to be localized. Localizing this string would create another pool after
  30. // installing a foreign language MUI.
  31. //
  32. #define REMOTE_STORAGE_APP_NAME OLESTR("Remote Storage")
  33. /////////////////////////////////////////////////////////////////////////////
  34. // IRmsNTMS implementation
  35. /*
  36. HINSTANCE hInstDll;
  37. typedef DWORD (*FunctionName)( void );
  38. FunctionName FunctionNameFn;
  39. hInstDll = LoadLibrary( "dll" );
  40. FunctionNameFn = (FunctionName) GetProcAddress( hInstDll, "FunctionName" );
  41. result = (FunctionNameFn)();
  42. */
  43. STDMETHODIMP
  44. CRmsNTMS::FinalConstruct(void)
  45. /*++
  46. Implements:
  47. CComObjectRoot::FinalConstruct
  48. --*/
  49. {
  50. HRESULT hr = S_OK;
  51. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
  52. WsbTraceIn(OLESTR("CRmsNTMS::FinalConstruct"), OLESTR(""));
  53. m_pLibGuids = NULL;
  54. m_dwNofLibs = 0;
  55. try {
  56. WsbAffirmHr(CComObjectRoot::FinalConstruct());
  57. WsbAffirmHr( changeState( RmsNtmsStateStarting ));
  58. m_SessionHandle = INVALID_HANDLE_VALUE;
  59. m_IsRmsConfiguredForNTMS = FALSE;
  60. m_IsNTMSRegistered = FALSE;
  61. m_Name = RMS_NTMS_OBJECT_NAME;
  62. m_Description = RMS_NTMS_OBJECT_DESCRIPTION;
  63. if ( S_OK == getNtmsSupportFromRegistry(NULL) ) {
  64. m_IsRmsConfiguredForNTMS = TRUE;
  65. }
  66. HKEY hKeyMachine = 0;
  67. HKEY hKey = 0;
  68. if ( S_OK == WsbOpenRegistryKey(NULL, RMS_NTMS_REGISTRY_STRING, KEY_QUERY_VALUE, &hKeyMachine, &hKey) ) {
  69. WsbCloseRegistryKey (&hKeyMachine, &hKey);
  70. m_IsNTMSRegistered = TRUE;
  71. }
  72. // Failure precedence.
  73. WsbAffirm(m_IsRmsConfiguredForNTMS, RMS_E_NOT_CONFIGURED_FOR_NTMS);
  74. WsbAffirm(m_IsNTMSRegistered, RMS_E_NTMS_NOT_REGISTERED);
  75. WsbAffirmHr( changeState( RmsNtmsStateStarted ));
  76. } WsbCatchAndDo(hr,
  77. pObject->Disable( hr );
  78. WsbLogEvent(RMS_MESSAGE_NTMS_CONNECTION_NOT_ESABLISHED, 0, NULL, WsbHrAsString(hr), NULL);
  79. // Always construct!
  80. hr = S_OK;
  81. );
  82. WsbTraceOut(OLESTR("CRmsNTMS::FinalConstruct"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  83. return hr;
  84. }
  85. STDMETHODIMP
  86. CRmsNTMS::FinalRelease(void)
  87. /*++
  88. Implements:
  89. CComObjectRoot::FinalRelease
  90. --*/
  91. {
  92. HRESULT hr = S_OK;
  93. WsbTraceIn(OLESTR("CRmsNTMS::FinalRelease"), OLESTR(""));
  94. try {
  95. WsbAffirmHr( changeState( RmsNtmsStateStopping ));
  96. endSession();
  97. if (m_pLibGuids) {
  98. WsbFree(m_pLibGuids);
  99. }
  100. CComObjectRoot::FinalRelease();
  101. WsbAffirmHr( changeState( RmsNtmsStateStopped ));
  102. } WsbCatch(hr);
  103. WsbTraceOut(OLESTR("CRmsNTMS::FinalRelease"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  104. return hr;
  105. }
  106. STDMETHODIMP
  107. CRmsNTMS::IsInstalled(void)
  108. {
  109. HRESULT hr = S_OK;
  110. try {
  111. if ( !m_IsEnabled ) {
  112. if ( !m_IsNTMSRegistered ) {
  113. // check again... NTMS can get registered at anytime.
  114. HKEY hKeyMachine = 0;
  115. HKEY hKey = 0;
  116. WsbAffirm(S_OK == WsbOpenRegistryKey(NULL, RMS_NTMS_REGISTRY_STRING, KEY_QUERY_VALUE, &hKeyMachine, &hKey), RMS_E_NTMS_NOT_REGISTERED);
  117. WsbCloseRegistryKey (&hKeyMachine, &hKey);
  118. m_IsNTMSRegistered = TRUE;
  119. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
  120. pObject->Enable();
  121. // now need to initialize
  122. WsbAffirmHr(InitializeInAnotherThread());
  123. }
  124. WsbAffirm(m_IsRmsConfiguredForNTMS, RMS_E_NOT_CONFIGURED_FOR_NTMS);
  125. WsbAffirm(m_IsNTMSRegistered, RMS_E_NTMS_NOT_REGISTERED);
  126. }
  127. } WsbCatch(hr);
  128. return hr;
  129. }
  130. STDMETHODIMP
  131. CRmsNTMS::Initialize(void)
  132. {
  133. HRESULT hr = E_FAIL;
  134. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
  135. WsbTraceIn(OLESTR("CRmsNTMS::Initialize"), OLESTR(""));
  136. try {
  137. WsbAffirmHr( changeState( RmsNtmsStateInitializing ));
  138. if ( INVALID_HANDLE_VALUE == m_SessionHandle ) {
  139. WsbAffirmHr(beginSession());
  140. }
  141. HANDLE hSession = m_SessionHandle;
  142. //
  143. // Create Remote Storage specific NTMS media pools
  144. //
  145. WsbAffirmHr( createMediaPools() );
  146. //
  147. // Report on other NTMS objects of interest
  148. //
  149. HANDLE hFind = NULL;
  150. NTMS_OBJECTINFORMATION objectInfo;
  151. hr = findFirstNtmsObject( NTMS_MEDIA_TYPE, GUID_NULL, NULL, GUID_NULL, &hFind, &objectInfo);
  152. while( S_OK == hr ) {
  153. reportNtmsObjectInformation( &objectInfo );
  154. hr = findNextNtmsObject( hFind, &objectInfo );
  155. }
  156. findCloseNtmsObject( hFind );
  157. hr = findFirstNtmsObject( NTMS_CHANGER, GUID_NULL, NULL, GUID_NULL, &hFind, &objectInfo);
  158. while( S_OK == hr ) {
  159. reportNtmsObjectInformation( &objectInfo );
  160. hr = findNextNtmsObject( hFind, &objectInfo );
  161. }
  162. findCloseNtmsObject( hFind );
  163. hr = findFirstNtmsObject( NTMS_CHANGER_TYPE, GUID_NULL, NULL, GUID_NULL, &hFind, &objectInfo);
  164. while( S_OK == hr ) {
  165. reportNtmsObjectInformation( &objectInfo );
  166. hr = findNextNtmsObject( hFind, &objectInfo );
  167. }
  168. findCloseNtmsObject( hFind );
  169. hr = findFirstNtmsObject( NTMS_DRIVE, GUID_NULL, NULL, GUID_NULL, &hFind, &objectInfo);
  170. while( S_OK == hr ) {
  171. reportNtmsObjectInformation( &objectInfo );
  172. hr = findNextNtmsObject( hFind, &objectInfo );
  173. }
  174. findCloseNtmsObject( hFind );
  175. hr = findFirstNtmsObject( NTMS_DRIVE_TYPE, GUID_NULL, NULL, GUID_NULL, &hFind, &objectInfo);
  176. while( S_OK == hr ) {
  177. reportNtmsObjectInformation( &objectInfo );
  178. hr = findNextNtmsObject( hFind, &objectInfo );
  179. }
  180. findCloseNtmsObject( hFind );
  181. WsbAffirmHr( changeState( RmsNtmsStateReady ));
  182. hr = S_OK;
  183. } WsbCatchAndDo(hr,
  184. pObject->Disable( hr );
  185. WsbLogEvent( RMS_MESSAGE_NTMS_INITIALIZATION_FAILED, 0, NULL, WsbHrAsString(hr), NULL );
  186. );
  187. WsbTraceOut( OLESTR("CRmsNTMS::Initialize"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
  188. return hr;
  189. }
  190. HRESULT
  191. CRmsNTMS::findFirstNtmsObject(
  192. IN DWORD objectType,
  193. IN REFGUID containerId,
  194. IN WCHAR *objectName,
  195. IN REFGUID objectId,
  196. OUT HANDLE *hFindObject,
  197. OUT LPNTMS_OBJECTINFORMATION pFindObjectData
  198. )
  199. {
  200. HRESULT hr = E_FAIL;
  201. try {
  202. int maxObjects = 16; // Initial size of object id array to allocate
  203. LPRMS_NTMS_SEARCH_HANDLE pFind;
  204. HANDLE hSession = m_SessionHandle;
  205. DWORD errCode;
  206. DWORD numberOfObjects = maxObjects;
  207. LPNTMS_GUID pId = ( containerId == GUID_NULL ) ? NULL : (GUID *)&containerId;
  208. LPNTMS_GUID pObjects = NULL;
  209. NTMS_OBJECTINFORMATION objectInfo;
  210. WsbAssertPointer( hFindObject );
  211. if ( INVALID_HANDLE_VALUE == hSession ) {
  212. WsbThrow( E_UNEXPECTED );
  213. }
  214. *hFindObject = NULL;
  215. memset( &objectInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
  216. pObjects = (LPNTMS_GUID)WsbAlloc( maxObjects*sizeof(NTMS_GUID) );
  217. WsbAffirmPointer( pObjects );
  218. // NTMS - enumerate all objects of the given type
  219. WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
  220. errCode = EnumerateNtmsObject( hSession, pId, pObjects, &numberOfObjects, objectType, 0 );
  221. if ( (ERROR_OBJECT_NOT_FOUND == errCode) || (0 == numberOfObjects) ) { // Don't count on NTMS returning the correct errCode
  222. WsbThrow( RMS_E_NTMS_OBJECT_NOT_FOUND );
  223. }
  224. else if ( ERROR_INSUFFICIENT_BUFFER == errCode ) {
  225. while ( ERROR_INSUFFICIENT_BUFFER == errCode ) {
  226. // Allocate a new buffer, and retry.
  227. WsbTrace(OLESTR("CRmsNTMS::findFirstNtmsObject - Reallocating for %d objects @1.\n"), numberOfObjects);
  228. maxObjects = numberOfObjects;
  229. LPVOID pTemp = WsbRealloc( pObjects, maxObjects*sizeof(NTMS_GUID) );
  230. if( !pTemp ) {
  231. WsbFree( pObjects );
  232. WsbThrow( E_OUTOFMEMORY );
  233. }
  234. pObjects = (LPNTMS_GUID)pTemp;
  235. // NTMS - enumerate all objects of the given type
  236. WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
  237. errCode = EnumerateNtmsObject( hSession, pId, pObjects, &numberOfObjects, objectType, 0 );
  238. }
  239. }
  240. WsbAffirmNoError( errCode );
  241. HANDLE hTemp = (HANDLE)WsbAlloc( sizeof( RMS_NTMS_SEARCH_HANDLE) );
  242. *hFindObject = hTemp;
  243. WsbAffirmPointer( *hFindObject );
  244. pFind = (LPRMS_NTMS_SEARCH_HANDLE)*hFindObject;
  245. // Initialize the search handle
  246. if ( objectName ) {
  247. wcscpy( pFind->FindName, objectName );
  248. }
  249. else {
  250. wcscpy( pFind->FindName, OLESTR("") );
  251. }
  252. pFind->FindId = objectId;
  253. pFind->FindType = objectType;
  254. pFind->Objects = pObjects;
  255. pFind->NumberOfObjects = numberOfObjects;
  256. pFind->MaxObjects = maxObjects;
  257. pFind->Next = 0;
  258. pFind->LastError = NO_ERROR;
  259. BOOL bFound = FALSE;
  260. while( pFind->Next < pFind->NumberOfObjects ) {
  261. objectInfo.dwType = pFind->FindType;
  262. objectInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  263. // NTMS - Get object information
  264. WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
  265. errCode = GetNtmsObjectInformation( hSession, &pObjects[pFind->Next++], &objectInfo );
  266. pFind->LastError = errCode;
  267. // Media Pools require special handling because they contain other Media Pools
  268. if ( (NTMS_MEDIA_POOL == pFind->FindType) &&
  269. (objectInfo.Info.MediaPool.dwNumberOfMediaPools > 0) ) {
  270. DWORD numberToAdd = objectInfo.Info.MediaPool.dwNumberOfMediaPools;
  271. do {
  272. numberOfObjects = pFind->NumberOfObjects + numberToAdd;
  273. // Allocate a new buffer, and retry.
  274. WsbTrace(OLESTR("CRmsNTMS::findFirstNtmsObject - Reallocating for %d objects @2.\n"), numberOfObjects);
  275. maxObjects = numberOfObjects;
  276. pObjects = (LPNTMS_GUID)WsbRealloc( pFind->Objects, maxObjects*sizeof(NTMS_GUID) );
  277. WsbAffirmAlloc( pObjects );
  278. pFind->Objects = pObjects;
  279. // NTMS - enumerate all objects of the given type
  280. WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
  281. errCode = EnumerateNtmsObject( hSession,
  282. &objectInfo.ObjectGuid, &pObjects[pFind->NumberOfObjects],
  283. &numberToAdd, pFind->FindType, 0 );
  284. } while ( ERROR_INSUFFICIENT_BUFFER == errCode ) ;
  285. if ( NO_ERROR == errCode ) {
  286. pFind->NumberOfObjects += numberToAdd;
  287. pFind->MaxObjects = maxObjects;
  288. }
  289. else {
  290. WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
  291. OLESTR("EnumerateNtmsObject"),
  292. WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
  293. NULL );
  294. WsbAffirmNoError(errCode);
  295. }
  296. }
  297. if ( NO_ERROR == pFind->LastError ) {
  298. // Now see if it is the one we're looking for
  299. if ( GUID_NULL != pFind->FindId ) {
  300. if ( pFind->FindId == objectInfo.ObjectGuid ) { // Match the GUID
  301. bFound = TRUE;
  302. if ( pFindObjectData != NULL ) {
  303. memcpy( pFindObjectData, &objectInfo, sizeof( NTMS_OBJECTINFORMATION ) );
  304. }
  305. break;
  306. }
  307. }
  308. else if ( wcslen( pFind->FindName ) > 0 ) { // Match the Name
  309. if ( 0 == wcscmp( pFind->FindName, objectInfo.szName ) ) {
  310. bFound = TRUE;
  311. if ( pFindObjectData != NULL ) {
  312. memcpy( pFindObjectData, &objectInfo, sizeof( NTMS_OBJECTINFORMATION ) );
  313. }
  314. break;
  315. }
  316. }
  317. else { // Any GUID or Name
  318. bFound = TRUE;
  319. if ( pFindObjectData != NULL ) {
  320. memcpy( pFindObjectData, &objectInfo, sizeof( NTMS_OBJECTINFORMATION ) );
  321. }
  322. break;
  323. }
  324. }
  325. else {
  326. WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
  327. OLESTR("GetNTMSObjectInformation"),
  328. WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
  329. NULL );
  330. WsbThrow( RMS_E_NTMS_OBJECT_NOT_FOUND );
  331. }
  332. }
  333. hr = ( bFound ) ? S_OK : RMS_E_NTMS_OBJECT_NOT_FOUND;
  334. } WsbCatch(hr);
  335. return hr;
  336. }
  337. HRESULT
  338. CRmsNTMS::findNextNtmsObject(
  339. IN HANDLE hFindObject,
  340. OUT LPNTMS_OBJECTINFORMATION pFindObjectData
  341. )
  342. {
  343. HRESULT hr = E_FAIL;
  344. try {
  345. HANDLE hSession = m_SessionHandle;
  346. DWORD errCode;
  347. LPRMS_NTMS_SEARCH_HANDLE pFind = (LPRMS_NTMS_SEARCH_HANDLE)hFindObject;
  348. LPNTMS_GUID pObjects = pFind->Objects;
  349. NTMS_OBJECTINFORMATION objectInfo;
  350. if ( INVALID_HANDLE_VALUE == hSession ) {
  351. WsbThrow( E_UNEXPECTED );
  352. }
  353. BOOL bFound = FALSE;
  354. while( pFind->Next < pFind->NumberOfObjects ) {
  355. objectInfo.dwType = pFind->FindType;
  356. objectInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  357. // NTMS - get object information of next object
  358. WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
  359. errCode = GetNtmsObjectInformation( hSession, &pObjects[pFind->Next++], &objectInfo );
  360. pFind->LastError = errCode;
  361. // Media Pools require special handling because they contain other Media Pools
  362. if ( (NTMS_MEDIA_POOL == pFind->FindType) &&
  363. (objectInfo.Info.MediaPool.dwNumberOfMediaPools > 0) ) {
  364. DWORD maxObjects;
  365. DWORD numberOfObjects;
  366. DWORD numberToAdd = objectInfo.Info.MediaPool.dwNumberOfMediaPools;
  367. do {
  368. numberOfObjects = pFind->NumberOfObjects + numberToAdd;
  369. // Allocate a new buffer, and retry.
  370. WsbTrace(OLESTR("CRmsNTMS::findNextNtmsObject - Reallocating for %d objects.\n"), numberOfObjects);
  371. maxObjects = numberOfObjects;
  372. pObjects = (LPNTMS_GUID)WsbRealloc( pFind->Objects, maxObjects*sizeof(NTMS_GUID) );
  373. WsbAffirmAlloc( pObjects );
  374. pFind->Objects = pObjects;
  375. // NTMS - enumerate all objects of the given type
  376. WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
  377. errCode = EnumerateNtmsObject( hSession,
  378. &objectInfo.ObjectGuid, &pObjects[pFind->NumberOfObjects],
  379. &numberToAdd, pFind->FindType, 0 );
  380. } while ( ERROR_INSUFFICIENT_BUFFER == errCode ) ;
  381. if ( NO_ERROR == errCode ) {
  382. pFind->NumberOfObjects += numberToAdd;
  383. pFind->MaxObjects = maxObjects;
  384. }
  385. else {
  386. WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
  387. OLESTR("EnumerateNtmsObject"),
  388. WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
  389. NULL );
  390. WsbAffirmNoError(errCode);
  391. }
  392. }
  393. if ( NO_ERROR == pFind->LastError ) {
  394. // Now see if it is the one we're looking for
  395. if ( GUID_NULL != pFind->FindId ) {
  396. if ( pFind->FindId == objectInfo.ObjectGuid ) { // Match the GUID
  397. bFound = TRUE;
  398. if ( pFindObjectData != NULL ) {
  399. memcpy( pFindObjectData, &objectInfo, sizeof( NTMS_OBJECTINFORMATION ) );
  400. }
  401. break;
  402. }
  403. }
  404. else if ( wcslen( pFind->FindName ) > 0 ) { // Match the Name
  405. if ( 0 == wcscmp( pFind->FindName, objectInfo.szName ) ) {
  406. bFound = TRUE;
  407. if ( pFindObjectData != NULL ) {
  408. memcpy( pFindObjectData, &objectInfo, sizeof( NTMS_OBJECTINFORMATION ) );
  409. }
  410. break;
  411. }
  412. }
  413. else { // Any GUID or Name
  414. bFound = TRUE;
  415. if ( pFindObjectData != NULL ) {
  416. memcpy( pFindObjectData, &objectInfo, sizeof( NTMS_OBJECTINFORMATION ) );
  417. }
  418. break;
  419. }
  420. }
  421. else {
  422. WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
  423. OLESTR("GetNTMSObjectInformation"),
  424. WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
  425. NULL );
  426. WsbThrow( RMS_E_NTMS_OBJECT_NOT_FOUND );
  427. }
  428. }
  429. hr = (bFound) ? S_OK : RMS_E_NTMS_OBJECT_NOT_FOUND;
  430. } WsbCatch(hr);
  431. return hr;
  432. }
  433. HRESULT
  434. CRmsNTMS::findCloseNtmsObject(
  435. IN HANDLE hFindObject)
  436. {
  437. HRESULT hr = S_OK;
  438. try {
  439. WsbAffirmPointer(hFindObject); // We don't need to assert here... It's possible to call
  440. // findCloseNtmsObject even if nothing was found with
  441. // findFirstNtmsObject. Skip the free step.
  442. WsbFree(((LPRMS_NTMS_SEARCH_HANDLE)hFindObject)->Objects);
  443. WsbFree(hFindObject);
  444. } WsbCatch(hr);
  445. return hr;
  446. }
  447. HRESULT
  448. CRmsNTMS::reportNtmsObjectInformation(
  449. IN LPNTMS_OBJECTINFORMATION pObjectInfo)
  450. {
  451. HRESULT hr = S_OK;
  452. static DWORD lastTypeReported = 0;
  453. try {
  454. WsbAssertPointer( pObjectInfo );
  455. BOOL bHeaders = (lastTypeReported == pObjectInfo->dwType) ? FALSE : TRUE;
  456. lastTypeReported = pObjectInfo->dwType;
  457. // Output a header to trace file
  458. if ( bHeaders ) {
  459. switch ( pObjectInfo->dwType ) {
  460. case NTMS_UNKNOWN:
  461. case NTMS_OBJECT:
  462. WsbTrace( OLESTR("!!! WARNING !!! - CRmsServer::reportNtmsObjectInformation: report for NTMS object type: %d is not available.\n") );
  463. break;
  464. case NTMS_CHANGER:
  465. break;
  466. case NTMS_CHANGER_TYPE:
  467. break;
  468. case NTMS_COMPUTER:
  469. WsbTrace( OLESTR("!!! WARNING !!! - CRmsServer::reportNtmsObjectInformation: report for NTMS object type: %d is not available.\n") );
  470. break;
  471. case NTMS_DRIVE:
  472. case NTMS_DRIVE_TYPE:
  473. break;
  474. case NTMS_IEDOOR:
  475. case NTMS_IEPORT:
  476. WsbTrace( OLESTR("!!! WARNING !!! - CRmsServer::reportNtmsObjectInformation: report for NTMS object type: %d is not available.\n") );
  477. break;
  478. case NTMS_LIBRARY:
  479. break;
  480. case NTMS_LIBREQUEST:
  481. case NTMS_LOGICAL_MEDIA:
  482. WsbTrace( OLESTR("!!! WARNING !!! - CRmsServer::reportNtmsObjectInformation: report for NTMS object type: %d is not available.\n") );
  483. break;
  484. case NTMS_MEDIA_POOL:
  485. WsbTrace( OLESTR("GUID Enabl Type Media Type GUID Parent GUID A-Pol D-Pol Allocate Physical Logical Pools Name / Description\n") );
  486. WsbTrace( OLESTR("====================================== ===== ==== ====================================== ====================================== ===== ===== ======== ======== ======== ===== ========================================\n") );
  487. break;
  488. case NTMS_MEDIA_TYPE:
  489. WsbTrace( OLESTR("GUID Enabl Type Sides RW Name / Description\n") );
  490. WsbTrace( OLESTR("====================================== ===== ==== ===== == ========================================\n") );
  491. break;
  492. case NTMS_PARTITION:
  493. break;
  494. case NTMS_PHYSICAL_MEDIA:
  495. case NTMS_STORAGESLOT:
  496. case NTMS_OPREQUEST:
  497. default:
  498. WsbTrace( OLESTR("!!! WARNING !!! - CRmsServer::reportNtmsObjectInformation: report for object type: %d is not supported\n") );
  499. break;
  500. }
  501. }
  502. // Convert SYSTEMTIME to FILETIME for output.
  503. SYSTEMTIME sCreated, sModified;
  504. FILETIME fCreated, fModified;
  505. sCreated = pObjectInfo->Created;
  506. sModified = pObjectInfo->Modified;
  507. SystemTimeToFileTime(&sCreated, &fCreated);
  508. SystemTimeToFileTime(&sModified, &fModified);
  509. switch ( pObjectInfo->dwType ) {
  510. case NTMS_UNKNOWN:
  511. case NTMS_OBJECT:
  512. break;
  513. case NTMS_CHANGER:
  514. WsbTrace(OLESTR("Changer %d Information:\n"), pObjectInfo->Info.Changer.Number );
  515. WsbTrace(OLESTR(" GUID........... %-ls\n"), WsbGuidAsString(pObjectInfo->ObjectGuid) );
  516. WsbTrace(OLESTR(" Name........... <%-ls>\n"), pObjectInfo->szName );
  517. WsbTrace(OLESTR(" Description.... <%-ls>\n"), pObjectInfo->szDescription );
  518. WsbTrace(OLESTR(" Enabled........ %-ls\n"), WsbBoolAsString(pObjectInfo->Enabled) );
  519. WsbTrace(OLESTR(" Op State....... %-ls\n"), WsbLongAsString(pObjectInfo->dwOperationalState) );
  520. WsbTrace(OLESTR(" Created........ %-ls\n"), WsbFiletimeAsString(FALSE, fCreated) );
  521. WsbTrace(OLESTR(" Modified....... %-ls\n"), WsbFiletimeAsString(FALSE, fModified) );
  522. WsbTrace(OLESTR(" Number......... %-d\n"), pObjectInfo->Info.Changer.Number );
  523. WsbTrace(OLESTR(" Changer Type... %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Changer.ChangerType) );
  524. WsbTrace(OLESTR(" Serial Number.. <%-ls>\n"), pObjectInfo->Info.Changer.szSerialNumber );
  525. WsbTrace(OLESTR(" Revision....... <%-ls>\n"), pObjectInfo->Info.Changer.szRevision );
  526. WsbTrace(OLESTR(" Device Name.... <%-ls>\n"), pObjectInfo->Info.Changer.szDeviceName );
  527. WsbTrace(OLESTR(" SCSI Port...... %-d\n"), pObjectInfo->Info.Changer.ScsiPort );
  528. WsbTrace(OLESTR(" SCSI Bus....... %-d\n"), pObjectInfo->Info.Changer.ScsiBus );
  529. WsbTrace(OLESTR(" SCSI Target.... %-d\n"), pObjectInfo->Info.Changer.ScsiTarget );
  530. WsbTrace(OLESTR(" SCSI Lun....... %-d\n"), pObjectInfo->Info.Changer.ScsiLun );
  531. WsbTrace(OLESTR(" Library....... %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Changer.Library) );
  532. break;
  533. case NTMS_CHANGER_TYPE:
  534. WsbTrace(OLESTR("Changer Type Information:\n") );
  535. WsbTrace(OLESTR(" GUID........... %-ls\n"), WsbGuidAsString(pObjectInfo->ObjectGuid) );
  536. WsbTrace(OLESTR(" Name........... <%-ls>\n"), pObjectInfo->szName );
  537. WsbTrace(OLESTR(" Description.... <%-ls>\n"), pObjectInfo->szDescription );
  538. WsbTrace(OLESTR(" Enabled........ %-ls\n"), WsbBoolAsString(pObjectInfo->Enabled) );
  539. WsbTrace(OLESTR(" Op State....... %-ls\n"), WsbLongAsString(pObjectInfo->dwOperationalState) );
  540. WsbTrace(OLESTR(" Created........ %-ls\n"), WsbFiletimeAsString(FALSE, fCreated) );
  541. WsbTrace(OLESTR(" Modified....... %-ls\n"), WsbFiletimeAsString(FALSE, fModified) );
  542. WsbTrace(OLESTR(" Vendor......... <%-ls>\n"), pObjectInfo->Info.ChangerType.szVendor );
  543. WsbTrace(OLESTR(" Product........ <%-ls>\n"), pObjectInfo->Info.ChangerType.szProduct );
  544. WsbTrace(OLESTR(" Device Type.... %-d\n"), pObjectInfo->Info.ChangerType.DeviceType );
  545. break;
  546. case NTMS_COMPUTER:
  547. break;
  548. case NTMS_DRIVE:
  549. WsbTrace(OLESTR("Drive %d Information:\n"), pObjectInfo->Info.Drive.Number );
  550. WsbTrace(OLESTR(" GUID........... %-ls\n"), WsbGuidAsString(pObjectInfo->ObjectGuid) );
  551. WsbTrace(OLESTR(" Name........... <%-ls>\n"), pObjectInfo->szName );
  552. WsbTrace(OLESTR(" Description.... <%-ls>\n"), pObjectInfo->szDescription );
  553. WsbTrace(OLESTR(" Enabled........ %-ls\n"), WsbBoolAsString(pObjectInfo->Enabled) );
  554. WsbTrace(OLESTR(" Op State....... %-ls\n"), WsbLongAsString(pObjectInfo->dwOperationalState) );
  555. WsbTrace(OLESTR(" Created........ %-ls\n"), WsbFiletimeAsString(FALSE, fCreated) );
  556. WsbTrace(OLESTR(" Modified....... %-ls\n"), WsbFiletimeAsString(FALSE, fModified) );
  557. WsbTrace(OLESTR(" Number......... %-d\n"), pObjectInfo->Info.Drive.Number );
  558. WsbTrace(OLESTR(" State.......... %-d\n"), pObjectInfo->Info.Drive.State );
  559. WsbTrace(OLESTR(" Drive Type..... %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Drive.DriveType) );
  560. WsbTrace(OLESTR(" Device Name.... <%-ls>\n"), pObjectInfo->Info.Drive.szDeviceName );
  561. WsbTrace(OLESTR(" Serial Number.. <%-ls>\n"), pObjectInfo->Info.Drive.szSerialNumber );
  562. WsbTrace(OLESTR(" Revision....... <%-ls>\n"), pObjectInfo->Info.Drive.szRevision );
  563. WsbTrace(OLESTR(" SCSI Port...... %-d\n"), pObjectInfo->Info.Drive.ScsiPort );
  564. WsbTrace(OLESTR(" SCSI Bus....... %-d\n"), pObjectInfo->Info.Drive.ScsiBus );
  565. WsbTrace(OLESTR(" SCSI Target.... %-d\n"), pObjectInfo->Info.Drive.ScsiTarget );
  566. WsbTrace(OLESTR(" SCSI Lun....... %-d\n"), pObjectInfo->Info.Drive.ScsiLun );
  567. WsbTrace(OLESTR(" Mount Count.... %-d\n"), pObjectInfo->Info.Drive.dwMountCount );
  568. WsbTrace(OLESTR(" Last Cleaned... %02d/%02d/%02d %02d:%02d:%02d.%03d\n"),
  569. pObjectInfo->Info.Drive.LastCleanedTs.wMonth,
  570. pObjectInfo->Info.Drive.LastCleanedTs.wDay,
  571. pObjectInfo->Info.Drive.LastCleanedTs.wYear,
  572. pObjectInfo->Info.Drive.LastCleanedTs.wHour,
  573. pObjectInfo->Info.Drive.LastCleanedTs.wMinute,
  574. pObjectInfo->Info.Drive.LastCleanedTs.wSecond,
  575. pObjectInfo->Info.Drive.LastCleanedTs.wMilliseconds );
  576. WsbTrace(OLESTR(" Partition...... %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Drive.SavedPartitionId) );
  577. WsbTrace(OLESTR(" Library........ %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Drive.Library) );
  578. break;
  579. case NTMS_DRIVE_TYPE:
  580. WsbTrace(OLESTR("Drive Type Information:\n") );
  581. WsbTrace(OLESTR(" GUID........... %-ls\n"), WsbGuidAsString(pObjectInfo->ObjectGuid) );
  582. WsbTrace(OLESTR(" Name........... <%-ls>\n"), pObjectInfo->szName );
  583. WsbTrace(OLESTR(" Description.... <%-ls>\n"), pObjectInfo->szDescription );
  584. WsbTrace(OLESTR(" Enabled........ %-ls\n"), WsbBoolAsString(pObjectInfo->Enabled) );
  585. WsbTrace(OLESTR(" Op State....... %-ls\n"), WsbLongAsString(pObjectInfo->dwOperationalState) );
  586. WsbTrace(OLESTR(" Created........ %-ls\n"), WsbFiletimeAsString(FALSE, fCreated) );
  587. WsbTrace(OLESTR(" Modified....... %-ls\n"), WsbFiletimeAsString(FALSE, fModified) );
  588. WsbTrace(OLESTR(" Vendor......... <%-ls>\n"), pObjectInfo->Info.DriveType.szVendor );
  589. WsbTrace(OLESTR(" Product........ <%-ls>\n"), pObjectInfo->Info.DriveType.szProduct );
  590. WsbTrace(OLESTR(" Number of Heads %-d\n"), pObjectInfo->Info.DriveType.NumberOfHeads );
  591. WsbTrace(OLESTR(" Device Type.... %-d\n"), pObjectInfo->Info.DriveType.DeviceType );
  592. break;
  593. case NTMS_IEDOOR:
  594. case NTMS_IEPORT:
  595. break;
  596. case NTMS_LIBRARY:
  597. WsbTrace(OLESTR("Library Information:\n") );
  598. WsbTrace(OLESTR(" GUID........... %-ls\n"), WsbGuidAsString(pObjectInfo->ObjectGuid) );
  599. WsbTrace(OLESTR(" Name........... <%-ls>\n"), pObjectInfo->szName );
  600. WsbTrace(OLESTR(" Description.... <%-ls>\n"), pObjectInfo->szDescription );
  601. WsbTrace(OLESTR(" Enabled........ %-ls\n"), WsbBoolAsString(pObjectInfo->Enabled) );
  602. WsbTrace(OLESTR(" Op State....... %-ls\n"), WsbLongAsString(pObjectInfo->dwOperationalState) );
  603. WsbTrace(OLESTR(" Created........ %-ls\n"), WsbFiletimeAsString(FALSE, fCreated) );
  604. WsbTrace(OLESTR(" Modified....... %-ls\n"), WsbFiletimeAsString(FALSE, fModified) );
  605. WsbTrace(OLESTR(" Library Type... %-d\n"), pObjectInfo->Info.Library.LibraryType );
  606. WsbTrace(OLESTR(" CleanerSlot.... %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Library.CleanerSlot) );
  607. WsbTrace(OLESTR(" CleanerSlotD... %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Library.CleanerSlotDefault) );
  608. WsbTrace(OLESTR(" Can Clean...... %-ls\n"), WsbBoolAsString(pObjectInfo->Info.Library.LibrarySupportsDriveCleaning) );
  609. WsbTrace(OLESTR(" Has Bar Code... %-ls\n"), WsbBoolAsString(pObjectInfo->Info.Library.BarCodeReaderInstalled) );
  610. WsbTrace(OLESTR(" Inventory Method %-d\n"), pObjectInfo->Info.Library.InventoryMethod );
  611. WsbTrace(OLESTR(" Cleans Remaining %-d\n"), pObjectInfo->Info.Library.dwCleanerUsesRemaining );
  612. WsbTrace(OLESTR(" Drives......... %-d (%d)\n"),
  613. pObjectInfo->Info.Library.dwNumberOfDrives,
  614. pObjectInfo->Info.Library.FirstDriveNumber);
  615. WsbTrace(OLESTR(" Slots.......... %-d (%d)\n"),
  616. pObjectInfo->Info.Library.dwNumberOfSlots,
  617. pObjectInfo->Info.Library.FirstSlotNumber);
  618. WsbTrace(OLESTR(" Doors.......... %-d (%d)\n"),
  619. pObjectInfo->Info.Library.dwNumberOfDoors,
  620. pObjectInfo->Info.Library.FirstDoorNumber);
  621. WsbTrace(OLESTR(" Ports.......... %-d (%d)\n"),
  622. pObjectInfo->Info.Library.dwNumberOfPorts,
  623. pObjectInfo->Info.Library.FirstPortNumber);
  624. WsbTrace(OLESTR(" Changers....... %-d (%d)\n"),
  625. pObjectInfo->Info.Library.dwNumberOfChangers,
  626. pObjectInfo->Info.Library.FirstChangerNumber);
  627. WsbTrace(OLESTR(" Media Count.... %-d\n"), pObjectInfo->Info.Library.dwNumberOfMedia );
  628. WsbTrace(OLESTR(" Media Types.... %-d\n"), pObjectInfo->Info.Library.dwNumberOfMediaTypes );
  629. WsbTrace(OLESTR(" Requests....... %-d\n"), pObjectInfo->Info.Library.dwNumberOfLibRequests );
  630. break;
  631. case NTMS_LIBREQUEST:
  632. case NTMS_LOGICAL_MEDIA:
  633. break;
  634. case NTMS_MEDIA_POOL:
  635. {
  636. // We need some temporaries since WsbGuidAsString() uses static memory to store string.
  637. CWsbStringPtr g1 = pObjectInfo->ObjectGuid;
  638. CWsbStringPtr g2 = pObjectInfo->Info.MediaPool.MediaType;
  639. CWsbStringPtr g3 = pObjectInfo->Info.MediaPool.Parent;
  640. WsbTrace( OLESTR("%ls %5ls %4d %ls %ls %5d %5d %8d %8d %8d %5d <%ls> / <%ls>\n"),
  641. (WCHAR *)g1,
  642. WsbBoolAsString(pObjectInfo->Enabled),
  643. pObjectInfo->Info.MediaPool.PoolType,
  644. (WCHAR *)g2,
  645. (WCHAR *)g3,
  646. pObjectInfo->Info.MediaPool.AllocationPolicy,
  647. pObjectInfo->Info.MediaPool.DeallocationPolicy,
  648. pObjectInfo->Info.MediaPool.dwMaxAllocates,
  649. pObjectInfo->Info.MediaPool.dwNumberOfPhysicalMedia,
  650. pObjectInfo->Info.MediaPool.dwNumberOfLogicalMedia,
  651. pObjectInfo->Info.MediaPool.dwNumberOfMediaPools,
  652. pObjectInfo->szName,
  653. pObjectInfo->szDescription );
  654. }
  655. break;
  656. case NTMS_MEDIA_TYPE:
  657. WsbTrace( OLESTR("%ls %5ls %4d %5d %2d <%ls> / <%ls>\n"),
  658. WsbGuidAsString(pObjectInfo->ObjectGuid),
  659. WsbBoolAsString(pObjectInfo->Enabled),
  660. pObjectInfo->Info.MediaType.MediaType,
  661. pObjectInfo->Info.MediaType.NumberOfSides,
  662. pObjectInfo->Info.MediaType.ReadWriteCharacteristics,
  663. pObjectInfo->szName,
  664. pObjectInfo->szDescription );
  665. break;
  666. case NTMS_PARTITION:
  667. WsbTrace(OLESTR("Partion Information:\n") );
  668. WsbTrace(OLESTR(" GUID........... %-ls\n"), WsbGuidAsString(pObjectInfo->ObjectGuid) );
  669. WsbTrace(OLESTR(" Name........... <%-ls>\n"), pObjectInfo->szName );
  670. WsbTrace(OLESTR(" Description.... <%-ls>\n"), pObjectInfo->szDescription );
  671. WsbTrace(OLESTR(" Enabled........ %-ls\n"), WsbBoolAsString(pObjectInfo->Enabled) );
  672. WsbTrace(OLESTR(" Op State....... %-ls\n"), WsbLongAsString(pObjectInfo->dwOperationalState) );
  673. WsbTrace(OLESTR(" Created........ %-ls\n"), WsbFiletimeAsString(FALSE, fCreated) );
  674. WsbTrace(OLESTR(" Modified....... %-ls\n"), WsbFiletimeAsString(FALSE, fModified) );
  675. WsbTrace(OLESTR(" PhysicalMedia.. %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Partition.PhysicalMedia));
  676. WsbTrace(OLESTR(" LogicalMedia... %-ls\n"), WsbGuidAsString(pObjectInfo->Info.Partition.LogicalMedia));
  677. WsbTrace(OLESTR(" State.......... %-d\n"), pObjectInfo->Info.Partition.State);
  678. WsbTrace(OLESTR(" Side........... %-d\n"), pObjectInfo->Info.Partition.Side);
  679. WsbTrace(OLESTR(" OmidLabelIdLen %-d\n"), pObjectInfo->Info.Partition.dwOmidLabelIdLength);
  680. WsbTrace(OLESTR(" OmidLableId:\n"));
  681. WsbTraceBuffer(pObjectInfo->Info.Partition.dwOmidLabelIdLength, pObjectInfo->Info.Partition.OmidLabelId);
  682. WsbTrace(OLESTR(" OmidLabelType.. %-ls\n"), pObjectInfo->Info.Partition.szOmidLabelType);
  683. WsbTrace(OLESTR(" OmidLabelInfo.. %-ls\n"), pObjectInfo->Info.Partition.szOmidLabelInfo);
  684. WsbTrace(OLESTR(" MountCount..... %-d\n"), pObjectInfo->Info.Partition.dwMountCount);
  685. WsbTrace(OLESTR(" AllocateCount.. %-d\n"), pObjectInfo->Info.Partition.dwAllocateCount);
  686. WsbTrace(OLESTR(" Capacity....... %-I64d\n"), pObjectInfo->Info.Partition.Capacity.QuadPart);
  687. break;
  688. case NTMS_PHYSICAL_MEDIA:
  689. case NTMS_STORAGESLOT:
  690. case NTMS_OPREQUEST:
  691. default:
  692. break;
  693. }
  694. } WsbCatch(hr);
  695. return hr;
  696. }
  697. HRESULT
  698. CRmsNTMS::getNtmsSupportFromRegistry(
  699. OUT DWORD *pNTMSSupportValue)
  700. /*++
  701. Routine Description:
  702. Determines if NTMS flag is set in the Registry.
  703. Arguments:
  704. pNTMSSupportValue - Receives the actual value of the regstry key value. Any non-zero
  705. values indicates NTMS support.
  706. Return Values:
  707. S_OK - NTMS support flag is on.
  708. S_FALSE - NTMS support flag is off.
  709. --*/
  710. {
  711. HRESULT hr = S_OK;
  712. DWORD val = RMS_DEFAULT_NTMS_SUPPORT;
  713. WsbTraceIn(OLESTR("CRmsNTMS::getNtmsSupportFromRegistry"), OLESTR(""));
  714. try {
  715. DWORD sizeGot;
  716. const int cDataSizeToGet = 100;
  717. OLECHAR dataString[cDataSizeToGet];
  718. OLECHAR *stopString;
  719. //
  720. // Get the value. If the key doesn't exists, the default value is used.
  721. //
  722. try {
  723. WsbAffirmHrOk(WsbEnsureRegistryKeyExists(NULL, RMS_REGISTRY_STRING));
  724. WsbAffirmHrOk(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_NTMS_SUPPORT,
  725. dataString, cDataSizeToGet, &sizeGot));
  726. val = wcstoul(dataString, &stopString, 10);
  727. } WsbCatch(hr);
  728. if (pNTMSSupportValue != NULL) {
  729. *pNTMSSupportValue = val;
  730. }
  731. hr = (val) ? S_OK : S_FALSE;
  732. } WsbCatchAndDo( hr,
  733. hr = S_FALSE;
  734. );
  735. WsbTraceOut(OLESTR("CRmsNTMS::getNtmsSupportFromRegistry"), OLESTR("hr = <%ls>, val = <%ld>"), WsbHrAsString(hr), val);
  736. return hr;
  737. }
  738. HRESULT
  739. CRmsNTMS::beginSession(void)
  740. /*++
  741. Implements:
  742. CRmsNTMS::beginSession
  743. --*/
  744. {
  745. HRESULT hr = S_OK;
  746. WsbTraceIn( OLESTR("CRmsNTMS::beginSession"), OLESTR("") );
  747. try {
  748. WsbAffirmHrOk(IsInstalled());
  749. WsbAffirmHrOk(endSession()); // clear the old session
  750. WsbAffirmHrOk(waitUntilReady()); // starts a new session
  751. //WsbAffirmHrOk(waitForScratchPool());
  752. } WsbCatch(hr);
  753. WsbTraceOut( OLESTR("CRmsNTMS::beginSession"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
  754. return hr;
  755. }
  756. HRESULT
  757. CRmsNTMS::endSession(void)
  758. /*++
  759. Implements:
  760. CRmsNTMS::endSession
  761. --*/
  762. {
  763. HRESULT hr = S_OK;
  764. WsbTraceIn( OLESTR("CRmsNTMS::endSession"), OLESTR("") );
  765. try {
  766. if ( m_SessionHandle != INVALID_HANDLE_VALUE ) {
  767. // NTMS - Close session
  768. WsbTraceAlways(OLESTR("CloseNtmsSession()\n"));
  769. WsbAffirmNoError(CloseNtmsSession(m_SessionHandle));
  770. }
  771. } WsbCatchAndDo(hr,
  772. switch (HRESULT_CODE(hr)) {
  773. case ERROR_CONNECTION_UNAVAIL:
  774. case ERROR_INVALID_HANDLE:
  775. break;
  776. default:
  777. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  778. OLESTR("CloseNtmsSession"), OLESTR("Undocumented Error: "),
  779. WsbHrAsString(hr), NULL);
  780. break;
  781. }
  782. );
  783. m_SessionHandle = INVALID_HANDLE_VALUE;
  784. hr = S_OK;
  785. WsbTraceOut( OLESTR("CRmsNTMS::endSession"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
  786. return hr;
  787. }
  788. HRESULT
  789. CRmsNTMS::waitUntilReady(void)
  790. {
  791. HRESULT hr = S_OK;
  792. WsbTraceIn(OLESTR("CRmsNTMS::waitUntilReady"), OLESTR(""));
  793. try {
  794. int retry = 360; // number of retries
  795. // Retrieve the NotificationWaitTime parameter
  796. DWORD size;
  797. OLECHAR tmpString[256];
  798. DWORD notificationWaitTime = RMS_DEFAULT_NOTIFICATION_WAIT_TIME;
  799. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_NOTIFICATION_WAIT_TIME, tmpString, 256, &size))) {
  800. notificationWaitTime = wcstol(tmpString, NULL, 10);
  801. WsbTrace(OLESTR("NotificationWaitTime is %d milliseconds.\n"), notificationWaitTime);
  802. }
  803. do {
  804. // NTMS - Open session
  805. WsbTraceAlways(OLESTR("OpenNtmsSession()\n"));
  806. CWsbStringPtr appName;
  807. WsbAffirmHr(appName.LoadFromRsc(_Module.m_hInst, IDS_PRODUCT_NAME));
  808. m_SessionHandle = OpenNtmsSession(NULL, (WCHAR *) appName, 0);
  809. if ( m_SessionHandle != INVALID_HANDLE_VALUE ) {
  810. break;
  811. }
  812. else {
  813. hr = HRESULT_FROM_WIN32(GetLastError());
  814. switch (HRESULT_CODE(hr)) {
  815. case ERROR_NOT_READY:
  816. if ( retry > 0 ) {
  817. WsbTrace(OLESTR("Waiting for NTMS to come ready - Seconds remaining before timeout: %d\n"), retry*notificationWaitTime/1000);
  818. Sleep(notificationWaitTime);
  819. hr = S_OK;
  820. }
  821. else {
  822. //
  823. // This is the last try, so log the failure.
  824. //
  825. WsbLogEvent(RMS_MESSAGE_NTMS_CONNECTION_NOT_ESABLISHED,
  826. 0, NULL, WsbHrAsString(hr), NULL);
  827. WsbThrow(RMS_E_NTMS_NOT_CONNECTED);
  828. }
  829. break;
  830. case ERROR_INVALID_COMPUTERNAME:
  831. case ERROR_INVALID_PARAMETER:
  832. case ERROR_NO_NETWORK:
  833. case ERROR_NOT_CONNECTED:
  834. WsbLogEvent(RMS_MESSAGE_NTMS_CONNECTION_NOT_ESABLISHED,
  835. 0, NULL, WsbHrAsString(hr), NULL);
  836. WsbThrow(hr);
  837. break;
  838. default:
  839. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  840. OLESTR("OpenNtmsSession"), OLESTR("Undocumented Error: "),
  841. WsbHrAsString(hr), NULL);
  842. WsbThrow(hr);
  843. break;
  844. }
  845. }
  846. } while( retry-- > 0 ) ;
  847. } WsbCatch(hr);
  848. WsbTraceOut(OLESTR("CRmsNTMS::waitUntilReady"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  849. return hr;
  850. }
  851. HRESULT
  852. CRmsNTMS::waitForScratchPool(void)
  853. {
  854. HRESULT hr = S_OK;
  855. DWORD err1 = NO_ERROR;
  856. DWORD err2 = NO_ERROR;
  857. DWORD err3 = NO_ERROR;
  858. HANDLE hNotify = INVALID_HANDLE_VALUE;
  859. WsbTraceIn(OLESTR("CRmsNTMS::waitForScratchPool"), OLESTR(""));
  860. try {
  861. int retry = 60; // number of retries
  862. // Retrieve the NotificationWaitTime parameter
  863. DWORD size;
  864. OLECHAR tmpString[256];
  865. DWORD notificationWaitTime = RMS_DEFAULT_NOTIFICATION_WAIT_TIME;
  866. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_NOTIFICATION_WAIT_TIME, tmpString, 256, &size))) {
  867. notificationWaitTime = wcstol(tmpString, NULL, 10);
  868. WsbTrace(OLESTR("NotificationWaitTime is %d milliseconds.\n"), notificationWaitTime);
  869. }
  870. if ( INVALID_HANDLE_VALUE == m_SessionHandle ) {
  871. WsbThrow(E_UNEXPECTED);
  872. }
  873. HANDLE hSession = m_SessionHandle;
  874. NTMS_OBJECTINFORMATION objectInfo;
  875. NTMS_OBJECTINFORMATION scratchInfo;
  876. NTMS_NOTIFICATIONINFORMATION notifyInfo;
  877. HANDLE hFind = NULL;
  878. BOOL bFound = FALSE;
  879. // TODO: We really should wait around until all libraries are classified.
  880. DWORD mediaCount = 0;
  881. hr = findFirstNtmsObject( NTMS_LIBRARY, GUID_NULL, NULL, GUID_NULL, &hFind, &objectInfo);
  882. while( S_OK == hr ) {
  883. reportNtmsObjectInformation( &objectInfo );
  884. mediaCount += objectInfo.Info.Library.dwNumberOfMedia;
  885. hr = findNextNtmsObject( hFind, &objectInfo );
  886. }
  887. findCloseNtmsObject( hFind );
  888. if ( 0 == mediaCount) {
  889. WsbThrow( RMS_E_NTMS_OBJECT_NOT_FOUND );
  890. }
  891. /*
  892. // First see if there is any media to be classified, if not we don't bother waiting around for
  893. // nothing to happen.
  894. hr = findFirstNtmsObject( NTMS_PHYSICAL_MEDIA, GUID_NULL, NULL, GUID_NULL, &hFind, &objectInfo);
  895. WsbAffirmHrOk( hr );
  896. findCloseNtmsObject( hFind );
  897. */
  898. // NTMS - Open notification channel
  899. WsbTraceAlways(OLESTR("OpenNtmsNotification()\n"));
  900. hNotify = OpenNtmsNotification(hSession, NTMS_MEDIA_POOL);
  901. if ( INVALID_HANDLE_VALUE == hNotify ) {
  902. err1 = GetLastError();
  903. WsbAffirmNoError(err1);
  904. WsbThrow(E_UNEXPECTED);
  905. }
  906. do {
  907. err2 = NO_ERROR;
  908. //
  909. // Count the number of NTMS Scratch pools, and if
  910. // there are more than one, we return. If not,
  911. // we wait until the root level scratch pool object
  912. // is updated.
  913. //
  914. // More that one scratch media pools implies that at
  915. // least one unit of media was classified. We don't
  916. // know until we complete the initialization if it
  917. // was one of the media types supported by RemoteStorage.
  918. //
  919. int count = 0;
  920. hr = findFirstNtmsObject( NTMS_MEDIA_POOL, GUID_NULL, NULL, GUID_NULL, &hFind, &objectInfo);
  921. while( S_OK == hr ) {
  922. if ( NTMS_POOLTYPE_SCRATCH == objectInfo.Info.MediaPool.PoolType ) {
  923. count++;
  924. if ( count == 1 ) {
  925. // Assueme this is the rool pool and one we'll check on for updates
  926. // If the assumption is wrong count will end up > 1.
  927. memcpy(&scratchInfo, &objectInfo, sizeof(NTMS_OBJECTINFORMATION));
  928. }
  929. }
  930. hr = findNextNtmsObject( hFind, &objectInfo );
  931. }
  932. findCloseNtmsObject( hFind );
  933. if ( count > 1 ) {
  934. bFound = TRUE;
  935. hr = S_OK;
  936. break; // Normal exit.
  937. }
  938. if ( count == 0 ) {
  939. WsbThrow(E_UNEXPECTED);
  940. }
  941. // Just one scratch pool detected... wait until a media-type specific pool
  942. // is added root scratch pool. This will show up as an update to the root
  943. // scratch pool.
  944. do {
  945. WsbTrace(OLESTR("Waiting for NTMS scratch pool - Seconds remaining before timeout: %d\n"), retry*notificationWaitTime/1000);
  946. // NTMS - Wait for notification
  947. WsbTraceAlways(OLESTR("WaitForNtmsNotification()\n"));
  948. err2 = WaitForNtmsNotification(hNotify, &notifyInfo, notificationWaitTime);
  949. if ( NO_ERROR == err2 ) {
  950. //
  951. // Note: With this notification mechanism, chances
  952. // are slim that we got notified on the object we really
  953. // care about.
  954. //
  955. WsbTrace(OLESTR("Processing: <%d> %ls\n"), notifyInfo.dwOperation, WsbGuidAsString(notifyInfo.ObjectId));
  956. if ( notifyInfo.ObjectId != scratchInfo.ObjectGuid ) {
  957. WsbTrace(OLESTR("Wrong object, try again...\n"));
  958. continue; // skip this one
  959. }
  960. else {
  961. if ( NTMS_OBJ_UPDATE != notifyInfo.dwOperation ) {
  962. WsbTrace(OLESTR("Wrong operation, try again...\n"));
  963. continue; // skip this one
  964. }
  965. else {
  966. WsbTrace(OLESTR("Scratch pool update detected.\n"));
  967. break; // A scratch pool may have inserted, go check it out...
  968. }
  969. }
  970. }
  971. else if ( ERROR_TIMEOUT != err2 && ERROR_NO_DATA != err2 ) {
  972. WsbAffirmNoError(err2);
  973. }
  974. retry--;
  975. } while( (retry > 0) && (!bFound) );
  976. } while( (retry > 0) && (!bFound) );
  977. // NTMS - Close notification channel
  978. WsbTraceAlways(OLESTR("CloseNtmsNotification()\n"));
  979. err3 = CloseNtmsNotification(hNotify);
  980. WsbAffirmNoError(err3);
  981. if ( !bFound ) {
  982. hr = RMS_E_RESOURCE_UNAVAILABLE;
  983. }
  984. } WsbCatchAndDo(hr,
  985. if ( hNotify != INVALID_HANDLE_VALUE ) {
  986. // NTMS - Close notification channel
  987. WsbTraceAlways(OLESTR("CloseNtmsNotification()\n"));
  988. err3 = CloseNtmsNotification(hNotify);
  989. }
  990. if (err1 != NO_ERROR) {
  991. // OpenNtmsNotification
  992. switch (HRESULT_CODE(hr)) {
  993. case ERROR_DATABASE_FAILURE:
  994. case ERROR_INVALID_HANDLE:
  995. case ERROR_NOT_CONNECTED:
  996. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  997. OLESTR("OpenNtmsNotification"), OLESTR(""),
  998. WsbHrAsString(hr), NULL);
  999. break;
  1000. default:
  1001. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  1002. OLESTR("OpenNtmsNotification"), OLESTR("Undocumented Error: "),
  1003. WsbHrAsString(hr), NULL);
  1004. break;
  1005. }
  1006. }
  1007. if (err2 != NO_ERROR) {
  1008. // WaitForNtmsNotification
  1009. switch (HRESULT_CODE(hr)) {
  1010. case ERROR_INVALID_HANDLE:
  1011. case ERROR_NOT_CONNECTED:
  1012. case ERROR_DATABASE_FAILURE:
  1013. case ERROR_TIMEOUT:
  1014. case ERROR_NO_DATA:
  1015. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  1016. OLESTR("WaitForNtmsNotification"), OLESTR(""),
  1017. WsbHrAsString(hr), NULL);
  1018. break;
  1019. default:
  1020. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  1021. OLESTR("WaitForNtmsNotification"), OLESTR("Undocumented Error: "),
  1022. WsbHrAsString(hr), NULL);
  1023. break;
  1024. }
  1025. }
  1026. if (err3 != NO_ERROR) {
  1027. // CloseNtmsNotification
  1028. switch (HRESULT_CODE(hr)) {
  1029. case ERROR_INVALID_HANDLE:
  1030. case ERROR_NOT_CONNECTED:
  1031. case ERROR_DATABASE_FAILURE:
  1032. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  1033. OLESTR("CloseNtmsNotification"), OLESTR(""),
  1034. WsbHrAsString(hr), NULL);
  1035. break;
  1036. default:
  1037. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  1038. OLESTR("CloseNtmsNotification"), OLESTR("Undocumented Error: "),
  1039. WsbHrAsString(hr), NULL);
  1040. break;
  1041. }
  1042. }
  1043. );
  1044. WsbTraceOut(OLESTR("CRmsNTMS::waitForScratchPool"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1045. return hr;
  1046. }
  1047. HRESULT
  1048. CRmsNTMS::storageMediaTypeToRmsMedia(
  1049. IN NTMS_MEDIATYPEINFORMATION *pMediaTypeInfo,
  1050. OUT RmsMedia *pTranslatedMediaType)
  1051. {
  1052. HRESULT hr = S_OK;
  1053. DWORD size;
  1054. OLECHAR tmpString[256];
  1055. // Media type is the main criteria
  1056. WsbAssertPointer(pMediaTypeInfo);
  1057. STORAGE_MEDIA_TYPE mediaType = (STORAGE_MEDIA_TYPE)(pMediaTypeInfo->MediaType);
  1058. DWORD tapeEnabled = RMS_DEFAULT_TAPE;
  1059. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_TAPE, tmpString, 256, &size))) {
  1060. // Get the value.
  1061. tapeEnabled = wcstol(tmpString, NULL, 10);
  1062. }
  1063. DWORD opticalEnabled = RMS_DEFAULT_OPTICAL;
  1064. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_OPTICAL, tmpString, 256, &size))) {
  1065. // Get the value.
  1066. opticalEnabled = wcstol(tmpString, NULL, 10);
  1067. }
  1068. DWORD dvdEnabled = RMS_DEFAULT_DVD;
  1069. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_DVD, tmpString, 256, &size))) {
  1070. // Get the value.
  1071. dvdEnabled = wcstol(tmpString, NULL, 10);
  1072. }
  1073. switch ( mediaType ) {
  1074. case DDS_4mm: // Tape - DAT DDS1,2,... (all vendors) (0x20)
  1075. *pTranslatedMediaType = (tapeEnabled) ? RmsMedia4mm : RmsMediaUnknown;
  1076. break;
  1077. case MiniQic: // Tape - miniQIC Tape
  1078. case Travan: // Tape - Travan TR-1,2,3,...
  1079. case QIC: // Tape - QIC
  1080. *pTranslatedMediaType = RmsMediaUnknown;
  1081. break;
  1082. case MP_8mm: // Tape - 8mm Exabyte Metal Particle
  1083. case AME_8mm: // Tape - 8mm Exabyte Advanced Metal Evap
  1084. case AIT1_8mm: // Tape - 8mm Sony AIT1
  1085. *pTranslatedMediaType = (tapeEnabled) ? RmsMedia8mm : RmsMediaUnknown;
  1086. break;
  1087. case DLT: // Tape - DLT Compact IIIxt: IV
  1088. *pTranslatedMediaType = (tapeEnabled) ? RmsMediaDLT : RmsMediaUnknown;
  1089. break;
  1090. case NCTP: // Tape - Philips NCTP
  1091. case IBM_3480: // Tape - IBM 3480
  1092. case IBM_3490E: // Tape - IBM 3490E
  1093. case IBM_Magstar_3590: // Tape - IBM Magstar 3590
  1094. case IBM_Magstar_MP: // Tape - IBM Magstar MP
  1095. case STK_DATA_D3: // Tape - STK Data D3
  1096. case SONY_DTF: // Tape - Sony DTF
  1097. case DV_6mm: // Tape - 6mm Digital Video
  1098. case DMI: // Tape - Exabyte DMI and compatibles
  1099. case SONY_D2: // Tape - Sony D2S and D2L
  1100. case CLEANER_CARTRIDGE: // Cleaner - All Drive types that support Drive Cleaners
  1101. case CD_ROM: // Opt_Disk - CD
  1102. case CD_R: // Opt_Disk - CD-Recordable (Write Once)
  1103. case CD_RW: // Opt_Disk - CD-Rewriteable
  1104. case DVD_ROM: // Opt_Disk - DVD-ROM
  1105. case DVD_R: // Opt_Disk - DVD-Recordable (Write Once)
  1106. case MO_5_WO: // Opt_Disk - MO 5.25" Write Once
  1107. *pTranslatedMediaType = RmsMediaUnknown;
  1108. break;
  1109. case DVD_RW: // Opt_Disk - DVD-Rewriteable
  1110. *pTranslatedMediaType = (dvdEnabled) ? RmsMediaDVD : RmsMediaUnknown;
  1111. break;
  1112. case MO_5_RW: // Opt_Disk - MO 5.25" Rewriteable (not LIMDOW)
  1113. case MO_3_RW: // Opt_Disk - 3.5" Rewriteable MO Disk
  1114. case MO_5_LIMDOW: // Opt_Disk - MO 5.25" Rewriteable (LIMDOW)
  1115. case PC_5_RW: // Opt_Disk - Phase Change 5.25" Rewriteable
  1116. case PD_5_RW: // Opt_Disk - PhaseChange Dual Rewriteable
  1117. case PINNACLE_APEX_5_RW: // Opt_Disk - Pinnacle Apex 4.6GB Rewriteable Optical
  1118. case NIKON_12_RW: // Opt_Disk - Nikon 12" Rewriteable
  1119. *pTranslatedMediaType = (opticalEnabled) ? RmsMediaOptical : RmsMediaUnknown;
  1120. break;
  1121. case PC_5_WO: // Opt_Disk - Phase Change 5.25" Write Once Optical
  1122. case ABL_5_WO: // Opt_Disk - Ablative 5.25" Write Once Optical
  1123. *pTranslatedMediaType = RmsMediaUnknown;
  1124. break;
  1125. case SONY_12_WO: // Opt_Disk - Sony 12" Write Once
  1126. case PHILIPS_12_WO: // Opt_Disk - Philips/LMS 12" Write Once
  1127. case HITACHI_12_WO: // Opt_Disk - Hitachi 12" Write Once
  1128. case CYGNET_12_WO: // Opt_Disk - Cygnet/ATG 12" Write Once
  1129. case KODAK_14_WO: // Opt_Disk - Kodak 14" Write Once
  1130. case MO_NFR_525: // Opt_Disk - Near Field Recording (Terastor)
  1131. case IOMEGA_ZIP: // Mag_Disk - Iomega Zip
  1132. case IOMEGA_JAZ: // Mag_Disk - Iomega Jaz
  1133. case SYQUEST_EZ135: // Mag_Disk - Syquest EZ135
  1134. case SYQUEST_EZFLYER: // Mag_Disk - Syquest EzFlyer
  1135. case SYQUEST_SYJET: // Mag_Disk - Syquest SyJet
  1136. case AVATAR_F2: // Mag_Disk - 2.5" Floppy
  1137. *pTranslatedMediaType = RmsMediaUnknown;
  1138. break;
  1139. case RemovableMedia: // This is reported on stand-alone optical drives.
  1140. default:
  1141. // Check RSM characteristics for Rewriteable Disk
  1142. if ((pMediaTypeInfo->ReadWriteCharacteristics == NTMS_MEDIARW_REWRITABLE) &&
  1143. (pMediaTypeInfo->DeviceType == FILE_DEVICE_DISK)) {
  1144. *pTranslatedMediaType = (opticalEnabled) ? RmsMediaOptical : RmsMediaUnknown;
  1145. } else {
  1146. // Not a rewritable disk and not one of the supported tape types...
  1147. *pTranslatedMediaType = RmsMediaUnknown;
  1148. }
  1149. break;
  1150. }
  1151. if ((*pTranslatedMediaType == RmsMediaUnknown) &&
  1152. (pMediaTypeInfo->DeviceType == FILE_DEVICE_TAPE)) {
  1153. // Check in the Registry whether there are additional tapes that we need to support
  1154. ULONG *pTypes= NULL;
  1155. ULONG uTypes = 0;
  1156. if (SUCCEEDED(WsbGetRegistryValueUlongAsMultiString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_ADDITIONAL_TAPE, &pTypes, &uTypes))) {
  1157. // Compare Registry types to the media type we have
  1158. for (ULONG u=0; u<uTypes; u++) {
  1159. if ((STORAGE_MEDIA_TYPE)(pTypes[u]) == mediaType) {
  1160. // Support it !!
  1161. WsbTraceAlways(OLESTR("CRmsNTMS::storageMediaTypeToRmsMedia: Registry asks to support tape type %lu\n"),
  1162. pTypes[u]);
  1163. *pTranslatedMediaType = RmsMediaTape;
  1164. break;
  1165. }
  1166. }
  1167. }
  1168. if (pTypes != NULL) {
  1169. WsbFree(pTypes);
  1170. pTypes = NULL;
  1171. }
  1172. }
  1173. return hr;
  1174. }
  1175. HRESULT
  1176. CRmsNTMS::createMediaPools(void)
  1177. {
  1178. HRESULT hr = S_OK;
  1179. WsbTraceIn(OLESTR("CRmsNTMS::createMediaPools"), OLESTR(""));
  1180. try {
  1181. HANDLE hSession;
  1182. NTMS_GUID rootPoolId = GUID_NULL;
  1183. if ( INVALID_HANDLE_VALUE == m_SessionHandle ) {
  1184. WsbAffirmHr(beginSession());
  1185. }
  1186. hSession = m_SessionHandle;
  1187. try {
  1188. // NTMS - Create Application Media Pool.
  1189. WsbTraceAlways(OLESTR("CreateNtmsMediaPool()\n"));
  1190. WsbAffirmNoError(CreateNtmsMediaPool(hSession, REMOTE_STORAGE_APP_NAME, NULL, NTMS_OPEN_ALWAYS, NULL, &rootPoolId));
  1191. // Now set access permissions on the pool: turn off ordinary users access
  1192. WsbAffirmHrOk(setPoolDACL(&rootPoolId, DOMAIN_ALIAS_RID_USERS, REMOVE_ACE_MASK_BITS,NTMS_USE_ACCESS | NTMS_MODIFY_ACCESS | NTMS_CONTROL_ACCESS));
  1193. } WsbCatchAndDo(hr,
  1194. switch(HRESULT_CODE(hr)) {
  1195. case ERROR_INVALID_PARAMETER:
  1196. case ERROR_INVALID_HANDLE:
  1197. case ERROR_INVALID_NAME:
  1198. case ERROR_OBJECT_NOT_FOUND:
  1199. case ERROR_ALREADY_EXISTS:
  1200. case ERROR_ACCESS_DENIED:
  1201. case ERROR_DATABASE_FAILURE:
  1202. case ERROR_DATABASE_FULL:
  1203. WsbLogEvent( RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  1204. OLESTR("CreateNtmsMediaPool"), OLESTR(""),
  1205. WsbHrAsString(hr),
  1206. NULL );
  1207. break;
  1208. default:
  1209. WsbLogEvent( RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  1210. OLESTR("CreateNtmsMediaPool"), OLESTR("Undocumented Error: "),
  1211. WsbHrAsString(hr),
  1212. NULL );
  1213. break;
  1214. }
  1215. WsbThrow(hr);
  1216. );
  1217. //
  1218. // Only one of the following should be executed, comment out the other.
  1219. //
  1220. WsbAffirmHr( createMediaPoolForEveryMediaType(rootPoolId) ); // New way
  1221. /*
  1222. WsbAffirmHr( replicateScratchMediaPool(rootPoolId) ); // Old way
  1223. */
  1224. } WsbCatch(hr);
  1225. WsbTraceOut( OLESTR("CRmsNTMS::createMediaPools"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
  1226. return hr;
  1227. }
  1228. HRESULT
  1229. CRmsNTMS::replicateScratchMediaPool(
  1230. IN REFGUID /*rootPoolId*/)
  1231. {
  1232. HRESULT hr = E_FAIL;
  1233. WsbTraceIn(OLESTR("CRmsNTMS::replicateScratchMediaPool"), OLESTR(""));
  1234. try {
  1235. HANDLE hSession;
  1236. DWORD errCode;
  1237. NTMS_OBJECTINFORMATION mediaTypeInfo;
  1238. NTMS_OBJECTINFORMATION mediaPoolInfo;
  1239. HANDLE hFind = NULL;
  1240. NTMS_GUID poolId = GUID_NULL;
  1241. if ( INVALID_HANDLE_VALUE == m_SessionHandle ) {
  1242. WsbAffirmHr(beginSession());
  1243. }
  1244. hSession = m_SessionHandle;
  1245. // For each media pool in the scratch pool create an application specific pool.
  1246. hr = findFirstNtmsObject( NTMS_MEDIA_POOL, GUID_NULL, NULL, GUID_NULL, &hFind, &mediaPoolInfo);
  1247. while( S_OK == hr ) {
  1248. reportNtmsObjectInformation( &mediaPoolInfo );
  1249. poolId = GUID_NULL;
  1250. try {
  1251. // Set up application specific NTMS Media Pools. One for each compatible type.
  1252. //
  1253. // To get here we had to already detect a media-type specific scratch pool
  1254. // in waitForScratchPool()
  1255. if ( NTMS_POOLTYPE_SCRATCH == mediaPoolInfo.Info.MediaPool.PoolType &&
  1256. 0 == mediaPoolInfo.Info.MediaPool.dwNumberOfMediaPools ) {
  1257. // This is a base level scratch media pool.
  1258. // Create a similar pool for application specific use.
  1259. CWsbStringPtr name = REMOTE_STORAGE_APP_NAME;
  1260. name.Append( OLESTR("\\") );
  1261. name.Append( mediaPoolInfo.szName );
  1262. NTMS_GUID mediaTypeId = mediaPoolInfo.Info.MediaPool.MediaType;
  1263. // We need more information about the media type.
  1264. memset( &mediaTypeInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
  1265. mediaTypeInfo.dwType = NTMS_MEDIA_TYPE;
  1266. mediaTypeInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  1267. // NTMS - Get Media Pool Information
  1268. WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
  1269. errCode = GetNtmsObjectInformation( hSession, &mediaTypeId, &mediaTypeInfo );
  1270. if ( errCode != NO_ERROR ) {
  1271. WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
  1272. OLESTR("GetNtmsObjectInformation"),
  1273. WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
  1274. NULL );
  1275. WsbThrow( E_UNEXPECTED );
  1276. }
  1277. // Translate the NTMS media type into something understood by RMS
  1278. RmsMedia translatedMediaType;
  1279. storageMediaTypeToRmsMedia(&(mediaTypeInfo.Info.MediaType), &translatedMediaType);
  1280. if ( translatedMediaType != RmsMediaUnknown ) {
  1281. // This something that Remote Storage can deal with
  1282. CWsbBstrPtr mediaSetName = RMS_UNDEFINED_STRING;
  1283. CWsbBstrPtr mediaSetDesc = RMS_UNDEFINED_STRING;
  1284. BOOL mediaSetIsEnabled = FALSE;
  1285. // NTMS - Create Application Media Pool.
  1286. WsbTraceAlways(OLESTR("CreateNtmsMediaPool()\n"));
  1287. errCode = CreateNtmsMediaPool( hSession, (WCHAR *) name, &mediaTypeId, NTMS_CREATE_NEW, NULL, &poolId );
  1288. if ( ERROR_ALREADY_EXISTS == errCode ) {
  1289. // We still need the poolId of the existing pool.
  1290. // NTMS - Create Application Media Pool.
  1291. WsbTraceAlways(OLESTR("CreateNtmsMediaPool()\n"));
  1292. errCode = CreateNtmsMediaPool( hSession, (WCHAR *)name, &mediaTypeId, NTMS_OPEN_EXISTING, NULL, &poolId );
  1293. if ( errCode != NO_ERROR ) {
  1294. WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
  1295. OLESTR("CreateNtmsMediaPool"),
  1296. WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
  1297. NULL );
  1298. WsbThrow( E_UNEXPECTED );
  1299. }
  1300. NTMS_OBJECTINFORMATION mediaPoolInfo;
  1301. memset( &mediaPoolInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
  1302. mediaPoolInfo.dwType = NTMS_MEDIA_POOL;
  1303. mediaPoolInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  1304. // NTMS - Get Media Pool Information
  1305. WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
  1306. errCode = GetNtmsObjectInformation( hSession, &poolId, &mediaPoolInfo );
  1307. if ( errCode != NO_ERROR ) {
  1308. WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
  1309. OLESTR("GetNtmsObjectInformation"),
  1310. WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
  1311. NULL );
  1312. WsbThrow( E_UNEXPECTED );
  1313. }
  1314. // Save relevant info
  1315. mediaSetName = mediaPoolInfo.szName;
  1316. mediaSetDesc = mediaPoolInfo.szDescription;
  1317. mediaSetIsEnabled = mediaPoolInfo.Enabled;
  1318. }
  1319. else if ( NO_ERROR == errCode ) {
  1320. memset( &mediaPoolInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
  1321. mediaPoolInfo.dwType = NTMS_MEDIA_POOL;
  1322. mediaPoolInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  1323. // NTMS - Get Media Pool Information
  1324. WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
  1325. errCode = GetNtmsObjectInformation( hSession, &poolId, &mediaPoolInfo );
  1326. if ( errCode != NO_ERROR ) {
  1327. WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
  1328. OLESTR("GetNtmsObjectInformation"),
  1329. WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
  1330. NULL );
  1331. WsbThrow( E_UNEXPECTED );
  1332. }
  1333. WsbAssert( NTMS_POOLTYPE_APPLICATION == mediaPoolInfo.Info.MediaPool.PoolType, E_UNEXPECTED );
  1334. // Set media pool parameters
  1335. // Aallocation/deallocation policy
  1336. mediaPoolInfo.Info.MediaPool.AllocationPolicy = NTMS_ALLOCATE_FROMSCRATCH;
  1337. mediaPoolInfo.Info.MediaPool.DeallocationPolicy = 0;
  1338. // Max number of allocates per media
  1339. mediaPoolInfo.Info.MediaPool.dwMaxAllocates = 5;// Just a few... we automatically
  1340. // deallocate media if there's
  1341. // problem with scratch mount
  1342. // operation.
  1343. // NOTE: This can be overridden using
  1344. // the NTMS GUI.
  1345. // NTMS - Set Media Pool Information.
  1346. WsbTraceAlways(OLESTR("SetNtmsObjectInformation()\n"));
  1347. errCode = SetNtmsObjectInformation( hSession, &poolId, &mediaPoolInfo );
  1348. if ( errCode != NO_ERROR ) {
  1349. WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
  1350. OLESTR("SetNtmsObjectInformation"),
  1351. WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
  1352. NULL );
  1353. WsbThrow( E_UNEXPECTED );
  1354. }
  1355. // Save relevant info
  1356. mediaSetName = mediaPoolInfo.szName;
  1357. mediaSetDesc = mediaPoolInfo.szDescription;
  1358. mediaSetIsEnabled = mediaPoolInfo.Enabled;
  1359. }
  1360. else {
  1361. WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
  1362. OLESTR("CreateNtmsMediaPool"),
  1363. WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
  1364. NULL );
  1365. WsbThrow( E_UNEXPECTED );
  1366. }
  1367. // Now we have an NTMS media pool for our specific use. Now expose it
  1368. // through the RMS interface by creating a CRmsMediaSet.
  1369. if ( poolId != GUID_NULL ) {
  1370. CComPtr<IRmsMediaSet> pMediaSet;
  1371. // Find the RmsMediaSet with the same id, or create a new one.
  1372. CComQIPtr<IRmsServer, &IID_IRmsServer> pServer = g_pServer;
  1373. WsbAffirmHr( pServer->CreateObject( poolId, CLSID_CRmsMediaSet, IID_IRmsMediaSet, RmsOpenAlways, (void **)&pMediaSet ) );
  1374. WsbTrace(OLESTR("CRmsNTMS::replicateScratchMediaPool - type %d CRmsMediaSet created.\n"), translatedMediaType);
  1375. WsbAffirmHr( pMediaSet->SetMediaSetType( RmsMediaSetNTMS ) );
  1376. WsbAffirmHr( pMediaSet->SetMediaSupported( translatedMediaType ) );
  1377. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pMediaSet;
  1378. WsbTrace(OLESTR("CRmsNTMS::createMediaPoolForEveryMediaType - MediaSet: <%ls/%ls>; Enabled: %ls\n"),
  1379. WsbQuickString(WsbStringAsString(mediaSetName)),
  1380. WsbQuickString(WsbStringAsString(mediaSetDesc)),
  1381. WsbQuickString(WsbBoolAsString(mediaSetIsEnabled)));
  1382. WsbAffirmHr(pObject->SetName(mediaSetName));
  1383. WsbAffirmHr(pObject->SetDescription(mediaSetDesc));
  1384. if (!mediaSetIsEnabled) {
  1385. WsbAffirmHr(pObject->Disable(E_FAIL));
  1386. }
  1387. if (S_OK == IsMediaCopySupported(poolId)) {
  1388. WsbAffirmHr( pMediaSet->SetIsMediaCopySupported(TRUE));
  1389. }
  1390. hr = pMediaSet->IsMediaCopySupported();
  1391. WsbTrace(OLESTR("CRmsNTMS::replicateScratchMediaPool - media copies are %ls.\n"),
  1392. (S_OK == pMediaSet->IsMediaCopySupported()) ? OLESTR("enabled") : OLESTR("disabled"));
  1393. }
  1394. }
  1395. }
  1396. } WsbCatch(hr);
  1397. hr = findNextNtmsObject( hFind, &mediaPoolInfo );
  1398. } // while finding media pools
  1399. findCloseNtmsObject( hFind );
  1400. hr = S_OK;
  1401. } WsbCatch(hr);
  1402. WsbTraceOut( OLESTR("CRmsNTMS::replicateScratchMediaPool"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
  1403. return hr;
  1404. }
  1405. HRESULT
  1406. CRmsNTMS::createMediaPoolForEveryMediaType(
  1407. IN REFGUID /*rootPoolId*/)
  1408. {
  1409. HRESULT hr = S_OK;
  1410. WsbTraceIn(OLESTR("CRmsNTMS::createMediaPoolForEveryMediaType"), OLESTR(""));
  1411. try {
  1412. DWORD errCode;
  1413. if ( INVALID_HANDLE_VALUE == m_SessionHandle ) {
  1414. WsbAffirmHr(beginSession());
  1415. }
  1416. HANDLE hSession = m_SessionHandle;
  1417. HANDLE hFindLib = NULL;
  1418. NTMS_OBJECTINFORMATION libraryInfo;
  1419. BOOL bSupportedLib = FALSE;
  1420. m_dwNofLibs = 0;
  1421. hr = findFirstNtmsObject( NTMS_LIBRARY, GUID_NULL, NULL, GUID_NULL, &hFindLib, &libraryInfo);
  1422. while( S_OK == hr ) {
  1423. bSupportedLib = FALSE;
  1424. reportNtmsObjectInformation( &libraryInfo );
  1425. if (libraryInfo.Info.Library.dwNumberOfMediaTypes > 0) {
  1426. HANDLE hFindType = NULL;
  1427. NTMS_OBJECTINFORMATION mediaTypeInfo;
  1428. hr = findFirstNtmsObject( NTMS_MEDIA_TYPE, libraryInfo.ObjectGuid, NULL, GUID_NULL, &hFindType, &mediaTypeInfo);
  1429. while( S_OK == hr ) {
  1430. //
  1431. // Create an application Media Pool for each type
  1432. //
  1433. NTMS_GUID poolId;
  1434. // This is a base level scratch media pool.
  1435. // Create a similar pool for application specific use.
  1436. CWsbStringPtr name = REMOTE_STORAGE_APP_NAME;
  1437. name.Append( OLESTR("\\") );
  1438. name.Append( mediaTypeInfo.szName );
  1439. NTMS_GUID mediaTypeId = mediaTypeInfo.ObjectGuid;
  1440. // Translate the NTMS media type into something understood by RMS
  1441. RmsMedia translatedMediaType;
  1442. storageMediaTypeToRmsMedia(&(mediaTypeInfo.Info.MediaType), &translatedMediaType);
  1443. if ( translatedMediaType != RmsMediaUnknown ) {
  1444. // This something that Remote Storage can deal with
  1445. CWsbBstrPtr mediaSetName = RMS_UNDEFINED_STRING;
  1446. CWsbBstrPtr mediaSetDesc = RMS_UNDEFINED_STRING;
  1447. BOOL mediaSetIsEnabled = FALSE;
  1448. // NTMS - Create Application Media Pool.
  1449. WsbTraceAlways(OLESTR("CreateNtmsMediaPool(<%ls>) - Try New.\n"), (WCHAR *) name);
  1450. errCode = CreateNtmsMediaPool( hSession, (WCHAR *) name, &mediaTypeId, NTMS_CREATE_NEW, NULL, &poolId );
  1451. if ( ERROR_ALREADY_EXISTS == errCode ) {
  1452. WsbTraceAlways(OLESTR("MediaPool <%ls> already exists.\n"), (WCHAR *) name);
  1453. // We still need the poolId of the existing pool.
  1454. // NTMS - Create Application Media Pool.
  1455. WsbTraceAlways(OLESTR("CreateNtmsMediaPool(<%ls>) - Try Existing.\n"), (WCHAR *) name);
  1456. errCode = CreateNtmsMediaPool( hSession, (WCHAR *)name, &mediaTypeId, NTMS_OPEN_EXISTING, NULL, &poolId );
  1457. if ( errCode != NO_ERROR ) {
  1458. WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
  1459. OLESTR("CreateNtmsMediaPool"),
  1460. WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
  1461. NULL );
  1462. WsbThrow( E_UNEXPECTED );
  1463. }
  1464. WsbTraceAlways(OLESTR("Media Pool %ls detected.\n"), WsbGuidAsString(poolId));
  1465. NTMS_OBJECTINFORMATION mediaPoolInfo;
  1466. memset( &mediaPoolInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
  1467. mediaPoolInfo.dwType = NTMS_MEDIA_POOL;
  1468. mediaPoolInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  1469. // NTMS - Get Media Pool Information
  1470. WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
  1471. errCode = GetNtmsObjectInformation( hSession, &poolId, &mediaPoolInfo );
  1472. if ( errCode != NO_ERROR ) {
  1473. WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
  1474. OLESTR("GetNtmsObjectInformation"),
  1475. WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
  1476. NULL );
  1477. WsbThrow( E_UNEXPECTED );
  1478. }
  1479. // Save relevant info
  1480. mediaSetName = mediaPoolInfo.szName;
  1481. mediaSetDesc = mediaPoolInfo.szDescription;
  1482. mediaSetIsEnabled = mediaPoolInfo.Enabled;
  1483. }
  1484. else if ( NO_ERROR == errCode ) {
  1485. WsbTraceAlways(OLESTR("MediaPool <%ls> created.\n"), (WCHAR *) name);
  1486. NTMS_OBJECTINFORMATION mediaPoolInfo;
  1487. memset( &mediaPoolInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
  1488. mediaPoolInfo.dwType = NTMS_MEDIA_POOL;
  1489. mediaPoolInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  1490. // NTMS - Get Media Pool Information
  1491. WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
  1492. errCode = GetNtmsObjectInformation( hSession, &poolId, &mediaPoolInfo );
  1493. if ( errCode != NO_ERROR ) {
  1494. WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
  1495. OLESTR("GetNtmsObjectInformation"),
  1496. WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
  1497. NULL );
  1498. WsbThrow( E_UNEXPECTED );
  1499. }
  1500. WsbAssert( NTMS_POOLTYPE_APPLICATION == mediaPoolInfo.Info.MediaPool.PoolType, E_UNEXPECTED );
  1501. // Set media pool parameters
  1502. // Aallocation/deallocation policy
  1503. mediaPoolInfo.Info.MediaPool.AllocationPolicy = NTMS_ALLOCATE_FROMSCRATCH;
  1504. mediaPoolInfo.Info.MediaPool.DeallocationPolicy = 0;
  1505. // Max number of allocates per media
  1506. mediaPoolInfo.Info.MediaPool.dwMaxAllocates = 0;// Unlimited... we automatically
  1507. // deallocate media if there's
  1508. // problem with scratch mount
  1509. // operation.
  1510. // TODO: Verify that NTMS always allocates
  1511. // media with the lowest allocation
  1512. // count.
  1513. // NOTE: This can be overridden using
  1514. // the NTMS GUI.
  1515. // NTMS - Set Media Pool Information.
  1516. WsbTraceAlways(OLESTR("SetNtmsObjectInformation()\n"));
  1517. errCode = SetNtmsObjectInformation( hSession, &poolId, &mediaPoolInfo );
  1518. if ( errCode != NO_ERROR ) {
  1519. WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
  1520. OLESTR("SetNtmsObjectInformation"),
  1521. WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
  1522. NULL );
  1523. WsbThrow( E_UNEXPECTED );
  1524. }
  1525. // Save relevant info
  1526. mediaSetName = mediaPoolInfo.szName;
  1527. mediaSetDesc = mediaPoolInfo.szDescription;
  1528. mediaSetIsEnabled = mediaPoolInfo.Enabled;
  1529. }
  1530. else {
  1531. WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
  1532. OLESTR("CreateNtmsMediaPool"),
  1533. WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
  1534. NULL );
  1535. WsbThrow( E_UNEXPECTED );
  1536. }
  1537. // Now set access permissions on the pool: turn off ordinary users access
  1538. WsbAffirmHrOk(setPoolDACL(&poolId, DOMAIN_ALIAS_RID_USERS, REMOVE_ACE_MASK_BITS,NTMS_USE_ACCESS | NTMS_MODIFY_ACCESS | NTMS_CONTROL_ACCESS));
  1539. // Now we have an NTMS media pool for our specific use. Now expose it
  1540. // through the RMS interface by creating a CRmsMediaSet.
  1541. if ( poolId != GUID_NULL ) {
  1542. //
  1543. // Add to CRmsMediaSet collection
  1544. //
  1545. CComPtr<IRmsMediaSet> pMediaSet;
  1546. // Find the CRmsMediaSet with the same id, or create a new one.
  1547. CComQIPtr<IRmsServer, &IID_IRmsServer> pServer = g_pServer;
  1548. WsbAffirmHr( pServer->CreateObject( poolId, CLSID_CRmsMediaSet, IID_IRmsMediaSet, RmsOpenAlways, (void **)&pMediaSet ) );
  1549. WsbTrace(OLESTR("CRmsNTMS::createMediaPoolForEveryMediaType - type %d CRmsMediaSet established.\n"), translatedMediaType);
  1550. WsbAffirmHr( pMediaSet->SetMediaSetType( RmsMediaSetNTMS ) );
  1551. WsbAffirmHr( pMediaSet->SetMediaSupported( translatedMediaType ) );
  1552. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = pMediaSet;
  1553. WsbTrace(OLESTR("CRmsNTMS::createMediaPoolForEveryMediaType - MediaSet: <%ls/%ls> %ls; Enabled: %ls\n"),
  1554. WsbQuickString(WsbStringAsString(mediaSetName)),
  1555. WsbQuickString(WsbStringAsString(mediaSetDesc)),
  1556. WsbQuickString(WsbGuidAsString(poolId)),
  1557. WsbQuickString(WsbBoolAsString(mediaSetIsEnabled)));
  1558. WsbAffirmHr(pObject->SetName(mediaSetName));
  1559. WsbAffirmHr(pObject->SetDescription(mediaSetDesc));
  1560. if (!mediaSetIsEnabled) {
  1561. WsbAffirmHr(pObject->Disable(E_FAIL));
  1562. }
  1563. if (S_OK == IsMediaCopySupported(poolId)) {
  1564. WsbAffirmHr( pMediaSet->SetIsMediaCopySupported(TRUE));
  1565. }
  1566. hr = pMediaSet->IsMediaCopySupported();
  1567. WsbTrace(OLESTR("CRmsNTMS::createMediaPoolForEveryMediaType - media copies are %ls.\n"),
  1568. (S_OK == pMediaSet->IsMediaCopySupported()) ? OLESTR("enabled") : OLESTR("disabled"));
  1569. }
  1570. // The library has a supported media type
  1571. bSupportedLib = TRUE;
  1572. }
  1573. hr = findNextNtmsObject( hFindType, &mediaTypeInfo );
  1574. }
  1575. findCloseNtmsObject( hFindType );
  1576. }
  1577. // Check if the library has supported media type
  1578. if (bSupportedLib) {
  1579. // Add library GUI to the libraries list
  1580. // (Realloc one item each time since we don't expect many items)
  1581. m_dwNofLibs++;
  1582. LPVOID pTemp = WsbRealloc(m_pLibGuids, m_dwNofLibs*sizeof(NTMS_GUID));
  1583. if (!pTemp) {
  1584. WsbThrow(E_OUTOFMEMORY);
  1585. }
  1586. m_pLibGuids = (LPNTMS_GUID)pTemp;
  1587. m_pLibGuids[m_dwNofLibs-1] = libraryInfo.ObjectGuid;
  1588. }
  1589. // Continue library enumeration
  1590. hr = findNextNtmsObject( hFindLib, &libraryInfo );
  1591. }
  1592. findCloseNtmsObject( hFindLib );
  1593. hr = S_OK;
  1594. } WsbCatch(hr);
  1595. WsbTraceOut( OLESTR("CRmsNTMS::createMediaPoolForEveryMediaType"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
  1596. return hr;
  1597. }
  1598. STDMETHODIMP
  1599. CRmsNTMS::Allocate(
  1600. IN REFGUID fromMediaSet,
  1601. IN REFGUID prevSideId,
  1602. IN OUT LONGLONG *pFreeSpace,
  1603. IN BSTR displayName,
  1604. IN DWORD dwOptions,
  1605. OUT IRmsCartridge **ppCartridge)
  1606. /*++
  1607. Implements:
  1608. IRmsNTMS::Allocate
  1609. --*/
  1610. {
  1611. HRESULT hr = S_OK;
  1612. DWORD err1 = NO_ERROR;
  1613. DWORD err2 = NO_ERROR;
  1614. DWORD err3 = NO_ERROR;
  1615. DWORD err4 = NO_ERROR;
  1616. DWORD err5 = NO_ERROR;
  1617. DWORD err6 = NO_ERROR;
  1618. DWORD err7 = NO_ERROR;
  1619. WsbTraceIn(OLESTR("CRmsNTMS::Allocate"), OLESTR("<%ls> <%ls> <%ls> <%ls> <0x%08x"),
  1620. WsbGuidAsString(fromMediaSet), WsbGuidAsString(prevSideId),
  1621. WsbPtrToLonglongAsString(pFreeSpace), WsbStringAsString(displayName), dwOptions);
  1622. try {
  1623. WsbAssert(fromMediaSet != GUID_NULL, E_INVALIDARG);
  1624. WsbAssertPointer(ppCartridge);
  1625. // Retrieve the AllocateWaitTime and RequestWaitTime parameters
  1626. DWORD size;
  1627. OLECHAR tmpString[256];
  1628. DWORD allocateWaitTime;
  1629. DWORD requestWaitTime;
  1630. BOOL bShortTimeout = ( dwOptions & RMS_SHORT_TIMEOUT ) ? TRUE : FALSE;
  1631. BOOL bFailOnSize = ( dwOptions & RMS_FAIL_ALLOCATE_ON_SIZE ) ? TRUE : FALSE;
  1632. if (bShortTimeout) {
  1633. allocateWaitTime = RMS_DEFAULT_SHORT_WAIT_TIME;
  1634. requestWaitTime = RMS_DEFAULT_SHORT_WAIT_TIME;
  1635. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_SHORT_WAIT_TIME, tmpString, 256, &size))) {
  1636. allocateWaitTime = wcstol(tmpString, NULL, 10);
  1637. requestWaitTime = wcstol(tmpString, NULL, 10);
  1638. WsbTrace(OLESTR("allocateWaitTime (Short) is %d milliseconds.\n"), allocateWaitTime);
  1639. WsbTrace(OLESTR("RequestWaitTime (Short) is %d milliseconds.\n"), requestWaitTime);
  1640. }
  1641. } else {
  1642. allocateWaitTime = RMS_DEFAULT_ALLOCATE_WAIT_TIME;
  1643. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_ALLOCATE_WAIT_TIME, tmpString, 256, &size))) {
  1644. allocateWaitTime = wcstol(tmpString, NULL, 10);
  1645. WsbTrace(OLESTR("AllocateWaitTime is %d milliseconds.\n"), allocateWaitTime);
  1646. }
  1647. requestWaitTime = RMS_DEFAULT_REQUEST_WAIT_TIME;
  1648. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_REQUEST_WAIT_TIME, tmpString, 256, &size))) {
  1649. requestWaitTime = wcstol(tmpString, NULL, 10);
  1650. WsbTrace(OLESTR("RequestWaitTime is %d milliseconds.\n"), requestWaitTime);
  1651. }
  1652. }
  1653. // Special error recovery to handle when NTMS is down, or was cycled.
  1654. do {
  1655. hr = S_OK;
  1656. HANDLE hSession = m_SessionHandle;
  1657. NTMS_GUID setId = fromMediaSet;
  1658. NTMS_GUID partId = GUID_NULL;
  1659. NTMS_GUID *pPartId = NULL;
  1660. NTMS_GUID requestId;
  1661. err1 = NO_ERROR;
  1662. err2 = NO_ERROR;
  1663. err3 = NO_ERROR;
  1664. err4 = NO_ERROR;
  1665. err5 = NO_ERROR;
  1666. err6 = NO_ERROR;
  1667. err7 = NO_ERROR;
  1668. try {
  1669. // Look for a specific media ourselves if:
  1670. // 1. A specific capacity is required AND
  1671. // 2. We do not try to allocate a second side
  1672. if (pFreeSpace && (prevSideId == GUID_NULL)) {
  1673. if (*pFreeSpace > 0) {
  1674. int retry = 3; // Give the operator 3 chances to get it right!
  1675. do {
  1676. // We need to allocate a unit of media that matches the capacity specified.
  1677. // However, if fail-on-size is indicated AND free media exists, we need to fail
  1678. // instead of asking the operator for free media with the required size
  1679. //
  1680. // Enumerate the partitions in the scratch pool of the same type as
  1681. // specified to find a capatible unit of media
  1682. //
  1683. BOOL bFreeMediaExists = FALSE;
  1684. // First find the media type we looking for
  1685. NTMS_OBJECTINFORMATION mediaPoolInfo;
  1686. NTMS_OBJECTINFORMATION partitionInfo;
  1687. HANDLE hFindPool = NULL;
  1688. HANDLE hFindPart = NULL;
  1689. BOOL bFound = FALSE;
  1690. NTMS_GUID scratchPoolId;
  1691. err1 = NO_ERROR;
  1692. err2 = NO_ERROR;
  1693. err3 = NO_ERROR;
  1694. err4 = NO_ERROR;
  1695. err5 = NO_ERROR;
  1696. err6 = NO_ERROR;
  1697. err7 = NO_ERROR;
  1698. // First look in our pool for scratch media of the correct size
  1699. hr = findFirstNtmsObject(NTMS_PARTITION, setId, NULL, GUID_NULL, &hFindPart, &partitionInfo);
  1700. while(S_OK == hr) {
  1701. reportNtmsObjectInformation(&partitionInfo);
  1702. if ((TRUE == partitionInfo.Enabled) &&
  1703. (NTMS_READY == partitionInfo.dwOperationalState) &&
  1704. (NTMS_PARTSTATE_AVAILABLE == partitionInfo.Info.Partition.State)) {
  1705. NTMS_GUID physicalPartMediaId = partitionInfo.Info.Partition.PhysicalMedia;
  1706. try {
  1707. // Check if the media is online and enabled
  1708. NTMS_OBJECTINFORMATION mediaPartInfo;
  1709. mediaPartInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  1710. mediaPartInfo.dwType = NTMS_PHYSICAL_MEDIA;
  1711. // NTMS - Get physical media information
  1712. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PHYSICAL_MEDIA)\n"));
  1713. WsbAffirmNoError( GetNtmsObjectInformation( hSession, &physicalPartMediaId, &mediaPartInfo ) );
  1714. // Check location type, if enabled & if all new
  1715. if ( (mediaPartInfo.Info.PhysicalMedia.LocationType != NTMS_UNKNOWN)
  1716. && (mediaPartInfo.Enabled) ) {
  1717. // Ensure that ALL sides are not allocated yet
  1718. hr = EnsureAllSidesNotAllocated(physicalPartMediaId);
  1719. if (S_OK == hr) {
  1720. // Check required free space
  1721. if (partitionInfo.Info.Partition.Capacity.QuadPart >= *pFreeSpace) {
  1722. // We'll use this unit of media.
  1723. // Save parameterers required for Allocate.
  1724. bFound = TRUE;
  1725. partId = partitionInfo.ObjectGuid;
  1726. pPartId = &partId;
  1727. break;
  1728. } else {
  1729. // Track the fact that we found a free media which meets
  1730. // all criteria besides capacity
  1731. bFreeMediaExists = TRUE;
  1732. }
  1733. } else if (S_FALSE != hr) {
  1734. WsbAffirmHr(hr);
  1735. }
  1736. }
  1737. } WsbCatchAndDo (hr,
  1738. WsbTraceAlways(OLESTR("CRmsNTMS::Allocate: Failed to check media <%ls> hr = <%ls>\n"),
  1739. WsbGuidAsString(physicalPartMediaId), WsbHrAsString(hr));
  1740. hr = S_OK;
  1741. )
  1742. }
  1743. hr = findNextNtmsObject(hFindPart, &partitionInfo);
  1744. } // while finding media pools
  1745. findCloseNtmsObject(hFindPart);
  1746. hr = S_OK;
  1747. if (!bFound) {
  1748. // Now try the Scratch Pool
  1749. memset(&mediaPoolInfo, 0, sizeof(NTMS_OBJECTINFORMATION));
  1750. mediaPoolInfo.dwType = NTMS_MEDIA_POOL;
  1751. mediaPoolInfo.dwSize = sizeof(NTMS_OBJECTINFORMATION);
  1752. // NTMS - Get Media Pool Information
  1753. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_MEDIA_POOL)\n"));
  1754. err3 = GetNtmsObjectInformation(hSession, &setId, &mediaPoolInfo);
  1755. WsbAffirmNoError( err3 );
  1756. // Save the media type for the media pool
  1757. NTMS_GUID mediaTypeId = mediaPoolInfo.Info.MediaPool.MediaType;
  1758. // Find the scratch pool with the same media type
  1759. hr = findFirstNtmsObject(NTMS_MEDIA_POOL, GUID_NULL, NULL, GUID_NULL, &hFindPool, &mediaPoolInfo);
  1760. while(S_OK == hr) {
  1761. if ((NTMS_POOLTYPE_SCRATCH == mediaPoolInfo.Info.MediaPool.PoolType) &&
  1762. (mediaTypeId == mediaPoolInfo.Info.MediaPool.MediaType)) {
  1763. // This is a base level scratch media pool for type we're looking for.
  1764. scratchPoolId = mediaPoolInfo.ObjectGuid;
  1765. hr = findFirstNtmsObject(NTMS_PARTITION, scratchPoolId, NULL, GUID_NULL, &hFindPart, &partitionInfo);
  1766. while(S_OK == hr) {
  1767. reportNtmsObjectInformation(&partitionInfo);
  1768. if ((TRUE == partitionInfo.Enabled) &&
  1769. (NTMS_READY == partitionInfo.dwOperationalState) &&
  1770. (NTMS_PARTSTATE_AVAILABLE == partitionInfo.Info.Partition.State)) {
  1771. // Check if the media is online and enabled
  1772. DWORD errPart = NO_ERROR;
  1773. NTMS_OBJECTINFORMATION mediaPartInfo;
  1774. NTMS_GUID physicalPartMediaId = partitionInfo.Info.Partition.PhysicalMedia;
  1775. mediaPartInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  1776. mediaPartInfo.dwType = NTMS_PHYSICAL_MEDIA;
  1777. // NTMS - Get physical media information
  1778. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PHYSICAL_MEDIA)\n"));
  1779. errPart = GetNtmsObjectInformation( hSession, &physicalPartMediaId, &mediaPartInfo );
  1780. // Ignore error here, just don't use this partition
  1781. if (errPart == NO_ERROR) {
  1782. // Check location type and if enabled
  1783. if ( (mediaPartInfo.Info.PhysicalMedia.LocationType != NTMS_UNKNOWN)
  1784. && (mediaPartInfo.Enabled) ) {
  1785. // Check required free space
  1786. if (partitionInfo.Info.Partition.Capacity.QuadPart >= *pFreeSpace) {
  1787. // We'll use this unit of media.
  1788. // Save parameterers required for Allocate.
  1789. bFound = TRUE;
  1790. partId = partitionInfo.ObjectGuid;
  1791. pPartId = &partId;
  1792. break;
  1793. } else {
  1794. // Track the fact that we found a free media which meets
  1795. // all criteria besides capacity
  1796. bFreeMediaExists = TRUE;
  1797. }
  1798. }
  1799. } else {
  1800. WsbTraceAlways(OLESTR("CRmsNTMS::Allocate: Failed to get object info for media <%ls> hr = <%ls>\n"),
  1801. WsbGuidAsString(physicalPartMediaId), WsbHrAsString(HRESULT_FROM_WIN32(errPart)));
  1802. }
  1803. }
  1804. hr = findNextNtmsObject(hFindPart, &partitionInfo);
  1805. } // while finding media pools
  1806. findCloseNtmsObject(hFindPart);
  1807. hr = S_OK;
  1808. break;
  1809. }
  1810. hr = findNextNtmsObject(hFindPool, &mediaPoolInfo);
  1811. } // while finding media pools
  1812. findCloseNtmsObject(hFindPool);
  1813. hr = S_OK;
  1814. }
  1815. if (bFound) {
  1816. // Found free media to allocate
  1817. break;
  1818. } else if (bFreeMediaExists && bFailOnSize) {
  1819. // Free media exists, but not with the right capacity - fail
  1820. WsbTrace(OLESTR("CRmsNTMS::Allocate: Failing allocate request since there are free media but all with too small capacity\n"));
  1821. WsbThrow(RMS_E_SCRATCH_NOT_FOUND_TOO_SMALL);
  1822. } else {
  1823. // No sufficient free media - submit operator request
  1824. OLECHAR * messageText = NULL;
  1825. WCHAR *stringArr[2];
  1826. WCHAR capString[40];
  1827. DWORD dwMessageId;
  1828. WsbShortSizeFormat64(*pFreeSpace, capString);
  1829. stringArr[0] = mediaPoolInfo.szName;
  1830. stringArr[1] = capString;
  1831. // Set which request to sumbit (with or without size specification)
  1832. if (bFailOnSize) {
  1833. dwMessageId = RMS_MESSAGE_SCRATCH_MEDIA_NO_SIZE_REQUEST;
  1834. } else {
  1835. dwMessageId = RMS_MESSAGE_SCRATCH_MEDIA_REQUEST;
  1836. }
  1837. if (0 == FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  1838. LoadLibraryEx( WSB_FACILITY_PLATFORM_NAME, NULL, LOAD_LIBRARY_AS_DATAFILE ),
  1839. dwMessageId, MAKELANGID ( LANG_NEUTRAL, SUBLANG_DEFAULT ),
  1840. (LPTSTR)&messageText, 0, (va_list *)stringArr)) {
  1841. WsbTrace(OLESTR("CRmsNTMS::Allocate: FormatMessage failed: %ls\n"),
  1842. WsbHrAsString(HRESULT_FROM_WIN32(GetLastError())));
  1843. }
  1844. // NTMS - Submit operator request
  1845. WsbTraceAlways(OLESTR("SubmitNtmsOperatorRequest()\n"));
  1846. err5 = SubmitNtmsOperatorRequest(hSession, NTMS_OPREQ_NEWMEDIA, messageText, &scratchPoolId, NULL, &requestId);
  1847. LocalFree(messageText);
  1848. WsbAffirmNoError(err5);
  1849. // NTMS - Wait for operator request
  1850. WsbTraceAlways(OLESTR("WaitForNtmsOperatorRequest()\n"));
  1851. err6 = WaitForNtmsOperatorRequest(hSession, &requestId, requestWaitTime);
  1852. //
  1853. // !!! NOTE !!! At the time of this writting WaitForNtmsOperatorRequest
  1854. // did not return ERROR_TIMEOUT.
  1855. //
  1856. if (ERROR_TIMEOUT == err6) {
  1857. // Best effort cleanup...
  1858. // NTMS - Cancel operator request
  1859. WsbTraceAlways(OLESTR("CancelNtmsOperatorRequest()\n"));
  1860. err7 = CancelNtmsOperatorRequest(hSession, &requestId);
  1861. }
  1862. WsbAffirmNoError(err6);
  1863. }
  1864. WsbAssertHrOk(hr);
  1865. // At this point the operator added a compatable unit of media...
  1866. // Verify until we're exceed the retry count.
  1867. retry--;
  1868. } while (retry > 0);
  1869. if (0 == retry) {
  1870. WsbThrow(RMS_E_SCRATCH_NOT_FOUND);
  1871. }
  1872. }
  1873. }
  1874. // NTMS - Allocate a unit of scratch media
  1875. WsbTraceAlways(OLESTR("AllocateNtmsMedia()\n"));
  1876. // Set additional allocation settings
  1877. DWORD dwAllocateOptions = 0;
  1878. NTMS_GUID mediaId = prevSideId;
  1879. if (mediaId == GUID_NULL) {
  1880. dwAllocateOptions |= NTMS_ALLOCATE_NEW;
  1881. } else {
  1882. // Allocating the second side: mediaId should hold the LMID of the first side
  1883. dwAllocateOptions |= NTMS_ALLOCATE_NEXT;
  1884. }
  1885. if (dwOptions & RMS_ALLOCATE_NO_BLOCK) {
  1886. dwAllocateOptions |= NTMS_ALLOCATE_ERROR_IF_UNAVAILABLE;
  1887. allocateWaitTime = 0;
  1888. }
  1889. err1 = AllocateNtmsMedia( hSession, &setId, pPartId, &mediaId,
  1890. dwAllocateOptions, allocateWaitTime, NULL );
  1891. WsbAffirmNoError( err1 );
  1892. // Now get/set the various information fields for the unit of media.
  1893. DWORD sideNo = 2;
  1894. NTMS_GUID side[2];
  1895. // NTMS - Enumerate the sides of a unit of media
  1896. WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
  1897. err2 = EnumerateNtmsObject(hSession, &mediaId, side, &sideNo, NTMS_PARTITION, 0);
  1898. WsbAffirmNoError( err2 );
  1899. NTMS_OBJECTINFORMATION partitionInfo;
  1900. partitionInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  1901. partitionInfo.dwType = NTMS_PARTITION;
  1902. // NTMS - Get partition information
  1903. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PARTITION)\n"));
  1904. err3 = GetNtmsObjectInformation( hSession, &side[0], &partitionInfo );
  1905. WsbAffirmNoError( err3 );
  1906. NTMS_OBJECTINFORMATION mediaInfo;
  1907. NTMS_GUID physicalMediaId = partitionInfo.Info.Partition.PhysicalMedia;
  1908. mediaInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  1909. mediaInfo.dwType = NTMS_PHYSICAL_MEDIA;
  1910. // NTMS - Get physical media information
  1911. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PHYSICAL_MEDIA)\n"));
  1912. err3 = GetNtmsObjectInformation( hSession, &physicalMediaId, &mediaInfo );
  1913. WsbAffirmNoError( err3 );
  1914. NTMS_OBJECTINFORMATION logicalMediaInfo;
  1915. logicalMediaInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  1916. logicalMediaInfo.dwType = NTMS_LOGICAL_MEDIA;
  1917. // NTMS - Get physical media information
  1918. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_LOGICAL_MEDIA)\n"));
  1919. err3 = GetNtmsObjectInformation( hSession, &mediaId, &logicalMediaInfo );
  1920. WsbAffirmNoError( err3 );
  1921. // Save the capacity for the return arg.
  1922. if (pFreeSpace) {
  1923. *pFreeSpace = partitionInfo.Info.Partition.Capacity.QuadPart;
  1924. }
  1925. // Set name & description
  1926. CWsbStringPtr mediaDisplayName;
  1927. // Set new physical media name for first side
  1928. // Modify original name for second side
  1929. if ( !(dwAllocateOptions & NTMS_ALLOCATE_NEXT) ) {
  1930. mediaDisplayName = (WCHAR *)displayName;
  1931. } else {
  1932. WCHAR *dashPtr = wcsrchr((WCHAR *)displayName, L'-');
  1933. mediaDisplayName = mediaInfo.szName;
  1934. if (dashPtr) {
  1935. WsbAffirmHr(mediaDisplayName.Append(dashPtr));
  1936. }
  1937. }
  1938. // Set the Name to the displayName, only if there's no bar code.
  1939. if ( NTMS_BARCODESTATE_OK != mediaInfo.Info.PhysicalMedia.BarCodeState) {
  1940. wcscpy(mediaInfo.szName, mediaDisplayName);
  1941. wcscpy(partitionInfo.szName, (WCHAR *) displayName);
  1942. // NTMS doesn't allow dup logical media names. We set
  1943. // the name to the mediaId to keep it unique. The logical
  1944. // media name is not displayed in the Removable Storage UI.
  1945. CWsbStringPtr strGuid;
  1946. WsbAffirmHr(WsbSafeGuidAsString(mediaId, strGuid));
  1947. wcscpy(logicalMediaInfo.szName, (WCHAR *)strGuid);
  1948. }
  1949. // Set the Description to the displayName
  1950. wcscpy(logicalMediaInfo.szDescription, (WCHAR *) displayName);
  1951. wcscpy(partitionInfo.szDescription, (WCHAR *) displayName);
  1952. wcscpy(mediaInfo.szDescription, (WCHAR *) mediaDisplayName);
  1953. // NTMS - Set partition information.
  1954. WsbTraceAlways(OLESTR("SetNtmsObjectInformation()\n"));
  1955. err4 = SetNtmsObjectInformation( hSession, &side[0], &partitionInfo );
  1956. WsbAffirmNoError( err4 );
  1957. // NTMS - Set physical media information.
  1958. WsbTraceAlways(OLESTR("SetNtmsObjectInformation()\n"));
  1959. err4 = SetNtmsObjectInformation( hSession, &physicalMediaId, &mediaInfo );
  1960. WsbAffirmNoError( err4 );
  1961. // NTMS - Set logical media information.
  1962. WsbTraceAlways(OLESTR("SetNtmsObjectInformation()\n"));
  1963. err4 = SetNtmsObjectInformation( hSession, &mediaId, &logicalMediaInfo );
  1964. WsbAffirmNoError( err4 );
  1965. WsbAssertHrOk(FindCartridge(mediaId, ppCartridge));
  1966. WsbAssertHr((*ppCartridge)->SetStatus(RmsStatusScratch));
  1967. break;
  1968. } WsbCatchAndDo(hr,
  1969. switch (HRESULT_CODE(hr)) {
  1970. case ERROR_INVALID_HANDLE:
  1971. case ERROR_NOT_CONNECTED:
  1972. case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running
  1973. case RPC_S_CALL_FAILED_DNE: // Media Services is up, handle is not valid.
  1974. case RPC_S_CALL_FAILED: // Media Services crashed.
  1975. WsbAffirmHr(beginSession());
  1976. continue;
  1977. }
  1978. WsbThrow(hr);
  1979. );
  1980. } while(1);
  1981. } WsbCatchAndDo(hr,
  1982. if (err1 != NO_ERROR) {
  1983. // AllocateNtmsMedia
  1984. switch (HRESULT_CODE(hr)) {
  1985. case ERROR_TIMEOUT:
  1986. case ERROR_MEDIA_UNAVAILABLE:
  1987. hr = RMS_E_SCRATCH_NOT_FOUND;
  1988. break;
  1989. case ERROR_CANCELLED:
  1990. hr = RMS_E_CANCELLED;
  1991. break;
  1992. case ERROR_MEDIA_OFFLINE:
  1993. hr = RMS_E_MEDIA_OFFLINE;
  1994. break;
  1995. case ERROR_REQUEST_REFUSED:
  1996. hr = RMS_E_REQUEST_REFUSED;
  1997. break;
  1998. case ERROR_WRITE_PROTECT:
  1999. hr = RMS_E_WRITE_PROTECT;
  2000. break;
  2001. case ERROR_INVALID_MEDIA_POOL:
  2002. hr = RMS_E_MEDIASET_NOT_FOUND;
  2003. break;
  2004. case ERROR_ACCESS_DENIED:
  2005. case ERROR_DATABASE_FAILURE:
  2006. case ERROR_DATABASE_FULL:
  2007. case ERROR_DEVICE_NOT_AVAILABLE:
  2008. case ERROR_INVALID_HANDLE:
  2009. case ERROR_INVALID_MEDIA:
  2010. case ERROR_INVALID_PARAMETER:
  2011. case ERROR_NOT_ENOUGH_MEMORY:
  2012. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2013. OLESTR("AllocateNtmsMedia"), OLESTR(""),
  2014. WsbHrAsString(hr), NULL);
  2015. break;
  2016. default:
  2017. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2018. OLESTR("AllocateNtmsMedia"), OLESTR("Undocumented Error: "),
  2019. WsbHrAsString(hr), NULL);
  2020. break;
  2021. }
  2022. }
  2023. else if (err2 != NO_ERROR ) {
  2024. // EnumerateNtmsObject
  2025. switch (HRESULT_CODE(hr)) {
  2026. case ERROR_OBJECT_NOT_FOUND:
  2027. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  2028. break;
  2029. case ERROR_INVALID_PARAMETER:
  2030. case ERROR_INSUFFICIENT_BUFFER:
  2031. case ERROR_INVALID_HANDLE:
  2032. case ERROR_NOT_ENOUGH_MEMORY:
  2033. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2034. OLESTR("EnumerateNtmsObject"), OLESTR(""),
  2035. WsbHrAsString(hr), NULL);
  2036. break;
  2037. default:
  2038. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2039. OLESTR("EnumerateNtmsObject"), OLESTR("Undocumented Error: "),
  2040. WsbHrAsString(hr), NULL);
  2041. break;
  2042. }
  2043. }
  2044. else if (err3 != NO_ERROR) {
  2045. // GetNtmsObjectInformation
  2046. switch (HRESULT_CODE(hr)) {
  2047. case ERROR_OBJECT_NOT_FOUND:
  2048. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  2049. break;
  2050. case ERROR_INVALID_HANDLE:
  2051. case ERROR_INVALID_PARAMETER:
  2052. case ERROR_NOT_ENOUGH_MEMORY:
  2053. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2054. OLESTR("GetNtmsObjectInformation"), OLESTR(""),
  2055. WsbHrAsString(hr), NULL);
  2056. break;
  2057. default:
  2058. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2059. OLESTR("GetNtmsObjectInformation"), OLESTR("Undocumented Error: "),
  2060. WsbHrAsString(hr), NULL);
  2061. break;
  2062. }
  2063. }
  2064. else if (err4 != NO_ERROR) {
  2065. // SetNtmsObjectInformation
  2066. switch (HRESULT_CODE(hr)) {
  2067. case ERROR_ACCESS_DENIED:
  2068. case ERROR_DATABASE_FAILURE:
  2069. case ERROR_DATABASE_FULL:
  2070. case ERROR_INVALID_HANDLE:
  2071. case ERROR_INVALID_PARAMETER:
  2072. case ERROR_NOT_ENOUGH_MEMORY:
  2073. case ERROR_OBJECT_NOT_FOUND:
  2074. case ERROR_OBJECT_ALREADY_EXISTS: // bmd: 1/18/99 - Not documented, but NTMS doesn't allow dup logical media names.
  2075. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2076. OLESTR("SetNtmsObjectInformation"), OLESTR(""),
  2077. WsbHrAsString(hr), NULL);
  2078. break;
  2079. default:
  2080. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2081. OLESTR("SetNtmsObjectInformation"), OLESTR("Undocumented Error: "),
  2082. WsbHrAsString(hr), NULL);
  2083. break;
  2084. }
  2085. }
  2086. else if (err5 != NO_ERROR) {
  2087. // SubmitNtmsOperatorRequest
  2088. switch (HRESULT_CODE(hr)) {
  2089. case ERROR_ACCESS_DENIED:
  2090. case ERROR_DATABASE_FAILURE:
  2091. case ERROR_INVALID_HANDLE:
  2092. case ERROR_INVALID_PARAMETER:
  2093. case ERROR_NOT_CONNECTED:
  2094. case ERROR_OBJECT_NOT_FOUND:
  2095. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2096. OLESTR("SubmitNtmsOperatorRequest"), OLESTR(""),
  2097. WsbHrAsString(hr), NULL);
  2098. break;
  2099. default:
  2100. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2101. OLESTR("SubmitNtmsOperatorRequest"), OLESTR("Undocumented Error: "),
  2102. WsbHrAsString(hr), NULL);
  2103. break;
  2104. }
  2105. }
  2106. else if (err6 != NO_ERROR) {
  2107. // WaitForNtmsOperatorRequest
  2108. switch (HRESULT_CODE(hr)) {
  2109. case ERROR_TIMEOUT:
  2110. hr = RMS_E_TIMEOUT;
  2111. break;
  2112. case ERROR_CANCELLED:
  2113. hr = RMS_E_CANCELLED;
  2114. break;
  2115. case ERROR_REQUEST_REFUSED:
  2116. hr = RMS_E_REQUEST_REFUSED;
  2117. break;
  2118. case ERROR_ACCESS_DENIED:
  2119. case ERROR_INVALID_HANDLE:
  2120. case ERROR_INVALID_PARAMETER:
  2121. case ERROR_NOT_CONNECTED:
  2122. case ERROR_OBJECT_NOT_FOUND:
  2123. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2124. OLESTR("WaitForNtmsOperatorRequest"), OLESTR(""),
  2125. WsbHrAsString(hr), NULL);
  2126. break;
  2127. default:
  2128. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2129. OLESTR("WaitForNtmsOperatorRequest"), OLESTR("Undocumented Error: "),
  2130. WsbHrAsString(hr), NULL);
  2131. break;
  2132. }
  2133. }
  2134. );
  2135. WsbTraceOut(OLESTR("CRmsNTMS::Allocate"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2136. return hr;
  2137. }
  2138. STDMETHODIMP
  2139. CRmsNTMS::Mount(
  2140. IN IRmsCartridge *pCart,
  2141. IN OUT IRmsDrive **ppDrive,
  2142. IN DWORD dwOptions OPTIONAL,
  2143. IN DWORD threadId OPTIONAL)
  2144. /*++
  2145. Implements:
  2146. IRmsNTMS::Mount
  2147. --*/
  2148. {
  2149. HRESULT hr = S_OK;
  2150. DWORD err1 = NO_ERROR;
  2151. DWORD err2 = NO_ERROR;
  2152. DWORD err3 = NO_ERROR;
  2153. DWORD err4 = NO_ERROR;
  2154. BOOL mediaMounted = FALSE;
  2155. BOOL bNoBlock = ( dwOptions & RMS_MOUNT_NO_BLOCK ) ? TRUE : FALSE;
  2156. // declared outside try block so it can be accessible throughout the method
  2157. DWORD sideNo = 2;
  2158. NTMS_GUID side[2];
  2159. WsbTraceIn( OLESTR("CRmsNTMS::Mount"), OLESTR("") );
  2160. try {
  2161. WsbAssertPointer(pCart);
  2162. CComPtr<IRmsDrive> pDrive;
  2163. // determine the timeout for the operator request
  2164. DWORD size;
  2165. OLECHAR tmpString[256];
  2166. BOOL bShortTimeout = ( dwOptions & RMS_SHORT_TIMEOUT ) ? TRUE : FALSE;
  2167. DWORD mountWaitTime;
  2168. if (bShortTimeout) {
  2169. mountWaitTime = RMS_DEFAULT_SHORT_WAIT_TIME;
  2170. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_SHORT_WAIT_TIME, tmpString, 256, &size))) {
  2171. mountWaitTime = wcstol(tmpString, NULL, 10);
  2172. WsbTrace(OLESTR("MountWaitTime (Short) is %d milliseconds.\n"), mountWaitTime);
  2173. }
  2174. } else {
  2175. mountWaitTime = RMS_DEFAULT_MOUNT_WAIT_TIME;
  2176. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_MOUNT_WAIT_TIME, tmpString, 256, &size))) {
  2177. mountWaitTime = wcstol(tmpString, NULL, 10);
  2178. WsbTrace(OLESTR("MountWaitTime is %d milliseconds.\n"), mountWaitTime);
  2179. }
  2180. }
  2181. NTMS_OBJECTINFORMATION driveInfo;
  2182. memset( &driveInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
  2183. // Special error recovery to handle when NTMS is down, or was cycled.
  2184. do {
  2185. hr = S_OK;
  2186. HANDLE hSession = m_SessionHandle;
  2187. NTMS_GUID mediaId = GUID_NULL;
  2188. WsbAffirmHr(pCart->GetCartridgeId(&mediaId));
  2189. WsbAssert(mediaId != GUID_NULL, E_INVALIDARG);
  2190. err1 = NO_ERROR;
  2191. err2 = NO_ERROR;
  2192. err3 = NO_ERROR;
  2193. try {
  2194. // NTMS - enumerate the sides of a unit of media
  2195. WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
  2196. err1 = EnumerateNtmsObject( hSession, &mediaId, side, &sideNo, NTMS_PARTITION, 0 );
  2197. WsbAffirmNoError( err1 );
  2198. DWORD count = 1;
  2199. NTMS_GUID driveId;
  2200. // NTMS - issue mount request
  2201. WsbTraceAlways(OLESTR("MountNtmsMedia()\n"));
  2202. DWORD dwOpt = NTMS_MOUNT_READ | NTMS_MOUNT_WRITE;
  2203. if (bNoBlock) {
  2204. dwOpt |= (NTMS_MOUNT_ERROR_NOT_AVAILABLE | NTMS_MOUNT_ERROR_OFFLINE);
  2205. }
  2206. if (dwOptions & RMS_USE_MOUNT_NO_DEADLOCK) {
  2207. /*
  2208. DEADLOCK AVOIDANCE: when RSM support for MountNtmsMediaDA is
  2209. in, the next line should be uncommented, and the other 2 lines
  2210. in this 'if' block should be removed.
  2211. err2 = MountNtmsMediaDA( hSession, &side[0], &driveId, count, dwOpt, NTMS_PRIORITY_NORMAL, mountWaitTime, NULL, &threadId, 1);
  2212. */
  2213. UNREFERENCED_PARAMETER(threadId);
  2214. err2 = MountNtmsMedia( hSession, &side[0], &driveId, count, dwOpt, NTMS_PRIORITY_NORMAL, mountWaitTime, NULL);
  2215. } else {
  2216. err2 = MountNtmsMedia( hSession, &side[0], &driveId, count, dwOpt, NTMS_PRIORITY_NORMAL, mountWaitTime, NULL);
  2217. }
  2218. WsbAffirmNoError( err2 );
  2219. mediaMounted = TRUE;
  2220. //
  2221. // We now need two critical pieces of information. The Device name and
  2222. // the kind of media we just mounted. This gives use the essential information
  2223. // to create a data mover. Since we drill through NTMS to get this information
  2224. // we also create cartridge, drive objects.
  2225. //
  2226. driveInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  2227. driveInfo.dwType = NTMS_DRIVE;
  2228. // NTMS - get drive information
  2229. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_DRIVE)\n"));
  2230. err3 = GetNtmsObjectInformation( hSession, &driveId, &driveInfo );
  2231. WsbAffirmNoError( err3 );
  2232. break;
  2233. } WsbCatchAndDo(hr,
  2234. switch (HRESULT_CODE(hr)) {
  2235. case ERROR_INVALID_HANDLE:
  2236. case ERROR_NOT_CONNECTED:
  2237. case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running
  2238. case RPC_S_CALL_FAILED_DNE: // Media Services is up, handle is not valid.
  2239. case RPC_S_CALL_FAILED: // Media Services crashed.
  2240. WsbAffirmHr(beginSession());
  2241. continue;
  2242. }
  2243. WsbThrow(hr);
  2244. );
  2245. } while(1);
  2246. RmsMedia mediaType;
  2247. WsbAffirmHr(pCart->GetType((LONG *)&mediaType));
  2248. // Create Drive
  2249. WsbAssertHr(CoCreateInstance(CLSID_CRmsDrive, 0, CLSCTX_SERVER, IID_IRmsDrive, (void **)&pDrive));
  2250. CComQIPtr<IRmsChangerElement, &IID_IRmsChangerElement> pElmt = pDrive;
  2251. WsbAssertHr(pElmt->SetMediaSupported(mediaType));
  2252. CComQIPtr<IRmsDevice, &IID_IRmsDevice> pDevice = pDrive;
  2253. WsbAssertHr(pDevice->SetDeviceAddress(
  2254. (BYTE) driveInfo.Info.Drive.ScsiPort,
  2255. (BYTE) driveInfo.Info.Drive.ScsiBus,
  2256. (BYTE) driveInfo.Info.Drive.ScsiTarget,
  2257. (BYTE) driveInfo.Info.Drive.ScsiLun));
  2258. CWsbBstrPtr deviceName = driveInfo.Info.Drive.szDeviceName;
  2259. ////////////////////////////////////////////////////////////////////////////////////////
  2260. // Convert the NTMS device name to something usable.
  2261. //
  2262. switch (mediaType) {
  2263. case RmsMediaOptical:
  2264. case RmsMediaDVD:
  2265. case RmsMediaDisk:
  2266. {
  2267. // We need to convert \\.\PhysicalDriveN to something accessible by the file system.
  2268. WCHAR *szDriveLetter = NULL;
  2269. WCHAR *szVolumeName = NULL;
  2270. err4 = GetVolumesFromDrive( (WCHAR *)deviceName, &szVolumeName, &szDriveLetter );
  2271. if (szVolumeName) {
  2272. delete [] szVolumeName; // don't need it for now
  2273. }
  2274. if (NO_ERROR == err4) {
  2275. if (szDriveLetter) {
  2276. deviceName = szDriveLetter;
  2277. } else {
  2278. WsbTraceAlways(OLESTR("CRmsNTMS::Mount: GetVolumesFromDrive succeeded but output drive is NULL !!\n"));
  2279. WsbThrow(RMS_E_RESOURCE_UNAVAILABLE);
  2280. }
  2281. }
  2282. if (szDriveLetter) {
  2283. delete [] szDriveLetter;
  2284. }
  2285. WsbAffirmNoError( err4 );
  2286. WsbTrace(OLESTR("CRmsNTMS::Mount: device name after convert is %s\n"), (WCHAR *)deviceName);
  2287. }
  2288. break;
  2289. default:
  2290. break;
  2291. }
  2292. ////////////////////////////////////////////////////////////////////////////////////////
  2293. WsbAssertHr(pDevice->SetDeviceName(deviceName));
  2294. WsbAssertHr(pCart->SetDrive(pDrive));
  2295. // Fill in the return arguments.
  2296. *ppDrive = pDrive;
  2297. pDrive.p->AddRef();
  2298. } WsbCatchAndDo(hr,
  2299. // Process the exception
  2300. if (err1 != NO_ERROR ) {
  2301. // EnumerateNtmsObject
  2302. switch (HRESULT_CODE(hr)) {
  2303. case ERROR_OBJECT_NOT_FOUND:
  2304. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  2305. break;
  2306. case ERROR_INVALID_PARAMETER:
  2307. case ERROR_INSUFFICIENT_BUFFER:
  2308. case ERROR_INVALID_HANDLE:
  2309. case ERROR_NOT_ENOUGH_MEMORY:
  2310. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2311. OLESTR("EnumerateNtmsObject"), OLESTR(""),
  2312. WsbHrAsString(hr), NULL);
  2313. break;
  2314. default:
  2315. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2316. OLESTR("EnumerateNtmsObject"), OLESTR("Undocumented Error: "),
  2317. WsbHrAsString(hr), NULL);
  2318. break;
  2319. }
  2320. }
  2321. else if (err2 != NO_ERROR) {
  2322. // MountNtmsMedia
  2323. switch (HRESULT_CODE(hr)) {
  2324. case ERROR_TIMEOUT:
  2325. hr = RMS_E_CARTRIDGE_UNAVAILABLE;
  2326. break;
  2327. case ERROR_CANCELLED:
  2328. hr = RMS_E_CANCELLED;
  2329. break;
  2330. case ERROR_MEDIA_OFFLINE:
  2331. hr = RMS_E_MEDIA_OFFLINE;
  2332. if (bNoBlock) {
  2333. DWORD errSub = NO_ERROR;
  2334. try {
  2335. // Since we are not blocking for NTMS to ask the operator
  2336. // to mount the offline media, we do it ourselves
  2337. // create operator message
  2338. CWsbBstrPtr cartridgeName = "";
  2339. CWsbBstrPtr cartridgeDesc = "";
  2340. OLECHAR * messageText = NULL;
  2341. WCHAR *stringArr[2];
  2342. cartridgeName.Free();
  2343. WsbAffirmHr(pCart->GetName(&cartridgeName));
  2344. cartridgeDesc.Free();
  2345. WsbAffirmHr(pCart->GetDescription(&cartridgeDesc));
  2346. stringArr[0] = (WCHAR *) cartridgeName;
  2347. stringArr[1] = (WCHAR *) cartridgeDesc;
  2348. if (0 == FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  2349. LoadLibraryEx( WSB_FACILITY_PLATFORM_NAME, NULL, LOAD_LIBRARY_AS_DATAFILE ),
  2350. RMS_MESSAGE_OFFLINE_MEDIA_REQUEST, MAKELANGID ( LANG_NEUTRAL, SUBLANG_DEFAULT ),
  2351. (LPTSTR)&messageText, 0, (va_list *)stringArr)) {
  2352. WsbTrace(OLESTR("CRmsNTMS::Mount: FormatMessage failed: %ls\n"),
  2353. WsbHrAsString(HRESULT_FROM_WIN32(GetLastError())));
  2354. messageText = NULL;
  2355. }
  2356. NTMS_GUID mediaId = GUID_NULL;
  2357. NTMS_GUID libId = GUID_NULL;
  2358. NTMS_GUID requestId = GUID_NULL;
  2359. WsbAffirmHr(pCart->GetCartridgeId(&mediaId));
  2360. WsbAssert(mediaId != GUID_NULL, E_INVALIDARG);
  2361. // Library Id should be gathered here - need to clarify why
  2362. // does the GetHome return a null id !!!
  2363. // WsbAffirmHr(pCart->GetHome(NULL, &libId, NULL, NULL, NULL, NULL, NULL, NULL));
  2364. // WsbAssert(libId != GUID_NULL, E_INVALIDARG);
  2365. // submit operator request
  2366. errSub = SubmitNtmsOperatorRequest(m_SessionHandle, NTMS_OPREQ_MOVEMEDIA,
  2367. messageText, &mediaId, &libId, &requestId);
  2368. LocalFree(messageText);
  2369. WsbAffirmNoError (errSub);
  2370. } WsbCatchAndDo(hr,
  2371. // Process the error of the Corrective Action
  2372. if (errSub != NO_ERROR ) {
  2373. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2374. OLESTR("SubmitNtmsOperatorRequest"), OLESTR(""),
  2375. WsbHrAsString(hr), NULL);
  2376. }
  2377. // place back the original mane error
  2378. hr = RMS_E_MEDIA_OFFLINE;
  2379. );
  2380. }
  2381. break;
  2382. case ERROR_REQUEST_REFUSED:
  2383. hr = RMS_E_REQUEST_REFUSED;
  2384. break;
  2385. case ERROR_WRITE_PROTECT:
  2386. hr = RMS_E_WRITE_PROTECT;
  2387. break;
  2388. case ERROR_INVALID_STATE:
  2389. case ERROR_INVALID_DRIVE: {
  2390. // when performing NTMS mount in non-blocking mode , this error may
  2391. // just mean that a corrective action such as drive cleaning should
  2392. // be performed before mounting (note that ONLY when not blocking,
  2393. // NTMS can not instruct corrective actions by itself)
  2394. if (bNoBlock) {
  2395. try {
  2396. CWsbBstrPtr cartridgeName = "";
  2397. CWsbBstrPtr cartridgeDesc = "";
  2398. cartridgeName.Free();
  2399. WsbAffirmHr(pCart->GetName(&cartridgeName));
  2400. cartridgeDesc.Free();
  2401. WsbAffirmHr(pCart->GetDescription(&cartridgeDesc));
  2402. WsbLogEvent(RMS_MESSAGE_DRIVE_NOT_AVAILABLE, 0, NULL,
  2403. (WCHAR *) cartridgeName, (WCHAR *) cartridgeDesc, NULL);
  2404. } WsbCatch(hr);
  2405. break;
  2406. }
  2407. }
  2408. case ERROR_RESOURCE_DISABLED: {
  2409. // Check if the the media (cartridge) is disabled - different error should
  2410. // be returned for media and for other resources (library, drive, etc.)
  2411. HRESULT hrOrg = hr;
  2412. DWORD errSub1 = NO_ERROR;
  2413. DWORD errSub2 = NO_ERROR;
  2414. try {
  2415. // get physical media information
  2416. NTMS_OBJECTINFORMATION objectInfo;
  2417. objectInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  2418. objectInfo.dwType = NTMS_PARTITION;
  2419. WsbAssert(side[0] != GUID_NULL, E_INVALIDARG);
  2420. errSub1 = GetNtmsObjectInformation( m_SessionHandle, &side[0], &objectInfo );
  2421. WsbAffirmNoError (errSub1);
  2422. NTMS_GUID physicalMediaId = objectInfo.Info.Partition.PhysicalMedia;
  2423. WsbAssert(physicalMediaId != GUID_NULL, E_INVALIDARG);
  2424. objectInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  2425. objectInfo.dwType = NTMS_PHYSICAL_MEDIA;
  2426. errSub2 = GetNtmsObjectInformation( m_SessionHandle, &physicalMediaId, &objectInfo );
  2427. WsbAffirmNoError (errSub2);
  2428. // set our dedicated error only if (physical) media is disabled
  2429. if (! objectInfo.Enabled) {
  2430. hr = RMS_E_CARTRIDGE_DISABLED;
  2431. }
  2432. } WsbCatchAndDo(hr,
  2433. // Process the error of the get-info requests
  2434. if (errSub1 != NO_ERROR ) {
  2435. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2436. OLESTR("GetNtmsObjectInformation (Partition)"), OLESTR(""),
  2437. WsbHrAsString(hr), NULL);
  2438. } else if (errSub2 != NO_ERROR ) {
  2439. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2440. OLESTR("GetNtmsObjectInformation (Physical Media)"), OLESTR(""),
  2441. WsbHrAsString(hr), NULL);
  2442. }
  2443. // place back the original mane error
  2444. hr = hrOrg;
  2445. );
  2446. break;
  2447. }
  2448. case ERROR_ACCESS_DENIED:
  2449. case ERROR_BUSY:
  2450. case ERROR_DATABASE_FAILURE:
  2451. case ERROR_DATABASE_FULL:
  2452. case ERROR_DRIVE_MEDIA_MISMATCH:
  2453. case ERROR_INVALID_LIBRARY:
  2454. case ERROR_INVALID_MEDIA:
  2455. case ERROR_NOT_ENOUGH_MEMORY: {
  2456. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2457. OLESTR("MountNtmsMedia"), OLESTR(""),
  2458. WsbHrAsString(hr), NULL);
  2459. break;
  2460. }
  2461. default: {
  2462. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2463. OLESTR("MountNtmsMedia"), OLESTR("Undocumented Error: "),
  2464. WsbHrAsString(hr), NULL);
  2465. break;
  2466. }
  2467. }
  2468. }
  2469. else if (err3 != NO_ERROR) {
  2470. // GetNtmsObjectInformation
  2471. switch (HRESULT_CODE(hr)) {
  2472. case ERROR_OBJECT_NOT_FOUND:
  2473. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  2474. break;
  2475. case ERROR_INVALID_HANDLE:
  2476. case ERROR_INVALID_PARAMETER:
  2477. case ERROR_NOT_ENOUGH_MEMORY:
  2478. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2479. OLESTR("GetNtmsObjectInformation"), OLESTR(""),
  2480. WsbHrAsString(hr), NULL);
  2481. break;
  2482. default:
  2483. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2484. OLESTR("GetNtmsObjectInformation"), OLESTR("Undocumented Error: "),
  2485. WsbHrAsString(hr), NULL);
  2486. break;
  2487. }
  2488. } else if (err4 != NO_ERROR) {
  2489. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2490. OLESTR("GetVolumesFromDrive"), OLESTR("Unexpected Failure: "),
  2491. WsbHrAsString(hr), NULL);
  2492. }
  2493. if (mediaMounted) {
  2494. // Something failed after the mount completed, so need to clean up...
  2495. // Dismount the media to release the resource before returning.
  2496. Dismount(pCart, FALSE);
  2497. }
  2498. );
  2499. WsbTraceOut( OLESTR("CRmsNTMS::Mount"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
  2500. return hr;
  2501. }
  2502. STDMETHODIMP
  2503. CRmsNTMS::Dismount(
  2504. IN IRmsCartridge *pCart, IN DWORD dwOptions)
  2505. /*++
  2506. Implements:
  2507. IRmsNTMS::Dismount
  2508. --*/
  2509. {
  2510. HRESULT hr = S_OK;
  2511. DWORD err1 = NO_ERROR;
  2512. DWORD err2 = NO_ERROR;
  2513. WsbTraceIn( OLESTR("CRmsNTMS::Dismount"), OLESTR("") );
  2514. try {
  2515. WsbAssertPointer(pCart);
  2516. do {
  2517. hr = S_OK;
  2518. HANDLE hSession = m_SessionHandle;
  2519. NTMS_GUID mediaId = GUID_NULL;
  2520. WsbAffirmHr(pCart->GetCartridgeId(&mediaId));
  2521. WsbAssert(mediaId != GUID_NULL, E_INVALIDARG);
  2522. NTMS_GUID side[2];
  2523. DWORD sideNo = 2;
  2524. err1 = NO_ERROR;
  2525. err2 = NO_ERROR;
  2526. try {
  2527. // NTMS - enumerate the sides of a unit of media
  2528. WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
  2529. err1 = EnumerateNtmsObject( hSession, &mediaId, side, &sideNo, NTMS_PARTITION, 0 );
  2530. WsbAffirmNoError( err1 );
  2531. // NTMS - dismount media
  2532. DWORD dwNtmsOptions = 0;
  2533. WsbTraceAlways(OLESTR("DismountNtmsMedia()\n"));
  2534. if (! ( dwOptions & RMS_DISMOUNT_IMMEDIATE )) {
  2535. dwNtmsOptions |= NTMS_DISMOUNT_DEFERRED;
  2536. }
  2537. err2 = DismountNtmsMedia( hSession, &side[0], 1, dwNtmsOptions );
  2538. #ifdef DBG
  2539. // TODO: Remove this trap for the unexpected ERROR_ACCESS_DENIED error.
  2540. WsbAssert(err2 != ERROR_ACCESS_DENIED, HRESULT_FROM_WIN32(err2));
  2541. #endif
  2542. WsbAffirmNoError( err2 );
  2543. // Since RSM Dismount is asyncronous, we may need to wait some arbitrary time,
  2544. // in order that when we come back, the media is really dismounted
  2545. if ( (dwOptions & RMS_DISMOUNT_DEFERRED_ONLY) && (!(dwOptions & RMS_DISMOUNT_IMMEDIATE)) ) {
  2546. CComQIPtr<IRmsServer, &IID_IRmsServer> pServer = g_pServer;
  2547. if (S_OK == pServer->IsReady()) {
  2548. DWORD size;
  2549. OLECHAR tmpString[256];
  2550. DWORD waitTime = RMS_DEFAULT_AFTER_DISMOUNT_WAIT_TIME;
  2551. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_AFTER_DISMOUNT_WAIT_TIME, tmpString, 256, &size))) {
  2552. waitTime = wcstol(tmpString, NULL, 10);
  2553. WsbTrace(OLESTR("AfterDismountWaitTime is %d milliseconds.\n"), waitTime);
  2554. }
  2555. Sleep(waitTime);
  2556. }
  2557. }
  2558. break;
  2559. } WsbCatchAndDo(hr,
  2560. switch (HRESULT_CODE(hr)) {
  2561. case ERROR_INVALID_HANDLE:
  2562. case ERROR_NOT_CONNECTED:
  2563. case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running
  2564. case RPC_S_CALL_FAILED_DNE: // Media Services is up, handle is not valid.
  2565. case RPC_S_CALL_FAILED: // Media Services crashed.
  2566. WsbAffirmHr(beginSession());
  2567. continue;
  2568. }
  2569. WsbThrow(hr);
  2570. );
  2571. } while(1);
  2572. } WsbCatchAndDo(hr,
  2573. if (err1 != NO_ERROR) {
  2574. // EnumerateNtmsObject
  2575. switch (HRESULT_CODE(hr)) {
  2576. case ERROR_INVALID_PARAMETER:
  2577. case ERROR_INVALID_HANDLE:
  2578. case ERROR_OBJECT_NOT_FOUND:
  2579. case ERROR_NOT_ENOUGH_MEMORY:
  2580. case ERROR_INSUFFICIENT_BUFFER:
  2581. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2582. OLESTR("EnumerateNtmsObject"), OLESTR(""),
  2583. WsbHrAsString(hr), NULL);
  2584. break;
  2585. default:
  2586. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2587. OLESTR("EnumerateNtmsObject"), OLESTR("Undocumented Error: "),
  2588. WsbHrAsString(hr), NULL);
  2589. break;
  2590. }
  2591. }
  2592. else if (err2 != NO_ERROR) {
  2593. // DismountNtmsMedia
  2594. switch (HRESULT_CODE(hr)) {
  2595. case ERROR_MEDIA_OFFLINE:
  2596. hr = RMS_E_MEDIA_OFFLINE;
  2597. break;
  2598. case ERROR_TIMEOUT:
  2599. case ERROR_INVALID_MEDIA:
  2600. case ERROR_INVALID_LIBRARY:
  2601. case ERROR_DEVICE_NOT_AVAILABLE:
  2602. case ERROR_MEDIA_NOT_AVAILABLE:
  2603. case ERROR_NOT_ENOUGH_MEMORY:
  2604. case ERROR_INVALID_STATE:
  2605. case ERROR_ACCESS_DENIED:
  2606. case ERROR_DATABASE_FAILURE:
  2607. case ERROR_DATABASE_FULL:
  2608. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2609. OLESTR("DismountNtmsMedia"), OLESTR(""),
  2610. WsbHrAsString(hr), NULL);
  2611. break;
  2612. default:
  2613. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2614. OLESTR("DismountNtmsMedia"), OLESTR("Undocumented Error: "),
  2615. WsbHrAsString(hr), NULL);
  2616. break;
  2617. }
  2618. }
  2619. );
  2620. WsbTraceOut( OLESTR("CRmsNTMS::Dismount"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
  2621. return hr;
  2622. }
  2623. STDMETHODIMP
  2624. CRmsNTMS::Deallocate(
  2625. IN IRmsCartridge *pCart)
  2626. /*++
  2627. Implements:
  2628. IRmsNTMS::DeallocateMedia
  2629. --*/
  2630. {
  2631. HRESULT hr = S_OK;
  2632. DWORD err1 = NO_ERROR;
  2633. DWORD err2 = NO_ERROR;
  2634. DWORD err3 = NO_ERROR;
  2635. DWORD err4 = NO_ERROR;
  2636. WsbTraceIn(OLESTR("CRmsNTMS::Deallocate"), OLESTR(""));
  2637. try {
  2638. WsbAssertPointer(pCart);
  2639. do {
  2640. hr = S_OK;
  2641. HANDLE hSession = m_SessionHandle;
  2642. NTMS_GUID mediaId = GUID_NULL;
  2643. WsbAffirmHr(pCart->GetCartridgeId(&mediaId));
  2644. WsbAssert(mediaId != GUID_NULL, E_INVALIDARG);
  2645. err1 = NO_ERROR;
  2646. err2 = NO_ERROR;
  2647. err3 = NO_ERROR;
  2648. err4 = NO_ERROR;
  2649. NTMS_OBJECTINFORMATION partitionInfo;
  2650. memset( &partitionInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
  2651. DWORD sideNo = 2;
  2652. NTMS_GUID side[2];
  2653. try {
  2654. // NTMS - enumerate the sides of a unit of media
  2655. WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
  2656. err1 = EnumerateNtmsObject( hSession, &mediaId, side, &sideNo, NTMS_PARTITION, 0 );
  2657. WsbAffirmNoError( err1 );
  2658. // NTMS - get partition information
  2659. partitionInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  2660. partitionInfo.dwType = NTMS_PARTITION;
  2661. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PARTITION)\n"));
  2662. err2 = GetNtmsObjectInformation( hSession, &side[0], &partitionInfo );
  2663. WsbAffirmNoError( err2 );
  2664. // NULL the Description
  2665. wcscpy(partitionInfo.szDescription, L"");
  2666. // NTMS - Set partition information.
  2667. WsbTraceAlways(OLESTR("SetNtmsObjectInformation()\n"));
  2668. err3 = SetNtmsObjectInformation( hSession, &side[0], &partitionInfo );
  2669. WsbAffirmNoError( err3 );
  2670. // NTMS - deallocate media
  2671. WsbTraceAlways(OLESTR("DeallocateNtmsMedia()\n"));
  2672. err4 = DeallocateNtmsMedia( hSession, &mediaId, 0 );
  2673. WsbAffirmNoError( err4 );
  2674. break;
  2675. } WsbCatchAndDo(hr,
  2676. switch (HRESULT_CODE(hr)) {
  2677. case ERROR_INVALID_HANDLE:
  2678. case ERROR_NOT_CONNECTED:
  2679. case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running
  2680. case RPC_S_CALL_FAILED_DNE: // Media Services is up, handle is not valid.
  2681. case RPC_S_CALL_FAILED: // Media Services crashed.
  2682. WsbAffirmHr(beginSession());
  2683. continue;
  2684. }
  2685. WsbThrow(hr);
  2686. );
  2687. } while(1);
  2688. } WsbCatchAndDo(hr,
  2689. if (err1 != NO_ERROR ) {
  2690. // EnumerateNtmsObject
  2691. switch (HRESULT_CODE(hr)) {
  2692. case ERROR_OBJECT_NOT_FOUND:
  2693. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  2694. break;
  2695. case ERROR_INVALID_PARAMETER:
  2696. case ERROR_INVALID_HANDLE:
  2697. case ERROR_NOT_ENOUGH_MEMORY:
  2698. case ERROR_INSUFFICIENT_BUFFER:
  2699. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2700. OLESTR("EnumerateNtmsObject"), OLESTR(""),
  2701. WsbHrAsString(hr), NULL);
  2702. break;
  2703. default:
  2704. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2705. OLESTR("EnumerateNtmsObject"), OLESTR("Undocumented Error: "),
  2706. WsbHrAsString(hr), NULL);
  2707. break;
  2708. }
  2709. }
  2710. else if (err2 != NO_ERROR) {
  2711. // GetNtmsObjectInformation
  2712. switch (HRESULT_CODE(hr)) {
  2713. case ERROR_OBJECT_NOT_FOUND:
  2714. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  2715. break;
  2716. case ERROR_INVALID_HANDLE:
  2717. case ERROR_INVALID_PARAMETER:
  2718. case ERROR_NOT_ENOUGH_MEMORY:
  2719. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2720. OLESTR("GetNtmsObjectInformation"), OLESTR(""),
  2721. WsbHrAsString(hr), NULL);
  2722. break;
  2723. default:
  2724. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2725. OLESTR("GetNtmsObjectInformation"), OLESTR("Undocumented Error: "),
  2726. WsbHrAsString(hr), NULL);
  2727. break;
  2728. }
  2729. }
  2730. else if (err3 != NO_ERROR) {
  2731. // SetNtmsObjectInformation
  2732. switch (HRESULT_CODE(hr)) {
  2733. case ERROR_ACCESS_DENIED:
  2734. case ERROR_DATABASE_FAILURE:
  2735. case ERROR_DATABASE_FULL:
  2736. case ERROR_INVALID_HANDLE:
  2737. case ERROR_INVALID_PARAMETER:
  2738. case ERROR_NOT_ENOUGH_MEMORY:
  2739. case ERROR_OBJECT_NOT_FOUND:
  2740. case ERROR_OBJECT_ALREADY_EXISTS: // bmd: 1/18/99 - Not documented, but NTMS doesn't allow dup logical media names.
  2741. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2742. OLESTR("SetNtmsObjectInformation"), OLESTR(""),
  2743. WsbHrAsString(hr), NULL);
  2744. break;
  2745. default:
  2746. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2747. OLESTR("SetNtmsObjectInformation"), OLESTR("Undocumented Error: "),
  2748. WsbHrAsString(hr), NULL);
  2749. break;
  2750. }
  2751. }
  2752. else if (err4 != NO_ERROR) {
  2753. // DeallocateNtmsMedia
  2754. switch (HRESULT_CODE(hr)) {
  2755. case ERROR_INVALID_PARAMETER:
  2756. case ERROR_INVALID_HANDLE:
  2757. case ERROR_INVALID_MEDIA:
  2758. //case ERROR_INVALID_PARTITION:
  2759. case ERROR_NOT_ENOUGH_MEMORY:
  2760. case ERROR_DATABASE_FAILURE:
  2761. case ERROR_DATABASE_FULL:
  2762. case ERROR_ACCESS_DENIED:
  2763. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2764. OLESTR("DeallocateNtmsMedia"), OLESTR(""),
  2765. WsbHrAsString(hr),
  2766. NULL);
  2767. break;
  2768. default:
  2769. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2770. OLESTR("DeallocateNtmsMedia"), OLESTR("Undocumented Error: "),
  2771. WsbHrAsString(hr), NULL);
  2772. break;
  2773. }
  2774. }
  2775. );
  2776. WsbTraceOut(OLESTR("CRmsNTMS::Deallocate"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2777. return hr;
  2778. }
  2779. STDMETHODIMP
  2780. CRmsNTMS::UpdateOmidInfo(
  2781. IN REFGUID cartId,
  2782. IN BYTE *pBuffer,
  2783. IN LONG size,
  2784. IN LONG type)
  2785. /*++
  2786. Implements:
  2787. IRmsNTMS::UpdateOmidInfo
  2788. --*/
  2789. {
  2790. HRESULT hr = S_OK;
  2791. DWORD err1 = NO_ERROR;
  2792. WsbTraceIn( OLESTR("CRmsNTMS::UpdateOmidInfo"), OLESTR("<%ls> <0x%08x> <%d>"), WsbGuidAsString(cartId), pBuffer, size );
  2793. try {
  2794. WsbAssert(cartId != GUID_NULL, E_INVALIDARG);
  2795. WsbAssertPointer(pBuffer);
  2796. WsbAssert(size > 0, E_INVALIDARG);
  2797. WsbTraceBuffer(size, pBuffer);
  2798. do {
  2799. hr = S_OK;
  2800. HANDLE hSession = m_SessionHandle;
  2801. NTMS_GUID mediaId = cartId;
  2802. err1 = NO_ERROR;
  2803. try {
  2804. // NTMS - update on media information.
  2805. WsbTraceAlways(OLESTR("UpdateNtmsOmidInfo()\n"));
  2806. switch((RmsOnMediaIdentifier)type) {
  2807. case RmsOnMediaIdentifierMTF:
  2808. err1 = UpdateNtmsOmidInfo(hSession, &mediaId, NTMS_OMID_TYPE_RAW_LABEL, size, pBuffer);
  2809. break;
  2810. case RmsOnMediaIdentifierWIN32:
  2811. WsbAssert(size == sizeof(NTMS_FILESYSTEM_INFO), E_UNEXPECTED);
  2812. err1 = UpdateNtmsOmidInfo(hSession, &mediaId, NTMS_OMID_TYPE_FILESYSTEM_INFO, size, pBuffer);
  2813. break;
  2814. default:
  2815. WsbThrow(E_UNEXPECTED);
  2816. }
  2817. WsbAffirmNoError( err1 );
  2818. break;
  2819. } WsbCatchAndDo(hr,
  2820. switch (HRESULT_CODE(hr)) {
  2821. case ERROR_INVALID_HANDLE:
  2822. case ERROR_NOT_CONNECTED:
  2823. case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running
  2824. case RPC_S_CALL_FAILED_DNE: // Media Services is up, handle is not valid.
  2825. case RPC_S_CALL_FAILED: // Media Services crashed.
  2826. WsbAffirmHr(beginSession());
  2827. continue;
  2828. }
  2829. WsbThrow(hr);
  2830. );
  2831. } while(1);
  2832. } WsbCatchAndDo(hr,
  2833. if (err1 != NO_ERROR) {
  2834. // UpdateNtmsOmidInfo
  2835. switch (HRESULT_CODE(hr)) {
  2836. case ERROR_ACCESS_DENIED:
  2837. case ERROR_DATABASE_FAILURE:
  2838. case ERROR_INVALID_HANDLE:
  2839. case ERROR_INVALID_MEDIA:
  2840. //case ERROR_INVALID_PARTITION:
  2841. case ERROR_INVALID_PARAMETER:
  2842. case ERROR_NOT_CONNECTED:
  2843. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2844. OLESTR("UpdateNtmsOmidInfo"), OLESTR(""),
  2845. WsbHrAsString(hr), NULL);
  2846. break;
  2847. default:
  2848. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2849. OLESTR("UpdateNtmsOmidInfo"), OLESTR("Undocumented Error: "),
  2850. WsbHrAsString(hr), NULL);
  2851. break;
  2852. }
  2853. }
  2854. );
  2855. WsbTraceOut( OLESTR("CRmsNTMS::UpdateOmidInfo"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
  2856. return hr;
  2857. }
  2858. STDMETHODIMP
  2859. CRmsNTMS::GetBlockSize(
  2860. IN REFGUID cartId,
  2861. OUT LONG *pBlockSize
  2862. )
  2863. /*++
  2864. Implements:
  2865. IRmsNTMS::GetBlockSize
  2866. --*/
  2867. {
  2868. HRESULT hr = S_OK;
  2869. DWORD err1 = NO_ERROR;
  2870. WsbTraceIn(OLESTR("CRmsNTMS::GetBlockSize"), OLESTR("<%ls> <x%08x>"), WsbGuidAsString(cartId), pBlockSize);
  2871. try {
  2872. WsbAssertPointer(pBlockSize);
  2873. do {
  2874. hr = S_OK;
  2875. err1 = NO_ERROR;
  2876. HANDLE hSession = m_SessionHandle;
  2877. NTMS_GUID mediaId = cartId;
  2878. DWORD nBlockSize;
  2879. DWORD sizeOfBlockSize = sizeof(DWORD);
  2880. try {
  2881. err1 = GetNtmsObjectAttribute(hSession, &mediaId, NTMS_LOGICAL_MEDIA, OLESTR("BlockSize"), (LPVOID) &nBlockSize, &sizeOfBlockSize);
  2882. WsbAffirmNoError(err1);
  2883. *pBlockSize = (LONG) nBlockSize;
  2884. break;
  2885. } WsbCatchAndDo(hr,
  2886. switch (HRESULT_CODE(hr)) {
  2887. case ERROR_INVALID_HANDLE:
  2888. case ERROR_NOT_CONNECTED:
  2889. case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running
  2890. case RPC_S_CALL_FAILED_DNE: // Media Services is up, handle is not valid.
  2891. case RPC_S_CALL_FAILED: // Media Services crashed.
  2892. WsbAffirmHr(beginSession());
  2893. continue;
  2894. }
  2895. WsbThrow(hr);
  2896. );
  2897. } while(1);
  2898. } WsbCatchAndDo(hr,
  2899. if (err1 != NO_ERROR) {
  2900. // GetNtmsObjectAttribute
  2901. switch (HRESULT_CODE(hr)) {
  2902. case ERROR_OBJECT_NOT_FOUND: // Don't log this error. Attribute doesn't
  2903. break; // exist for new media. We skip this error
  2904. // and let the caller deal with it.
  2905. case ERROR_DATABASE_FAILURE: // Log these errors.
  2906. case ERROR_INVALID_HANDLE:
  2907. case ERROR_NOT_CONNECTED:
  2908. case ERROR_INSUFFICIENT_BUFFER:
  2909. case ERROR_NO_DATA:
  2910. case ERROR_INVALID_PARAMETER:
  2911. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2912. OLESTR("GetNtmsObjectAttribute"), OLESTR(""),
  2913. WsbHrAsString(hr), NULL);
  2914. break;
  2915. default:
  2916. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2917. OLESTR("GetNtmsObjectAttribute"), OLESTR("Undocumented Error: "),
  2918. WsbHrAsString(hr), NULL);
  2919. break;
  2920. }
  2921. }
  2922. );
  2923. WsbTraceOut(OLESTR("CRmsNTMS::GetBlockSize"), OLESTR("hr = <%ls>, BlockSize = <%d>"), WsbHrAsString(hr), *pBlockSize);
  2924. return hr;
  2925. }
  2926. STDMETHODIMP
  2927. CRmsNTMS::SetBlockSize(
  2928. IN REFGUID cartId,
  2929. IN LONG blockSize
  2930. )
  2931. /*++
  2932. Implements:
  2933. IRmsNTMS::SetBlockSize
  2934. --*/
  2935. {
  2936. HRESULT hr = S_OK;
  2937. DWORD err1 = NO_ERROR;
  2938. WsbTraceIn(OLESTR("CRmsNTMS::SetBlockSize"), OLESTR("<%ls> <%d>"), WsbGuidAsString(cartId), blockSize);
  2939. try {
  2940. do {
  2941. hr = S_OK;
  2942. err1 = NO_ERROR;
  2943. HANDLE hSession = m_SessionHandle;
  2944. NTMS_GUID mediaId = cartId;
  2945. DWORD nBlockSize = blockSize;
  2946. DWORD sizeOfBlockSize = sizeof(DWORD);
  2947. try {
  2948. err1 = SetNtmsObjectAttribute(hSession, &mediaId, NTMS_LOGICAL_MEDIA, OLESTR("BlockSize"), (LPVOID) &nBlockSize, sizeOfBlockSize);
  2949. WsbAffirmNoError(err1);
  2950. break;
  2951. } WsbCatchAndDo(hr,
  2952. switch (HRESULT_CODE(hr)) {
  2953. case ERROR_INVALID_HANDLE:
  2954. case ERROR_NOT_CONNECTED:
  2955. case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running
  2956. case RPC_S_CALL_FAILED_DNE: // Media Services is up, handle is not valid.
  2957. case RPC_S_CALL_FAILED: // Media Services crashed.
  2958. WsbAffirmHr(beginSession());
  2959. continue;
  2960. }
  2961. WsbThrow(hr);
  2962. );
  2963. } while(1);
  2964. } WsbCatchAndDo(hr,
  2965. if (err1 != NO_ERROR) {
  2966. // SetNtmsObjectAttribute
  2967. switch (HRESULT_CODE(hr)) {
  2968. case ERROR_DATABASE_FAILURE:
  2969. case ERROR_INVALID_HANDLE:
  2970. case ERROR_INSUFFICIENT_BUFFER:
  2971. case ERROR_NOT_CONNECTED:
  2972. case ERROR_NO_DATA:
  2973. case ERROR_INVALID_PARAMETER:
  2974. case ERROR_OBJECT_NOT_FOUND:
  2975. case ERROR_INVALID_NAME:
  2976. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2977. OLESTR("SetNtmsObjectAttribute"), OLESTR(""),
  2978. WsbHrAsString(hr), NULL);
  2979. break;
  2980. default:
  2981. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  2982. OLESTR("SetNtmsObjectAttribute"), OLESTR("Undocumented Error: "),
  2983. WsbHrAsString(hr), NULL);
  2984. break;
  2985. }
  2986. }
  2987. );
  2988. WsbTraceOut(OLESTR("CRmsNTMS::SetBlockSize"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2989. return hr;
  2990. }
  2991. HRESULT
  2992. CRmsNTMS::changeState(
  2993. IN LONG newState
  2994. )
  2995. /*++
  2996. Routine Description:
  2997. Changes the state of the NTMS object.
  2998. Arguments:
  2999. None.
  3000. Return Values:
  3001. S_OK - Success.
  3002. --*/
  3003. {
  3004. HRESULT hr = S_OK;
  3005. WsbTraceIn(OLESTR("CRmsNTMS::changeState"), OLESTR("<%d>"), newState);
  3006. try {
  3007. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
  3008. WsbAssertPointer( pObject );
  3009. // TODO: Validate the state change
  3010. WsbAffirmHr(pObject->SetState(newState));
  3011. } WsbCatch(hr);
  3012. WsbTraceOut(OLESTR("CRmsNTMS::changeState"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3013. return hr;
  3014. }
  3015. STDMETHODIMP
  3016. CRmsNTMS::ExportDatabase(void)
  3017. /*++
  3018. Implements:
  3019. CRmsNTMS::ExportDatabase
  3020. --*/
  3021. {
  3022. HRESULT hr = S_OK;
  3023. DWORD err1 = NO_ERROR;
  3024. WsbTraceIn( OLESTR("CRmsNTMS::ExportDatabase"), OLESTR(""));
  3025. try {
  3026. do {
  3027. hr = S_OK;
  3028. HANDLE hSession = m_SessionHandle;
  3029. err1 = NO_ERROR;
  3030. try {
  3031. err1 = ExportNtmsDatabase(hSession);
  3032. WsbAffirmNoError(err1);
  3033. break;
  3034. } WsbCatchAndDo(hr,
  3035. switch (HRESULT_CODE(hr)) {
  3036. case ERROR_INVALID_HANDLE:
  3037. case ERROR_NOT_CONNECTED:
  3038. case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running
  3039. case RPC_S_CALL_FAILED_DNE: // Media Services is up, handle is not valid.
  3040. case RPC_S_CALL_FAILED: // Media Services crashed.
  3041. WsbAffirmHr(beginSession());
  3042. continue;
  3043. }
  3044. WsbThrow(hr);
  3045. );
  3046. } while(1);
  3047. } WsbCatchAndDo(hr,
  3048. if (err1 != NO_ERROR) {
  3049. // ExportNtmsDatabase
  3050. switch (HRESULT_CODE(hr)) {
  3051. case ERROR_ACCESS_DENIED:
  3052. case ERROR_DATABASE_FAILURE:
  3053. case ERROR_INVALID_HANDLE:
  3054. case ERROR_NOT_CONNECTED:
  3055. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3056. OLESTR("ExportNtmsDatabase"), OLESTR(""),
  3057. WsbHrAsString(hr), NULL);
  3058. break;
  3059. default:
  3060. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3061. OLESTR("ExportNtmsDatabase"), OLESTR("Undocumented Error: "),
  3062. WsbHrAsString(hr), NULL);
  3063. break;
  3064. }
  3065. }
  3066. );
  3067. WsbTraceOut(OLESTR("CRmsNTMS::ExportDatabase"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3068. return hr;
  3069. }
  3070. STDMETHODIMP
  3071. CRmsNTMS::FindCartridge(
  3072. IN REFGUID cartId,
  3073. OUT IRmsCartridge **ppCartridge)
  3074. /*++
  3075. Implements:
  3076. CRmsNTMS::FindCartridge
  3077. --*/
  3078. {
  3079. HRESULT hr = S_OK;
  3080. DWORD err1 = NO_ERROR;
  3081. DWORD err2 = NO_ERROR;
  3082. WsbTraceIn( OLESTR("CRmsNTMS::FindCartridge"), OLESTR("<%ls> <0x%08x>"), WsbGuidAsString(cartId), ppCartridge);
  3083. try {
  3084. WsbAssert(cartId != GUID_NULL, E_INVALIDARG);
  3085. WsbAssertPointer(ppCartridge);
  3086. NTMS_OBJECTINFORMATION partitionInfo;
  3087. memset( &partitionInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
  3088. NTMS_OBJECTINFORMATION mediaInfo;
  3089. memset( &mediaInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
  3090. NTMS_OBJECTINFORMATION mediaTypeInfo;
  3091. memset( &mediaTypeInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
  3092. NTMS_OBJECTINFORMATION libraryInfo;
  3093. memset( &libraryInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
  3094. NTMS_OBJECTINFORMATION logicalMediaInfo;
  3095. memset( &logicalMediaInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
  3096. RmsMedia translatedMediaType = RmsMediaUnknown;
  3097. // Special error recovery to handle when NTMS is down, or was cycled.
  3098. do {
  3099. hr = S_OK;
  3100. HANDLE hSession = m_SessionHandle;
  3101. NTMS_GUID mediaId = cartId;
  3102. DWORD sideNo = 2;
  3103. NTMS_GUID side[2];
  3104. err1 = NO_ERROR;
  3105. err2 = NO_ERROR;
  3106. try {
  3107. // NTMS - enumerate the sides of a unit of media
  3108. WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
  3109. err1 = EnumerateNtmsObject( hSession, &mediaId, side, &sideNo, NTMS_PARTITION, 0 );
  3110. WsbAffirmNoError( err1 );
  3111. // NTMS - get partition information
  3112. partitionInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  3113. partitionInfo.dwType = NTMS_PARTITION;
  3114. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PARTITION)\n"));
  3115. err2 = GetNtmsObjectInformation( hSession, &side[0], &partitionInfo );
  3116. WsbAffirmNoError( err2 );
  3117. // NTMS - get physical media information
  3118. NTMS_GUID physicalMediaId = partitionInfo.Info.Partition.PhysicalMedia;
  3119. mediaInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  3120. mediaInfo.dwType = NTMS_PHYSICAL_MEDIA;
  3121. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PHYSICAL_MEDIA)\n"));
  3122. err2 = GetNtmsObjectInformation( hSession, &physicalMediaId, &mediaInfo );
  3123. WsbAffirmNoError( err2);
  3124. // NTMS - get media type information
  3125. NTMS_GUID mediaTypeId = mediaInfo.Info.PhysicalMedia.MediaType;
  3126. mediaTypeInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  3127. mediaTypeInfo.dwType = NTMS_MEDIA_TYPE;
  3128. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_MEDIA_TYPE)\n"));
  3129. err2 = GetNtmsObjectInformation( hSession, &mediaTypeId, &mediaTypeInfo );
  3130. WsbAffirmNoError( err2 );
  3131. // Translate the NTMS media type into something understood by RMS
  3132. storageMediaTypeToRmsMedia(&(mediaTypeInfo.Info.MediaType), &translatedMediaType);
  3133. // NTMS - get logical media information
  3134. logicalMediaInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  3135. logicalMediaInfo.dwType = NTMS_LOGICAL_MEDIA;
  3136. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_LOGICAL_MEDIA)\n"));
  3137. err2 = GetNtmsObjectInformation( hSession, &mediaId, &logicalMediaInfo );
  3138. WsbAffirmNoError( err2 );
  3139. // NTMS - get library information
  3140. NTMS_GUID libraryId = mediaInfo.Info.PhysicalMedia.CurrentLibrary;
  3141. libraryInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  3142. libraryInfo.dwType = NTMS_LIBRARY;
  3143. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_LIBRARY)\n"));
  3144. err2 = GetNtmsObjectInformation( hSession, &libraryId, &libraryInfo );
  3145. WsbAffirmNoError( err2 );
  3146. break;
  3147. } WsbCatchAndDo(hr,
  3148. switch (HRESULT_CODE(hr)) {
  3149. case ERROR_INVALID_HANDLE:
  3150. case ERROR_NOT_CONNECTED:
  3151. case RPC_S_SERVER_UNAVAILABLE: // Media Services is not running.
  3152. case RPC_S_CALL_FAILED_DNE: // Media Services is up; handle is not valid.
  3153. case RPC_S_CALL_FAILED: // Media Services crashed.
  3154. WsbAffirmHr(beginSession());
  3155. continue;
  3156. }
  3157. WsbThrow(hr);
  3158. );
  3159. } while(1);
  3160. // Create Cartridge
  3161. IRmsCartridge *pCart = 0;
  3162. WsbAssertHr(CoCreateInstance(CLSID_CRmsCartridge, 0, CLSCTX_SERVER,
  3163. IID_IRmsCartridge, (void **)&pCart));
  3164. // Fill in the object data
  3165. // The media Name is what is displaye by NTMS UI
  3166. CWsbBstrPtr name = mediaInfo.szName;
  3167. WsbAffirmHr(pCart->SetName(name));
  3168. // The partition Description is what is displayed by NTMS UI.
  3169. CWsbBstrPtr desc = partitionInfo.szDescription;
  3170. WsbAffirmHr(pCart->SetDescription(desc));
  3171. WsbAffirmHr(pCart->SetCartridgeId(cartId));
  3172. CWsbBstrPtr barCode = mediaInfo.Info.PhysicalMedia.szBarCode;
  3173. CWsbBstrPtr seqNo = mediaInfo.Info.PhysicalMedia.szSequenceNumber; // Not used
  3174. WsbAffirmHr(pCart->SetTagAndNumber(barCode, 0));
  3175. WsbAffirmHr(pCart->SetType((LONG) translatedMediaType));
  3176. switch (mediaInfo.Info.PhysicalMedia.MediaState) {
  3177. case NTMS_MEDIASTATE_IDLE:
  3178. case NTMS_MEDIASTATE_UNLOADED:
  3179. WsbAffirmHr(pCart->SetIsAvailable(TRUE));
  3180. break;
  3181. default:
  3182. WsbAffirmHr(pCart->SetIsAvailable(FALSE));
  3183. break;
  3184. }
  3185. RmsElement type = RmsElementUnknown;
  3186. if ( NTMS_LIBRARYTYPE_ONLINE == libraryInfo.Info.Library.LibraryType ) {
  3187. switch (mediaInfo.Info.PhysicalMedia.LocationType) {
  3188. case NTMS_STORAGESLOT:
  3189. type = RmsElementStorage;
  3190. break;
  3191. case NTMS_DRIVE:
  3192. type = RmsElementDrive;
  3193. break;
  3194. case NTMS_IEPORT:
  3195. type = RmsElementIEPort;
  3196. break;
  3197. case NTMS_CHANGER:
  3198. type = RmsElementChanger;
  3199. break;
  3200. default:
  3201. type = RmsElementUnknown;
  3202. break;
  3203. }
  3204. }
  3205. else if ( NTMS_LIBRARYTYPE_STANDALONE == libraryInfo.Info.Library.LibraryType ) {
  3206. switch (mediaInfo.Info.PhysicalMedia.LocationType) {
  3207. case NTMS_DRIVE:
  3208. type = RmsElementDrive;
  3209. break;
  3210. default:
  3211. type = RmsElementUnknown;
  3212. break;
  3213. }
  3214. } else {
  3215. type = RmsElementShelf;
  3216. }
  3217. WsbAffirmHr(pCart->SetLocation(type,
  3218. mediaInfo.Info.PhysicalMedia.CurrentLibrary,
  3219. logicalMediaInfo.Info.LogicalMedia.MediaPool,
  3220. 0, 0, 0, 0, 0));
  3221. WsbAffirmHr(pCart->SetManagedBy((LONG)RmsMediaManagerNTMS));
  3222. WsbAssertHr(pCart->SetStatus(RmsStatusPrivate));
  3223. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObj = pCart;
  3224. if (!mediaInfo.Enabled) {
  3225. WsbAffirmHr(pObj->Disable(RMS_E_CARTRIDGE_DISABLED));
  3226. }
  3227. CComQIPtr<IRmsStorageInfo, &IID_IRmsStorageInfo> pInfo = pCart;
  3228. WsbAffirmHr(pInfo->SetCapacity(partitionInfo.Info.Partition.Capacity.QuadPart));
  3229. WsbTrace(OLESTR("Cartridge id <name/desc>: %ls <%ls/%ls>\n"), WsbGuidAsString(cartId), (WCHAR *) name, (WCHAR *) desc);
  3230. WsbTrace(OLESTR("Cartridge <barCode/seqNo>: <%ls/%ls>\n"), (WCHAR *) barCode, (WCHAR *) seqNo );
  3231. WsbTrace(OLESTR("Cartridge Enabled: %ls\n"), WsbHrAsString(pObj->IsEnabled()));
  3232. WsbTrace(OLESTR("Cartridge type: %d\n"), translatedMediaType);
  3233. WsbTrace(OLESTR("Cartridge capacity: %I64d\n"), partitionInfo.Info.Partition.Capacity.QuadPart);
  3234. WsbTrace(OLESTR("Cartridge domain: %ls\n"), WsbGuidAsString(logicalMediaInfo.Info.LogicalMedia.MediaPool));
  3235. if (mediaInfo.Info.PhysicalMedia.MediaPool != logicalMediaInfo.Info.LogicalMedia.MediaPool) {
  3236. CWsbStringPtr idPhysical = mediaInfo.Info.PhysicalMedia.CurrentLibrary;
  3237. CWsbStringPtr idLogical = logicalMediaInfo.Info.LogicalMedia.MediaPool;
  3238. WsbTraceAlways(OLESTR("CRmsNTMS::FindCartridge - Media Pool Id mismatch %ls != %ls\n"), idPhysical, idLogical );
  3239. }
  3240. // Fill in the return argument.
  3241. *ppCartridge = pCart;
  3242. } WsbCatchAndDo( hr,
  3243. WsbTrace(OLESTR("CRmsNTMS::FindCartridge - %ls Not Found. hr = <%ls>\n"),WsbGuidAsString(cartId),WsbHrAsString(hr));
  3244. if (err1 != NO_ERROR ) {
  3245. // EnumerateNtmsObject
  3246. switch (HRESULT_CODE(hr)) {
  3247. case ERROR_OBJECT_NOT_FOUND:
  3248. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  3249. break;
  3250. case ERROR_INVALID_PARAMETER:
  3251. case ERROR_INVALID_HANDLE:
  3252. case ERROR_NOT_ENOUGH_MEMORY:
  3253. case ERROR_INSUFFICIENT_BUFFER:
  3254. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3255. OLESTR("EnumerateNtmsObject"), OLESTR(""),
  3256. WsbHrAsString(hr), NULL);
  3257. break;
  3258. default:
  3259. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3260. OLESTR("EnumerateNtmsObject"), OLESTR("Undocumented Error: "),
  3261. WsbHrAsString(hr), NULL);
  3262. break;
  3263. }
  3264. }
  3265. else if (err2 != NO_ERROR) {
  3266. // GetNtmsObjectInformation
  3267. switch (HRESULT_CODE(hr)) {
  3268. case ERROR_OBJECT_NOT_FOUND:
  3269. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  3270. break;
  3271. case ERROR_INVALID_HANDLE:
  3272. case ERROR_INVALID_PARAMETER:
  3273. case ERROR_NOT_ENOUGH_MEMORY:
  3274. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3275. OLESTR("GetNtmsObjectInformation"), OLESTR(""),
  3276. WsbHrAsString(hr), NULL);
  3277. break;
  3278. default:
  3279. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3280. OLESTR("GetNtmsObjectInformation"), OLESTR("Undocumented Error: "),
  3281. WsbHrAsString(hr), NULL);
  3282. break;
  3283. }
  3284. }
  3285. );
  3286. WsbTraceOut( OLESTR("CRmsNTMS::FindCartridge"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
  3287. return hr;
  3288. }
  3289. STDMETHODIMP
  3290. CRmsNTMS::Suspend(void)
  3291. /*++
  3292. Implements:
  3293. CRmsNTMS::Suspend
  3294. --*/
  3295. {
  3296. HRESULT hr = S_OK;
  3297. WsbTraceIn( OLESTR("CRmsNTMS::Suspend"), OLESTR(""));
  3298. try {
  3299. WsbAffirmHr(changeState(RmsNtmsStateSuspending));
  3300. WsbAffirmHr(endSession());
  3301. WsbAffirmHr(changeState(RmsNtmsStateSuspended));
  3302. } WsbCatch(hr);
  3303. WsbTraceOut( OLESTR("CRmsNTMS::Suspend"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
  3304. return hr;
  3305. }
  3306. STDMETHODIMP
  3307. CRmsNTMS::Resume(void)
  3308. /*++
  3309. Implements:
  3310. CRmsNTMS::Resume
  3311. --*/
  3312. {
  3313. HRESULT hr = S_OK;
  3314. WsbTraceIn( OLESTR("CRmsNTMS::Resume"), OLESTR(""));
  3315. try {
  3316. WsbAffirmHr(changeState(RmsNtmsStateResuming));
  3317. WsbAffirmHr(beginSession());
  3318. WsbAffirmHr(changeState(RmsNtmsStateReady));
  3319. } WsbCatch(hr);
  3320. WsbTraceOut( OLESTR("CRmsNTMS::Resume"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
  3321. return hr;
  3322. }
  3323. HRESULT
  3324. CRmsNTMS::InitializeInAnotherThread(void)
  3325. {
  3326. HRESULT hr = S_OK;
  3327. WsbTraceIn(OLESTR("CRmsNTMS::InitializeInAnotherThread"), OLESTR(""));
  3328. try {
  3329. DWORD threadId;
  3330. HANDLE hThread;
  3331. CComQIPtr<IRmsServer, &IID_IRmsServer> pServer = g_pServer;
  3332. WsbAffirmHr( pServer->ChangeState( RmsServerStateInitializing ));
  3333. WsbAffirmHandle(hThread = CreateThread(NULL, 1024, CRmsNTMS::InitializationThread, this, 0, &threadId));
  3334. CloseHandle(hThread);
  3335. } WsbCatch(hr);
  3336. WsbTraceOut(OLESTR("CRmsNTMS::InitializeInAnotherThread"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3337. return hr;
  3338. }
  3339. DWORD WINAPI
  3340. CRmsNTMS::InitializationThread(
  3341. IN LPVOID pv)
  3342. {
  3343. HRESULT hr = S_OK;
  3344. WsbTraceIn(OLESTR("CRmsNTMS::InitializationThread"), OLESTR(""));
  3345. try {
  3346. WsbAssertPointer(pv);
  3347. CRmsNTMS *pNTMS = (CRmsNTMS*)pv;
  3348. WsbAffirmHr(pNTMS->Initialize());
  3349. CComQIPtr<IRmsServer, &IID_IRmsServer> pServer = g_pServer;
  3350. WsbAffirmHr( pServer->ChangeState( RmsServerStateReady ));
  3351. } WsbCatch(hr);
  3352. WsbTraceOut(OLESTR("CRmsNTMS::InitializationThread"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3353. return hr;
  3354. }
  3355. HRESULT
  3356. CRmsNTMS::isReady(void)
  3357. {
  3358. HRESULT hr = S_OK;
  3359. try {
  3360. BOOL isEnabled;
  3361. HRESULT status;
  3362. RmsServerState state;
  3363. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pObject = this;
  3364. WsbAssertPointer( pObject );
  3365. WsbAffirmHr( isEnabled = pObject->IsEnabled());
  3366. WsbAffirmHr( pObject->GetState( (LONG *)&state ));
  3367. WsbAffirmHr( pObject->GetStatusCode( &status ));
  3368. if ( S_OK == isEnabled ) {
  3369. if ( RmsServerStateReady == state ) {
  3370. hr = S_OK;
  3371. }
  3372. else {
  3373. if ( S_OK == status ) {
  3374. WsbThrow(E_UNEXPECTED);
  3375. }
  3376. else {
  3377. WsbThrow(status);
  3378. }
  3379. }
  3380. }
  3381. else {
  3382. if ( S_OK == status ) {
  3383. WsbThrow(E_UNEXPECTED);
  3384. }
  3385. else {
  3386. WsbThrow(status);
  3387. }
  3388. }
  3389. } WsbCatch(hr);
  3390. return hr;
  3391. }
  3392. HRESULT
  3393. CRmsNTMS::setPoolDACL (
  3394. IN OUT NTMS_GUID *pPoolId,
  3395. IN DWORD subAuthority,
  3396. IN DWORD action,
  3397. IN DWORD mask)
  3398. {
  3399. HRESULT hr = S_OK;
  3400. WsbTraceIn(OLESTR("CRmsNTMS::SetPoolDACL"), OLESTR("%ls <%d> <%d> <%d>"), WsbGuidAsString(*pPoolId), subAuthority, action, mask);
  3401. PSID psidAccount = NULL;
  3402. PSECURITY_DESCRIPTOR psdRePoolSd = NULL;
  3403. try {
  3404. SID_IDENTIFIER_AUTHORITY ntauth = SECURITY_NT_AUTHORITY;
  3405. DWORD errCode = NO_ERROR, sizeTry = 5, sizeReturned = 0;
  3406. PACL paclDis = NULL;
  3407. BOOL daclPresent = FALSE, daclDefaulted = FALSE;
  3408. HANDLE hSession = m_SessionHandle;
  3409. WsbAffirmStatus(AllocateAndInitializeSid(&ntauth, 2, SECURITY_BUILTIN_DOMAIN_RID, subAuthority, 0, 0, 0, 0, 0, 0, &psidAccount));
  3410. //Get the security descriptor for the pool
  3411. for (;;) {
  3412. if (psdRePoolSd != NULL) {
  3413. free(psdRePoolSd);
  3414. }
  3415. psdRePoolSd = (PSECURITY_DESCRIPTOR)malloc(sizeTry);
  3416. WsbAffirm(NULL != psdRePoolSd, E_OUTOFMEMORY);
  3417. errCode = GetNtmsObjectSecurity(hSession, pPoolId, NTMS_MEDIA_POOL, DACL_SECURITY_INFORMATION, psdRePoolSd, sizeTry, &sizeReturned);
  3418. if (errCode == ERROR_SUCCESS) {
  3419. break;
  3420. }
  3421. else if (errCode == ERROR_INSUFFICIENT_BUFFER) {
  3422. sizeTry = sizeReturned;
  3423. continue;
  3424. }
  3425. else {
  3426. WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
  3427. OLESTR("GetNtmsObjectSecurity"),
  3428. WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
  3429. NULL );
  3430. WsbAffirmNoError(errCode);
  3431. }
  3432. }
  3433. // Get a pointer to the DACL
  3434. WsbAffirmStatus(GetSecurityDescriptorDacl(psdRePoolSd, &daclPresent, &paclDis, &daclDefaulted));
  3435. // Go through the DACL and change the mask of the ACE that matches the SID
  3436. for (DWORD i = 0;i < paclDis->AceCount; ++i) {
  3437. // Get the ACE and its header
  3438. LPVOID pAce = NULL;
  3439. WsbAffirmStatus(GetAce(paclDis, i, &pAce));
  3440. ACE_HEADER * pAceHeader = (ACE_HEADER*) pAce;
  3441. // Ignore non-allowed ACEs - BUG 584785
  3442. if (pAceHeader->AceType != ACCESS_ALLOWED_ACE_TYPE)
  3443. continue;
  3444. // Take out the flags
  3445. ACCESS_ALLOWED_ACE *pAccessAllowedAce = (ACCESS_ALLOWED_ACE *)pAce;
  3446. if (EqualSid(psidAccount, &(pAccessAllowedAce->SidStart))) {
  3447. if (action == ADD_ACE_MASK_BITS) {
  3448. pAccessAllowedAce->Mask |= mask;
  3449. } else {
  3450. pAccessAllowedAce->Mask &= ~mask;
  3451. }
  3452. }
  3453. }
  3454. // Set the pool security descriptor
  3455. errCode = SetNtmsObjectSecurity(hSession, pPoolId, NTMS_MEDIA_POOL, DACL_SECURITY_INFORMATION, psdRePoolSd);
  3456. WsbAffirmNoError(errCode);
  3457. } WsbCatch(hr);
  3458. if (psdRePoolSd) {
  3459. free(psdRePoolSd);
  3460. }
  3461. if (psidAccount) {
  3462. FreeSid(psidAccount);
  3463. }
  3464. WsbTraceOut(OLESTR("CRmsNTMS::SetPoolDACL"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3465. return hr;
  3466. }
  3467. HRESULT
  3468. CRmsNTMS::IsMediaCopySupported (
  3469. IN REFGUID mediaPoolId)
  3470. {
  3471. HRESULT hr = S_OK;
  3472. WsbTraceIn(OLESTR("CRmsNTMS::IsMediaCopySupported"), OLESTR("%ls"), WsbGuidAsString(mediaPoolId));
  3473. try {
  3474. // If we can find two drives that support this media type then
  3475. // the media copy operation is supported.
  3476. // For each drive known to NTMS we need to find what media types
  3477. // it supports. NTMS doesn't keep media type information for the
  3478. // drive, but assumes homogeneous drives in a library (per HighGound) -
  3479. // so detecting this is a bit convoluted.
  3480. // we'll search through each library and find the media types
  3481. // supported, and count the number of drives in the library.
  3482. if ( INVALID_HANDLE_VALUE == m_SessionHandle ) {
  3483. WsbAffirmHr(beginSession());
  3484. }
  3485. HANDLE hSession = m_SessionHandle;
  3486. NTMS_OBJECTINFORMATION mediaPoolInfo;
  3487. NTMS_GUID poolId = mediaPoolId;
  3488. memset(&mediaPoolInfo, 0, sizeof(NTMS_OBJECTINFORMATION));
  3489. mediaPoolInfo.dwType = NTMS_MEDIA_POOL;
  3490. mediaPoolInfo.dwSize = sizeof(NTMS_OBJECTINFORMATION);
  3491. // NTMS - Get Media Pool Information
  3492. WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
  3493. DWORD errCode = GetNtmsObjectInformation( hSession, &poolId, &mediaPoolInfo );
  3494. if ( errCode != NO_ERROR ) {
  3495. WsbLogEvent( RMS_MESSAGE_NTMS_FAILURE, 0, NULL,
  3496. OLESTR("GetNtmsObjectInformation"),
  3497. WsbHrAsString(HRESULT_FROM_WIN32(errCode)),
  3498. NULL );
  3499. WsbThrow( E_UNEXPECTED );
  3500. }
  3501. NTMS_GUID mediaTypeId = mediaPoolInfo.Info.MediaPool.MediaType;
  3502. NTMS_OBJECTINFORMATION libInfo;
  3503. HANDLE hFindLib = NULL;
  3504. int driveCount = 0;
  3505. hr = findFirstNtmsObject( NTMS_LIBRARY,
  3506. GUID_NULL, NULL, GUID_NULL, &hFindLib, &libInfo);
  3507. while( S_OK == hr ) {
  3508. HANDLE hFindLib2 = NULL;
  3509. // now see if the library in which the drive is contained supported
  3510. // the specified media type
  3511. if ( libInfo.Info.Library.dwNumberOfDrives > 0 ) {
  3512. hr = findFirstNtmsObject( NTMS_MEDIA_TYPE,
  3513. libInfo.ObjectGuid, NULL, mediaTypeId, &hFindLib2, NULL);
  3514. WsbTrace(OLESTR("Searching <%ls> for media type and drives; hr = %ls (state = %d, enabled = %ls, drives = %d)\n"),
  3515. libInfo.szName, WsbHrAsString(hr),
  3516. libInfo.dwOperationalState,
  3517. WsbBoolAsString(libInfo.Enabled),
  3518. libInfo.Info.Library.dwNumberOfDrives);
  3519. if ((S_OK == hr) &&
  3520. ((NTMS_READY == libInfo.dwOperationalState) ||
  3521. (NTMS_INITIALIZING == libInfo.dwOperationalState)) &&
  3522. (libInfo.Enabled)) {
  3523. driveCount += libInfo.Info.Library.dwNumberOfDrives;
  3524. }
  3525. findCloseNtmsObject( hFindLib2 );
  3526. }
  3527. hr = findNextNtmsObject( hFindLib, &libInfo );
  3528. }
  3529. findCloseNtmsObject( hFindLib );
  3530. hr = (driveCount > 1) ? S_OK : S_FALSE;
  3531. } WsbCatch(hr);
  3532. WsbTraceOut(OLESTR("CRmsNTMS::IsMediaCopySupported"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3533. return hr;
  3534. }
  3535. STDMETHODIMP
  3536. CRmsNTMS::UpdateDrive(
  3537. IN IRmsDrive *pDrive)
  3538. /*++
  3539. Implements:
  3540. IRmsNTMS::UpdateDrive
  3541. --*/
  3542. {
  3543. HRESULT hr = S_OK;
  3544. CComPtr<IRmsComObject> pObject;
  3545. GUID driveId;
  3546. DWORD err1 = NO_ERROR;
  3547. WsbTraceIn(OLESTR("CRmsNTMS::UpdateDrive"), OLESTR(""));
  3548. try {
  3549. // get drive information
  3550. WsbAffirmHr(pDrive->QueryInterface(IID_IRmsComObject, (void **)&pObject));
  3551. WsbAffirmHr(pObject->GetObjectId(&driveId));
  3552. NTMS_OBJECTINFORMATION objectInfo;
  3553. objectInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  3554. objectInfo.dwType = NTMS_DRIVE;
  3555. WsbAssert(driveId != GUID_NULL, E_INVALIDARG);
  3556. err1 = GetNtmsObjectInformation( m_SessionHandle, &driveId, &objectInfo );
  3557. WsbAffirmNoError (err1);
  3558. // Note: Currently, the method updates only the enable/disable state of the drive
  3559. // If required, the method may update more fields
  3560. if (objectInfo.Enabled) {
  3561. WsbAffirmHr(pObject->Enable());
  3562. } else {
  3563. WsbAffirmHr(pObject->Disable(S_OK));
  3564. }
  3565. } WsbCatchAndDo(hr,
  3566. // Process the error of the get-info request
  3567. if (err1 != NO_ERROR ) {
  3568. if (err1 == ERROR_OBJECT_NOT_FOUND) {
  3569. hr = RMS_E_NTMS_OBJECT_NOT_FOUND;
  3570. }
  3571. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3572. OLESTR("GetNtmsObjectInformation (Drive)"), OLESTR(""),
  3573. WsbHrAsString(hr), NULL);
  3574. }
  3575. );
  3576. WsbTraceOut(OLESTR("CRmsNTMS::UpdateDrive"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3577. return(hr);
  3578. }
  3579. HRESULT
  3580. CRmsNTMS::GetNofAvailableDrives(
  3581. OUT DWORD* pdwNofDrives
  3582. )
  3583. /*++
  3584. Implements:
  3585. IRmsNTMS::GetNofAvailableDrives().
  3586. --*/
  3587. {
  3588. HRESULT hr = S_OK;
  3589. WsbTraceIn(OLESTR("CRmsNTMS::GetNofAvailableDrives"), OLESTR(""));
  3590. *pdwNofDrives = 0;
  3591. // Enumerate over all libraries that HSM uses
  3592. // (Outside the try block, since we want to continue if a failure occur on a specific library)
  3593. WsbTrace(OLESTR("CRmsNTMS::GetNofAvailableDrives: Total number of libraries is %lu\n"), m_dwNofLibs);
  3594. for (int j=0; j<(int)m_dwNofLibs; j++) {
  3595. LPNTMS_GUID pObjects = NULL;
  3596. DWORD errCode = NO_ERROR;
  3597. // get library id
  3598. GUID libId = m_pLibGuids[j];
  3599. // If object is suspended/suspending, just terminate (without logging an error)
  3600. if ((m_State == RmsNtmsStateSuspended) || (m_State == RmsNtmsStateSuspending)) {
  3601. WsbTrace(OLESTR("CRmsNTMS::GetNofAvailableDrives: Object is suspended/suspending - exit\n"));
  3602. break;
  3603. }
  3604. try {
  3605. // Enumerate on all drives in the library
  3606. DWORD dwNofObjects = 16; // Initial size of object id array to allocate
  3607. int nRetry = 0;
  3608. // Allocate according to
  3609. pObjects = (LPNTMS_GUID)WsbAlloc( dwNofObjects*sizeof(NTMS_GUID) );
  3610. WsbAffirmPointer( pObjects );
  3611. // Enumerate all drives
  3612. do {
  3613. errCode = EnumerateNtmsObject(m_SessionHandle, &libId, pObjects, &dwNofObjects, NTMS_DRIVE, 0);
  3614. WsbTraceAlways(OLESTR("CRmsNTMS::GetNofAvailableDrives: Total number of drives is %lu\n"),
  3615. dwNofObjects);
  3616. nRetry++;
  3617. if ( (ERROR_OBJECT_NOT_FOUND == errCode) || (0 == dwNofObjects) ) { // Don't count on NTMS returning the correct errCode
  3618. // Not considered as an NTMS error, prevent logging by setting to NO_ERROR
  3619. errCode = NO_ERROR;
  3620. WsbThrow( RMS_E_NTMS_OBJECT_NOT_FOUND );
  3621. } else if (ERROR_INSUFFICIENT_BUFFER == errCode) {
  3622. // Don't retry more than 3 times
  3623. if (3 <= nRetry) {
  3624. WsbThrow(HRESULT_FROM_WIN32(errCode));
  3625. }
  3626. // Allocate a new buffer, and retry.
  3627. WsbTrace(OLESTR("CRmsNTMS::GetNofAvailableDrives: Reallocating buffer\n"));
  3628. LPVOID pTemp = WsbRealloc( pObjects, dwNofObjects*sizeof(NTMS_GUID) );
  3629. if (!pTemp) {
  3630. WsbThrow(E_OUTOFMEMORY);
  3631. }
  3632. pObjects = (LPNTMS_GUID)pTemp;
  3633. } else {
  3634. // Other unexpected error
  3635. WsbAffirmNoError(errCode);
  3636. }
  3637. } while (ERROR_INSUFFICIENT_BUFFER == errCode);
  3638. // go over all drives, get information and check availablity
  3639. for (int i = 0; i < (int)dwNofObjects; i++) {
  3640. GUID driveId = pObjects[i];
  3641. try {
  3642. NTMS_OBJECTINFORMATION objectInfo;
  3643. memset( &objectInfo, 0, sizeof(NTMS_OBJECTINFORMATION) );
  3644. objectInfo.dwSize = sizeof(NTMS_OBJECTINFORMATION);
  3645. objectInfo.dwType = NTMS_DRIVE;
  3646. WsbAssert(driveId != GUID_NULL, E_INVALIDARG);
  3647. errCode = GetNtmsObjectInformation(m_SessionHandle, &driveId, &objectInfo );
  3648. WsbAffirmNoError (errCode);
  3649. WsbTrace(OLESTR("CRmsNTMS::GetNofAvailableDrives: drive <%ls> enable/disable = %ls\n"),
  3650. WsbGuidAsString(driveId), WsbBoolAsString(objectInfo.Enabled));
  3651. if (objectInfo.Enabled) {
  3652. (*pdwNofDrives)++;
  3653. }
  3654. } WsbCatchAndDo(hr,
  3655. // Log error and go on to the next drive
  3656. if (errCode != NO_ERROR ) {
  3657. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3658. OLESTR("GetNtmsObjectInformation (Drive)"), OLESTR(""),
  3659. WsbHrAsString(hr), NULL);
  3660. }
  3661. WsbTraceAlways(OLESTR("CRmsNTMS::GetNofAvailableDrives: Failed to get info for drive <%ls> hr = <%ls>\n"),
  3662. WsbGuidAsString(driveId), WsbHrAsString(hr));
  3663. hr = S_OK;
  3664. );
  3665. }
  3666. } WsbCatchAndDo(hr,
  3667. // Log error and go on to the next library
  3668. if (errCode != NO_ERROR ) {
  3669. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3670. OLESTR("EnumerateNtmsObject (Drive)"), OLESTR(""),
  3671. WsbHrAsString(hr), NULL);
  3672. }
  3673. WsbTraceAlways(OLESTR("CRmsNTMS::GetNofAvailableDrives: Failed to enumerate drives in library <%ls> hr = <%ls>\n"),
  3674. WsbGuidAsString(libId), WsbHrAsString(hr));
  3675. hr = S_OK;
  3676. );
  3677. if (pObjects) {
  3678. WsbFree(pObjects);
  3679. }
  3680. } // of for
  3681. WsbTraceOut(OLESTR("CRmsNTMS::GetNofAvailableDrives"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3682. return(hr);
  3683. }
  3684. HRESULT
  3685. CRmsNTMS::CheckSecondSide(
  3686. IN REFGUID firstSideId,
  3687. OUT BOOL *pbValid,
  3688. OUT GUID *pSecondSideId
  3689. )
  3690. /*++
  3691. Implements:
  3692. IRmsNTMS::CheckSecondSide().
  3693. --*/
  3694. {
  3695. HRESULT hr = S_OK;
  3696. DWORD err1 = NO_ERROR;
  3697. DWORD err2 = NO_ERROR;
  3698. WsbTraceIn(OLESTR("CRmsNTMS::CheckSecondSide"), OLESTR(""));
  3699. *pbValid = FALSE;
  3700. *pSecondSideId = GUID_NULL;
  3701. try {
  3702. WsbAssert(firstSideId != GUID_NULL, E_INVALIDARG);
  3703. WsbAssertPointer(pbValid);
  3704. WsbAssertPointer(pSecondSideId);
  3705. NTMS_OBJECTINFORMATION partitionInfo;
  3706. memset( &partitionInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
  3707. NTMS_OBJECTINFORMATION mediaInfo;
  3708. memset( &mediaInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
  3709. HANDLE hSession = m_SessionHandle;
  3710. NTMS_GUID mediaId = firstSideId;
  3711. NTMS_GUID firstSidePartitionId;
  3712. NTMS_GUID side[2];
  3713. DWORD sideNo = 2;
  3714. // NTMS - get Partition from LMID
  3715. WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
  3716. err1 = EnumerateNtmsObject(hSession, &mediaId, side, &sideNo, NTMS_PARTITION, 0);
  3717. WsbAffirmNoError(err1);
  3718. firstSidePartitionId = side[0];
  3719. // NTMS - get partition information (using size 0 - LMID relates 1:1 to Partition
  3720. partitionInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  3721. partitionInfo.dwType = NTMS_PARTITION;
  3722. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PARTITION)\n"));
  3723. err2 = GetNtmsObjectInformation(hSession, &firstSidePartitionId, &partitionInfo);
  3724. WsbAffirmNoError(err2);
  3725. // NTMS - get physical media information
  3726. NTMS_GUID physicalMediaId = partitionInfo.Info.Partition.PhysicalMedia;
  3727. mediaInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  3728. mediaInfo.dwType = NTMS_PHYSICAL_MEDIA;
  3729. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PHYSICAL_MEDIA)\n"));
  3730. err2 = GetNtmsObjectInformation(hSession, &physicalMediaId, &mediaInfo);
  3731. WsbAffirmNoError(err2);
  3732. // Check whether there are more than one side
  3733. if (mediaInfo.Info.PhysicalMedia.dwNumberOfPartitions > 1) {
  3734. // Enumerate physical meida - expect 2 sides here.
  3735. WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
  3736. sideNo = 2;
  3737. err1 = EnumerateNtmsObject(hSession, &physicalMediaId, side, &sideNo, NTMS_PARTITION, 0);
  3738. WsbAffirmNoError(err1);
  3739. WsbAffirm(sideNo > 1, RMS_E_NOT_FOUND);
  3740. // Look for a side whos partition id is different from first side
  3741. for (DWORD i=0; i<sideNo; i++) {
  3742. if (firstSidePartitionId != side[i]) {
  3743. *pbValid = TRUE; // Valid second side found
  3744. // Get its LMID
  3745. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PARTITION)\n"));
  3746. err2 = GetNtmsObjectInformation(hSession, &side[i], &partitionInfo);
  3747. WsbAffirmNoError(err2);
  3748. *pSecondSideId = partitionInfo.Info.Partition.LogicalMedia;
  3749. }
  3750. }
  3751. } // of if two sides
  3752. } WsbCatchAndDo( hr,
  3753. WsbTrace(OLESTR("CRmsNTMS::CheckSecondSide - of %ls failed: hr = <%ls>\n"),WsbGuidAsString(firstSideId),WsbHrAsString(hr));
  3754. if (err1 != NO_ERROR ) {
  3755. // EnumerateNtmsObject
  3756. switch (HRESULT_CODE(hr)) {
  3757. case ERROR_OBJECT_NOT_FOUND:
  3758. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  3759. break;
  3760. case ERROR_INVALID_PARAMETER:
  3761. case ERROR_INVALID_HANDLE:
  3762. case ERROR_NOT_ENOUGH_MEMORY:
  3763. case ERROR_INSUFFICIENT_BUFFER:
  3764. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3765. OLESTR("EnumerateNtmsObject"), OLESTR(""),
  3766. WsbHrAsString(hr), NULL);
  3767. break;
  3768. default:
  3769. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3770. OLESTR("EnumerateNtmsObject"), OLESTR("Unexpected Error: "),
  3771. WsbHrAsString(hr), NULL);
  3772. break;
  3773. }
  3774. }
  3775. else if (err2 != NO_ERROR) {
  3776. // GetNtmsObjectInformation
  3777. switch (HRESULT_CODE(hr)) {
  3778. case ERROR_OBJECT_NOT_FOUND:
  3779. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  3780. break;
  3781. case ERROR_INVALID_HANDLE:
  3782. case ERROR_INVALID_PARAMETER:
  3783. case ERROR_NOT_ENOUGH_MEMORY:
  3784. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3785. OLESTR("GetNtmsObjectInformation"), OLESTR(""),
  3786. WsbHrAsString(hr), NULL);
  3787. break;
  3788. default:
  3789. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3790. OLESTR("GetNtmsObjectInformation"), OLESTR("Unexpected Error: "),
  3791. WsbHrAsString(hr), NULL);
  3792. break;
  3793. }
  3794. }
  3795. );
  3796. WsbTraceOut(OLESTR("CRmsNTMS::CheckSecondSide"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3797. return(hr);
  3798. }
  3799. HRESULT
  3800. CRmsNTMS::EnsureAllSidesNotAllocated(
  3801. IN REFGUID mediaId
  3802. )
  3803. {
  3804. HRESULT hr = S_OK;
  3805. DWORD err1 = NO_ERROR;
  3806. DWORD err2 = NO_ERROR;
  3807. WsbTraceIn(OLESTR("CRmsNTMS::EnsureAllSidesNotAllocated"), OLESTR(""));
  3808. try {
  3809. WsbAssert(mediaId != GUID_NULL, E_INVALIDARG);
  3810. NTMS_OBJECTINFORMATION partitionInfo;
  3811. memset( &partitionInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
  3812. NTMS_OBJECTINFORMATION mediaInfo;
  3813. memset( &mediaInfo, 0, sizeof( NTMS_OBJECTINFORMATION ) );
  3814. HANDLE hSession = m_SessionHandle;
  3815. NTMS_GUID physicalMediaId = mediaId;
  3816. mediaInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  3817. mediaInfo.dwType = NTMS_PHYSICAL_MEDIA;
  3818. partitionInfo.dwSize = sizeof( NTMS_OBJECTINFORMATION );
  3819. partitionInfo.dwType = NTMS_PARTITION;
  3820. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PHYSICAL_MEDIA)\n"));
  3821. err2 = GetNtmsObjectInformation(hSession, &physicalMediaId, &mediaInfo);
  3822. WsbAffirmNoError(err2);
  3823. // Check whether there are more than one side
  3824. if (mediaInfo.Info.PhysicalMedia.dwNumberOfPartitions > 1) {
  3825. // Enumerate physical meida - expect 2 sides here.
  3826. NTMS_GUID side[2];
  3827. DWORD sideNo = 2;
  3828. WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
  3829. err1 = EnumerateNtmsObject(hSession, &physicalMediaId, side, &sideNo, NTMS_PARTITION, 0);
  3830. WsbAffirmNoError(err1);
  3831. // Look for a side which is allocated
  3832. for (DWORD i=0; i<sideNo; i++) {
  3833. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_PARTITION)\n"));
  3834. err2 = GetNtmsObjectInformation(hSession, &side[i], &partitionInfo);
  3835. WsbAffirmNoError(err2);
  3836. if (GUID_NULL != partitionInfo.Info.Partition.LogicalMedia) {
  3837. hr = S_FALSE;
  3838. break;
  3839. }
  3840. }
  3841. } // of if two sides
  3842. } WsbCatchAndDo( hr,
  3843. WsbTrace(OLESTR("CRmsNTMS::EnsureAllSidesNotAllocated - of %ls failed: hr = <%ls>\n"),WsbGuidAsString(mediaId),WsbHrAsString(hr));
  3844. if (err1 != NO_ERROR ) {
  3845. // EnumerateNtmsObject
  3846. switch (HRESULT_CODE(hr)) {
  3847. case ERROR_OBJECT_NOT_FOUND:
  3848. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  3849. break;
  3850. case ERROR_INVALID_PARAMETER:
  3851. case ERROR_INVALID_HANDLE:
  3852. case ERROR_NOT_ENOUGH_MEMORY:
  3853. case ERROR_INSUFFICIENT_BUFFER:
  3854. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3855. OLESTR("EnumerateNtmsObject"), OLESTR(""),
  3856. WsbHrAsString(hr), NULL);
  3857. break;
  3858. default:
  3859. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3860. OLESTR("EnumerateNtmsObject"), OLESTR("Unexpected Error: "),
  3861. WsbHrAsString(hr), NULL);
  3862. break;
  3863. }
  3864. }
  3865. else if (err2 != NO_ERROR) {
  3866. // GetNtmsObjectInformation
  3867. switch (HRESULT_CODE(hr)) {
  3868. case ERROR_OBJECT_NOT_FOUND:
  3869. hr = RMS_E_CARTRIDGE_NOT_FOUND;
  3870. break;
  3871. case ERROR_INVALID_HANDLE:
  3872. case ERROR_INVALID_PARAMETER:
  3873. case ERROR_NOT_ENOUGH_MEMORY:
  3874. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3875. OLESTR("GetNtmsObjectInformation"), OLESTR(""),
  3876. WsbHrAsString(hr), NULL);
  3877. break;
  3878. default:
  3879. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3880. OLESTR("GetNtmsObjectInformation"), OLESTR("Unexpected Error: "),
  3881. WsbHrAsString(hr), NULL);
  3882. break;
  3883. }
  3884. }
  3885. );
  3886. WsbTraceOut(OLESTR("CRmsNTMS::EnsureAllSidesNotAllocated"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3887. return(hr);
  3888. }
  3889. STDMETHODIMP
  3890. CRmsNTMS::DismountAll(
  3891. IN REFGUID fromMediaSet,
  3892. IN DWORD dwOptions)
  3893. /*++
  3894. Implements:
  3895. IRmsNTMS::DismountAll
  3896. --*/
  3897. {
  3898. HRESULT hr = S_OK;
  3899. WsbTraceIn( OLESTR("CRmsNTMS::DismountAll"), OLESTR("") );
  3900. try {
  3901. WsbAssert(GUID_NULL != fromMediaSet, E_INVALIDARG);
  3902. HANDLE hFindMedia = NULL;
  3903. DWORD err1 = NO_ERROR;
  3904. HANDLE hSession = m_SessionHandle;
  3905. NTMS_OBJECTINFORMATION physicalMediaInfo;
  3906. NTMS_GUID setId = fromMediaSet;
  3907. NTMS_GUID partId = GUID_NULL;
  3908. // Dismount all mounted medias from the given pool
  3909. hr = findFirstNtmsObject(NTMS_PHYSICAL_MEDIA, setId, NULL, GUID_NULL, &hFindMedia, &physicalMediaInfo);
  3910. while(S_OK == hr) {
  3911. switch (physicalMediaInfo.Info.PhysicalMedia.MediaState) {
  3912. case NTMS_MEDIASTATE_LOADED:
  3913. case NTMS_MEDIASTATE_MOUNTED:
  3914. // Dismount the media
  3915. try {
  3916. partId = physicalMediaInfo.Info.PhysicalMedia.MountedPartition;
  3917. WsbAffirm(GUID_NULL != partId, E_UNEXPECTED);
  3918. DWORD dwNtmsOptions = 0;
  3919. WsbTraceAlways(OLESTR("DismountNtmsMedia()\n"));
  3920. if (! ( dwOptions & RMS_DISMOUNT_IMMEDIATE )) {
  3921. dwNtmsOptions |= NTMS_DISMOUNT_DEFERRED;
  3922. }
  3923. err1 = DismountNtmsMedia(hSession, &partId, 1, dwNtmsOptions);
  3924. WsbAffirmNoError(err1);
  3925. } WsbCatchAndDo(hr,
  3926. if (err1 != NO_ERROR) {
  3927. WsbLogEvent(RMS_MESSAGE_NTMS_FAULT, 0, NULL,
  3928. OLESTR("DismountNtmsMedia"), OLESTR(""),
  3929. WsbHrAsString(hr), NULL);
  3930. }
  3931. );
  3932. break;
  3933. default:
  3934. // Media is not mounted - skip it
  3935. break;
  3936. }
  3937. hr = findNextNtmsObject(hFindMedia, &physicalMediaInfo);
  3938. }
  3939. findCloseNtmsObject(hFindMedia);
  3940. hr = S_OK;
  3941. } WsbCatch(hr);
  3942. WsbTraceOut( OLESTR("CRmsNTMS::DismountAll"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
  3943. return hr;
  3944. }
  3945. HRESULT
  3946. CRmsNTMS::GetMaxMediaCapacity(
  3947. IN REFGUID fromMediaSet,
  3948. OUT LONGLONG *pMaxCapacity
  3949. )
  3950. /*++
  3951. Implements:
  3952. IRmsNTMS::GetMaxMediaCapacity
  3953. Notes:
  3954. Traverse all the media in the Remote Storage pool & the free media pool and retruns max capacity
  3955. --*/
  3956. {
  3957. HRESULT hr = S_OK;
  3958. DWORD err1 = NO_ERROR;
  3959. DWORD err2 = NO_ERROR;
  3960. WsbTraceIn(OLESTR("CRmsNTMS::GetMaxMediaCapacity"), OLESTR(""));
  3961. try {
  3962. WsbAssert(fromMediaSet != GUID_NULL, E_INVALIDARG);
  3963. WsbAssertPointer(pMaxCapacity);
  3964. *pMaxCapacity = 0;
  3965. NTMS_GUID setId = fromMediaSet;
  3966. HANDLE hFindPart = NULL;
  3967. NTMS_OBJECTINFORMATION partitionInfo;
  3968. HANDLE hFindPool = NULL;
  3969. NTMS_OBJECTINFORMATION mediaPoolInfo;
  3970. NTMS_GUID scratchPoolId;
  3971. HANDLE hSession = m_SessionHandle;
  3972. // First look in RSS pool for media which are OK for capacity comparison
  3973. hr = findFirstNtmsObject(NTMS_PARTITION, setId, NULL, GUID_NULL, &hFindPart, &partitionInfo);
  3974. while(S_OK == hr) {
  3975. BOOL bCheckState = (partitionInfo.Info.Partition.State == NTMS_PARTSTATE_ALLOCATED) ||
  3976. (partitionInfo.Info.Partition.State == NTMS_PARTSTATE_AVAILABLE) ||
  3977. (partitionInfo.Info.Partition.State == NTMS_PARTSTATE_COMPLETE) ||
  3978. (partitionInfo.Info.Partition.State == NTMS_PARTSTATE_RESERVED);
  3979. if ((TRUE == partitionInfo.Enabled) &&
  3980. (NTMS_READY == partitionInfo.dwOperationalState) &&
  3981. (TRUE == bCheckState)) {
  3982. // Compare capacity to maximum
  3983. if (partitionInfo.Info.Partition.Capacity.QuadPart > *pMaxCapacity) {
  3984. *pMaxCapacity = partitionInfo.Info.Partition.Capacity.QuadPart;
  3985. }
  3986. }
  3987. hr = findNextNtmsObject(hFindPart, &partitionInfo);
  3988. }
  3989. findCloseNtmsObject(hFindPart);
  3990. hr = S_OK;
  3991. // Now look in scratch pool for media which are OK for capacity comparison
  3992. // Get and save the media type for the RSS media pool
  3993. memset(&mediaPoolInfo, 0, sizeof(NTMS_OBJECTINFORMATION));
  3994. mediaPoolInfo.dwType = NTMS_MEDIA_POOL;
  3995. mediaPoolInfo.dwSize = sizeof(NTMS_OBJECTINFORMATION);
  3996. WsbTraceAlways(OLESTR("GetNtmsObjectInformation(NTMS_MEDIA_POOL)\n"));
  3997. WsbAffirmNoError(GetNtmsObjectInformation(hSession, &setId, &mediaPoolInfo));
  3998. NTMS_GUID mediaTypeId = mediaPoolInfo.Info.MediaPool.MediaType;
  3999. // Find the scratch pool with the same media type
  4000. hr = findFirstNtmsObject(NTMS_MEDIA_POOL, GUID_NULL, NULL, GUID_NULL, &hFindPool, &mediaPoolInfo);
  4001. while(S_OK == hr) {
  4002. if ((NTMS_POOLTYPE_SCRATCH == mediaPoolInfo.Info.MediaPool.PoolType) &&
  4003. (mediaTypeId == mediaPoolInfo.Info.MediaPool.MediaType)) {
  4004. // This is a base level scratch media pool for type we're looking for.
  4005. scratchPoolId = mediaPoolInfo.ObjectGuid;
  4006. hr = findFirstNtmsObject(NTMS_PARTITION, scratchPoolId, NULL, GUID_NULL, &hFindPart, &partitionInfo);
  4007. while(S_OK == hr) {
  4008. BOOL bCheckState = (partitionInfo.Info.Partition.State == NTMS_PARTSTATE_ALLOCATED) ||
  4009. (partitionInfo.Info.Partition.State == NTMS_PARTSTATE_AVAILABLE) ||
  4010. (partitionInfo.Info.Partition.State == NTMS_PARTSTATE_COMPLETE) ||
  4011. (partitionInfo.Info.Partition.State == NTMS_PARTSTATE_RESERVED);
  4012. if ((TRUE == partitionInfo.Enabled) &&
  4013. (NTMS_READY == partitionInfo.dwOperationalState) &&
  4014. (TRUE == bCheckState)) {
  4015. // Compare capacity to maximum
  4016. if (partitionInfo.Info.Partition.Capacity.QuadPart > *pMaxCapacity) {
  4017. *pMaxCapacity = partitionInfo.Info.Partition.Capacity.QuadPart;
  4018. }
  4019. }
  4020. hr = findNextNtmsObject(hFindPart, &partitionInfo);
  4021. }
  4022. findCloseNtmsObject(hFindPart);
  4023. hr = S_OK;
  4024. // Get out - no need to traverse more pools...
  4025. break;
  4026. }
  4027. hr = findNextNtmsObject(hFindPool, &mediaPoolInfo);
  4028. } // while finding media pools
  4029. findCloseNtmsObject(hFindPool);
  4030. hr = S_OK;
  4031. } WsbCatch(hr);
  4032. WsbTraceOut(OLESTR("CRmsNTMS::GetMaxMediaCapacity"), OLESTR("hr = <%ls>, Max-media-size = %I64d"),
  4033. WsbHrAsString(hr), *pMaxCapacity);
  4034. return(hr);
  4035. }
  4036. STDMETHODIMP
  4037. CRmsNTMS::DisableAndEject(
  4038. IN IRmsCartridge *pCart,
  4039. IN DWORD dwOptions
  4040. )
  4041. /*++
  4042. Implements:
  4043. IRmsNTMS::DisableAndEject
  4044. Notes:
  4045. 1) Currently, the operator request to eject media has a format failure as a reason.
  4046. In the future, the dwOptions parameter could be used to specify other operator requests
  4047. or the method may get a partial text for the operator request from the caller
  4048. 2) The dwOptions is not used at all for now. In the future, it may be used to speficy
  4049. disable-only, other operator requests, etc.
  4050. --*/
  4051. {
  4052. HRESULT hr = S_OK;
  4053. DWORD err1 = NO_ERROR;
  4054. WsbTraceIn(OLESTR("CRmsNTMS::DisableAndEject"), OLESTR(""));
  4055. UNREFERENCED_PARAMETER(dwOptions);
  4056. try {
  4057. WsbAssertPointer(pCart);
  4058. HANDLE hSession = m_SessionHandle;
  4059. DWORD sideNo = 2;
  4060. NTMS_GUID side[2];
  4061. NTMS_GUID mediaId = GUID_NULL;
  4062. WsbAffirmHr(pCart->GetCartridgeId(&mediaId));
  4063. WsbAssert(mediaId != GUID_NULL, E_INVALIDARG);
  4064. // Enumerate to get partition id out of a logical media
  4065. WsbTraceAlways(OLESTR("EnumerateNtmsObject()\n"));
  4066. err1 = EnumerateNtmsObject(hSession, &mediaId, side, &sideNo, NTMS_PARTITION, 0);
  4067. WsbAffirmNoError(err1);
  4068. WsbAssert(side[0] != GUID_NULL, E_INVALIDARG);
  4069. // Get physical media id
  4070. NTMS_OBJECTINFORMATION partInfo;
  4071. partInfo.dwSize = sizeof(NTMS_OBJECTINFORMATION);
  4072. partInfo.dwType = NTMS_PARTITION;
  4073. WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
  4074. err1 = GetNtmsObjectInformation(hSession, &side[0], &partInfo );
  4075. WsbAffirmNoError(err1);
  4076. NTMS_GUID physicalMediaId = partInfo.Info.Partition.PhysicalMedia;
  4077. WsbAssert(physicalMediaId != GUID_NULL, E_INVALIDARG);
  4078. // Disable the media
  4079. WsbTraceAlways(OLESTR("DisableNtmsObject()\n"));
  4080. err1 = DisableNtmsObject(hSession, NTMS_PHYSICAL_MEDIA, &physicalMediaId);
  4081. // Since RSM Disable object is asyncronous, we may need to wait some arbitrary time,
  4082. // in order that when we come back, the media is really disabled
  4083. if (NO_ERROR == err1) {
  4084. DWORD size;
  4085. OLECHAR tmpString[256];
  4086. DWORD waitTime = RMS_DEFAULT_AFTER_DISABLE_WAIT_TIME;
  4087. if (SUCCEEDED(WsbGetRegistryValueString(NULL, RMS_REGISTRY_STRING, RMS_PARAMETER_AFTER_DISABLE_WAIT_TIME, tmpString, 256, &size))) {
  4088. waitTime = wcstol(tmpString, NULL, 10);
  4089. WsbTrace(OLESTR("AfterDisableWaitTime is %d milliseconds.\n"), waitTime);
  4090. }
  4091. Sleep(waitTime);
  4092. }
  4093. // Continue even if there's an error
  4094. if (NO_ERROR != err1) {
  4095. WsbTraceAlways(OLESTR("CRmsNTMS::DisableAndEject: DisableNtmsObject on media %ls failed with error %lu\n"),
  4096. WsbGuidAsString(physicalMediaId), err1);
  4097. }
  4098. // Try to get the slot number for the operator request. ignore error - slot is set to blank
  4099. WCHAR slotNumber[16];
  4100. wcscpy(slotNumber, L" ");
  4101. NTMS_OBJECTINFORMATION mediaInfo;
  4102. mediaInfo.dwSize = sizeof(NTMS_OBJECTINFORMATION);
  4103. mediaInfo.dwType = NTMS_PHYSICAL_MEDIA;
  4104. WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
  4105. err1 = GetNtmsObjectInformation(hSession, &physicalMediaId, &mediaInfo);
  4106. if (NO_ERROR == err1) {
  4107. NTMS_GUID homeSlotId = mediaInfo.Info.PhysicalMedia.HomeSlot;
  4108. NTMS_OBJECTINFORMATION slotInfo;
  4109. slotInfo.dwSize = sizeof(NTMS_OBJECTINFORMATION);
  4110. slotInfo.dwType = NTMS_STORAGESLOT;
  4111. WsbTraceAlways(OLESTR("GetNtmsObjectInformation()\n"));
  4112. err1 = GetNtmsObjectInformation(hSession, &homeSlotId, &slotInfo);
  4113. if (NO_ERROR == err1) {
  4114. swprintf(slotNumber, L"%lu", slotInfo.Info.StorageSlot.Number);
  4115. } else {
  4116. WsbTraceAlways(OLESTR("CRmsNTMS::DisableAndEject: GetNtmsObjectInformation failed for slot %ls with error %lu\n"),
  4117. WsbGuidAsString(homeSlotId), err1);
  4118. }
  4119. } else {
  4120. WsbTraceAlways(OLESTR("CRmsNTMS::DisableAndEject: GetNtmsObjectInformation failed for media %ls with error %lu\n"),
  4121. WsbGuidAsString(physicalMediaId), err1);
  4122. }
  4123. // Get text for the operator request (assume eject due to a format failure for now)
  4124. CWsbBstrPtr cartridgeName;
  4125. WCHAR *messageText = NULL;
  4126. WCHAR *stringArr[2];
  4127. WsbAffirmHr(pCart->GetName(&cartridgeName));
  4128. stringArr[0] = (WCHAR *)cartridgeName;
  4129. stringArr[1] = (WCHAR *)slotNumber;
  4130. WsbAffirmStatus(FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  4131. LoadLibraryEx( WSB_FACILITY_PLATFORM_NAME, NULL, LOAD_LIBRARY_AS_DATAFILE ),
  4132. RMS_MESSAGE_EJECT_BAD_MEDIA_REQUEST, MAKELANGID ( LANG_NEUTRAL, SUBLANG_DEFAULT ),
  4133. (LPTSTR)&messageText, 0, (va_list *)stringArr));
  4134. // Submit an operator request to eject the media
  4135. NTMS_GUID libId = GUID_NULL;
  4136. NTMS_GUID requestId = GUID_NULL;
  4137. WsbTraceAlways(OLESTR("SubmitNtmsOperatorRequest()\n"));
  4138. err1 = SubmitNtmsOperatorRequest(hSession, NTMS_OPREQ_MESSAGE,
  4139. messageText, &physicalMediaId, &libId, &requestId);
  4140. LocalFree(messageText);
  4141. WsbAffirmNoError (err1);
  4142. } WsbCatch(hr);
  4143. WsbTraceOut(OLESTR("CRmsNTMS::DisableAndEject"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  4144. return hr;
  4145. }