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.

5362 lines
179 KiB

  1. /*++
  2. Copyright (c) 1998 Seagate Software, Inc. All rights reserved.
  3. Module Name:
  4. hsmServ.cpp
  5. Abstract:
  6. This component provides the functions to access the HSM
  7. IHsmServer interfaces.
  8. Author:
  9. Cat Brant [cbrant] 24-Jan-1997
  10. Revision History:
  11. Chris Timmes [ctimmes] 11-Sep-1997
  12. - renamed COM method FindStoragePoolById() to FindHSMStoragePoolByMediaSetId()
  13. to better reflect its purpose. Also created new COM method
  14. FindHsmStoragePoolById(). Action required since the Engine maintains 2
  15. sets of (original/master) secondary storage media set ids (GUIDs). First,
  16. the Engine maintains its own 'media set' id, called a Storage Pool id, which
  17. is only maintained by the Engine. Second, the Engine also maintains the NT
  18. Media Services (NTMS) id, called the Media Set id, which comes from NTMS and
  19. is passed to the Engine by RMS (the Remote Storage Subsystem). (Note that the
  20. concept of a Storage Pool encompasses more info than that of a Media Set.)
  21. These 2 lookup functions allow for lookup by either id.
  22. Chris Timmes [ctimmes] 22-Sep-1997
  23. - added new COM methods FindMediaIdByDisplayName() and RecreateMaster(). Changes
  24. made to enable Copy Set usage. Code written to be both Sakkara and Phoenix
  25. compatible.
  26. Chris Timmes [ctimmes] 21-Oct-1997
  27. - added new COM method MarkMediaForRecreation(). Change made to allow
  28. RecreateMaster() to be invokable directly from RsLaunch (without going through
  29. the UI).
  30. Chris Timmes [ctimmes] 18-Nov-1997
  31. - added new COM method CreateTask(). Change made to move NT Task Scheduler task
  32. creation code from the UI to the Engine. Change required to allow Remote
  33. Storage system to run under LocalSystem account. CreateTask() is a generic
  34. method callable by anyone wanting to create any supported type of Remote Storage
  35. task in Task Scheduler.
  36. --*/
  37. #include "stdafx.h"
  38. #include "HsmServ.h"
  39. #include "HsmConn.h"
  40. #include "metalib.h"
  41. #include "task.h"
  42. #include "wsbdb.h"
  43. #include "rsbuild.h"
  44. #include "wsb.h"
  45. #include "ntverp.h" // for GetNtProductVersion() and GetNtProductBuild()
  46. #include "Rms.h"
  47. #include "rsevents.h"
  48. #include "HsmEng.h"
  49. #define WSB_TRACE_IS WSB_TRACE_BIT_HSMENG
  50. #define HSM_PERSIST_FILE "\\RsEng.col"
  51. #define RMS_WIN2K_PERSIST_FILE "\\RsSub.col"
  52. #define DEFAULT_COPYFILES_USER_LIMIT 10
  53. BOOL g_HsmSaveInProcess = FALSE;
  54. /////////////////////////////////////////////////////////////////////////////
  55. //
  56. // Non-member function initially called for autosave thread
  57. static DWORD HsmengStartAutosave(
  58. void* pVoid
  59. )
  60. {
  61. return(((CHsmServer*) pVoid)->Autosave());
  62. }
  63. // Non-member function run in a separate thread to call CheckManagedResources
  64. static DWORD HsmengStartCheckManagedResources(
  65. void* pVoid
  66. )
  67. {
  68. DWORD result;
  69. result = ((CHsmServer*) pVoid)->CheckManagedResources();
  70. return(result);
  71. }
  72. HRESULT
  73. CHsmServer::Autosave(
  74. void
  75. )
  76. /*++
  77. Routine Description:
  78. Implements an autosave loop.
  79. Arguments:
  80. None.
  81. Return Value:
  82. Doesn't matter.
  83. --*/
  84. {
  85. HRESULT hr = S_OK;
  86. ULONG l_autosaveInterval = m_autosaveInterval;
  87. BOOL exitLoop = FALSE;
  88. WsbTraceIn(OLESTR("CHsmServer::Autosave"), OLESTR(""));
  89. try {
  90. while (m_autosaveInterval && (! exitLoop)) {
  91. // Wait for termination event, if timeout occurs, check if we can perform Autosave
  92. switch (WaitForSingleObject(m_terminateEvent, l_autosaveInterval)) {
  93. case WAIT_OBJECT_0:
  94. // Need to terminate
  95. WsbTrace(OLESTR("CHsmServer::Autosave: signaled to terminate\n"));
  96. exitLoop = TRUE;
  97. break;
  98. case WAIT_TIMEOUT:
  99. // Check if backup need to be performed
  100. WsbTrace(OLESTR("CHsmServer::Autosave: Autosave awakened\n"));
  101. // Don't do this if we're suspended
  102. if (!m_Suspended) {
  103. // Save data
  104. // NOTE: Because this is a separate thread, there is the possibility
  105. // of a conflict if the main thread is changing some data at the same
  106. // time we're trying to save it.
  107. // If a save is already happening, just skip this one and
  108. // go back to sleep
  109. hr = SaveAll();
  110. // If the save fails, increase the sleep time to avoid filling
  111. // the event log
  112. if (!SUCCEEDED(hr)) {
  113. if ((MAX_AUTOSAVE_INTERVAL / 2) < l_autosaveInterval) {
  114. l_autosaveInterval = MAX_AUTOSAVE_INTERVAL;
  115. } else {
  116. l_autosaveInterval *= 2;
  117. }
  118. } else {
  119. l_autosaveInterval = m_autosaveInterval;
  120. }
  121. }
  122. break; // end of timeout case
  123. case WAIT_FAILED:
  124. default:
  125. WsbTrace(OLESTR("CHsmServer::Autosave: WaitForSingleObject returned error %lu\n"), GetLastError());
  126. exitLoop = TRUE;
  127. break;
  128. } // end of switch
  129. } // end of while
  130. } WsbCatch(hr);
  131. WsbTraceOut(OLESTR("CHsmServer::Autosave"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  132. return(hr);
  133. }
  134. HRESULT
  135. CHsmServer::GetAutosave(
  136. OUT ULONG* pMilliseconds
  137. )
  138. /*++
  139. Implements:
  140. CHsmServer::GetAutosave().
  141. --*/
  142. {
  143. HRESULT hr = S_OK;
  144. WsbTraceIn(OLESTR("CHsmServer::GetAutosave"), OLESTR(""));
  145. try {
  146. WsbAssert(0 != pMilliseconds, E_POINTER);
  147. *pMilliseconds = m_autosaveInterval;
  148. } WsbCatch(hr);
  149. WsbTraceOut(OLESTR("CHsmServer::GetAutosave"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  150. return(hr);
  151. }
  152. HRESULT
  153. CHsmServer::SetAutosave(
  154. IN ULONG milliseconds
  155. )
  156. /*++
  157. Implements:
  158. CHsmServer::SetAutosave().
  159. --*/
  160. {
  161. HRESULT hr = S_OK;
  162. WsbTraceIn(OLESTR("CHsmServer::SetAutosave"), OLESTR("milliseconds = <%ls>"), WsbPtrToUlongAsString( &milliseconds ) );
  163. try {
  164. // Don't do anything if interval isn't changing
  165. if (milliseconds != m_autosaveInterval) {
  166. // Close the current thread
  167. if (m_autosaveThread) {
  168. StopAutosaveThread();
  169. }
  170. m_autosaveInterval = milliseconds;
  171. // Start/restart the autosave thread
  172. if (m_autosaveInterval) {
  173. DWORD threadId;
  174. WsbAffirm((m_autosaveThread = CreateThread(0, 0, HsmengStartAutosave, (void*) this, 0, &threadId))
  175. != 0, HRESULT_FROM_WIN32(GetLastError()));
  176. }
  177. }
  178. } WsbCatch(hr);
  179. WsbTraceOut(OLESTR("CHsmServer::SetAutosave"), OLESTR("hr = <%ls> m_runInterval = <%ls>"), WsbHrAsString(hr), WsbPtrToUlongAsString( &m_autosaveInterval ) );
  180. return(hr);
  181. }
  182. HRESULT CHsmServer::GetID(
  183. GUID *phid
  184. )
  185. {
  186. if( !phid )
  187. return E_INVALIDARG;
  188. *phid = m_hId;
  189. return S_OK;
  190. }
  191. HRESULT CHsmServer::GetId(
  192. GUID *phid
  193. )
  194. {
  195. return (GetID(phid));
  196. }
  197. HRESULT CHsmServer::SetId(
  198. GUID id
  199. )
  200. {
  201. m_hId = id;
  202. return S_OK;
  203. }
  204. HRESULT
  205. CHsmServer::GetDbPath(
  206. OUT OLECHAR** pPath,
  207. IN ULONG bufferSize
  208. )
  209. /*++
  210. Implements:
  211. IHsmServer::GetDbPath().
  212. --*/
  213. {
  214. HRESULT hr = S_OK;
  215. try {
  216. WsbAssert(0 != pPath, E_POINTER);
  217. WsbAffirmHr(m_dbPath.CopyTo(pPath, bufferSize));
  218. } WsbCatch(hr);
  219. return(hr);
  220. }
  221. HRESULT
  222. CHsmServer::GetDbPathAndName(
  223. OUT OLECHAR** pPath,
  224. IN ULONG bufferSize
  225. )
  226. /*++
  227. Implements:
  228. IHsmServer::GetDbPathAndName().
  229. --*/
  230. {
  231. HRESULT hr = S_OK;
  232. CWsbStringPtr tmpString;
  233. try {
  234. WsbAssert(0 != pPath, E_POINTER);
  235. tmpString = m_dbPath;
  236. WsbAffirmHr(tmpString.Append(HSM_PERSIST_FILE));
  237. WsbAffirmHr(tmpString.CopyTo(pPath, bufferSize));
  238. } WsbCatch(hr);
  239. return(hr);
  240. }
  241. HRESULT
  242. CHsmServer::GetIDbPath(
  243. OUT OLECHAR** pPath,
  244. IN ULONG bufferSize
  245. )
  246. /*++
  247. Routine Description:
  248. Returns the path (directory) for the Engine IDB files
  249. Arguments:
  250. pPath - address of pointer to buffer
  251. bufferSize - size of buffer (or zero)
  252. Return Value:
  253. S_OK - On success
  254. --*/
  255. {
  256. HRESULT hr = S_OK;
  257. try {
  258. CWsbStringPtr temp;
  259. WsbAssert(0 != pPath, E_POINTER);
  260. temp = m_dbPath;
  261. temp.Append(OLESTR("\\"));
  262. temp.Append(ENG_DB_DIRECTORY);
  263. WsbAffirmHr(temp.CopyTo(pPath, bufferSize));
  264. } WsbCatch(hr);
  265. return(hr);
  266. }
  267. HRESULT CHsmServer::GetName (
  268. OLECHAR **ppName
  269. )
  270. {
  271. HRESULT hr = S_OK;
  272. try {
  273. WsbAssert(0 != ppName, E_POINTER);
  274. WsbAffirmHr(m_name.CopyTo(ppName));
  275. } WsbCatch( hr );
  276. return (hr);
  277. }
  278. HRESULT CHsmServer::GetRegistryName (
  279. OLECHAR **pName,
  280. ULONG bufferSize
  281. )
  282. {
  283. HRESULT hr = S_OK;
  284. try {
  285. CWsbStringPtr tmpString;
  286. WsbAssert(0 != pName, E_POINTER);
  287. tmpString = HSM_ENGINE_REGISTRY_NAME;
  288. WsbAffirmHr(tmpString.CopyTo(pName, bufferSize));
  289. } WsbCatch( hr );
  290. return (hr);
  291. }
  292. HRESULT CHsmServer::GetHsmExtVerHi (
  293. SHORT * /*pExtVerHi*/
  294. )
  295. {
  296. return( E_NOTIMPL );
  297. }
  298. HRESULT CHsmServer::GetHsmExtVerLo (
  299. SHORT * /*pExtVerLo*/
  300. )
  301. {
  302. return( E_NOTIMPL );
  303. }
  304. HRESULT CHsmServer::GetHsmExtRev (
  305. SHORT * /*pExtRev*/
  306. )
  307. {
  308. return( E_NOTIMPL );
  309. };
  310. HRESULT CHsmServer::GetManagedResources(
  311. IWsbIndexedCollection **ppCollection
  312. )
  313. {
  314. HRESULT hr = S_OK;
  315. WsbTraceIn(OLESTR("CHsmServer::GetManagedResources"),OLESTR(""));
  316. //
  317. // If the resources have been loaded, return the pointer. Otherwise,
  318. // fail.
  319. try {
  320. WsbAssert(0 != ppCollection, E_POINTER);
  321. *ppCollection = m_pManagedResources;
  322. WsbAffirm(m_pManagedResources != 0, E_FAIL);
  323. m_pManagedResources.p->AddRef();
  324. } WsbCatch(hr);
  325. WsbTraceOut(OLESTR("CHsmServer::GetManagedResources"),OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  326. return (hr);
  327. }
  328. HRESULT CHsmServer::SaveMetaData(
  329. void
  330. )
  331. {
  332. HRESULT hr = S_OK;
  333. WsbTraceIn(OLESTR("CHsmServer::SaveMetaData"), OLESTR(""));
  334. //
  335. // Force a save of all metadata
  336. //
  337. try {
  338. if (m_pSegmentDatabase != 0) {
  339. WsbAffirmHr(StoreSegmentInformation());
  340. }
  341. } WsbCatch(hr);
  342. WsbTraceOut(OLESTR("CHsmServer::SaveMetaData"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  343. return (hr);
  344. }
  345. HRESULT CHsmServer::LoadPersistData(
  346. void
  347. )
  348. {
  349. HRESULT hr = S_OK;
  350. WsbTraceIn(OLESTR("CHsmServer::LoadPersistData"), OLESTR(""));
  351. //
  352. // Create persistent collections and attempt to load from file
  353. //
  354. try {
  355. CComPtr<IWsbServer> pWsbServer;
  356. CWsbStringPtr tmpString;
  357. // Create the collections
  358. WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, 0, CLSCTX_SERVER,
  359. IID_IWsbIndexedCollection, (void **)&m_pJobs ));
  360. WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, 0, CLSCTX_SERVER,
  361. IID_IWsbIndexedCollection, (void **)&m_pJobDefs ));
  362. WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, 0, CLSCTX_SERVER,
  363. IID_IWsbIndexedCollection, (void **)&m_pPolicies ));
  364. WsbAffirmHr(CoCreateInstance(CLSID_CHsmManagedResourceCollection, 0, CLSCTX_SERVER,
  365. IID_IWsbIndexedCollection, (void **)&m_pManagedResources ));
  366. WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, 0, CLSCTX_SERVER,
  367. IID_IWsbIndexedCollection, (void **)&m_pStoragePools ));
  368. WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, 0, CLSCTX_SERVER,
  369. IID_IWsbIndexedCollection, (void **)&m_pMessages ));
  370. // Try to read from the persistence file
  371. // Note: currently Engine doesn't verify the service id in the Registry
  372. // If Engine would ever start without an Fsa in the HSM server process -
  373. // this should be changed
  374. WsbAffirmHr(((IUnknown*) (IHsmServer*) this)->QueryInterface(IID_IWsbServer,
  375. (void**) &pWsbServer));
  376. WsbAffirmHr(WsbServiceSafeInitialize(pWsbServer, FALSE, TRUE, &m_persistWasCreated));
  377. } WsbCatch(hr);
  378. WsbTraceOut(OLESTR("CHsmServer::LoadPersistData"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  379. return (hr);
  380. }
  381. HRESULT CHsmServer::SavePersistData(
  382. void
  383. )
  384. {
  385. HRESULT hr = S_OK;
  386. WsbTraceIn(OLESTR("CHsmServer::SavePersistData"), OLESTR(""));
  387. if (FALSE == g_HsmSaveInProcess) {
  388. g_HsmSaveInProcess = TRUE;
  389. //
  390. // Force a save of all non-meta persistent data
  391. //
  392. hr = InternalSavePersistData();
  393. g_HsmSaveInProcess = FALSE;
  394. } else {
  395. WsbTrace( OLESTR("Save already occurring - so wait"));
  396. while (TRUE == g_HsmSaveInProcess) {
  397. //
  398. // Sleep a half a second then see if flag
  399. // is cleared. We want to wait until the
  400. // save is done before returning.
  401. //
  402. Sleep(500);
  403. }
  404. }
  405. WsbTraceOut(OLESTR("CHsmServer::SavePersistData"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  406. return (hr);
  407. }
  408. HRESULT
  409. CHsmServer::FindHsmStoragePoolById(
  410. IN GUID StoragePoolId,
  411. OUT IHsmStoragePool** ppStoragePool
  412. )
  413. /*++
  414. Implements:
  415. IHsmServer::FindHsmStoragePoolById().
  416. Routine Description:
  417. This routine implements the COM method for looking up an HSM (Engine)
  418. Storage Pool object by the HSM Storage Pool id (a GUID). If found, a
  419. COM interface pointer to that object is returned.
  420. After using the Engine's stored pointer to an indexed collection of valid
  421. storage pools to obtain an iterator (enumerator) to the collection, the
  422. code searches the collection. For each record it obtains that Storage
  423. Pool's interface pointer, which it uses to get that pool's id. Once
  424. it finds the record whose Storage Pool id matches the HSM pool id
  425. passed in, it returns the interface pointer .
  426. Note that with Sakkara there is only 1 storage pool, so a match should be
  427. found on the first (and only) record. However, the code is written to
  428. allow for future enhancements where there may be more than 1 storage pool.
  429. Arguments:
  430. StoragePoolId - The HSM id (GUID) - as opposed to the NTMS id - for the
  431. Storage Pool whose interface pointer is to be returned by this method.
  432. ppStoragePool - a pointer to the Storage Pool Interface Pointer which will
  433. be returned by this method.
  434. Return Value:
  435. S_OK - The call succeeded (the specified storage pool record was found and
  436. its interface pointer was returned to the caller.
  437. Any other value - The call failed. Generally this should only happen if
  438. a matching storage pool record is not found in the storage pool
  439. indexed collection (this error will return HR = 81000001, 'search
  440. of a collection failed', aka WSB_E_NOTFOUND).
  441. --*/
  442. {
  443. // since this code is currently only used by the CopyMedia routines,
  444. // reset the Tracing bit
  445. #undef WSB_TRACE_IS
  446. #define WSB_TRACE_IS WSB_TRACE_BIT_COPYMEDIA
  447. HRESULT hr = S_OK;
  448. GUID poolId = GUID_NULL;
  449. CComPtr<IWsbEnum> pEnum;
  450. CComPtr<IHsmStoragePool> pStoragePool;
  451. WsbTraceIn(OLESTR("CHsmServer::FindHsmStoragePoolById"),
  452. OLESTR("StoragePoolId = <%ls>"), WsbGuidAsString(StoragePoolId));
  453. try {
  454. // ensure the OUT parameter pointer is valid
  455. WsbAssert(0 != ppStoragePool, E_POINTER);
  456. // null out the interface pointer so garbage is not returned
  457. *ppStoragePool = 0;
  458. // obtain an iterator (enumerator) to the indexed storage pool collection
  459. // from the engine's stored storage pool pointer.
  460. WsbAffirmHr(m_pStoragePools->Enum(&pEnum));
  461. // get the first record in the collection. Get that storage pool's id (GUID).
  462. WsbAffirmHr(pEnum->First(IID_IHsmStoragePool, (void**) &pStoragePool));
  463. WsbAffirmHr(pStoragePool->GetId(&poolId));
  464. // if the ids (GUIDs) don't match, iterate through the collection until
  465. // a match is found. Note that no match being found will cause an error
  466. // to be thrown when the Next() call is made after reaching the end of the
  467. // collection.
  468. while (poolId != StoragePoolId) {
  469. pStoragePool.Release();
  470. WsbAffirmHr(pEnum->Next(IID_IHsmStoragePool, (void**) &pStoragePool));
  471. WsbAffirmHr(pStoragePool->GetId(&poolId));
  472. }
  473. // Match found: return requested interface pointer after increasing COM
  474. // ref count
  475. *ppStoragePool = pStoragePool;
  476. if (pStoragePool != 0) {
  477. (*ppStoragePool)->AddRef();
  478. }
  479. } WsbCatch(hr);
  480. WsbTraceOut(OLESTR("CHsmServer::FindHsmStoragePoolById"),
  481. OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  482. return(hr);
  483. // leaving CopyMedia code, so reset Tracing bit to the Hsm Engine
  484. #undef WSB_TRACE_IS
  485. #define WSB_TRACE_IS WSB_TRACE_BIT_HSMENG
  486. }
  487. HRESULT
  488. CHsmServer::FindHsmStoragePoolByMediaSetId(
  489. IN GUID RmsMediaSetId,
  490. OUT IHsmStoragePool** ppStoragePool
  491. )
  492. /*++
  493. Implements:
  494. IHsmServer::FindHsmStoragePoolByMediaSetId().
  495. Routine Description:
  496. This routine implements the COM method for looking up an HSM (Engine)
  497. Storage Pool object by the remote media subsystem Media Set id (a GUID which
  498. comes from NTMS in the case where tape is used as secondary storage). If found,
  499. a COM interface pointer to that object is returned.
  500. After using the Engine's stored pointer to an indexed collection of valid
  501. storage pools to obtain an iterator (enumerator) to the collection, the
  502. code searches the collection. For each record it obtains that Storage
  503. Pool's interface pointer, which it uses to get that pool's media set id.
  504. Once it finds the record whose Media Set (Storage Pool) id matches the media
  505. set id passed in, it returns that record's interface pointer.
  506. Note that with Sakkara there is only 1 storage pool, so a match should be
  507. found on the first (and only) record. However, the code is written to
  508. allow for future enhancements where there may be more than 1 storage pool.
  509. Arguments:
  510. MediaSetId - The Remote Storage Subsystem id (GUID) - as opposed to the Engine's
  511. local HSM id - for the Storage Pool (referred to by the subsystem as a
  512. Media Set) whose interface pointer is to be returned by this method.
  513. ppStoragePool - a pointer to the Storage Pool Interface Pointer which will
  514. be returned by this method.
  515. Return Value:
  516. S_OK - The call succeeded (the specified storage pool record was found and
  517. its interface pointer was returned to the caller).
  518. Any other value - The call failed. Generally this should only happen if
  519. a matching storage pool record is not found in the storage pool
  520. indexed collection (this error will return HR = 81000001, 'search
  521. of a collection failed', aka WSB_E_NOTFOUND).
  522. --*/
  523. {
  524. // since this code is currently only used by the CopyMedia routines,
  525. // reset the Tracing bit
  526. #undef WSB_TRACE_IS
  527. #define WSB_TRACE_IS WSB_TRACE_BIT_COPYMEDIA
  528. HRESULT hr = S_OK;
  529. GUID mediaSetId = GUID_NULL;
  530. CWsbBstrPtr mediaSetName;
  531. CComPtr<IWsbEnum> pEnum;
  532. CComPtr<IHsmStoragePool> pStoragePool;
  533. WsbTraceIn(OLESTR("CHsmServer::FindHsmStoragePoolByMediaSetId"),
  534. OLESTR("RmsMediaSetId = <%ls>"), WsbGuidAsString(RmsMediaSetId));
  535. try {
  536. // ensure OUT parameter is valid
  537. WsbAssert(0 != ppStoragePool, E_POINTER);
  538. // null out the returned interface pointer so garbage is not returned
  539. *ppStoragePool = 0;
  540. // obtain an iterator (enumerator) to the indexed storage pool collection
  541. WsbAffirmHr(m_pStoragePools->Enum(&pEnum));
  542. // Get first record in the collection and its Remote Storage Subsystem
  543. // Media Set GUID using its interface pointer.
  544. WsbAffirmHr(pEnum->First(IID_IHsmStoragePool, (void**) &pStoragePool));
  545. WsbAffirmHr(pStoragePool->GetMediaSet(&mediaSetId, &mediaSetName));
  546. // if the ids (GUIDs) don't match, iterate through the collection until
  547. // a match is found. Note that no match being found will cause an error
  548. // to be thrown when the Next() call is made after reaching the end of the
  549. // collection.
  550. while (mediaSetId != RmsMediaSetId) {
  551. pStoragePool.Release();
  552. WsbAffirmHr(pEnum->Next(IID_IHsmStoragePool, (void**) &pStoragePool));
  553. mediaSetName.Free();
  554. WsbAffirmHr(pStoragePool->GetMediaSet(&mediaSetId, &mediaSetName));
  555. }
  556. // Match found: return the requested interface pointer after increasing COM
  557. // ref count.
  558. *ppStoragePool = pStoragePool;
  559. if (pStoragePool != 0) {
  560. (*ppStoragePool)->AddRef();
  561. }
  562. } WsbCatch(hr);
  563. WsbTraceOut(OLESTR("CHsmServer::FindHsmStoragePoolByMediaSetId"),
  564. OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  565. return(hr);
  566. // leaving CopyMedia code, so reset Tracing bit to the Hsm Engine
  567. #undef WSB_TRACE_IS
  568. #define WSB_TRACE_IS WSB_TRACE_BIT_HSMENG
  569. }
  570. HRESULT
  571. CHsmServer::FindMediaIdByDescription(
  572. IN OLECHAR* description,
  573. OUT GUID* pMediaId
  574. )
  575. /*++
  576. Implements:
  577. IHsmServer::FindMediaIdByDescription().
  578. Routine Description:
  579. This routine implements the COM method for looking up the secondary storage
  580. master media's id (a GUID) by its description (display name). Both the id and
  581. description are fields stored in the Engine's MediaInfo database. (The MediaInfo
  582. database is actually a separate entity stored within the Engine's Segment database.)
  583. After opening the Engine's Segment database and getting the MediaInfo entity,
  584. the routine loops through the MediaInfo records to find the one whose Description
  585. matches that passed into this method. When it finds the matching record
  586. it gets and returns that record's media id. Any error conditions encountered
  587. result in the appropriate error HRESULT being thrown and returned to the caller.
  588. Arguments:
  589. description - Originally called the media's 'name', then the 'display name', later
  590. clarified to be the media's 'description', this is what is displayed in the
  591. UI to identify the Remote Storage secondary storage (master) media.
  592. pMediaId - a pointer to the media's id (a GUID) for that media whose description
  593. matches the one passed in as the first argument above.
  594. Return Value:
  595. S_OK - The call succeeded (the specified media record was found and a pointer to
  596. its id was returned to the caller.
  597. E_POINTER - Returned if an invalid pointer was passed in as the 'pMediaId' argument.
  598. WSB_E_NOTFOUND - Value 81000001. Returned if no media info record was found whose
  599. description matched the one passed in.
  600. Any other value - The call failed because one of the Remote Storage API calls
  601. contained internally in this method failed. The error value returned is
  602. specific to the API call which failed.
  603. --*/
  604. {
  605. // since this code is currently only used by the CopyMedia routines,
  606. // reset the Tracing bit from this source module's default setting
  607. #undef WSB_TRACE_IS
  608. #define WSB_TRACE_IS WSB_TRACE_BIT_COPYMEDIA
  609. HRESULT hr = S_OK;
  610. CWsbStringPtr mediaDescription;
  611. CComPtr<IWsbDbSession> pDbSession;
  612. CComPtr<IMediaInfo> pMediaInfo;
  613. WsbTraceIn( OLESTR("CHsmServer::FindMediaIdByDescription"),
  614. OLESTR("description = <%ls>"), description );
  615. try {
  616. // ensure OUT parameter is valid
  617. WsbAssert( pMediaId != 0, E_POINTER );
  618. // null out the returned value so garbage is not returned
  619. *pMediaId = GUID_NULL;
  620. // open Engine's Segment database
  621. WsbAffirmHr(m_pSegmentDatabase->Open(&pDbSession));
  622. try {
  623. // get an interface pointer to the MediaInfo entity (records) in the
  624. // Segment database.
  625. WsbAffirmHr(m_pSegmentDatabase->GetEntity( pDbSession, HSM_MEDIA_INFO_REC_TYPE,
  626. IID_IMediaInfo, (void**) &pMediaInfo ));
  627. // Get the first media record and its description
  628. WsbAffirmHr( pMediaInfo->First() );
  629. WsbAffirmHr( pMediaInfo->GetDescription( &mediaDescription, 0 ) );
  630. // Iterate through all media records until a record is found with a matching
  631. // description. Since an architectural feature of HSM is that all
  632. // descriptions (display names) are unique, even across storage pools,
  633. // a match means we found the media record we want. Note that no match
  634. // being found will cause an error to be thrown when the Next() call is
  635. // made after reaching the last media record.
  636. // check for description (display name) match (CASE INSENSITIVE)
  637. while ( _wcsicmp( description, mediaDescription ) != 0 ) {
  638. WsbAffirmHr( pMediaInfo->Next() );
  639. WsbAffirmHr( pMediaInfo->GetDescription( &mediaDescription, 0 ));
  640. }
  641. // We found the record we want. Get that media's id for return
  642. WsbAffirmHr( pMediaInfo->GetId( pMediaId ));
  643. } WsbCatch (hr); // 'try' to get MediaInfo entity and main processing body
  644. // close the database
  645. WsbAffirmHr( m_pSegmentDatabase->Close( pDbSession ));
  646. } WsbCatch (hr); // 'try' to open the Segment database
  647. // Done. Interface pointers used above are singly assigned smart pointers so
  648. // don't explicitly Release() them. They will do auto-garbage collection.
  649. WsbTraceOut(OLESTR("CHsmServer::FindMediaIdByDescription"),
  650. OLESTR("hr = <%ls>, media id = <%ls>"),
  651. WsbHrAsString(hr), WsbGuidAsString(*pMediaId));
  652. return(hr);
  653. // leaving CopyMedia code, reset Tracing bit to Hsm Engine (default for this module)
  654. #undef WSB_TRACE_IS
  655. #define WSB_TRACE_IS WSB_TRACE_BIT_HSMENG
  656. }
  657. HRESULT
  658. CHsmServer::FindStoragePoolByName(
  659. IN OLECHAR* name,
  660. OUT IHsmStoragePool** ppStoragePool
  661. )
  662. /*++
  663. Implements:
  664. IHsmServer::FindStoragePoolByName().
  665. --*/
  666. {
  667. // since this code is currently only used by the CopyMedia routines,
  668. // reset the Tracing bit
  669. #undef WSB_TRACE_IS
  670. #define WSB_TRACE_IS WSB_TRACE_BIT_COPYMEDIA
  671. HRESULT hr = S_OK;
  672. GUID id;
  673. CWsbStringPtr storagePoolName;
  674. CComPtr<IWsbCollection> pCollection;
  675. CComPtr<IWsbEnum> pEnum;
  676. CComPtr<IHsmStoragePool> pStoragePool;
  677. WsbTraceIn(OLESTR("CHsmServer::FindStoragePoolByName"), OLESTR("name = <%ls>"), name);
  678. try {
  679. WsbAssert(0 != ppStoragePool, E_POINTER);
  680. *ppStoragePool = 0;
  681. WsbAffirmHr(m_pStoragePools->QueryInterface(IID_IWsbCollection, (void**) &pCollection));
  682. WsbAffirmHr(pCollection->Enum(&pEnum));
  683. WsbAffirmHr(pEnum->First(IID_IHsmStoragePool, (void**) &pStoragePool));
  684. WsbAffirmHr(pStoragePool->GetMediaSet(&id, &storagePoolName));
  685. while (_wcsicmp(name, storagePoolName) != 0) {
  686. pStoragePool = 0;
  687. WsbAffirmHr(pEnum->Next(IID_IHsmStoragePool, (void**) &pStoragePool));
  688. storagePoolName.Free();
  689. WsbAffirmHr(pStoragePool->GetMediaSet(&id, &storagePoolName));
  690. }
  691. *ppStoragePool = pStoragePool;
  692. if (pStoragePool != 0) {
  693. (*ppStoragePool)->AddRef();
  694. }
  695. } WsbCatch(hr);
  696. WsbTraceOut(OLESTR("CHsmServer::FindStoragePoolByName"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  697. return(hr);
  698. // leaving CopyMedia code, so reset Tracing bit to the Hsm Engine
  699. #undef WSB_TRACE_IS
  700. #define WSB_TRACE_IS WSB_TRACE_BIT_HSMENG
  701. }
  702. HRESULT CHsmServer::GetStoragePools(
  703. IWsbIndexedCollection **ppCollection
  704. )
  705. {
  706. HRESULT hr = S_OK;
  707. //
  708. // If the pools have been loaded, return the pointer. Otherwise,
  709. // fail.
  710. try {
  711. WsbAssert(0 != ppCollection, E_POINTER);
  712. *ppCollection = m_pStoragePools;
  713. WsbAffirm(m_pStoragePools != 0, E_FAIL);
  714. m_pStoragePools.p->AddRef();
  715. } WsbCatch(hr);
  716. return (hr);
  717. }
  718. HRESULT CHsmServer::GetOnlineInformation(
  719. IWsbIndexedCollection **ppCollection
  720. )
  721. {
  722. HRESULT hr = S_OK;
  723. //
  724. // If the online information has been loaded, return it
  725. // Otherwise, fail.
  726. try {
  727. WsbAssert(0 != ppCollection, E_POINTER);
  728. *ppCollection = m_pOnlineInformation;
  729. WsbAffirm(m_pOnlineInformation != 0, E_FAIL);
  730. m_pOnlineInformation.p->AddRef();
  731. } WsbCatch(hr);
  732. return (hr);
  733. }
  734. HRESULT CHsmServer::GetMountingMedias(
  735. IWsbIndexedCollection **ppCollection
  736. )
  737. {
  738. HRESULT hr = S_OK;
  739. try {
  740. WsbAssert(0 != ppCollection, E_POINTER);
  741. *ppCollection = m_pMountingMedias;
  742. WsbAffirm(m_pMountingMedias != 0, E_FAIL);
  743. m_pMountingMedias.p->AddRef();
  744. } WsbCatch(hr);
  745. return (hr);
  746. }
  747. HRESULT CHsmServer::GetMessages(
  748. IWsbIndexedCollection **ppCollection
  749. )
  750. {
  751. HRESULT hr = S_OK;
  752. //
  753. // If messages have been loaded, return them.
  754. // Otherwise, fail.
  755. try {
  756. WsbAssert(0 != ppCollection, E_POINTER);
  757. *ppCollection = m_pMessages;
  758. WsbAffirm(m_pMessages != 0, E_FAIL);
  759. m_pMessages.p->AddRef();
  760. } WsbCatch(hr);
  761. return (hr);
  762. }
  763. HRESULT CHsmServer::GetUsrToNotify(
  764. IWsbIndexedCollection** /*ppCollection*/
  765. )
  766. {
  767. return E_NOTIMPL;
  768. }
  769. HRESULT CHsmServer::GetJobs(
  770. IWsbIndexedCollection **ppCollection
  771. )
  772. {
  773. HRESULT hr = S_OK;
  774. //
  775. // If the jobs have been loaded, return the pointer. Otherwise,
  776. // fail.
  777. try {
  778. WsbAssert(0 != ppCollection, E_POINTER);
  779. *ppCollection = m_pJobs;
  780. WsbAffirm(m_pJobs != 0, E_FAIL);
  781. m_pJobs.p->AddRef();
  782. } WsbCatch(hr);
  783. return (hr);
  784. }
  785. HRESULT
  786. CHsmServer::FindJobByName(
  787. IN OLECHAR* name,
  788. OUT IHsmJob** ppJob
  789. )
  790. /*++
  791. Implements:
  792. IHsmServer::FindJobByName().
  793. --*/
  794. {
  795. HRESULT hr = S_OK;
  796. CWsbStringPtr jobName;
  797. CComPtr<IWsbCollection> pCollection;
  798. CComPtr<IWsbEnum> pEnum;
  799. CComPtr<IHsmJob> pJob;
  800. WsbTraceIn(OLESTR("CHsmServer::FindJobByName"), OLESTR("name = <%ls>"), name);
  801. try {
  802. WsbAssert(0 != ppJob, E_POINTER);
  803. *ppJob = 0;
  804. WsbAffirmHr(m_pJobs->QueryInterface(IID_IWsbCollection, (void**) &pCollection));
  805. WsbAffirmHr(pCollection->Enum(&pEnum));
  806. hr = pEnum->First(IID_IHsmJob, (void**) &pJob);
  807. while (S_OK == hr) {
  808. WsbAffirmHr(pJob->GetName(&jobName, 0));
  809. WsbTrace(OLESTR("CHsmServer::FindJobByName: name = <%ls>\n"),
  810. jobName);
  811. if (_wcsicmp(name, jobName) == 0) break;
  812. pJob = 0;
  813. hr = pEnum->Next(IID_IHsmJob, (void**) &pJob);
  814. }
  815. if (S_OK == hr) {
  816. *ppJob = pJob;
  817. if (pJob != 0) {
  818. (*ppJob)->AddRef();
  819. }
  820. }
  821. } WsbCatch(hr);
  822. WsbTraceOut(OLESTR("CHsmServer::FindJobByName"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  823. return(hr);
  824. }
  825. HRESULT CHsmServer::GetJobDefs(
  826. IWsbIndexedCollection **ppCollection
  827. )
  828. {
  829. HRESULT hr = S_OK;
  830. //
  831. // If the job definitions have been loaded, return the pointer. Otherwise,
  832. // fail.
  833. try {
  834. WsbAssert(0 != ppCollection, E_POINTER);
  835. *ppCollection = m_pJobDefs;
  836. WsbAffirm(m_pJobDefs != 0, E_FAIL);
  837. m_pJobDefs.p->AddRef();
  838. } WsbCatch(hr);
  839. return (hr);
  840. }
  841. HRESULT CHsmServer::GetMediaRecs(
  842. IWsbIndexedCollection **ppCollection
  843. )
  844. {
  845. HRESULT hr = S_OK;
  846. WsbTraceIn(OLESTR("CHsmServer::GetMediaRecs"), OLESTR(""));
  847. try {
  848. HRESULT hr2;
  849. CComPtr<IWsbIndexedCollection> pCol;
  850. CComPtr<IWsbDbSession> pDbSes;
  851. CComPtr<IWsbDbEntity> pRec;
  852. WsbAffirm(m_pSegmentDatabase != 0, E_FAIL);
  853. WsbAssert(0 != ppCollection, E_POINTER);
  854. WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, 0, CLSCTX_SERVER,
  855. IID_IWsbIndexedCollection, (void **)&pCol ));
  856. WsbAffirmHr(m_pSegmentDatabase->Open(&pDbSes));
  857. WsbAffirmHr(m_pSegmentDatabase->GetEntity(pDbSes, HSM_MEDIA_INFO_REC_TYPE,
  858. IID_IWsbDbEntity, (void**)&pRec));
  859. // Loop over records in DB and copy to collection
  860. hr2 = pRec->First();
  861. while(S_OK == hr2) {
  862. CComPtr<IMediaInfo> pCopy;
  863. CComPtr<IMediaInfo> pOrig;
  864. GUID MediaId;
  865. GUID MediaSubsystemId;
  866. GUID StoragePoolId;
  867. LONGLONG FreeBytes;
  868. LONGLONG Capacity;
  869. HRESULT LastError;
  870. short NextRemoteDataSet;
  871. OLECHAR * pDescription = NULL;
  872. HSM_JOB_MEDIA_TYPE Type;
  873. OLECHAR * pName = NULL;
  874. BOOL ReadOnly;
  875. FILETIME Update;
  876. LONGLONG LogicalValidBytes;
  877. BOOL Recreate;
  878. // Create a copy for the collection
  879. WsbAffirmHr(CoCreateInstance(CLSID_CMediaInfo, NULL, CLSCTX_ALL,
  880. IID_IMediaInfo, (void**) &pCopy));
  881. // Copy data
  882. WsbAffirmHr(pRec->QueryInterface(IID_IMediaInfo, (void**)&pOrig));
  883. WsbAffirmHr(pOrig->GetMediaInfo(&MediaId, &MediaSubsystemId,
  884. &StoragePoolId, &FreeBytes, &Capacity, &LastError, &NextRemoteDataSet,
  885. &pDescription, 0, &Type, &pName, 0, &ReadOnly, &Update, &LogicalValidBytes,
  886. &Recreate));
  887. WsbTrace(OLESTR("CHsmServer::GetMediaRecs: after GetMediaInfo\n"));
  888. WsbAffirmHr(pCopy->SetMediaInfo(MediaId, MediaSubsystemId,
  889. StoragePoolId, FreeBytes, Capacity, LastError, NextRemoteDataSet,
  890. pDescription, Type, pName, ReadOnly, Update, LogicalValidBytes,
  891. Recreate));
  892. WsbTrace(OLESTR("CHsmServer::GetMediaRecs: after SetMediaInfo\n"));
  893. if (pDescription) {
  894. WsbFree(pDescription);
  895. pDescription = NULL;
  896. }
  897. if (pName) {
  898. WsbFree(pName);
  899. pName = NULL;
  900. }
  901. WsbAffirmHr(pCol->Add(pCopy));
  902. hr2 = pRec->Next();
  903. }
  904. WsbAffirm(WSB_E_NOTFOUND == hr2, hr2);
  905. *ppCollection = pCol;
  906. pCol.p->AddRef();
  907. } WsbCatch(hr);
  908. WsbTraceOut(OLESTR("CHsmServer::GetMediaRecs"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  909. return (hr);
  910. }
  911. HRESULT CHsmServer::GetPolicies(
  912. IWsbIndexedCollection **ppCollection
  913. )
  914. {
  915. HRESULT hr = S_OK;
  916. //
  917. // If the policies have been loaded, return the pointer. Otherwise,
  918. // fail.
  919. try {
  920. WsbAssert(0 != ppCollection, E_POINTER);
  921. *ppCollection = m_pPolicies;
  922. WsbAffirm(m_pPolicies != 0, E_FAIL);
  923. m_pPolicies.p->AddRef();
  924. } WsbCatch(hr);
  925. return (hr);
  926. }
  927. HRESULT CHsmServer::GetActions(
  928. IWsbIndexedCollection** /*ppCollection*/
  929. )
  930. {
  931. return E_NOTIMPL;
  932. }
  933. HRESULT CHsmServer::GetCriteria(
  934. IWsbIndexedCollection** /*ppCollection*/
  935. )
  936. {
  937. return E_NOTIMPL;
  938. }
  939. HRESULT CHsmServer::GetSegmentDb(
  940. IWsbDb **ppDb
  941. )
  942. {
  943. HRESULT hr = S_OK;
  944. //
  945. // If the segment table has been created, return the pointer. Otherwise,
  946. // fail.
  947. try {
  948. WsbAssert(0 != ppDb, E_POINTER);
  949. WsbAffirm(m_pSegmentDatabase != 0, E_FAIL);
  950. *ppDb = m_pSegmentDatabase;
  951. m_pSegmentDatabase.p->AddRef();
  952. } WsbCatch(hr);
  953. return (hr);
  954. }
  955. HRESULT CHsmServer::GetHsmFsaTskMgr(
  956. IHsmFsaTskMgr **ppHsmFsaTskMgr
  957. )
  958. {
  959. HRESULT hr = S_OK;
  960. //
  961. // If the Task Manager has been created, return the pointer. Otherwise,
  962. // fail.
  963. try {
  964. WsbAssert(0 != ppHsmFsaTskMgr, E_POINTER);
  965. *ppHsmFsaTskMgr = m_pHsmFsaTskMgr;
  966. WsbAffirm(m_pHsmFsaTskMgr != 0, E_FAIL);
  967. m_pHsmFsaTskMgr.p->AddRef();
  968. } WsbCatch(hr);
  969. return (hr);
  970. }
  971. HRESULT
  972. CHsmServer::CreateInstance (
  973. REFCLSID rclsid,
  974. REFIID riid,
  975. void **ppv
  976. )
  977. {
  978. HRESULT hr = S_OK;
  979. hr = CoCreateInstance( rclsid, NULL, CLSCTX_SERVER, riid, ppv );
  980. return hr;
  981. }
  982. HRESULT CHsmServer::FinalConstruct(
  983. )
  984. {
  985. HRESULT hr = S_OK;
  986. WsbTraceIn(OLESTR("CHsmServer::FinalConstruct"), OLESTR(""));
  987. //
  988. // Initialize member data
  989. //
  990. m_pRssWriter = NULL;
  991. m_savingEvent = NULL;
  992. m_terminateEvent = NULL;
  993. m_hId = GUID_NULL;
  994. m_initializationCompleted = FALSE;
  995. m_persistWasCreated = FALSE;
  996. m_mediaCount = 0;
  997. m_copyfilesUserLimit = DEFAULT_COPYFILES_USER_LIMIT;
  998. m_autosaveThread = 0;
  999. m_CheckManagedResourcesThread = 0;
  1000. m_cancelCopyMedia = FALSE;
  1001. m_inCopyMedia = FALSE;
  1002. m_Suspended = FALSE;
  1003. m_JobsEnabled = TRUE;
  1004. try {
  1005. m_bCritSecCreated = FALSE;
  1006. WsbAffirmStatus(InitializeCriticalSectionAndSpinCount(&m_JobDisableLock, 1000));
  1007. if (! InitializeCriticalSectionAndSpinCount(&m_MountingMediasLock, 1000)) {
  1008. DWORD dwErr = GetLastError();
  1009. hr = HRESULT_FROM_WIN32(dwErr);
  1010. DeleteCriticalSection(&m_JobDisableLock);
  1011. WsbAffirmHr(hr);
  1012. }
  1013. m_bCritSecCreated = TRUE;
  1014. WsbAffirmHr(CWsbPersistable::FinalConstruct( ));
  1015. } WsbCatch(hr);
  1016. WsbTraceOut(OLESTR("CHsmServer::FinalConstruct"), OLESTR("hr = <%ls>\n"), WsbHrAsString(hr));
  1017. return( hr );
  1018. }
  1019. void CHsmServer::FinalRelease(
  1020. )
  1021. {
  1022. WsbTraceIn(OLESTR("CHsmServer::FinalRelease"), OLESTR(""));
  1023. if (TRUE == m_initializationCompleted) {
  1024. HSM_SYSTEM_STATE SysState;
  1025. SysState.State = HSM_STATE_SHUTDOWN;
  1026. ChangeSysState(&SysState);
  1027. } else {
  1028. WsbTrace(OLESTR("CHsmServer::FinalRelease not saving persistent information.\n"));
  1029. }
  1030. // Let the parent class do his thing.
  1031. CWsbPersistable::FinalRelease();
  1032. if (m_bCritSecCreated) {
  1033. DeleteCriticalSection(&m_JobDisableLock);
  1034. DeleteCriticalSection(&m_MountingMediasLock);
  1035. }
  1036. // Free String members
  1037. // Note: Member objects held in smart-pointers are freed when the
  1038. // smart-pointer destructor is being called (as part of this object destruction)
  1039. m_name.Free();
  1040. m_dir.Free();
  1041. m_dbPath.Free();
  1042. if (m_terminateEvent != NULL) {
  1043. CloseHandle(m_terminateEvent);
  1044. m_terminateEvent = NULL;
  1045. }
  1046. // Cleanup the writer
  1047. if (m_pRssWriter != NULL) {
  1048. m_pRssWriter->Terminate();
  1049. delete m_pRssWriter;
  1050. m_pRssWriter = NULL;
  1051. }
  1052. // Clean up database system
  1053. if (m_pDbSys != NULL) {
  1054. m_pDbSys->Terminate();
  1055. }
  1056. if (m_savingEvent != NULL) {
  1057. CloseHandle(m_savingEvent);
  1058. m_savingEvent = NULL;
  1059. }
  1060. WsbTraceOut(OLESTR("CHsmServer::FinalRelease"), OLESTR(""));
  1061. }
  1062. HRESULT
  1063. CHsmServer::GetClassID(
  1064. OUT CLSID* pClsid
  1065. )
  1066. /*++
  1067. Implements:
  1068. IPersist::GetClassID().
  1069. --*/
  1070. {
  1071. HRESULT hr = S_OK;
  1072. WsbTraceIn(OLESTR("CHsmServer::GetClassID"), OLESTR(""));
  1073. try {
  1074. WsbAssert(0 != pClsid, E_POINTER);
  1075. *pClsid = CLSID_HsmServer;
  1076. } WsbCatch(hr);
  1077. WsbTraceOut(OLESTR("CHsmServer::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid));
  1078. return(hr);
  1079. }
  1080. HRESULT CHsmServer::Init(
  1081. void
  1082. )
  1083. {
  1084. HRESULT hr = S_OK;
  1085. WsbTraceIn(OLESTR("CHsmServer::Init"),OLESTR(""));
  1086. try {
  1087. CComPtr<IPersistFile> pPersistFile;
  1088. DWORD threadId;
  1089. CWsbStringPtr tmpString;
  1090. LUID backupValue;
  1091. HANDLE tokenHandle;
  1092. TOKEN_PRIVILEGES newState;
  1093. DWORD lErr;
  1094. HANDLE pHandle;
  1095. // Get our Name
  1096. WsbAffirmHr(WsbGetComputerName(m_name));
  1097. // Set the build and database parameters
  1098. WsbAffirmHr(WsbGetMetaDataPath(m_dbPath));
  1099. m_databaseVersion = ENGINE_CURRENT_DB_VERSION;
  1100. m_buildVersion = RS_BUILD_VERSION;
  1101. // Set the autosave parameters.
  1102. m_autosaveInterval = DEFAULT_AUTOSAVE_INTERVAL;
  1103. m_autosaveThread = 0;
  1104. // Enable the backup operator privilege. This is required to insure that we
  1105. // have full access to all resources on the system.
  1106. pHandle = GetCurrentProcess();
  1107. WsbAffirmStatus(OpenProcessToken(pHandle, MAXIMUM_ALLOWED, &tokenHandle));
  1108. // adjust backup token privileges
  1109. WsbAffirmStatus(LookupPrivilegeValueW(NULL, L"SeBackupPrivilege", &backupValue));
  1110. newState.PrivilegeCount = 1;
  1111. newState.Privileges[0].Luid = backupValue;
  1112. newState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  1113. WsbAffirmStatus(AdjustTokenPrivileges(tokenHandle, FALSE, &newState, (DWORD)0, NULL, NULL));
  1114. // Note that AdjustTokenPrivileges may return success even if it did not assign all privileges.
  1115. // We check last error here to insure everything was set.
  1116. if ((lErr = GetLastError()) != ERROR_SUCCESS) {
  1117. // Not backup user or some other error
  1118. //
  1119. // TODO: Should we fail here or just log something?
  1120. WsbLogEvent( HSM_MESSAGE_SERVICE_UNABLE_TO_SET_BACKUP_PRIVILEGE, 0, NULL,
  1121. WsbHrAsString(HRESULT_FROM_WIN32(lErr)), NULL );
  1122. }
  1123. WsbAffirmStatus(LookupPrivilegeValueW(NULL, L"SeRestorePrivilege", &backupValue));
  1124. newState.PrivilegeCount = 1;
  1125. newState.Privileges[0].Luid = backupValue;
  1126. newState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  1127. WsbAffirmStatus(AdjustTokenPrivileges(tokenHandle, FALSE, &newState, (DWORD)0, NULL, NULL));
  1128. // Note that AdjustTokenPrivileges may return success even if it did not assign all privileges.
  1129. // We check last error here to insure everything was set.
  1130. if ((lErr = GetLastError()) != ERROR_SUCCESS) {
  1131. // Not backup user or some other error
  1132. //
  1133. // TODO: Should we fail here or just log something?
  1134. WsbLogEvent( HSM_MESSAGE_SERVICE_UNABLE_TO_SET_RESTORE_PRIVILEGE, 0, NULL,
  1135. WsbHrAsString(HRESULT_FROM_WIN32(lErr)), NULL );
  1136. }
  1137. CloseHandle(tokenHandle);
  1138. // Create the Writer
  1139. m_pRssWriter = new CRssJetWriter;
  1140. WsbAffirm(NULL != m_pRssWriter, E_OUTOFMEMORY);
  1141. // Open the event that synchronize saving of persistent data with snapshots
  1142. // (Event should already exist - it is created in the CRssJetWriter constructor
  1143. WsbAffirmHandle(m_savingEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, HSM_ENGINE_STATE_EVENT));
  1144. //
  1145. // Create one instance of the Media Server Interface
  1146. // (It must be created before the persistent data is loaded.
  1147. //
  1148. WsbTrace(OLESTR("Creating Rsm Server member.\n"));
  1149. WsbAffirmHr(CoCreateInstance(CLSID_CRmsServer, NULL, CLSCTX_SERVER,
  1150. IID_IRmsServer, (void**)&m_pHsmMediaMgr));
  1151. //
  1152. // Load the persistent information
  1153. //
  1154. WsbTrace(OLESTR("Loading Persistent Information.\n"));
  1155. WsbAffirmHr(LoadPersistData());
  1156. // Create mounting-medias collection - Note: this collection is not persistent!
  1157. WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, 0, CLSCTX_SERVER,
  1158. IID_IWsbIndexedCollection, (void **)&m_pMountingMedias));
  1159. // Initialize the Media Server object
  1160. WsbAffirmHr(m_pHsmMediaMgr->InitializeInAnotherThread());
  1161. // Initialize the IDB system for this process
  1162. WsbAffirmHr(CoCreateInstance(CLSID_CWsbDbSys, NULL, CLSCTX_SERVER,
  1163. IID_IWsbDbSys, (void**) &m_pDbSys));
  1164. WsbAffirmHr(GetIDbPath(&tmpString, 0));
  1165. WsbAffirmHr(m_pDbSys->Init(tmpString, IDB_SYS_INIT_FLAG_FULL_LOGGING));
  1166. // Start automatic backup of DBs
  1167. WsbAffirmHr(m_pDbSys->Backup(NULL, IDB_BACKUP_FLAG_AUTO));
  1168. // Initialize Rss Writer
  1169. WsbAffirmHr(m_pRssWriter->Init());
  1170. WsbTrace(OLESTR("Loading Segment Information.\n"));
  1171. WsbAffirmHr(LoadSegmentInformation());
  1172. WsbAffirmHr(CreateDefaultJobs());
  1173. WsbTrace(OLESTR("CreateDefaultJobs OK\n"));
  1174. //
  1175. // Create one instance of the Hsm Task Manager Interface and one instance
  1176. // of the Hsm Fsa Task Manager Interface
  1177. //
  1178. WsbTrace(OLESTR("Creating Task Manager.\n"));
  1179. WsbAffirmHr(CoCreateInstance( CLSID_CHsmTskMgr, 0, CLSCTX_SERVER,
  1180. IID_IHsmFsaTskMgr, (void **)&m_pHsmFsaTskMgr ));
  1181. WsbAffirmHr(m_pHsmFsaTskMgr->Init((IUnknown*) (IHsmServer*) this));
  1182. //
  1183. // Tell the world that we are here
  1184. //
  1185. // Currently, avoid publishing HSM in the AD - if this becomes necessary,
  1186. // remove the comments from the following code
  1187. //
  1188. /*** WsbAffirmHr(HsmPublish (HSMCONN_TYPE_HSM, m_name, m_hId, m_name, CLSID_HsmServer ));
  1189. WsbTrace(OLESTR("Published OK\n")); ***/
  1190. // Create termination event for auto-backup thread
  1191. WsbAffirmHandle((m_terminateEvent = CreateEvent(NULL, FALSE, FALSE, NULL)));
  1192. // If the autosave interval is non-zero, start the autosave thread
  1193. if (m_autosaveInterval) {
  1194. ULONG interval = m_autosaveInterval;
  1195. WsbAffirm(0 == m_autosaveThread, E_FAIL);
  1196. m_autosaveInterval = 0;
  1197. // Trick SetAutosave into starting the thread
  1198. WsbAffirmHr(SetAutosave(interval));
  1199. }
  1200. m_initializationCompleted = TRUE;
  1201. // Start a thread that will check on the managed resources. This is done
  1202. // as a separate thread because the Resource code can call back into this
  1203. // process and hang the FSA and the Engine since the Engine code hasn't
  1204. // gotten to it's message loop yet.
  1205. WsbAssert(m_CheckManagedResourcesThread == 0, E_UNEXPECTED);
  1206. WsbAffirm((m_CheckManagedResourcesThread = CreateThread(0, 0, HsmengStartCheckManagedResources,
  1207. (void*) this, 0, &threadId)) != 0, HRESULT_FROM_WIN32(GetLastError()));
  1208. } WsbCatch( hr );
  1209. WsbTraceOut(OLESTR("CHsmServer::Init"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  1210. return( hr );
  1211. }
  1212. HRESULT
  1213. CHsmServer::GetSizeMax(
  1214. OUT ULARGE_INTEGER* pSize
  1215. )
  1216. /*++
  1217. Implements:
  1218. IPersistStream::GetSizeMax().
  1219. --*/
  1220. {
  1221. HRESULT hr = S_OK;
  1222. WsbTraceIn(OLESTR("CHsmServer::GetSizeMax"), OLESTR(""));
  1223. try {
  1224. WsbAssert(0 != pSize, E_POINTER);
  1225. pSize->QuadPart = 2000000;
  1226. } WsbCatch( hr );
  1227. WsbTraceOut(OLESTR("CHsmServer::GetSizeMax"), OLESTR("hr = <%ls>, size = <%ls>"),
  1228. WsbHrAsString(hr), WsbPtrToUliAsString(pSize));
  1229. return( hr );
  1230. }
  1231. HRESULT
  1232. CHsmServer::Load(
  1233. IN IStream* pStream
  1234. )
  1235. /*++
  1236. Implements:
  1237. IPersistStream::Load().
  1238. --*/
  1239. {
  1240. HRESULT hr = S_OK;
  1241. WsbTraceIn(OLESTR("CHsmServer::Load"), OLESTR(""));
  1242. try {
  1243. WsbAssert(0 != pStream, E_POINTER);
  1244. //
  1245. // Make sure these are in the same order as Save
  1246. //
  1247. // Make sure this is the right version of the database to load
  1248. //
  1249. ULONG tmpDatabaseVersion;
  1250. WsbAffirmHr(WsbLoadFromStream(pStream, &tmpDatabaseVersion));
  1251. if (tmpDatabaseVersion == ENGINE_WIN2K_DB_VERSION) {
  1252. // We are upgrading from an older version of the database
  1253. WsbLogEvent( HSM_MESSAGE_DATABASE_VERSION_UPGRADE, 0, NULL, WsbQuickString(WsbPtrToUlongAsString(&m_databaseVersion)),
  1254. WsbQuickString(WsbPtrToUlongAsString(&tmpDatabaseVersion)), NULL );
  1255. } else if (tmpDatabaseVersion != m_databaseVersion) {
  1256. //
  1257. // The database version this server is expecting does not
  1258. // match that of the saved database - so error out.
  1259. WsbLogEvent( HSM_MESSAGE_DATABASE_VERSION_MISMATCH, 0, NULL, WsbQuickString(WsbPtrToUlongAsString(&m_databaseVersion)),
  1260. WsbQuickString(WsbPtrToUlongAsString(&tmpDatabaseVersion)), NULL );
  1261. WsbThrow(HSM_E_DATABASE_VERSION_MISMATCH);
  1262. }
  1263. //
  1264. // Now read in the build version but don't do anything with it. It is in the
  1265. // databases for dump programs to display
  1266. //
  1267. ULONG tmpBuildVersion;
  1268. WsbAffirmHr(WsbLoadFromStream(pStream, &tmpBuildVersion));
  1269. WsbAffirmHr(WsbLoadFromStream(pStream, &m_hId));
  1270. WsbAffirmHr(WsbLoadFromStream(pStream, &m_autosaveInterval));
  1271. if (tmpDatabaseVersion == ENGINE_WIN2K_DB_VERSION) {
  1272. LONGLONG mediaCount;
  1273. WsbAffirmHr(WsbLoadFromStream(pStream, &mediaCount));
  1274. m_mediaCount = (LONG)mediaCount;
  1275. m_copyfilesUserLimit = DEFAULT_COPYFILES_USER_LIMIT;
  1276. } else {
  1277. WsbAffirmHr(WsbLoadFromStream(pStream, &m_mediaCount));
  1278. WsbAffirmHr(WsbLoadFromStream(pStream, &m_copyfilesUserLimit));
  1279. }
  1280. WsbTrace(OLESTR("Loading Jobs.\n"));
  1281. WsbAffirmHr(LoadJobs(pStream));
  1282. WsbTrace(OLESTR("Loading Job Definitions.\n"));
  1283. WsbAffirmHr(LoadJobDefs(pStream));
  1284. WsbTrace(OLESTR("Loading Policies.\n"));
  1285. WsbAffirmHr(LoadPolicies(pStream));
  1286. WsbTrace(OLESTR("Loading Managed Resources.\n"));
  1287. WsbAffirmHr(LoadManagedResources(pStream));
  1288. WsbTrace(OLESTR("Loading Storage Pools.\n"));
  1289. WsbAffirmHr(LoadStoragePools(pStream));
  1290. WsbTrace(OLESTR("Loading Messages.\n"));
  1291. WsbAffirmHr(LoadMessages(pStream));
  1292. WsbTrace(OLESTR("Loading Media Manager objects.\n"));
  1293. if (tmpDatabaseVersion == ENGINE_WIN2K_DB_VERSION) {
  1294. // Special procedure for upgrading a Win2K media manager data, which is located in a separate file
  1295. CComPtr<IHsmUpgradeRmsDb> pUpgrade;
  1296. CComPtr<IPersistFile> pServerPersist;
  1297. CWsbStringPtr rmsDbName;
  1298. WsbAffirmHr(CoCreateInstance(CLSID_CHsmUpgradeRmsDb, NULL, CLSCTX_SERVER,
  1299. IID_IHsmUpgradeRmsDb, (void**)&pUpgrade));
  1300. WsbAffirmHr(pUpgrade->Init(m_pHsmMediaMgr));
  1301. WsbAffirmHr(pUpgrade->QueryInterface(IID_IPersistFile, (void **)&pServerPersist));
  1302. rmsDbName = m_dbPath;
  1303. WsbAffirmHr(rmsDbName.Append(RMS_WIN2K_PERSIST_FILE));
  1304. hr = WsbSafeLoad(rmsDbName, pServerPersist, FALSE);
  1305. if (WSB_E_NOTFOUND == hr) {
  1306. // In case of upgrade, the Rms database must be there
  1307. hr = WSB_E_SERVICE_MISSING_DATABASES;
  1308. }
  1309. WsbAffirmHr(hr);
  1310. } else {
  1311. CComPtr<IPersistStream> pIStream;
  1312. WsbAffirmHr(m_pHsmMediaMgr->QueryInterface(IID_IPersistStream, (void **)&pIStream));
  1313. WsbAffirmHr(pIStream->Load(pStream));
  1314. }
  1315. } WsbCatch(hr);
  1316. WsbTraceOut(OLESTR("CHsmServer::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1317. return(hr);
  1318. }
  1319. HRESULT
  1320. CHsmServer::Save(
  1321. IN IStream* pStream,
  1322. IN BOOL clearDirty
  1323. )
  1324. /*++
  1325. Implements:
  1326. IPersistStream::Save().
  1327. --*/
  1328. {
  1329. HRESULT hr = S_OK;
  1330. WsbTraceIn(OLESTR("CHsmServer::Save"), OLESTR("clearDirty = <%ls>"), WsbBoolAsString(clearDirty));
  1331. try {
  1332. WsbAssert(0 != pStream, E_POINTER);
  1333. // Make sure these are in the same order as Load
  1334. WsbAffirmHr(WsbSaveToStream(pStream, m_databaseVersion));
  1335. WsbAffirmHr(WsbSaveToStream(pStream, m_buildVersion));
  1336. WsbAffirmHr(WsbSaveToStream(pStream, m_hId));
  1337. WsbAffirmHr(WsbSaveToStream(pStream, m_autosaveInterval));
  1338. WsbAffirmHr(WsbSaveToStream(pStream, m_mediaCount));
  1339. WsbAffirmHr(WsbSaveToStream(pStream, m_copyfilesUserLimit));
  1340. WsbTrace(OLESTR("Storing Jobs.\n"));
  1341. WsbAffirmHr(StoreJobs(pStream));
  1342. WsbTrace(OLESTR("Storing Job Definitions.\n"));
  1343. WsbAffirmHr(StoreJobDefs(pStream));
  1344. WsbTrace(OLESTR("Storing Policies.\n"));
  1345. WsbAffirmHr(StorePolicies(pStream));
  1346. WsbTrace(OLESTR("Storing Managed Resources.\n"));
  1347. WsbAffirmHr(StoreManagedResources(pStream));
  1348. WsbTrace(OLESTR("Storing Storage Pools.\n"));
  1349. WsbAffirmHr(StoreStoragePools(pStream));
  1350. WsbTrace(OLESTR("Storing Messages.\n"));
  1351. WsbAffirmHr(StoreMessages(pStream));
  1352. WsbTrace(OLESTR("Storing Media Manager objects.\n"));
  1353. CComPtr<IPersistStream> pIStream;
  1354. WsbAffirmHr(m_pHsmMediaMgr->QueryInterface(IID_IPersistStream, (void **)&pIStream));
  1355. WsbAffirmHr(pIStream->Save(pStream, clearDirty));
  1356. // If we got it saved and we were asked to clear the dirty bit, then
  1357. // do so now.
  1358. if (clearDirty) {
  1359. m_isDirty = FALSE;
  1360. }
  1361. } WsbCatch(hr);
  1362. WsbTraceOut(OLESTR("CHsmServer::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1363. return(hr);
  1364. }
  1365. STDMETHODIMP
  1366. CHsmServer::SaveAll(
  1367. void
  1368. )
  1369. /*++
  1370. Implements:
  1371. IwsbServer::SaveAll
  1372. Return Value:
  1373. S_OK - Success
  1374. S_FALSE - Already saving
  1375. Other - Error
  1376. --*/
  1377. {
  1378. HRESULT hr = S_OK;
  1379. WsbTraceIn(OLESTR("CHsmServer::SaveAll"), OLESTR(""));
  1380. try {
  1381. WsbAffirm(!g_HsmSaveInProcess, S_FALSE);
  1382. g_HsmSaveInProcess = TRUE;
  1383. hr = InternalSavePersistData();
  1384. g_HsmSaveInProcess = FALSE;
  1385. // call Media Server SaveAll
  1386. WsbAffirmHr(m_pHsmMediaMgr->SaveAll());
  1387. } WsbCatch(hr);
  1388. WsbTraceOut(OLESTR("CHsmServer::SaveAll"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1389. return(hr);
  1390. }
  1391. HRESULT
  1392. CHsmServer::GetNextMedia(
  1393. LONG *pNextMedia
  1394. )
  1395. /*++
  1396. Implements:
  1397. IHsmServer::GetNextMedia().
  1398. --*/
  1399. {
  1400. HRESULT hr = S_OK;
  1401. WsbTraceIn(OLESTR("CHsmServer::GetNextMedia"), OLESTR(""));
  1402. try {
  1403. WsbAssert(0 != pNextMedia, E_POINTER);
  1404. // Always increment media count
  1405. // If prior scratch mount failed, the mounting component should save the id that
  1406. // it got on the first call
  1407. // NOTE: One possible consequence is that if a job fails mounting scratch (one time
  1408. // or more) and gives up, one increment has already done, hence skipping one number.
  1409. *pNextMedia = InterlockedIncrement(&m_mediaCount);
  1410. //
  1411. // We want to make sure we never reuse this count so
  1412. // save it now
  1413. //
  1414. WsbAffirmHr(SavePersistData());
  1415. } WsbCatch(hr);
  1416. WsbTraceOut(OLESTR("CHsmServer::GetNextMedia"), OLESTR("hr = <%ls>, nextMedia = <%ls>"),
  1417. WsbHrAsString(hr), WsbPtrToLongAsString(pNextMedia));
  1418. return(hr);
  1419. }
  1420. HRESULT
  1421. CHsmServer::CreateTask(
  1422. IN const OLECHAR * jobName,
  1423. IN const OLECHAR * jobParameters,
  1424. IN const OLECHAR * jobComments,
  1425. IN const TASK_TRIGGER_TYPE jobTriggerType,
  1426. IN const WORD jobStartHour,
  1427. IN const WORD jobStartMinute,
  1428. IN const BOOL scheduledJob
  1429. )
  1430. /*++
  1431. Implements:
  1432. IHsmServer::CreateTask().
  1433. Routine Description:
  1434. This routine implements the Engine's COM method for creating a task (aka job) in the
  1435. NT Task Scheduler. If the task is to be run on a scheduled basis, that schedule
  1436. will be set. If the task is a disabled task (does not run on a scheduled basis),
  1437. it will be run at the end of this method.
  1438. The method creates a Task Scheduler object, which is first used to delete any old
  1439. task with the same name as the one about to be created, and then to create the new
  1440. task (aka job). The rest of the method deals with setting the various fields in
  1441. the NT Task Scheduler needed to run the job. The logic is straight forward, except
  1442. possibly for the code dealing with the Task Trigger.
  1443. The Task Trigger is a struct defined in the 'mstask.idl' file (nt\public\sdk\inc)
  1444. which is used to set the schedule for a scheduled task. (Note it is not used for
  1445. a disabled, or non-scheduled, job, since that type of job only runs once (at the end
  1446. of this method).) While a number of scheduling options are defined, this method
  1447. only supports 5 of the 8 defined. See 'jobTriggerType' in the 'Arguments' section,
  1448. and 'E_INVALIDARG' in the 'Return Value' section below for a listing of which options
  1449. are, and are not, supported. Also note that a filled-out Task Trigger structure can
  1450. not be passed to this method as an argument since a Task Trigger is non-marshallable
  1451. (by virtue of containing a simple union field). (This is why 3 of the fields
  1452. contained within the Task Trigger struct are passed as args.)
  1453. Note that this method does not create a job object in the HSM Engine. If a job
  1454. needs to be created, it is the caller's responsibility to do so.
  1455. Arguments:
  1456. jobName - The fully formatted task name as it will appear in the NT Task Scheduler UI.
  1457. It is the caller's responsibility to build/format this string prior to
  1458. calling this method. Can not be NULL.
  1459. jobParameters - The fully formatted parameter string for the program the task will
  1460. invoke. For Sakkara the invoked program is RsLaunch. 'jobParameters'
  1461. is the string added to the RsLaunch command line which specifies the
  1462. Remote Storage job to run (e.g., 'run manage'). Can not be NULL.
  1463. jobComments - The fully formatted comments string as it will appear in the NT Task
  1464. Scheduler UI. Can be null.
  1465. jobTriggerType - The value which specifies to the Task Scheduler the frequency with
  1466. which to run a scheduled task. For scheduled tasks, used to build the
  1467. Task Trigger structure. (Not used for non-scheduled (one time only)
  1468. tasks.) Supported values are 'TASK_TIME_TRIGGER_ONCE',
  1469. 'TASK_TIME_TRIGGER_DAILY', 'TASK_TIME_TRIGGER_ON_IDLE',
  1470. 'TASK_TIME_TRIGGER_AT_SYSTEMSTART', and 'TASK_TIME_TRIGGER_AT_LOGON'.
  1471. See return value 'E_INVALIDARG' below for a list of non-supported options.
  1472. jobStartHour - The value which specifies to the Task Scheduler the hour at which to
  1473. start a scheduled task. For scheduled tasks, used to build the Task
  1474. Trigger structure. (Not used for non-scheduled (one time only) tasks.)
  1475. jobStartMinute - The value which specifies to the Task Scheduler the minutes past
  1476. the hour at which to start a scheduled task. For scheduled tasks, used
  1477. to build the Task Trigger structure. (Not used for non-scheduled (one
  1478. time only) tasks.)
  1479. scheduledJob - A Boolean which indicates whether or not the task to be created is to
  1480. run as a scheduled task, or as a one time only task. One time only tasks
  1481. are run immediately at the end of this method.
  1482. Return Value:
  1483. S_OK - The call succeeded (the specified task was created (and run, in the case of
  1484. one time only tasks) in NT Task Scheduler).
  1485. E_INVALIDARG - Either an invalid (not supported by this method) or non-existent
  1486. 'jobTriggerType' value was passed into this method. Non-supported values
  1487. are 'TASK_TIME_TRIGGER_WEEKLY', 'TASK_TIME_TRIGGER_MONTHLYDATE', and
  1488. 'TASK_TIME_TRIGGER_MONTHLYDOW'. Supported values are listed in argument
  1489. 'jobTriggerType' above.
  1490. E_POINTER - Either the 'jobName' or 'jobParameters' argument was passed as NULL.
  1491. Any other value - The call failed because one of the Remote Storage API calls
  1492. contained internally in this method failed. The error value returned is
  1493. specific to the API call which failed.
  1494. --*/
  1495. {
  1496. // The below 'define' statement is used to control conditional compilation of the code
  1497. // which sets the account info in NT Task Scheduler. Once Task Scheduler is fixed to
  1498. // not need a specific user name and password to run a task, simply remove or comment
  1499. // out this statement.
  1500. HRESULT hr = S_OK;
  1501. CComPtr<ITaskScheduler> pTaskScheduler;
  1502. CComPtr<ITask> pTask;
  1503. CComPtr<IPersistFile> pPersist;
  1504. DWORD TaskFlags;
  1505. WsbTraceIn(OLESTR("CHsmServer::CreateTask"),
  1506. OLESTR("jobName = <%ls>, jobParameters = <%ls>, jobComments = <%ls>, "
  1507. L"jobTriggerType = <%d>, jobStartHour = <%d>, jobStartMinute = <%d>, "
  1508. L"scheduledJob = <%ls>"), jobName, jobParameters, jobComments,
  1509. jobTriggerType, jobStartHour, jobStartMinute,
  1510. WsbBoolAsString( scheduledJob ) );
  1511. try {
  1512. WsbAffirmPointer( jobName );
  1513. WsbAffirmPointer( jobParameters );
  1514. // Create a Task Scheduler object, which defaults to pointing to this computer's
  1515. // NT Task Scheduler.
  1516. WsbAffirmHr( CoCreateInstance( CLSID_CTaskScheduler, 0, CLSCTX_SERVER,
  1517. IID_ITaskScheduler, (void **) &pTaskScheduler ) );
  1518. // Delete any old job with the same name from the scheduler, if it exists.
  1519. // Ignore error.
  1520. pTaskScheduler->Delete( jobName );
  1521. // Create the new job in the scheduler
  1522. WsbAffirmHr( pTaskScheduler->NewWorkItem( jobName, CLSID_CTask, IID_ITask,
  1523. (IUnknown**)&pTask ) );
  1524. CWsbStringPtr appName;
  1525. WsbAffirmHr(appName.LoadFromRsc(_Module.m_hInst, IDS_PRODUCT_NAME));
  1526. // Set the Creator field for the task
  1527. WsbAffirmHr( pTask->SetCreator( appName ) );
  1528. // Branch on whether or not the task is to run by schedule
  1529. if ( scheduledJob ) {
  1530. CComPtr<ITaskTrigger> pTrigger;
  1531. WORD triggerNumber;
  1532. TASK_TRIGGER taskTrigger;
  1533. SYSTEMTIME sysTime;
  1534. // create Trigger scheduling object for the job
  1535. WsbAffirmHr( pTask->CreateTrigger( &triggerNumber, &pTrigger ) );
  1536. // Zero out Task Trigger struct contents, then init its structure size field
  1537. memset( &taskTrigger, 0, sizeof( taskTrigger ) );
  1538. taskTrigger.cbTriggerSize = sizeof( taskTrigger );
  1539. // Set up schedule for the job in the Task Trigger struct
  1540. GetSystemTime( &sysTime );
  1541. taskTrigger.wBeginYear = sysTime.wYear;
  1542. taskTrigger.wBeginMonth = sysTime.wMonth;
  1543. taskTrigger.wBeginDay = sysTime.wDay;
  1544. taskTrigger.wStartHour = jobStartHour;
  1545. taskTrigger.wStartMinute = jobStartMinute;
  1546. taskTrigger.TriggerType = jobTriggerType;
  1547. // Finish setting schedule info based on case, reject non-supported cases
  1548. switch ( jobTriggerType )
  1549. {
  1550. case TASK_TIME_TRIGGER_DAILY:
  1551. {
  1552. taskTrigger.Type.Daily.DaysInterval = 1;
  1553. }
  1554. break;
  1555. // these are supported cases that need no further set up
  1556. case TASK_TIME_TRIGGER_ONCE:
  1557. case TASK_EVENT_TRIGGER_ON_IDLE:
  1558. case TASK_EVENT_TRIGGER_AT_SYSTEMSTART:
  1559. case TASK_EVENT_TRIGGER_AT_LOGON:
  1560. {
  1561. }
  1562. break;
  1563. // non-supported cases
  1564. case TASK_TIME_TRIGGER_WEEKLY:
  1565. case TASK_TIME_TRIGGER_MONTHLYDATE:
  1566. case TASK_TIME_TRIGGER_MONTHLYDOW:
  1567. {
  1568. WsbTrace(
  1569. OLESTR("(CreateTask) Job Trigger Type passed <%d> is invalid (see mstask.idl)\n"),
  1570. jobTriggerType );
  1571. WsbThrow( E_INVALIDARG );
  1572. }
  1573. break;
  1574. default:
  1575. {
  1576. WsbTrace(
  1577. OLESTR("(CreateTask) Nonexistent Job Trigger Type passed <%d> (see mstask.idl)\n"),
  1578. jobTriggerType );
  1579. WsbThrow( E_INVALIDARG );
  1580. }
  1581. }
  1582. // Set the job schedule
  1583. WsbAffirmHr( pTrigger->SetTrigger( &taskTrigger ) );
  1584. }
  1585. // Note that for Disabled (non-scheduled) tasks, there is no need to 'SetFlags()'
  1586. // on the task (pTask) to 'TASK_FLAG_DISABLED'. In fact, this method will hang
  1587. // for an undetermined reason if you do issue that call.
  1588. // Below steps finish creating an entry for NT Task Scheduler
  1589. // Set the program that the Scheduler is to run (for Sakkara this is RsLaunch)
  1590. WsbAffirmHr( pTask->SetApplicationName( WSB_FACILITY_LAUNCH_NAME ) );
  1591. // Put the job name in as the task parameter - for Sakkara this is how RsLaunch
  1592. // knows which job to run.
  1593. WsbAffirmHr( pTask->SetParameters( jobParameters ) );
  1594. // Set the comments field for the task
  1595. WsbAffirmHr( pTask->SetComment( jobComments ) );
  1596. // Set Task Scheduler account info by passing nulls
  1597. WsbAffirmHr( pTask->SetAccountInformation( OLESTR(""), NULL ) );
  1598. // Set the SYSTEM_REQUIRED flag to deal with standby/sleep mode
  1599. WsbAffirmHr(pTask->GetTaskFlags(&TaskFlags));
  1600. TaskFlags |= TASK_FLAG_SYSTEM_REQUIRED;
  1601. WsbAffirmHr(pTask->SetTaskFlags(TaskFlags));
  1602. // Save the scheduled task
  1603. WsbAffirmHr( pTask->QueryInterface( IID_IPersistFile, (void**)&pPersist ) );
  1604. WsbAffirmHr( pPersist->Save( 0, 0 ) );
  1605. // If this is not a scheduled job, run it now
  1606. if ( !scheduledJob ) {
  1607. WsbAffirmHr( pTask->Run() );
  1608. }
  1609. } WsbCatch( hr );
  1610. WsbTraceOut( L"CHsmServer::CreateTask", L"hr = <%ls>", WsbHrAsString( hr ) );
  1611. return( hr );
  1612. }
  1613. HRESULT
  1614. CHsmServer::CreateTaskEx(
  1615. IN const OLECHAR * jobName,
  1616. IN const OLECHAR * jobParameters,
  1617. IN const OLECHAR * jobComments,
  1618. IN const TASK_TRIGGER_TYPE jobTriggerType,
  1619. IN const SYSTEMTIME runTime,
  1620. IN const DWORD runOccurrence,
  1621. IN const BOOL scheduledJob
  1622. )
  1623. /*++
  1624. Implements:
  1625. IHsmServer::CreateTaskEx().
  1626. Routine Description:
  1627. This routine implements the Engine's COM method for creating a task (aka job) in the
  1628. NT Task Scheduler. If the task is to be run on a scheduled basis, that schedule
  1629. will be set. If the task is a disabled task (does not run on a scheduled basis),
  1630. it will be run at the end of this method.
  1631. The method creates a Task Scheduler object, which is first used to delete any old
  1632. task with the same name as the one about to be created, and then to create the new
  1633. task (aka job). The rest of the method deals with setting the various fields in
  1634. the NT Task Scheduler needed to run the job. The logic is straight forward, except
  1635. possibly for the code dealing with the Task Trigger.
  1636. The Task Trigger is a struct defined in the 'mstask.idl' file (nt\public\sdk\inc)
  1637. which is used to set the schedule for a scheduled task. (Note it is not used for
  1638. a disabled, or non-scheduled, job, since that type of job only runs once (at the end
  1639. of this method).) While a number of scheduling options are defined, this method
  1640. only supports 5 of the 8 defined. See 'jobTriggerType' in the 'Arguments' section,
  1641. and 'E_INVALIDARG' in the 'Return Value' section below for a listing of which options
  1642. are, and are not, supported. Also note that a filled-out Task Trigger structure can
  1643. not be passed to this method as an argument since a Task Trigger is non-marshallable
  1644. (by virtue of containing a simple union field). (This is why 3 of the fields
  1645. contained within the Task Trigger struct are passed as args.)
  1646. Note that this method does not create a job object in the HSM Engine. If a job
  1647. needs to be created, it is the caller's responsibility to do so.
  1648. Arguments:
  1649. jobName - The fully formatted task name as it will appear in the NT Task Scheduler UI.
  1650. It is the caller's responsibility to build/format this string prior to
  1651. calling this method. Can not be NULL.
  1652. jobParameters - The fully formatted parameter string for the program the task will
  1653. invoke. For Sakkara the invoked program is RsLaunch. 'jobParameters'
  1654. is the string added to the RsLaunch command line which specifies the
  1655. Remote Storage job to run (e.g., 'run manage'). Can not be NULL.
  1656. jobComments - The fully formatted comments string as it will appear in the NT Task
  1657. Scheduler UI. Can be null.
  1658. jobTriggerType - The value which specifies to the Task Scheduler the frequency with
  1659. which to run a scheduled task. For scheduled tasks, used to build the
  1660. Task Trigger structure. (Not used for non-scheduled (one time only)
  1661. tasks.) Supported values are 'TASK_TIME_TRIGGER_ONCE',
  1662. 'TASK_TIME_TRIGGER_DAILY', TASK_TIME_TRIGGER_WEEKLY ,
  1663. TASK_TIME_TRIGGER_MONTHLYDATE, 'TASK_TIME_TRIGGER_ON_IDLE',
  1664. 'TASK_TIME_TRIGGER_AT_SYSTEMSTART', and 'TASK_TIME_TRIGGER_AT_LOGON'.
  1665. See return value 'E_INVALIDARG' below for a list of non-supported options.
  1666. runTime - Time when the job should be scheduled
  1667. runOccurrence - Occurrence for the job should to be scheduled, relevant for several trigger types
  1668. scheduledJob - A Boolean which indicates whether or not the task to be created is to
  1669. run as a scheduled task, or as a one time only task. One time only tasks
  1670. are run immediately at the end of this method.
  1671. Return Value:
  1672. S_OK - The call succeeded (the specified task was created (and run, in the case of
  1673. one time only tasks) in NT Task Scheduler).
  1674. E_INVALIDARG - Either an invalid (not supported by this method) or non-existent
  1675. 'jobTriggerType' value was passed into this method. Non-supported values
  1676. are 'TASK_TIME_TRIGGER_WEEKLY', 'TASK_TIME_TRIGGER_MONTHLYDATE', and
  1677. 'TASK_TIME_TRIGGER_MONTHLYDOW'. Supported values are listed in argument
  1678. 'jobTriggerType' above.
  1679. E_POINTER - Either the 'jobName' or 'jobParameters' argument was passed as NULL.
  1680. Any other value - The call failed because one of the Remote Storage API calls
  1681. contained internally in this method failed. The error value returned is
  1682. specific to the API call which failed.
  1683. --*/
  1684. {
  1685. // The below 'define' statement is used to control conditional compilation of the code
  1686. // which sets the account info in NT Task Scheduler. Once Task Scheduler is fixed to
  1687. // not need a specific user name and password to run a task, simply remove or comment
  1688. // out this statement.
  1689. HRESULT hr = S_OK;
  1690. CComPtr<ITaskScheduler> pTaskScheduler;
  1691. CComPtr<ITask> pTask;
  1692. CComPtr<IPersistFile> pPersist;
  1693. DWORD TaskFlags;
  1694. WsbTraceIn(OLESTR("CHsmServer::CreateTaskEx"),
  1695. OLESTR("jobName = <%ls>, jobParameters = <%ls>, jobComments = <%ls>, "
  1696. L"jobTriggerType = <%d>, jobStartHour = <%d>, jobStartMinute = <%d>, "
  1697. L"scheduledJob = <%ls>"), jobName, jobParameters, jobComments,
  1698. jobTriggerType, runTime.wHour, runTime.wMinute,
  1699. WsbBoolAsString( scheduledJob ) );
  1700. try {
  1701. WsbAffirmPointer( jobName );
  1702. WsbAffirmPointer( jobParameters );
  1703. // Create a Task Scheduler object, which defaults to pointing to this computer's
  1704. // NT Task Scheduler.
  1705. WsbAffirmHr( CoCreateInstance( CLSID_CTaskScheduler, 0, CLSCTX_SERVER,
  1706. IID_ITaskScheduler, (void **) &pTaskScheduler ) );
  1707. // Delete any old job with the same name from the scheduler, if it exists.
  1708. // Ignore error.
  1709. pTaskScheduler->Delete( jobName );
  1710. // Create the new job in the scheduler
  1711. WsbAffirmHr( pTaskScheduler->NewWorkItem( jobName, CLSID_CTask, IID_ITask,
  1712. (IUnknown**)&pTask ) );
  1713. CWsbStringPtr appName;
  1714. WsbAffirmHr(appName.LoadFromRsc(_Module.m_hInst, IDS_PRODUCT_NAME));
  1715. // Set the Creator field for the task
  1716. WsbAffirmHr( pTask->SetCreator( appName ) );
  1717. // Branch on whether or not the task is to run by schedule
  1718. if ( scheduledJob ) {
  1719. CComPtr<ITaskTrigger> pTrigger;
  1720. WORD triggerNumber;
  1721. TASK_TRIGGER taskTrigger;
  1722. // create Trigger scheduling object for the job
  1723. WsbAffirmHr( pTask->CreateTrigger( &triggerNumber, &pTrigger ) );
  1724. // Zero out Task Trigger struct contents, then init its structure size field
  1725. memset( &taskTrigger, 0, sizeof( taskTrigger ) );
  1726. taskTrigger.cbTriggerSize = sizeof( taskTrigger );
  1727. // Set up schedule for the job in the Task Trigger struct
  1728. taskTrigger.wBeginYear = runTime.wYear;
  1729. taskTrigger.wBeginMonth = runTime.wMonth;
  1730. taskTrigger.wBeginDay = runTime.wDay;
  1731. taskTrigger.wStartHour = runTime.wHour;
  1732. taskTrigger.wStartMinute = runTime.wMinute;
  1733. taskTrigger.TriggerType = jobTriggerType;
  1734. // Finish setting schedule info based on case, reject non-supported cases
  1735. switch ( jobTriggerType )
  1736. {
  1737. case TASK_TIME_TRIGGER_DAILY:
  1738. {
  1739. taskTrigger.Type.Daily.DaysInterval = (WORD)runOccurrence;
  1740. }
  1741. break;
  1742. case TASK_TIME_TRIGGER_WEEKLY:
  1743. {
  1744. taskTrigger.Type.Weekly.WeeksInterval = (WORD)runOccurrence;
  1745. switch (runTime.wDayOfWeek) {
  1746. case 0:
  1747. taskTrigger.Type.Weekly.rgfDaysOfTheWeek = TASK_SUNDAY;
  1748. break;
  1749. case 1:
  1750. taskTrigger.Type.Weekly.rgfDaysOfTheWeek = TASK_MONDAY;
  1751. break;
  1752. case 2:
  1753. taskTrigger.Type.Weekly.rgfDaysOfTheWeek = TASK_TUESDAY;
  1754. break;
  1755. case 3:
  1756. taskTrigger.Type.Weekly.rgfDaysOfTheWeek = TASK_WEDNESDAY;
  1757. break;
  1758. case 4:
  1759. taskTrigger.Type.Weekly.rgfDaysOfTheWeek = TASK_THURSDAY;
  1760. break;
  1761. case 5:
  1762. taskTrigger.Type.Weekly.rgfDaysOfTheWeek = TASK_FRIDAY;
  1763. break;
  1764. case 6:
  1765. taskTrigger.Type.Weekly.rgfDaysOfTheWeek = TASK_SATURDAY;
  1766. break;
  1767. }
  1768. }
  1769. break;
  1770. case TASK_TIME_TRIGGER_MONTHLYDATE:
  1771. {
  1772. WsbAssert(runTime.wDay < 32, E_INVALIDARG);
  1773. taskTrigger.Type.MonthlyDate.rgfDays = (1 << (runTime.wDay-1));
  1774. taskTrigger.Type.MonthlyDate.rgfMonths = (TASK_JANUARY | TASK_FEBRUARY | TASK_MARCH |TASK_APRIL |
  1775. TASK_MAY | TASK_JUNE |TASK_JULY | TASK_AUGUST |
  1776. TASK_SEPTEMBER | TASK_OCTOBER | TASK_NOVEMBER | TASK_DECEMBER);
  1777. }
  1778. break;
  1779. case TASK_EVENT_TRIGGER_ON_IDLE:
  1780. {
  1781. WORD wIdle, wTemp;
  1782. WsbAffirmHr(pTask->GetIdleWait(&wIdle, &wTemp));
  1783. wIdle = (WORD)runOccurrence;
  1784. WsbAffirmHr(pTask->SetIdleWait(wIdle, wTemp));
  1785. }
  1786. // these are supported cases that need no further set up
  1787. case TASK_TIME_TRIGGER_ONCE:
  1788. case TASK_EVENT_TRIGGER_AT_SYSTEMSTART:
  1789. case TASK_EVENT_TRIGGER_AT_LOGON:
  1790. {
  1791. }
  1792. break;
  1793. // non-supported cases
  1794. case TASK_TIME_TRIGGER_MONTHLYDOW:
  1795. {
  1796. WsbTrace(
  1797. OLESTR("(CreateTaskEx) Job Trigger Type passed <%d> is invalid (see mstask.idl)\n"),
  1798. jobTriggerType );
  1799. WsbThrow( E_INVALIDARG );
  1800. }
  1801. break;
  1802. default:
  1803. {
  1804. WsbTrace(
  1805. OLESTR("(CreateTaskEx) Nonexistent Job Trigger Type passed <%d> (see mstask.idl)\n"),
  1806. jobTriggerType );
  1807. WsbThrow( E_INVALIDARG );
  1808. }
  1809. }
  1810. // Set the job schedule
  1811. WsbAffirmHr( pTrigger->SetTrigger( &taskTrigger ) );
  1812. }
  1813. // Note that for Disabled (non-scheduled) tasks, there is no need to 'SetFlags()'
  1814. // on the task (pTask) to 'TASK_FLAG_DISABLED'. In fact, this method will hang
  1815. // for an undetermined reason if you do issue that call.
  1816. // Below steps finish creating an entry for NT Task Scheduler
  1817. // Set the program that the Scheduler is to run (for Sakkara this is RsLaunch)
  1818. WsbAffirmHr( pTask->SetApplicationName( WSB_FACILITY_LAUNCH_NAME ) );
  1819. // Put the job name in as the task parameter - for Sakkara this is how RsLaunch
  1820. // knows which job to run.
  1821. WsbAffirmHr( pTask->SetParameters( jobParameters ) );
  1822. // Set the comments field for the task
  1823. WsbAffirmHr( pTask->SetComment( jobComments ) );
  1824. // Set Task Scheduler account info by passing nulls
  1825. WsbAffirmHr( pTask->SetAccountInformation( OLESTR(""), NULL ) );
  1826. // Set the SYSTEM_REQUIRED flag to deal with standby/sleep mode
  1827. WsbAffirmHr(pTask->GetTaskFlags(&TaskFlags));
  1828. TaskFlags |= TASK_FLAG_SYSTEM_REQUIRED;
  1829. WsbAffirmHr(pTask->SetTaskFlags(TaskFlags));
  1830. // Save the scheduled task
  1831. WsbAffirmHr( pTask->QueryInterface( IID_IPersistFile, (void**)&pPersist ) );
  1832. WsbAffirmHr( pPersist->Save( 0, 0 ) );
  1833. // If this is not a scheduled job, run it now
  1834. if ( !scheduledJob ) {
  1835. WsbAffirmHr( pTask->Run() );
  1836. }
  1837. } WsbCatch( hr );
  1838. WsbTraceOut( L"CHsmServer::CreateTaskEx", L"hr = <%ls>", WsbHrAsString( hr ) );
  1839. return( hr );
  1840. }
  1841. HRESULT
  1842. CHsmServer::CancelCopyMedia(
  1843. void
  1844. )
  1845. /*++
  1846. Implements:
  1847. IHsmServer::CancelCopyMedia().
  1848. Routine Description:
  1849. Cancel any active media copy operations (synchronize copy or recreate master).
  1850. Arguments:
  1851. None.
  1852. Return Value:
  1853. S_OK - The call succeeded.
  1854. S_FALSE - No media copy operation is active.
  1855. --*/
  1856. {
  1857. // since this code is currently only used by the CopyMedia routines,
  1858. // reset the Tracing bit
  1859. #undef WSB_TRACE_IS
  1860. #define WSB_TRACE_IS WSB_TRACE_BIT_COPYMEDIA
  1861. HRESULT hr = S_OK;
  1862. WsbTraceIn( OLESTR("CHsmServer::CancelCopyMedia"),
  1863. OLESTR("m_inCopyMedia = %ls, m_cancelCopyMedia = %ls"),
  1864. WsbQuickString(WsbBoolAsString(m_inCopyMedia)),
  1865. WsbQuickString(WsbBoolAsString(m_cancelCopyMedia)));
  1866. Lock();
  1867. if (m_inCopyMedia) {
  1868. m_cancelCopyMedia = TRUE;
  1869. } else {
  1870. hr = S_FALSE;
  1871. }
  1872. Unlock();
  1873. WsbTraceOut(OLESTR("CHsmServer::CancelCopyMedia"), OLESTR("hr = <%ls>"),
  1874. WsbHrAsString(hr));
  1875. return(hr);
  1876. // leaving CopyMedia code, so reset Tracing bit to the Hsm Engine
  1877. #undef WSB_TRACE_IS
  1878. #define WSB_TRACE_IS WSB_TRACE_BIT_HSMENG
  1879. }
  1880. HRESULT
  1881. CHsmServer::MarkMediaForRecreation(
  1882. IN REFGUID masterMediaId
  1883. )
  1884. /*++
  1885. Implements:
  1886. IHsmServer::MarkMediaForRecreation().
  1887. Routine Description:
  1888. This routine implements the Engine's COM method for marking a master media for re-creation
  1889. Should we mark such a media as Recall Only as well ?
  1890. Arguments:
  1891. masterMediaId - The id (GUID) for the master media to be marked.
  1892. Return Value:
  1893. S_OK - The call succeeded (the specified master media was marked).
  1894. Any other value - The call failed because one of the Remote Storage API calls
  1895. contained internally in this method failed. The error value returned is
  1896. specific to the API call which failed.
  1897. --*/
  1898. {
  1899. // since this code is currently only used by the CopyMedia routines,
  1900. // reset the Tracing bit
  1901. #undef WSB_TRACE_IS
  1902. #define WSB_TRACE_IS WSB_TRACE_BIT_COPYMEDIA
  1903. HRESULT hr = S_OK;
  1904. CComPtr<IMediaInfo> pMediaInfo;
  1905. CComPtr<IWsbDbSession> pDbSession;
  1906. WsbTraceIn( OLESTR("CHsmServer::MarkMediaForRecreation"),
  1907. OLESTR("masterMediaId = <%ls>"), WsbGuidAsString(masterMediaId) );
  1908. // no event logging since this method is presently for development use only
  1909. try {
  1910. // open the Engine's Segment database
  1911. WsbAffirmHr( m_pSegmentDatabase->Open( &pDbSession ));
  1912. try {
  1913. // get an interface pointer to the MediaInfo records (entity) in the
  1914. // Segment database
  1915. WsbAffirmHr( m_pSegmentDatabase->GetEntity( pDbSession,
  1916. HSM_MEDIA_INFO_REC_TYPE, IID_IMediaInfo,
  1917. (void**) &pMediaInfo ));
  1918. // get the MediaInfo database record for the master media we will mark for
  1919. // re-creation
  1920. WsbAffirmHr( pMediaInfo->SetId( masterMediaId ));
  1921. WsbAffirmHr( pMediaInfo->FindEQ());
  1922. // mark this media for re-creation and as read only
  1923. WsbAffirmHr( pMediaInfo->SetRecreate( TRUE ) );
  1924. /*** WsbAffirmHr( pMediaInfo->RecreateMaster() ); TEMPORARY: Call this one instead for marking as Read Only as well ***/
  1925. // write updated record into the database
  1926. WsbAffirmHr( pMediaInfo->Write());
  1927. } WsbCatch(hr); // inner 'try' - get media info entity and process
  1928. WsbAffirmHr( m_pSegmentDatabase->Close(pDbSession));
  1929. } WsbCatch(hr); // 'try' to open the database
  1930. // processing is done. The singly-assigned smart interface pointers will auto-garbage
  1931. // collect themselves.
  1932. WsbTraceOut(OLESTR("CHsmServer::MarkMediaForRecreation"), OLESTR("hr = <%ls>"),
  1933. WsbHrAsString(hr));
  1934. return(hr);
  1935. // leaving CopyMedia code, so reset Tracing bit to the Hsm Engine
  1936. #undef WSB_TRACE_IS
  1937. #define WSB_TRACE_IS WSB_TRACE_BIT_HSMENG
  1938. }
  1939. HRESULT
  1940. CHsmServer::RecreateMaster(
  1941. IN REFGUID masterMediaId,
  1942. IN USHORT copySet
  1943. )
  1944. /*++
  1945. Implements:
  1946. IHsmServer::RecreateMaster().
  1947. Routine Description:
  1948. This routine implements the COM method for replacing (re-creating) a secondary
  1949. storage original (master) media. To replace the master, a duplicate is made of
  1950. the copy specified. The master record for that media in the Engine's
  1951. MediaInfo database is then updated to point to the 're-created' master (duplicated
  1952. media). For safety purposes all re-created masters are marked 'read only' if
  1953. the copy was not up to date with the original master.
  1954. Because of the potential for data loss (if the most recent copy is not up to date
  1955. with the original master which is being re-created), the user (System Administrator)
  1956. is urged to run a Validate job against the appropriate volume (via the UI) after
  1957. re-creating any master.
  1958. After opening the Segment database (a single database containing all Engine
  1959. database tables), getting the MediaInfo (remote storage master media) records
  1960. (entity) and connecting to the RMS subsystem, the method gets the media record
  1961. corresponding to the master to be re-created. It then checks that the specified
  1962. copy exists for that master. After ensuring the copy exists,
  1963. a 're-created master' is made by duplicating the that copy. The
  1964. database info for the media record is then updated to point to the newly 're-created'
  1965. master media. The method then cleans up (i.e., closes the database) and returns.
  1966. Arguments:
  1967. masterMediaId - The id (GUID) for the master media which is to be re-created.
  1968. copySet - The copyset number of the copy to use or zero, which means use the
  1969. most recent copy.
  1970. Return Value:
  1971. S_OK - The call succeeded (the specified master media was re-created from the
  1972. specified copy media).
  1973. HSM_E_RECREATE_FLAG_WRONGVALUE - Returned if the 'recreate' flag for the master
  1974. media record whose id was passed in, indicating it is to be recreated,
  1975. is not set properly. (The UI is supposed to set it to TRUE prior to
  1976. calling this method via RsLaunch.)
  1977. HSM_E_NO_COPIES_CONFIGURED - Returned if no copies have been configured or created
  1978. for the master which is to be recreated. Without a valid copy we can not
  1979. recreate a master secondary storage media.
  1980. HSM_E_NO_COPIES_EXIST - Returned if copies have been configured but they either
  1981. haven't been created yet, or had previously been created but the System
  1982. Administrator deleted them via UI action.
  1983. WSB_E_NOTFOUND - Value 81000001. Returned if no storage pool record was found whose
  1984. id matched the one contained in the media record.
  1985. HSM_E_BUSY - Another media copy operation was already in progress.
  1986. HSM_E_WORK_SKIPPED_CANCELLED - Operation was cancelled.
  1987. Any other value - The call failed because one of the Remote Storage API calls
  1988. contained internally in this method failed. The error value returned is
  1989. specific to the API call which failed.
  1990. --*/
  1991. {
  1992. // since this code is currently only used by the CopyMedia routines,
  1993. // reset the Tracing bit
  1994. #undef WSB_TRACE_IS
  1995. #define WSB_TRACE_IS WSB_TRACE_BIT_COPYMEDIA
  1996. HRESULT hr = S_OK;
  1997. HRESULT currentLastError = S_OK;
  1998. BOOL haveMasterMediaRecord = FALSE;
  1999. BOOL recreateMaster = FALSE;
  2000. BOOL currentRecallOnly = FALSE;
  2001. BOOL newRecallOnly = FALSE;
  2002. SHORT currentNextRemoteDataSet = 0;
  2003. SHORT copyNextRemoteDataSet = 0;
  2004. SHORT lastKnownGoodMasterNextRemoteDataSet = 0;
  2005. USHORT maxSets = 0;
  2006. GUID poolId = GUID_NULL;
  2007. GUID newMasterId = GUID_NULL;
  2008. GUID mediaSetId = GUID_NULL;
  2009. GUID currentMediaId = GUID_NULL;
  2010. GUID currentMediaSubsystemId = GUID_NULL;
  2011. GUID lastKnownGoodMasterId = GUID_NULL;
  2012. GUID copyMediaSubsystemId = GUID_NULL;
  2013. LONGLONG newFreeBytes = 0;
  2014. LONGLONG currentFreeBytes = 0;
  2015. LONGLONG currentLogicalValidBytes = 0;
  2016. LONGLONG newCapacity = 0;
  2017. LONGLONG currentCapacity = 0;
  2018. FILETIME copyUpdate;
  2019. FILETIME currentUpdate;
  2020. FILETIME lastKnownGoodMasterUpdate;
  2021. CComPtr<IHsmStoragePool> pPool;
  2022. CComPtr<IMediaInfo> pMediaInfo;
  2023. CComPtr<IRmsCartridge> pNewMasterMedia;
  2024. CComPtr<IRmsCartridge> pCopyMedia;
  2025. CComPtr<IWsbDbSession> pDbSession;
  2026. CWsbStringPtr currentName;
  2027. CWsbStringPtr currentDescription;
  2028. CWsbStringPtr copyDescription;
  2029. CWsbBstrPtr copyDescriptionAsBstr;
  2030. CWsbBstrPtr mediaSetName;
  2031. CWsbBstrPtr newName;
  2032. HSM_JOB_MEDIA_TYPE currentType;
  2033. WsbTraceIn( OLESTR("CHsmServer::RecreateMaster"), OLESTR("masterMediaId = <%ls>"),
  2034. WsbGuidAsString(masterMediaId) );
  2035. // log 'information' message
  2036. WsbLogEvent( HSM_MESSAGE_RECREATE_MASTER_START, 0, NULL, NULL );
  2037. try {
  2038. BOOL okToContinue = TRUE;
  2039. // Make sure we're not already busy & haven't been cancelled
  2040. Lock();
  2041. if (m_inCopyMedia) {
  2042. okToContinue = FALSE;
  2043. } else {
  2044. m_inCopyMedia = TRUE;
  2045. }
  2046. Unlock();
  2047. WsbAffirm(okToContinue, HSM_E_BUSY);
  2048. WsbAffirm(!m_cancelCopyMedia, HSM_E_WORK_SKIPPED_CANCELLED);
  2049. // open the Engine's Segment database
  2050. WsbAffirmHr( m_pSegmentDatabase->Open( &pDbSession ));
  2051. try {
  2052. // get an interface pointer to the MediaInfo records (entity) in the
  2053. // Segment database
  2054. WsbAffirmHr( m_pSegmentDatabase->GetEntity( pDbSession,
  2055. HSM_MEDIA_INFO_REC_TYPE, IID_IMediaInfo,
  2056. (void**) &pMediaInfo ));
  2057. // get the MediaInfo db record for the master media we want to re-create
  2058. WsbAffirmHr( pMediaInfo->SetId( masterMediaId ));
  2059. WsbAffirmHr( pMediaInfo->FindEQ());
  2060. haveMasterMediaRecord = TRUE;
  2061. // to check if this master has in fact been marked for re-creation, get
  2062. // the re-created flag value
  2063. WsbAffirmHr( pMediaInfo->GetRecreate( &recreateMaster ));
  2064. // do not proceed if re-created flag is not set
  2065. if ( recreateMaster == FALSE ) {
  2066. // log 'error' message and exit
  2067. WsbLogEvent( HSM_MESSAGE_RECREATE_MASTER_INVALID_FLAG_VALUE,
  2068. 0, NULL, NULL );
  2069. WsbThrow( HSM_E_RECREATE_FLAG_WRONGVALUE );
  2070. }
  2071. // recreateMaster flag is TRUE, so proceed to re-create...
  2072. // Get the storage pool the master to be re-created belongs to. We'll
  2073. // use this pool to determine number of copy sets configured for this
  2074. // media, and to specify what storage pool the 'new' (re-created) master
  2075. // is to belong to.
  2076. WsbAffirmHr( pMediaInfo->GetStoragePoolId( &poolId ));
  2077. // Get the storage pool object.
  2078. hr = FindHsmStoragePoolById( poolId, &pPool );
  2079. if (S_OK != hr) {
  2080. // log the returned error and throw the error
  2081. WsbLogEvent( HSM_MESSAGE_SEARCH_STGPOOL_BY_HSMID_ERROR,
  2082. 0, NULL, WsbHrAsString(hr), NULL );
  2083. WsbThrow( hr );
  2084. }
  2085. // get the number of copy sets configured for this pool
  2086. WsbAffirmHr( pPool->GetNumMediaCopies( &maxSets ));
  2087. // if none have been configured by SysAdmin, error out
  2088. WsbAffirm( maxSets > 0, HSM_E_NO_COPIES_CONFIGURED );
  2089. // If the copySet number was specified, make sure it is valid
  2090. WsbAffirm(((copySet == 0) || (copySet <= maxSets)), E_INVALIDARG);
  2091. // If the copySet was not specified, determine
  2092. // which copy belonging to this master is most recent, otherwise
  2093. // get information about specified copy.
  2094. if (copySet == 0) {
  2095. USHORT mostRecentCopy = 0;
  2096. USHORT mostDataSets = 0;
  2097. FILETIME mostRecentCopyUpdate = WsbLLtoFT(0);
  2098. // set invalid value for validity testing (testing if any media
  2099. // copies exist)
  2100. mostRecentCopy = (USHORT)( maxSets + 1 );
  2101. // loop through the configured copy sets
  2102. for (copySet = 1; copySet <= maxSets; copySet++ ) {
  2103. //
  2104. // We use the NextDataSet count to determine most recent copy.
  2105. //
  2106. WsbAffirmHr(pMediaInfo->GetCopyNextRemoteDataSet(copySet,
  2107. &copyNextRemoteDataSet));
  2108. if (copyNextRemoteDataSet > mostDataSets) {
  2109. //
  2110. // We need to make sure this copy is available.
  2111. //
  2112. WsbAffirmHr(pMediaInfo->GetCopyMediaSubsystemId(copySet,
  2113. &copyMediaSubsystemId));
  2114. try {
  2115. //
  2116. // Check the copy to make sure it exists and is enabled.
  2117. //
  2118. WsbAffirm(copyMediaSubsystemId != GUID_NULL, E_FAIL);
  2119. pCopyMedia = 0;
  2120. WsbAffirmHr(m_pHsmMediaMgr->FindCartridgeById(copyMediaSubsystemId, &pCopyMedia));
  2121. CComQIPtr<IRmsComObject, &IID_IRmsComObject> pCartCom = pCopyMedia;
  2122. WsbAffirmPointer(pCartCom);
  2123. if( S_OK == pCartCom->IsEnabled( ) ) {
  2124. //
  2125. // This copy is more recent, and available, so save info
  2126. //
  2127. WsbAffirmHr(pMediaInfo->GetCopyUpdate(copySet, &copyUpdate));
  2128. // set the NextRemoteDataSet to this copy's count
  2129. mostDataSets = copyNextRemoteDataSet;
  2130. // capture copy number, and update time
  2131. mostRecentCopy = copySet;
  2132. mostRecentCopyUpdate = copyUpdate;
  2133. }
  2134. } WsbCatchAndDo(hr,
  2135. hr = S_OK;
  2136. );
  2137. }
  2138. } // end 'for' loop
  2139. // Check to be sure there was a copy. If not, error out.
  2140. WsbAffirm( ((maxSets + 1) > mostRecentCopy), HSM_E_NO_COPIES_EXIST );
  2141. copySet = mostRecentCopy;
  2142. copyUpdate = mostRecentCopyUpdate;
  2143. } else {
  2144. WsbAffirmHr(pMediaInfo->GetCopyMediaSubsystemId(copySet, &copyMediaSubsystemId));
  2145. WsbAffirm(copyMediaSubsystemId != GUID_NULL, HSM_E_NO_COPY_EXISTS);
  2146. WsbAffirmHr(pMediaInfo->GetCopyUpdate(copySet, &copyUpdate));
  2147. }
  2148. WsbTrace(OLESTR("Source for re-creation: copySet number = %d; version: %ls\n"),
  2149. copySet, WsbFiletimeAsString(FALSE, copyUpdate) );
  2150. // Check to see if we are going to loose data because of re-creating
  2151. // the master.
  2152. // !!! IMPORTANT NOTE - bmd !!!
  2153. //
  2154. // We need to handle the case where we are recreating multiple times
  2155. // from out of sync copies. The last known good master always holds the info
  2156. // of the master in its last known good state. We are looking at the update
  2157. // timestamp which represent the version of the master or copy. The dataset
  2158. // number may be one more than what is store with the last known good master
  2159. // because of the particular logic required to handle partial/incomplete data sets:
  2160. // a) either the data set was written, but not committed, or b) the data set was started,
  2161. // but data was actually written.
  2162. CWsbStringPtr name;
  2163. CWsbStringPtr description;
  2164. GUID unusedGuid1;
  2165. GUID unusedGuid2; // NOTE: Use multiples so the trace in GetLastKnownGoodMasterInfo works
  2166. LONGLONG unusedLL1;
  2167. LONGLONG unusedLL2; // NOTE: Use multiples so the trace in GetLastKnownGoodMasterInfo works
  2168. BOOL lastKnownGoodMasterRecallOnly;
  2169. HRESULT lastKnownGoodMasterLastError;
  2170. HSM_JOB_MEDIA_TYPE unusedJMT;
  2171. // Get date the original master was last updated, this is stored with
  2172. // the last known good master.
  2173. WsbAffirmHr(pMediaInfo->GetLastKnownGoodMasterInfo(
  2174. &unusedGuid1, &lastKnownGoodMasterId, &unusedGuid2,
  2175. &unusedLL1, &unusedLL2,
  2176. &lastKnownGoodMasterLastError, &description, 0, &unusedJMT, &name, 0,
  2177. &lastKnownGoodMasterRecallOnly,
  2178. &lastKnownGoodMasterUpdate,
  2179. &lastKnownGoodMasterNextRemoteDataSet));
  2180. name.Free( );
  2181. description.Free( );
  2182. // If the original master is newer than the most
  2183. // recent copy... (it should not be possible for the master
  2184. // to be older than a copy!)
  2185. if (CompareFileTime(&lastKnownGoodMasterUpdate, &copyUpdate) != 0) {
  2186. // ...we may lose data, so log it.
  2187. WsbLogEvent( HSM_MESSAGE_RECREATE_MASTER_COPY_OLD, 0, NULL, NULL );
  2188. }
  2189. // Set up done. Now get/build necessary parameters for the call
  2190. // to actually duplicate the most recent copy onto scratch media.
  2191. // This copy will be the re-created master.
  2192. WsbAffirmHr(pMediaInfo->GetCopyMediaSubsystemId(copySet,
  2193. &copyMediaSubsystemId));
  2194. // Get copy description from RSM database since we don't cache it in
  2195. // RSS database anymore (Windows Bugs 407340)
  2196. pCopyMedia = 0;
  2197. WsbAffirmHr(m_pHsmMediaMgr->FindCartridgeById(copyMediaSubsystemId, &pCopyMedia));
  2198. WsbAffirmHr(pCopyMedia->GetDescription(&copyDescriptionAsBstr));
  2199. // Something simple for now.
  2200. copyDescriptionAsBstr.Prepend(OLESTR("RM-"));
  2201. // get the media set the storage pool contains so we assign the
  2202. // re-created master to the proper media set
  2203. WsbAffirmHr( pPool->GetMediaSet( &mediaSetId, &mediaSetName ));
  2204. // Parameters built. Call HSM subsystem to copy the most recent copy
  2205. // onto scratch media
  2206. WsbAffirm(!m_cancelCopyMedia, HSM_E_WORK_SKIPPED_CANCELLED);
  2207. GUID firstSideId = GUID_NULL;
  2208. WsbAffirmHrOk(m_pHsmMediaMgr->DuplicateCartridge(copyMediaSubsystemId,
  2209. firstSideId, &newMasterId, mediaSetId,
  2210. copyDescriptionAsBstr,
  2211. &newFreeBytes, &newCapacity,
  2212. RMS_DUPLICATE_RECYCLEONERROR));
  2213. // now that a replacement master media has been created, prepare
  2214. // to update the master media info in the database
  2215. // first get an interface pointer to the new re-created master
  2216. WsbAffirmHr(m_pHsmMediaMgr->FindCartridgeById(newMasterId, &pNewMasterMedia));
  2217. // Get re-created master's label name. Note that if secondary
  2218. // storage is tape, this 'name' is the tape's bar code. For
  2219. // other media (e.g., optical) this is a name.
  2220. WsbAffirmHr(pNewMasterMedia->GetName(&newName));
  2221. // Get Next Remote Data Set value from the copy. Used by the Validate
  2222. // job to determine what bags are on a master, it will be carried
  2223. // forward to the re-created master.
  2224. WsbAffirmHr(pMediaInfo->GetCopyNextRemoteDataSet(copySet,
  2225. &copyNextRemoteDataSet));
  2226. // get current master media info since some fields will not change
  2227. WsbAffirmHr(pMediaInfo->GetMediaInfo( &currentMediaId,
  2228. &currentMediaSubsystemId,
  2229. &poolId, &currentFreeBytes,
  2230. &currentCapacity,
  2231. &currentLastError,
  2232. &currentNextRemoteDataSet,
  2233. &currentDescription, 0,
  2234. &currentType, &currentName, 0,
  2235. &currentRecallOnly,
  2236. &currentUpdate,
  2237. &currentLogicalValidBytes,
  2238. &recreateMaster ));
  2239. WsbTrace(OLESTR("Original Master next dataset, ver = %d, %ls\n"), currentNextRemoteDataSet, WsbFiletimeAsString(FALSE, currentUpdate));
  2240. WsbTrace(OLESTR("Copy next dataset, ver = %d, %ls\n"), copyNextRemoteDataSet, WsbFiletimeAsString(FALSE, copyUpdate));
  2241. WsbTrace(OLESTR("LastKnownGoodMaster next dataset, ver = %d, %ls\n"), lastKnownGoodMasterNextRemoteDataSet, WsbFiletimeAsString(FALSE, lastKnownGoodMasterUpdate));
  2242. //
  2243. // Initialize the state of the recreated master
  2244. //
  2245. newRecallOnly = lastKnownGoodMasterRecallOnly;
  2246. BOOL inSync = (CompareFileTime(&lastKnownGoodMasterUpdate, &copyUpdate) == 0) &&
  2247. (lastKnownGoodMasterNextRemoteDataSet == copyNextRemoteDataSet);
  2248. if (!inSync) {
  2249. // If the copy was not up to date, mark the new master as RecallOnly.
  2250. // Also clear free bytes since we won't know this value
  2251. newRecallOnly = TRUE;
  2252. newFreeBytes = 0;
  2253. } else {
  2254. // This is an in-sync copy... check LastKnownGoodMaster RecallOnly and LastError to
  2255. // determine how to mark the recreated master RecallOnly status. Since the current,
  2256. // maybe recreated from an incomplete copy, we must use information about the
  2257. // LastKnownGoodMaster to determine the new RecallOnly status.
  2258. if (lastKnownGoodMasterRecallOnly) {
  2259. if (S_OK == lastKnownGoodMasterLastError) {
  2260. // If media is RecallOnly and there is no error (i.e. the media is full, or
  2261. // was marked RecallOnly via tool), we leave the media RecallOnly.
  2262. newRecallOnly = TRUE;
  2263. } else {
  2264. // If the original master was RecallOnly because of an error, reset
  2265. // the RecallOnly bit, since we should now have corrected the problem.
  2266. newRecallOnly = FALSE;
  2267. }
  2268. }
  2269. }
  2270. // Reset master media info - use new values where needed and original
  2271. // values where appropriate. The copy's Next Remote
  2272. // Data Set value allows the Validate job to handle managed files
  2273. // that are 'lost' by re-creating with an out of date copy.
  2274. WsbAffirmHr(pMediaInfo->SetMediaInfo(currentMediaId, newMasterId,
  2275. poolId,
  2276. newFreeBytes,
  2277. newCapacity, S_OK,
  2278. copyNextRemoteDataSet,
  2279. currentDescription, currentType,
  2280. newName,
  2281. newRecallOnly,
  2282. copyUpdate,
  2283. currentLogicalValidBytes, FALSE));
  2284. if (inSync) {
  2285. WsbAffirmHr(pMediaInfo->UpdateLastKnownGoodMaster());
  2286. }
  2287. // write the updated media record into the database
  2288. WsbAffirmHr(pMediaInfo->Write());
  2289. //
  2290. // Now we need to determine what to do with the old media...
  2291. // Note that recycling old media is done only after a successful update in the DB
  2292. //
  2293. HRESULT hrRecycle;
  2294. if (inSync) {
  2295. // We recreated an in sync master. The old LastKnownGoodMaster will be
  2296. // overwritten with the new recreated master, so we can safely recycle
  2297. // the LastKnownGoodMaster media.
  2298. // If the cartridge cannot be found we assume it
  2299. // was already deallocated through the media manager UI.
  2300. hrRecycle = m_pHsmMediaMgr->RecycleCartridge( lastKnownGoodMasterId, 0 );
  2301. WsbAffirm( S_OK == hrRecycle || RMS_E_CARTRIDGE_NOT_FOUND == hrRecycle, hrRecycle );
  2302. // if the current media is not the same as the LastKnownGoodMaster, we
  2303. // can recyle the current media, as well. This happens when the
  2304. // current media was recreated from an incomplete (out-of-sync) copy.
  2305. if (lastKnownGoodMasterId != currentMediaSubsystemId) {
  2306. // If the cartridge cannot be found we assume it
  2307. // was already deallocated through the media manager UI.
  2308. hrRecycle = m_pHsmMediaMgr->RecycleCartridge( currentMediaSubsystemId, 0 );
  2309. WsbAffirm( S_OK == hrRecycle || RMS_E_CARTRIDGE_NOT_FOUND == hrRecycle, hrRecycle );
  2310. }
  2311. } else {
  2312. // We recreated from an out-of-sync copy. If the current media
  2313. // and the LastKnownGoodMaster are different, we recycle the current
  2314. // media, since this will be overwritten with the new recreated master.
  2315. // This handles the case where we recreate from an out of sync copy
  2316. // multiple times.
  2317. if (lastKnownGoodMasterId != currentMediaSubsystemId) {
  2318. // If the cartridge cannot be found we assume it
  2319. // was already deallocated through the media manager UI.
  2320. hrRecycle = m_pHsmMediaMgr->RecycleCartridge( currentMediaSubsystemId, 0 );
  2321. WsbAffirm( S_OK == hrRecycle || RMS_E_CARTRIDGE_NOT_FOUND == hrRecycle, hrRecycle );
  2322. }
  2323. }
  2324. } WsbCatch(hr); // inner 'try' - get media info entity and process
  2325. // if any error was thrown after getting the master media record reset
  2326. // the 'recreate master' state to off (FALSE) for safety and so it appears
  2327. // correctly in the UI
  2328. if (( haveMasterMediaRecord ) && ( hr != S_OK )) {
  2329. WsbAffirmHr( pMediaInfo->SetRecreate( FALSE ) );
  2330. WsbAffirmHr( pMediaInfo->Write() );
  2331. }
  2332. // close the database
  2333. WsbAffirmHr( m_pSegmentDatabase->Close(pDbSession) );
  2334. } WsbCatch(hr);
  2335. // processing is done. Singly-assigned smart interface pointers will
  2336. // auto-garbage collect themselves.
  2337. if (S_OK == hr) {
  2338. WsbLogEvent( HSM_MESSAGE_RECREATE_MASTER_END, 0, NULL, WsbHrAsString(hr), NULL );
  2339. } else {
  2340. WsbLogEvent( HSM_MESSAGE_RECREATE_MASTER_ERROR_END, 0, NULL, WsbHrAsString(hr), NULL );
  2341. }
  2342. // Reset flags
  2343. Lock();
  2344. if (m_inCopyMedia && HSM_E_BUSY != hr) {
  2345. m_inCopyMedia = FALSE;
  2346. m_cancelCopyMedia = FALSE;
  2347. }
  2348. Unlock();
  2349. WsbTraceOut(OLESTR("CHsmServer::RecreateMaster"), OLESTR("hr = <%ls>"),
  2350. WsbHrAsString(hr));
  2351. return(hr);
  2352. // leaving CopyMedia code, reset Tracing bit to the Hsm Engine
  2353. #undef WSB_TRACE_IS
  2354. #define WSB_TRACE_IS WSB_TRACE_BIT_HSMENG
  2355. }
  2356. HRESULT
  2357. CHsmServer::SynchronizeMedia(
  2358. IN GUID poolId,
  2359. IN USHORT copySet
  2360. )
  2361. /*++
  2362. Implements:
  2363. IHsmServer::SynchronizeMedia().
  2364. Routine Description:
  2365. This routine implements the COM method for updating a specified Copy Set.
  2366. All copy media in the Copy Set either out of date (aka not synchronized
  2367. with the master) or non-existent (either hasn't been made or has been
  2368. deleted by the SysAdmin) will be 'synchronized' by this method. Out of
  2369. date media are copied (from the master) and the MediaInfo database is
  2370. updated to reflect the new info.
  2371. After opening the Segment database (a single database containing all Engine
  2372. database tables), getting the MediaInfo (secondary storage master media) records
  2373. (entity) and connecting to the RMS subsystem, the method enters its main loop.
  2374. The loop iterates through all MediaInfo records. Those that belong to the specified
  2375. storage pool are processed. First a check is made to ensure that the copy set
  2376. requested to be updated is valid. If valid, and if that copy set's media is out of
  2377. sync with the master (meaning it is outdated), the copy media is then duplicated
  2378. from the master. (The copy media is actually 'updated', meaning only that
  2379. portion of the master that was not previously written to the copy is copied.)
  2380. Finally, that master's specified Copy Set media record is updated in the database.
  2381. The loop then iterates to the next MediaInfo record. After all MediaInfo
  2382. records have been processed the database is closed and the method returns.
  2383. Arguments:
  2384. poolId - The id (GUID) for the Storage Pool whose copy set specified in the
  2385. following parameter is to synchronized (aka updated). (Sakkara only
  2386. has one storage pool.)
  2387. copySet - the number of the copy set that is to be updated. (Sakkara allows
  2388. anywhere from 1 to 3 copy sets of secondary storage media, as configured
  2389. by the System Administrator.)
  2390. Return Value:
  2391. S_OK - The call succeeded (the specified copy set in the specified storage
  2392. pool was updated).
  2393. HSM_E_BUSY - Another media copy operation was already in progress.
  2394. HSM_E_WORK_SKIPPED_CANCELLED - Operation was cancelled.
  2395. Any other value - The call failed in either opening the Engine's Segment
  2396. database, in getting the MediaInfo database entity, or in connecting
  2397. to the RMS subsystem.
  2398. NOTE that any error thrown during this routine's main loop will be
  2399. logged to the Event Log, but will then be over-written to S_OK. That
  2400. record is skipped and the next record in the loop is processed. Due
  2401. to this it is possible that an out of sync copy set media will not be
  2402. updated.
  2403. --*/
  2404. {
  2405. // since this code is currently only used by the CopyMedia routines,
  2406. // reset the Tracing bit
  2407. #undef WSB_TRACE_IS
  2408. #define WSB_TRACE_IS WSB_TRACE_BIT_COPYMEDIA
  2409. HRESULT hr = S_OK;
  2410. USHORT maxSets = 0;
  2411. FILETIME mediaTime;
  2412. GUID mediaId = GUID_NULL;
  2413. GUID mediaSetId = GUID_NULL;
  2414. GUID copyPoolId = GUID_NULL;
  2415. HRESULT hrDup = S_OK;
  2416. BOOL atLeastOneCopyError = FALSE;
  2417. SHORT masterNextRemoteDataSet;
  2418. CComPtr<IHsmStoragePool> pPool;
  2419. CComPtr<IMediaInfo> pMediaInfo;
  2420. CComPtr<IRmsCartridge> pCopyMedia;
  2421. CComPtr<IWsbDbSession> pDbSession;
  2422. CWsbStringPtr mediaDescription;
  2423. WsbTraceIn(OLESTR("CHsmServer::SynchronizeMedia"),
  2424. OLESTR("poolId = <%ls>, copySet = <%d>"),
  2425. WsbGuidAsString(poolId), copySet);
  2426. // log 'information' message
  2427. WsbLogEvent( HSM_MESSAGE_SYNCHRONIZE_MEDIA_START, 0, NULL, NULL );
  2428. try {
  2429. wchar_t copySetAsString[20];
  2430. BOOLEAN done = FALSE;
  2431. BOOLEAN firstPass = TRUE;
  2432. BOOL okToContinue = TRUE;
  2433. // Make sure we're not already busy & haven't been cancelled
  2434. Lock();
  2435. if (m_inCopyMedia) {
  2436. okToContinue = FALSE;
  2437. } else {
  2438. m_inCopyMedia = TRUE;
  2439. }
  2440. Unlock();
  2441. WsbAffirm(okToContinue, HSM_E_BUSY);
  2442. WsbAffirm(!m_cancelCopyMedia, HSM_E_WORK_SKIPPED_CANCELLED);
  2443. // open the Engine's Segment database
  2444. WsbAffirmHr(m_pSegmentDatabase->Open(&pDbSession));
  2445. // get interface pointer to the MediaInfo records (entity) in the
  2446. // Segment database
  2447. WsbAffirmHr(m_pSegmentDatabase->GetEntity(pDbSession,
  2448. HSM_MEDIA_INFO_REC_TYPE, IID_IMediaInfo,
  2449. (void**) &pMediaInfo));
  2450. WsbAffirm(!m_cancelCopyMedia, HSM_E_WORK_SKIPPED_CANCELLED);
  2451. // Convert copySet number to a sting for use later
  2452. _itow( copySet, copySetAsString, 10 );
  2453. // Main processing loop -- loop through all media at least once to
  2454. // check for out-of-date copies. Keep looping if any copies were
  2455. // skipped because the mount request timed out.
  2456. while (!done) {
  2457. LONG nTimedOut = 0;
  2458. // Iterate through the (master secondary storage) media looking for
  2459. // duplicate (copy) media in this copy set that either haven't been made
  2460. // or haven't been synchronized since the last time the master was updated.
  2461. for (hr = pMediaInfo->First(); SUCCEEDED(hr); hr = pMediaInfo->Next()) {
  2462. CWsbStringPtr copyDescription;
  2463. HRESULT copyError = S_OK;
  2464. GUID copyMediaId = GUID_NULL;
  2465. SHORT copyNextRemoteDataSet = 0;
  2466. CWsbStringPtr copyName;
  2467. FILETIME copyTime = WsbLLtoFT(0);
  2468. BOOL gotCopyInfo = FALSE;
  2469. BOOL updateMediaInfo = FALSE;
  2470. BOOLEAN mountingScratch = FALSE;
  2471. try {
  2472. WsbAffirm(!m_cancelCopyMedia, HSM_E_WORK_SKIPPED_CANCELLED);
  2473. // get the storage pool GUID of this master media (& its copies)
  2474. WsbAffirmHr(pMediaInfo->GetStoragePoolId(&copyPoolId));
  2475. // If the media is from the desired pool (or any pool) then check it.
  2476. // (Passing in a poolId of NULL has the effect of indicating the
  2477. // SysAdmin wants copy set 'x' in all storage pools updated in one
  2478. // operation. Note that Sakkara currently uses this technique
  2479. // when the 'Update Copyset x' command is issued via the UI
  2480. // (it launches RsLaunch with no pool id specified).)
  2481. if ((poolId == GUID_NULL) || (poolId == copyPoolId)) {
  2482. // Ensure the copy set requested for update is valid:
  2483. // Get the storage pool using the pool's HSM (not remote media
  2484. // subsystem) id (GUID).
  2485. hr = FindHsmStoragePoolById(copyPoolId, &pPool);
  2486. if (S_OK != hr) {
  2487. // log and throw the returned error (this media will be
  2488. // skipped)
  2489. WsbLogEvent( HSM_MESSAGE_SEARCH_STGPOOL_BY_HSMID_ERROR,
  2490. 0, NULL, WsbHrAsString(hr), NULL );
  2491. WsbThrow( hr );
  2492. }
  2493. // get the number of copy sets configured for this pool
  2494. WsbAffirmHr(pPool->GetNumMediaCopies(&maxSets));
  2495. // ensure requested copy set is valid
  2496. WsbAffirm(copySet <= maxSets, E_INVALIDARG);
  2497. // to determine if the copy set media needs to be updated
  2498. // get the date the master media was last updated,
  2499. // and the last dataset written to the media...
  2500. //
  2501. // !!! IMPORTANT NOTE !!!
  2502. // This is the current time and data set count. If a migrate
  2503. // is in progress this is NOT the final update time.
  2504. //
  2505. WsbAffirmHr(pMediaInfo->GetUpdate(&mediaTime));
  2506. WsbAffirmHr(pMediaInfo->GetNextRemoteDataSet(&masterNextRemoteDataSet));
  2507. // ...and get the date the copy media was last updated -
  2508. // for efficiency get all copy media info in 1 call
  2509. // (copyMediaId is used later).
  2510. WsbAffirmHr(pMediaInfo->GetCopyInfo(copySet, &copyMediaId,
  2511. &copyDescription, 0, &copyName, 0,
  2512. &copyTime, &copyError,
  2513. &copyNextRemoteDataSet));
  2514. gotCopyInfo = TRUE;
  2515. // If the copy media is out of date (copy's date last
  2516. // updated < master media's date last updated OR nextDataSet don't
  2517. // match), synchronize it.
  2518. //
  2519. // If this is not the first pass through the media records, we only
  2520. // want to retry copies that timed out.
  2521. if ((CompareFileTime( &copyTime, &mediaTime ) < 0 ||
  2522. copyNextRemoteDataSet != masterNextRemoteDataSet) &&
  2523. (firstPass ||
  2524. (RMS_E_TIMEOUT == copyError) ||
  2525. (RMS_E_SCRATCH_NOT_FOUND == copyError) ||
  2526. (RMS_E_CARTRIDGE_UNAVAILABLE == copyError))) {
  2527. CWsbBstrPtr mediaDescriptionAsBstr;
  2528. CWsbBstrPtr mediaSetName;
  2529. GUID copySecondSideId = GUID_NULL;
  2530. DWORD nofDrives = 0;
  2531. mountingScratch = FALSE;
  2532. // get media set id the storage pool contains so we assign
  2533. // the synchronized copy media to the proper media set
  2534. WsbAffirmHr(pPool->GetMediaSet( &mediaSetId, &mediaSetName ));
  2535. // since the duplication itself will be done by the remote
  2536. // media subsystem, get the subsystem GUID of the master
  2537. WsbAffirmHr(pMediaInfo->GetMediaSubsystemId(&mediaId));
  2538. // build the description (display name) for the copy set
  2539. // media as a BSTR (required format for duplicate call)
  2540. WsbAffirmHr(pMediaInfo->GetDescription(&mediaDescription, 0));
  2541. // check if we have at least 2 enabled drives for synchronizing the media
  2542. // if not - abort
  2543. WsbAffirmHr(m_pHsmMediaMgr->GetNofAvailableDrives(mediaSetId, &nofDrives));
  2544. WsbAffirm(nofDrives > 1, HSM_E_NO_TWO_DRIVES);
  2545. // If no media has been allocated for this copy, we need
  2546. // to construct a media description string
  2547. if (GUID_NULL == copyMediaId) {
  2548. mountingScratch = TRUE;
  2549. mediaDescriptionAsBstr = mediaDescription;
  2550. mediaDescriptionAsBstr.Append(" (Copy ");
  2551. mediaDescriptionAsBstr.Append(copySetAsString);
  2552. mediaDescriptionAsBstr.Append(")");
  2553. WsbTrace(OLESTR("CHsmServer::SynchronizeMedia: scratch desc = %ls\n"),
  2554. mediaDescriptionAsBstr);
  2555. // In case of two-sided medias, we need to check whether the
  2556. // original has a second side which has an existing copy
  2557. // If so, we want to allocate the second side of this existing copy
  2558. if (S_OK == m_pHsmMediaMgr->IsMultipleSidedMedia(mediaSetId)) {
  2559. GUID secondSideId;
  2560. BOOL bValid;
  2561. // Get second side of original
  2562. WsbAffirmHr(m_pHsmMediaMgr->CheckSecondSide(mediaId, &bValid, &secondSideId));
  2563. if (bValid && (GUID_NULL != secondSideId)) {
  2564. CComPtr<IMediaInfo> pSecondSideInfo;
  2565. GUID idFromDb;
  2566. // Get second side record (if second side exists and allocated - it must be allocated by us!)
  2567. // Since the subsystem-id is not a key, we must traverse the table
  2568. WsbAffirmHr(m_pSegmentDatabase->GetEntity(pDbSession, HSM_MEDIA_INFO_REC_TYPE,
  2569. IID_IMediaInfo, (void**) &pSecondSideInfo));
  2570. for (hr = pSecondSideInfo->First(); SUCCEEDED(hr); hr = pSecondSideInfo->Next()) {
  2571. WsbAffirmHr(pSecondSideInfo->GetMediaSubsystemId(&idFromDb));
  2572. if (idFromDb == secondSideId) {
  2573. BOOL bCopyValid;
  2574. GUID emptySideCopyId;
  2575. // Just set second side copy for allocation as the other side of the existing copy cartridge
  2576. WsbAffirmHr(pSecondSideInfo->GetCopyMediaSubsystemId(copySet, &copySecondSideId));
  2577. if (GUID_NULL != copySecondSideId) {
  2578. // Need to check if the second side of the existing copy is available:
  2579. // After recreate-a-master, it might not be available so then
  2580. // we'll have to allocate a new media for the copy
  2581. WsbAffirmHr(m_pHsmMediaMgr->CheckSecondSide(copySecondSideId, &bCopyValid, &emptySideCopyId));
  2582. if ((! bCopyValid) || (GUID_NULL != emptySideCopyId)) {
  2583. // Second side of existing copy is not valid or not empty...
  2584. // Reset copy-media-id ==> will allocate a new media for the copy
  2585. copySecondSideId = GUID_NULL;
  2586. }
  2587. }
  2588. break;
  2589. }
  2590. }
  2591. }
  2592. }
  2593. } else {
  2594. mediaDescriptionAsBstr = copyDescription;
  2595. }
  2596. // call remote media subsystem to copy the master
  2597. // onto the copy set media indicated
  2598. WsbAffirm(!m_cancelCopyMedia,
  2599. HSM_E_WORK_SKIPPED_CANCELLED);
  2600. // These two LONGLONGs are not used, but simply placeholders for the DuplicateCartridge
  2601. // function call (avoids passing null reference pointer errors).
  2602. LONGLONG FreeSpace = 0;
  2603. LONGLONG Capacity = 0;
  2604. hrDup = m_pHsmMediaMgr->DuplicateCartridge(mediaId,
  2605. copySecondSideId, &copyMediaId, mediaSetId,
  2606. mediaDescriptionAsBstr, &FreeSpace, &Capacity, 0);
  2607. WsbTrace(OLESTR("CHsmServer::SynchronizeMedia: DuplicateCartridge = <%ls>\n"),
  2608. WsbHrAsString(hrDup));
  2609. // Make sure the status get saved in DB
  2610. copyError = hrDup;
  2611. updateMediaInfo = TRUE;
  2612. //
  2613. // We need to refresh the mediaTime and next data set. This
  2614. // handles case were DuplicateCartridge was waiting on migrate to finish.
  2615. //
  2616. WsbAffirmHr(pMediaInfo->GetUpdate(&mediaTime));
  2617. WsbAffirmHr(pMediaInfo->GetNextRemoteDataSet(&masterNextRemoteDataSet));
  2618. // If we got a new piece of media, save the info about
  2619. // it in the DB.
  2620. // The DuplicateCartridge operation may fail after the media was
  2621. // allocated, so we need to record the copy media id in our databases
  2622. // no matter what. If copyMediaId is still GUID_NULL we know the
  2623. // failure occurred while allocating the media and skip this step.
  2624. if (mountingScratch && copyMediaId != GUID_NULL) {
  2625. CWsbBstrPtr mediaNameAsBstr;
  2626. // get the copy media
  2627. WsbAffirmHr(m_pHsmMediaMgr->FindCartridgeById(copyMediaId,
  2628. &pCopyMedia));
  2629. // Get the label name of the copy media that was just
  2630. // created. Note that if secondary storage is tape,
  2631. // this 'name' is the tape's bar code. For other media
  2632. // (e.g., optical) this is a name.
  2633. copyName.Free();
  2634. WsbAffirmHr(pCopyMedia->GetName(&mediaNameAsBstr));
  2635. copyName = mediaNameAsBstr;
  2636. // Save the description string
  2637. copyDescription = mediaDescriptionAsBstr;
  2638. }
  2639. // If the duplication succeeded, update the MediaInfo
  2640. // data
  2641. if (S_OK == hrDup) {
  2642. copyTime = mediaTime;
  2643. copyNextRemoteDataSet = masterNextRemoteDataSet;
  2644. // If the duplication failed because of a mount timeout,
  2645. // count it and we'll try again on the next pass
  2646. } else if ((RMS_E_TIMEOUT == hrDup) ||
  2647. (RMS_E_SCRATCH_NOT_FOUND == hrDup) ||
  2648. (RMS_E_CARTRIDGE_UNAVAILABLE == hrDup)) {
  2649. nTimedOut++;
  2650. } else {
  2651. WsbThrow(hrDup);
  2652. }
  2653. } // end 'if copy set media is out of date'
  2654. } // end 'if poolId is valid'
  2655. } WsbCatchAndDo(hr, // 'try' in the for loop
  2656. // If user cancelled, don't count it as an error, just exit
  2657. if (HSM_E_WORK_SKIPPED_CANCELLED == hr) {
  2658. WsbThrow(hr);
  2659. }
  2660. // If there are no 2 enabled drives, log a message but don't count it as a media error
  2661. if (HSM_E_NO_TWO_DRIVES == hr) {
  2662. WsbLogEvent(HSM_MESSAGE_SYNCHRONIZE_MEDIA_ABORT, 0, NULL,
  2663. copySetAsString, WsbHrAsString(hr), NULL);
  2664. WsbThrow(hr);
  2665. }
  2666. // If a piece of media fails during the 'for' loop log the error in
  2667. // the Event Log, then continue through loop to try the others.
  2668. atLeastOneCopyError = TRUE;
  2669. // Update the media info with the error
  2670. copyError = hr;
  2671. if (gotCopyInfo) {
  2672. updateMediaInfo = TRUE;
  2673. }
  2674. pMediaInfo->GetDescription( &mediaDescription, 0 );
  2675. WsbLogEvent( HSM_MESSAGE_SYNCHRONIZE_MEDIA_ERROR, 0, NULL,
  2676. copySetAsString, (OLECHAR*)mediaDescription,
  2677. WsbHrAsString( hr ), NULL );
  2678. );
  2679. // Update the MediaInfo record if anything changed
  2680. if (updateMediaInfo) {
  2681. // It may have been a while since we got the the media info
  2682. // record and some of the data could have changed (e.g. if a
  2683. // synchronize media job on a different copy set completed) so
  2684. // we re-read the record before the update and we do it inside
  2685. // a transaction to make sure it can't get changed while we're
  2686. // doing this
  2687. hr = S_OK;
  2688. WsbAffirmHr(pDbSession->TransactionBegin());
  2689. try {
  2690. // This FindEQ call will synchronize the data in our local
  2691. // MediaInfo record with what is in the DB
  2692. WsbAffirmHr(pMediaInfo->FindEQ());
  2693. // Update the copy media info - specifically the media id
  2694. // (if the copy media was just created), description,
  2695. // name (bar code for tape), date last updated (which
  2696. // is set to the master's date last updated) and the
  2697. // next remote dataset (conceptually same as next bag).
  2698. WsbAffirmHr(pMediaInfo->SetCopyInfo(copySet, copyMediaId,
  2699. copyDescription, copyName, copyTime, copyError,
  2700. copyNextRemoteDataSet));
  2701. // write the changes into the database
  2702. WsbAffirmHr(pMediaInfo->Write());
  2703. } WsbCatch(hr);
  2704. if (S_OK == hr) {
  2705. WsbAffirmHr(pDbSession->TransactionEnd());
  2706. } else {
  2707. WsbAffirmHr(pDbSession->TransactionCancel());
  2708. atLeastOneCopyError = TRUE;
  2709. //
  2710. // If the copy info could not be updated in the database and this is a new copy,
  2711. // we need to recycle the copy, otherwise, the RSS database is inconsistent
  2712. //
  2713. if (mountingScratch && copyMediaId != GUID_NULL) {
  2714. HRESULT hrRecycle = m_pHsmMediaMgr->RecycleCartridge( copyMediaId, 0 );
  2715. WsbTraceAlways(OLESTR("CHsmServer::SynchronizeMedia: Recycling copy cartridge after DB_update failure, hrRecycle = <%ls>\n"), WsbHrAsString(hrRecycle));
  2716. }
  2717. //
  2718. // Log a message on the error
  2719. //
  2720. mediaDescription = L"";
  2721. pMediaInfo->GetDescription( &mediaDescription, 0 );
  2722. WsbLogEvent( HSM_MESSAGE_SYNCHRONIZE_MEDIA_ERROR, 0, NULL,
  2723. copySetAsString, (OLECHAR*)mediaDescription,
  2724. WsbHrAsString( hr ), NULL );
  2725. //
  2726. // Make sure we don't continue the job if an unexpected database-update error occurs
  2727. //
  2728. WsbThrow(hr);
  2729. }
  2730. }
  2731. // Release the interface pointers that will be reassigned during the
  2732. // next iteration of the 'for' loop.
  2733. pPool = 0;
  2734. pCopyMedia = 0;
  2735. } // end 'for' loop
  2736. // We will fall out of the 'for' loop after processing all MediaInfo
  2737. // records. This is indicated by the Next() call returning WSB_E_NOTFOUND.
  2738. // Since this is normal, reset hr to indicate so.
  2739. if (WSB_E_NOTFOUND == hr) {
  2740. hr = S_OK;
  2741. }
  2742. if (0 == nTimedOut) {
  2743. done = TRUE;
  2744. }
  2745. firstPass = FALSE;
  2746. } // End of while loop
  2747. } WsbCatch(hr);
  2748. // Close the database (if it was opened)
  2749. if (pDbSession) {
  2750. m_pSegmentDatabase->Close(pDbSession);
  2751. }
  2752. // Report an error if any copy failed
  2753. if (S_OK == hr && atLeastOneCopyError) {
  2754. hr = HSM_E_MEDIA_COPY_FAILED;
  2755. }
  2756. WsbLogEvent( HSM_MESSAGE_SYNCHRONIZE_MEDIA_END, 0, NULL, WsbHrAsString(hr), NULL );
  2757. // Reset flags
  2758. Lock();
  2759. if (m_inCopyMedia && HSM_E_BUSY != hr) {
  2760. m_inCopyMedia = FALSE;
  2761. m_cancelCopyMedia = FALSE;
  2762. }
  2763. Unlock();
  2764. WsbTraceOut(OLESTR("CHsmServer::SynchronizeMedia"), OLESTR("hr = <%ls>"),
  2765. WsbHrAsString(hr));
  2766. return(hr);
  2767. // leaving CopyMedia code, reset Tracing bit to the Hsm Engine
  2768. #undef WSB_TRACE_IS
  2769. #define WSB_TRACE_IS WSB_TRACE_BIT_HSMENG
  2770. }
  2771. HRESULT
  2772. CHsmServer::CloseOutDb( void )
  2773. /*++
  2774. Implements:
  2775. IHsmServer::CloseOutDb().
  2776. --*/
  2777. {
  2778. HRESULT hr = S_OK;
  2779. WsbTraceIn(OLESTR("CHsmServer::CloseOutDb"), OLESTR(""));
  2780. try {
  2781. if (m_pDbSys != 0) {
  2782. WsbAffirmHr(m_pDbSys->Backup(NULL, 0));
  2783. }
  2784. } WsbCatch(hr);
  2785. WsbTraceOut(OLESTR("CHsmServer::CloseOutDb"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2786. return(hr);
  2787. }
  2788. HRESULT
  2789. CHsmServer::BackupSegmentDb( void )
  2790. /*++
  2791. Implements:
  2792. IHsmServer::BackupSegmentDb().
  2793. --*/
  2794. {
  2795. HRESULT hr = S_OK;
  2796. WsbTraceIn(OLESTR("CHsmServer::BackupSegmentDb"), OLESTR(""));
  2797. try {
  2798. if (m_pDbSys != 0) {
  2799. WsbAffirmHr(m_pDbSys->Backup(NULL, 0));
  2800. }
  2801. } WsbCatch(hr);
  2802. WsbTraceOut(OLESTR("CHsmServer::BackupSegmentDb"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2803. return(hr);
  2804. }
  2805. HRESULT
  2806. CHsmServer::ChangeSysState(
  2807. IN OUT HSM_SYSTEM_STATE* pSysState
  2808. )
  2809. /*++
  2810. Implements:
  2811. IHsmSystemState::ChangeSysState().
  2812. --*/
  2813. {
  2814. HRESULT hr = S_OK;
  2815. WsbTraceIn(OLESTR("CHsmServer::ChangeSysState"), OLESTR("State = %lx"),
  2816. pSysState->State);
  2817. try {
  2818. if (pSysState->State & HSM_STATE_SUSPEND) {
  2819. if (!m_Suspended) {
  2820. m_Suspended = TRUE;
  2821. // Pause the jobs
  2822. NotifyAllJobs(HSM_JOB_STATE_PAUSING);
  2823. // Save data
  2824. SavePersistData();
  2825. SaveMetaData();
  2826. }
  2827. } else if (pSysState->State & HSM_STATE_RESUME) {
  2828. m_Suspended = FALSE;
  2829. // Resume the jobs
  2830. NotifyAllJobs(HSM_JOB_STATE_RESUMING);
  2831. } else if (pSysState->State & HSM_STATE_SHUTDOWN) {
  2832. // Close the CheckManagedResources thread (if it is still running)
  2833. StopCheckManagedResourcesThread();
  2834. // Close the autosave thread
  2835. StopAutosaveThread();
  2836. //
  2837. // Since MediaCopy operations do not run as standard jobs,
  2838. // the only way to cancel these is to suspend or shutdown RMS
  2839. // directly.
  2840. //
  2841. try {
  2842. CComPtr<IHsmSystemState> pISysState;
  2843. HSM_SYSTEM_STATE SysState;
  2844. WsbAffirmHr(m_pHsmMediaMgr->QueryInterface(IID_IHsmSystemState, (void**) &pISysState));
  2845. WsbAffirmPointer(pISysState);
  2846. SysState.State = HSM_STATE_SUSPEND;
  2847. WsbAffirmHr(pISysState->ChangeSysState(&SysState));
  2848. SysState.State = HSM_STATE_RESUME;
  2849. WsbAffirmHr(pISysState->ChangeSysState(&SysState));
  2850. } WsbCatch(hr);
  2851. // Cancel jobs
  2852. CancelAllJobs();
  2853. // Save data
  2854. SavePersistData();
  2855. SaveMetaData();
  2856. }
  2857. // Notify the task manager
  2858. if (m_pHsmFsaTskMgr) {
  2859. m_pHsmFsaTskMgr->ChangeSysState(pSysState);
  2860. }
  2861. // Notify the Media Server
  2862. try {
  2863. CComPtr<IHsmSystemState> pISysState;
  2864. WsbAffirmHr(m_pHsmMediaMgr->QueryInterface(IID_IHsmSystemState, (void**) &pISysState));
  2865. WsbAffirmPointer(pISysState);
  2866. WsbAffirmHr(pISysState->ChangeSysState(pSysState));
  2867. } WsbCatch(hr);
  2868. if (pSysState->State & HSM_STATE_SHUTDOWN) {
  2869. CloseOutDb();
  2870. // Release collections
  2871. if (m_pMountingMedias) {
  2872. m_pMountingMedias->RemoveAllAndRelease();
  2873. }
  2874. // Release collections
  2875. if (m_pJobs) {
  2876. m_pJobs->RemoveAllAndRelease();
  2877. }
  2878. if (m_pJobDefs) {
  2879. m_pJobDefs->RemoveAllAndRelease();
  2880. }
  2881. if (m_pPolicies) {
  2882. m_pPolicies->RemoveAllAndRelease();
  2883. }
  2884. if (m_pManagedResources) {
  2885. ULONG count;
  2886. CComPtr<IHsmManagedResourceCollection> pIMRC;
  2887. // We can't use RemoveAllAndRelease because the Remove function for
  2888. // this non-standard collection tells the FSA to unmanage the resource.
  2889. // Then when the FSA shuts down, the list of managed resources is empty.
  2890. // The next time the FSA starts up, it loads an empty list of managed
  2891. // resources, which is wrong. The method DeleteAllAndRelesae avoids
  2892. // this problem.
  2893. WsbAffirmHr(m_pManagedResources->QueryInterface(IID_IHsmManagedResourceCollection,
  2894. (void**) &pIMRC));
  2895. pIMRC->DeleteAllAndRelease();
  2896. pIMRC = 0;
  2897. WsbAffirmHr(m_pManagedResources->GetEntries(&count));
  2898. }
  2899. if (m_pStoragePools) {
  2900. m_pStoragePools->RemoveAllAndRelease();
  2901. }
  2902. if (m_pMessages) {
  2903. m_pMessages->RemoveAllAndRelease();
  2904. }
  2905. if (m_pOnlineInformation) {
  2906. m_pOnlineInformation->RemoveAllAndRelease();
  2907. }
  2908. // Dump object table info
  2909. WSB_OBJECT_TRACE_TYPES;
  2910. WSB_OBJECT_TRACE_POINTERS(WSB_OTP_STATISTICS | WSB_OTP_ALL);
  2911. m_initializationCompleted = FALSE;
  2912. }
  2913. } WsbCatch(hr);
  2914. WsbTraceOut(OLESTR("CHsmServer::ChangeSysState"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2915. return(hr);
  2916. }
  2917. STDMETHODIMP
  2918. CHsmServer::Unload(
  2919. void
  2920. )
  2921. /*++
  2922. Implements:
  2923. IwsbServer::Unload
  2924. Return Value:
  2925. S_OK - Success
  2926. Other - Error
  2927. --*/
  2928. {
  2929. HRESULT hr = S_OK;
  2930. WsbTraceIn(OLESTR("CHsmServer::Unload"), OLESTR(""));
  2931. try {
  2932. // We only need to release what may have gotten set/created by
  2933. // a failed Load attempt.
  2934. if (m_pJobs) {
  2935. m_pJobs->RemoveAllAndRelease();
  2936. }
  2937. if (m_pJobDefs) {
  2938. m_pJobDefs->RemoveAllAndRelease();
  2939. }
  2940. if (m_pPolicies) {
  2941. m_pPolicies->RemoveAllAndRelease();
  2942. }
  2943. if (m_pManagedResources) {
  2944. CComPtr<IHsmManagedResourceCollection> pIMRC;
  2945. // We can't use RemoveAllAndRelease because the Remove function for
  2946. // this non-standard collection tells the FSA to unmanage the resource.
  2947. // Then when the FSA shuts down, the list of managed resources is empty.
  2948. // The next time the FSA starts up, it loads an empty list of managed
  2949. // resources, which is wrong. The method DeleteAllAndRelesae avoids
  2950. // this problem.
  2951. WsbAffirmHr(m_pManagedResources->QueryInterface(IID_IHsmManagedResourceCollection,
  2952. (void**) &pIMRC));
  2953. pIMRC->DeleteAllAndRelease();
  2954. }
  2955. if (m_pStoragePools) {
  2956. m_pStoragePools->RemoveAllAndRelease();
  2957. }
  2958. if (m_pMessages) {
  2959. m_pMessages->RemoveAllAndRelease();
  2960. }
  2961. } WsbCatch(hr);
  2962. WsbTraceOut(OLESTR("CHsmServer::Unload"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2963. return(hr);
  2964. }
  2965. STDMETHODIMP
  2966. CHsmServer::DestroyObject(
  2967. void
  2968. )
  2969. /*++
  2970. Implements:
  2971. IWsbServer::DestroyObject
  2972. Return Value:
  2973. S_OK - Success
  2974. --*/
  2975. {
  2976. HRESULT hr = S_OK;
  2977. WsbTraceIn(OLESTR("CHsmServer::DestroyObject"), OLESTR(""));
  2978. CComObject<CHsmServer> *pEngDelete = (CComObject<CHsmServer> *)this;
  2979. delete pEngDelete;
  2980. WsbTraceOut(OLESTR("CHsmServer::DestroyObject"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2981. return(hr);
  2982. }
  2983. HRESULT
  2984. CHsmServer::CancelAllJobs( void )
  2985. /*++
  2986. Implements:
  2987. IHsmServer::CancelAllJobs().
  2988. --*/
  2989. {
  2990. HRESULT hr = S_OK;
  2991. HRESULT hr2 = S_OK;
  2992. BOOL foundRunningJob = FALSE;
  2993. CComPtr<IWsbCollection> pCollection;
  2994. CComPtr<IWsbEnum> pEnum;
  2995. CComPtr<IHsmJob> pJob;
  2996. WsbTraceIn(OLESTR("CHsmServer::CancelAllJobs"), OLESTR(""));
  2997. try {
  2998. //
  2999. // Set up for the loops
  3000. //
  3001. WsbAffirmHr(m_pJobs->QueryInterface(IID_IWsbCollection, (void**) &pCollection));
  3002. WsbAffirmHr(pCollection->Enum(&pEnum));
  3003. //
  3004. // Loop through all jobs and cancel any currently running jobs
  3005. //
  3006. pJob = 0;
  3007. for (hr = pEnum->First(IID_IHsmJob, (void**) &pJob);
  3008. SUCCEEDED(hr);
  3009. pJob = 0, hr = pEnum->Next(IID_IHsmJob, (void**) &pJob)) {
  3010. try {
  3011. WsbAffirmHrOk(pJob->IsActive());
  3012. foundRunningJob = TRUE;
  3013. WsbAffirmHr(pJob->Cancel(HSM_JOB_PHASE_ALL));
  3014. } WsbCatchAndDo(hr2, hr = S_OK;);
  3015. }
  3016. //
  3017. // Clean up end of scan return
  3018. //
  3019. if (WSB_E_NOTFOUND == hr) {
  3020. hr = S_OK;
  3021. }
  3022. //
  3023. // Cancel all mounting medias so all jobs can finish
  3024. //
  3025. CancelMountingMedias();
  3026. //
  3027. // Make sure all jobs are done
  3028. //
  3029. if (TRUE == foundRunningJob) {
  3030. pJob = 0;
  3031. for (hr = pEnum->First(IID_IHsmJob, (void**) &pJob);
  3032. SUCCEEDED(hr);
  3033. pJob = 0, hr = pEnum->Next(IID_IHsmJob, (void**) &pJob)) {
  3034. try {
  3035. WsbAffirmHrOk(pJob->IsActive());
  3036. WsbAffirmHr(pJob->WaitUntilDone());
  3037. } WsbCatchAndDo(hr2, hr = S_OK;);
  3038. }
  3039. }
  3040. //
  3041. // Clean up end of scan return
  3042. //
  3043. if (WSB_E_NOTFOUND == hr) {
  3044. hr = S_OK;
  3045. }
  3046. } WsbCatch(hr);
  3047. WsbTraceOut(OLESTR("CHsmServer::CancelAllJobs"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3048. return(hr);
  3049. }
  3050. HRESULT
  3051. CHsmServer::CheckManagedResources( void )
  3052. /*++
  3053. Implements:
  3054. IHsmServer::CheckManagedResources().
  3055. --*/
  3056. {
  3057. HRESULT hr = S_OK;
  3058. CComPtr<IWsbEnum> pEnum;
  3059. CComPtr<IHsmManagedResource> pMngdRes;
  3060. CComPtr<IUnknown> pFsaResUnknown;
  3061. CComPtr<IFsaResource> pFsaRes;
  3062. WsbTraceIn(OLESTR("CHsmServer::CheckManagedResources"), OLESTR(""));
  3063. try {
  3064. //
  3065. // Get an enumerator for the managed resource collection
  3066. //
  3067. WsbAffirmHr(m_pManagedResources->Enum(&pEnum));
  3068. //
  3069. // Scan through all managed resources and start the validation
  3070. // job for each
  3071. //
  3072. pMngdRes = 0;
  3073. for (hr = pEnum->First(IID_IHsmManagedResource,(void **)&pMngdRes );
  3074. SUCCEEDED(hr);
  3075. pMngdRes = 0, hr = pEnum->Next(IID_IHsmManagedResource, (void **)&pMngdRes)) {
  3076. try {
  3077. pFsaResUnknown = 0;
  3078. pFsaRes = 0;
  3079. WsbAffirmHr(pMngdRes->GetFsaResource((IUnknown **)&pFsaResUnknown));
  3080. WsbAffirmHr(pFsaResUnknown->QueryInterface(IID_IFsaResource, (void**) &pFsaRes));
  3081. if ((pFsaRes->IsActive() == S_OK) && (pFsaRes->IsAvailable() == S_OK)) {
  3082. WsbAffirmHr(pFsaRes->CheckForValidate(FALSE));
  3083. }
  3084. } WsbCatchAndDo(hr, hr = S_OK; );
  3085. }
  3086. if (WSB_E_NOTFOUND == hr) {
  3087. hr = S_OK;
  3088. }
  3089. } WsbCatch(hr);
  3090. WsbTraceOut(OLESTR("CHsmServer::CheckManagedResources"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3091. return(hr);
  3092. }
  3093. HRESULT
  3094. CHsmServer::GetBuildVersion(
  3095. ULONG *pBuildVersion
  3096. )
  3097. /*++
  3098. Implements:
  3099. IWsbServer::GetBuildVersion().
  3100. --*/
  3101. {
  3102. HRESULT hr = S_OK;
  3103. WsbTraceIn(OLESTR("CHsmServer::GetBuildVersion"), OLESTR(""));
  3104. try {
  3105. WsbAssertPointer(pBuildVersion);
  3106. *pBuildVersion = m_buildVersion;
  3107. } WsbCatch(hr);
  3108. WsbTraceOut(OLESTR("CHsmServer::GetBuildVersion"), OLESTR("hr = <%ls>, Version = <%ls)"),
  3109. WsbHrAsString(hr), RsBuildVersionAsString(m_buildVersion));
  3110. return ( hr );
  3111. }
  3112. HRESULT
  3113. CHsmServer::GetDatabaseVersion(
  3114. ULONG *pDatabaseVersion
  3115. )
  3116. /*++
  3117. Implements:
  3118. IWsbServer::GetDatabaseVersion().
  3119. --*/
  3120. {
  3121. HRESULT hr = S_OK;
  3122. WsbTraceIn(OLESTR("CHsmServer::GetDatabaseVersion"), OLESTR(""));
  3123. *pDatabaseVersion = m_databaseVersion;
  3124. WsbTraceOut(OLESTR("CHsmServer::GetDatabaseVersion"), OLESTR("hr = <%ls>, Version = <%ls)"),
  3125. WsbHrAsString(hr), WsbPtrToUlongAsString(pDatabaseVersion));
  3126. return ( hr );
  3127. }
  3128. HRESULT
  3129. CHsmServer::GetNtProductVersion (
  3130. OLECHAR **pNtProductVersion,
  3131. ULONG bufferSize
  3132. )
  3133. /*++
  3134. Implements:
  3135. IWsbServer::GetNtProductVersion().
  3136. --*/
  3137. {
  3138. HRESULT hr = S_OK;
  3139. try {
  3140. CWsbStringPtr tmpString;
  3141. WsbAssert(0 != pNtProductVersion, E_POINTER);
  3142. tmpString = VER_PRODUCTVERSION_STRING;
  3143. WsbAffirmHr(tmpString.CopyTo(pNtProductVersion, bufferSize));
  3144. } WsbCatch( hr );
  3145. return (hr);
  3146. }
  3147. HRESULT
  3148. CHsmServer::GetNtProductBuild(
  3149. ULONG *pNtProductBuild
  3150. )
  3151. /*++
  3152. Implements:
  3153. IWsbServer::GetNtProductBuild().
  3154. --*/
  3155. {
  3156. HRESULT hr = S_OK;
  3157. WsbTraceIn(OLESTR("CHsmServer::GetNtProductBuild"), OLESTR(""));
  3158. *pNtProductBuild = VER_PRODUCTBUILD;
  3159. WsbTraceOut(OLESTR("CHsmServer::GetNtProductBuild"), OLESTR("hr = <%ls>, Version = <%ls)"),
  3160. WsbHrAsString(hr), WsbLongAsString(VER_PRODUCTBUILD));
  3161. return ( hr );
  3162. }
  3163. HRESULT
  3164. CHsmServer::CheckAccess(
  3165. WSB_ACCESS_TYPE AccessType
  3166. )
  3167. /*++
  3168. Implements:
  3169. IWsbServer::CheckAccess().
  3170. --*/
  3171. {
  3172. WsbTraceIn(OLESTR("CHsmServer::CheckAccess"), OLESTR(""));
  3173. HRESULT hr = S_OK;
  3174. try {
  3175. //
  3176. // Do the impersonation
  3177. //
  3178. WsbAffirmHr( CoImpersonateClient() );
  3179. hr = WsbCheckAccess( AccessType );
  3180. CoRevertToSelf();
  3181. } WsbCatchAndDo( hr,
  3182. //
  3183. // Handle case where there is no COM context to check against
  3184. // in which case we are the service so any security is allowed.
  3185. //
  3186. if( ( hr == RPC_E_NO_CONTEXT ) || ( hr != RPC_E_CALL_COMPLETE ) ) {
  3187. hr = S_OK;
  3188. }
  3189. );
  3190. WsbTraceOut(OLESTR("CHsmServer::CheckAccess"), OLESTR("hr = <%ls>"), WsbHrAsString( hr ) );
  3191. return( hr );
  3192. }
  3193. HRESULT
  3194. CHsmServer::GetTrace(
  3195. OUT IWsbTrace ** ppTrace
  3196. )
  3197. /*++
  3198. Implements:
  3199. IWsbServer::GetTrace().
  3200. --*/
  3201. {
  3202. WsbTraceIn(OLESTR("CHsmServer::GetTrace"), OLESTR("ppTrace = <0x%p>"), ppTrace);
  3203. HRESULT hr = S_OK;
  3204. try {
  3205. WsbAffirmPointer(ppTrace);
  3206. *ppTrace = 0;
  3207. WsbAffirmPointer(m_pTrace);
  3208. *ppTrace = m_pTrace;
  3209. (*ppTrace)->AddRef();
  3210. } WsbCatch(hr);
  3211. WsbTraceOut(OLESTR("CHsmServer::GetTrace"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3212. return(hr);
  3213. }
  3214. HRESULT
  3215. CHsmServer::SetTrace(
  3216. OUT IWsbTrace * pTrace
  3217. )
  3218. /*++
  3219. Implements:
  3220. IWsbServer::SetTrace().
  3221. --*/
  3222. {
  3223. WsbTraceIn(OLESTR("CHsmServer::SetTrace"), OLESTR("pTrace = <0x%p>"), pTrace);
  3224. HRESULT hr = S_OK;
  3225. try {
  3226. WsbAffirmPointer(pTrace);
  3227. m_pTrace = pTrace;
  3228. } WsbCatch(hr);
  3229. WsbTraceOut(OLESTR("CHsmServer::SetTrace"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3230. return(hr);
  3231. }
  3232. HRESULT
  3233. CHsmServer::NotifyAllJobs( HSM_JOB_STATE jobState )
  3234. /*++
  3235. Routine Description:
  3236. Notify all jobs of a change in status.
  3237. Arguments:
  3238. jobState - New job state.
  3239. Return Value:
  3240. S_OK - Success
  3241. --*/
  3242. {
  3243. HRESULT hr = S_OK;
  3244. HRESULT hr2 = S_OK;
  3245. CComPtr<IWsbCollection> pCollection;
  3246. CComPtr<IWsbEnum> pEnum;
  3247. CComPtr<IHsmJob> pJob;
  3248. WsbTraceIn(OLESTR("CHsmServer::NotifyAllJobs"), OLESTR(""));
  3249. try {
  3250. //
  3251. // Set up for the loops
  3252. //
  3253. WsbAffirmHr(m_pJobs->QueryInterface(IID_IWsbCollection,
  3254. (void**) &pCollection));
  3255. WsbAffirmHr(pCollection->Enum(&pEnum));
  3256. //
  3257. // Loop through all jobs and notify any currently running jobs
  3258. //
  3259. pJob = 0;
  3260. for (hr = pEnum->First(IID_IHsmJob, (void**) &pJob);
  3261. SUCCEEDED(hr);
  3262. pJob = 0, hr = pEnum->Next(IID_IHsmJob, (void**) &pJob)) {
  3263. try {
  3264. if (S_OK == pJob->IsActive()) {
  3265. if (HSM_JOB_STATE_PAUSING == jobState) {
  3266. WsbAffirmHr(pJob->Pause(HSM_JOB_PHASE_ALL));
  3267. } else {
  3268. WsbAffirmHr(pJob->Resume(HSM_JOB_PHASE_ALL));
  3269. }
  3270. }
  3271. } WsbCatchAndDo(hr2, hr = S_OK;);
  3272. }
  3273. //
  3274. // Clean up end of scan return
  3275. //
  3276. if (WSB_E_NOTFOUND == hr) {
  3277. hr = S_OK;
  3278. }
  3279. } WsbCatch(hr);
  3280. WsbTraceOut(OLESTR("CHsmServer::NotifyAllJobs"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3281. return(hr);
  3282. }
  3283. //
  3284. // Retrieves the Media Manager object
  3285. //
  3286. HRESULT CHsmServer::GetHsmMediaMgr(
  3287. IRmsServer **ppHsmMediaMgr
  3288. )
  3289. {
  3290. HRESULT hr = S_OK;
  3291. // If the Media Manager has been created, return the pointer. Otherwise, fail.
  3292. try {
  3293. WsbAssert(0 != ppHsmMediaMgr, E_POINTER);
  3294. *ppHsmMediaMgr = m_pHsmMediaMgr;
  3295. WsbAffirm(m_pHsmMediaMgr != 0, E_FAIL);
  3296. m_pHsmMediaMgr.p->AddRef();
  3297. } WsbCatch(hr);
  3298. return (hr);
  3299. }
  3300. HRESULT
  3301. CHsmServer::GetCopyFilesUserLimit(
  3302. OUT ULONG* pLimit
  3303. )
  3304. /*++
  3305. Implements:
  3306. CHsmServer::GetCopyFilesUserLimit().
  3307. --*/
  3308. {
  3309. HRESULT hr = S_OK;
  3310. WsbTraceIn(OLESTR("CHsmServer::GetCopyFilesUserLimit"), OLESTR(""));
  3311. try {
  3312. WsbAssert(0 != pLimit, E_POINTER);
  3313. *pLimit = m_copyfilesUserLimit;
  3314. } WsbCatch(hr);
  3315. WsbTraceOut(OLESTR("CHsmServer::GetCopyFilesUserLimit"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3316. return(hr);
  3317. }
  3318. HRESULT
  3319. CHsmServer::SetCopyFilesUserLimit(
  3320. IN ULONG limit
  3321. )
  3322. /*++
  3323. Implements:
  3324. CHsmServer::SetCopyFilesUserLimit().
  3325. --*/
  3326. {
  3327. HRESULT hr = S_OK;
  3328. WsbTraceIn(OLESTR("CHsmServer::SetCopyFilesUserLimit"), OLESTR(""));
  3329. m_copyfilesUserLimit= limit;
  3330. WsbTraceOut(OLESTR("CHsmServer::SetCopyFilesUserLimit"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3331. return(hr);
  3332. }
  3333. HRESULT
  3334. CHsmServer::GetCopyFilesLimit(
  3335. OUT ULONG* pLimit
  3336. )
  3337. /*++
  3338. Implements:
  3339. CHsmServer::GetCopyFilesLimit().
  3340. --*/
  3341. {
  3342. HRESULT hr = S_OK;
  3343. WsbTraceIn(OLESTR("CHsmServer::GetCopyFilesLimit"), OLESTR(""));
  3344. try {
  3345. CComPtr<IHsmStoragePool> pStoragePool;
  3346. ULONG count;
  3347. GUID mediaSetId;
  3348. CWsbBstrPtr dummy;
  3349. DWORD dwNofDrives;
  3350. WsbAssert(0 != pLimit, E_POINTER);
  3351. // Get relevant media set - assume only one pool !!
  3352. WsbAffirmHr(m_pStoragePools->GetEntries(&count));
  3353. WsbAffirm(1 == count, E_FAIL);
  3354. WsbAffirmHr(m_pStoragePools->At(0, IID_IHsmStoragePool, (void **)&pStoragePool));
  3355. WsbAffirmHr(pStoragePool->GetMediaSet(&mediaSetId, &dummy));
  3356. // Get number of available drives in the system
  3357. WsbAffirmHr(m_pHsmMediaMgr->GetNofAvailableDrives(mediaSetId, &dwNofDrives));
  3358. // Deteremine actual limit
  3359. *pLimit = max(1, min(m_copyfilesUserLimit, dwNofDrives));
  3360. WsbTrace(OLESTR("CHsmServer::GetCopyFilesLimit: Limit is %lu\n"), *pLimit);
  3361. } WsbCatch(hr);
  3362. WsbTraceOut(OLESTR("CHsmServer::GetCopyFilesLimit"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3363. return(hr);
  3364. }
  3365. HRESULT
  3366. CHsmServer::AreJobsEnabled( void )
  3367. /*++
  3368. Implements:
  3369. IHsmServer::AreJobsDisabled().
  3370. --*/
  3371. {
  3372. HRESULT hr = S_OK;
  3373. WsbTraceIn(OLESTR("CHsmServer::AreJobsEnabled"), OLESTR(""));
  3374. EnterCriticalSection(&m_JobDisableLock);
  3375. hr = (m_JobsEnabled ? S_OK : S_FALSE);
  3376. LeaveCriticalSection(&m_JobDisableLock);
  3377. WsbTraceOut(OLESTR("CHsmServer::AreJobsEnabled"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3378. return(hr);
  3379. }
  3380. HRESULT
  3381. CHsmServer::EnableAllJobs( void )
  3382. /*++
  3383. Implements:
  3384. IHsmServer::EnableAllJobs().
  3385. --*/
  3386. {
  3387. HRESULT hr = S_OK;
  3388. WsbTraceIn(OLESTR("CHsmServer::EnableAllJobs"), OLESTR(""));
  3389. EnterCriticalSection(&m_JobDisableLock);
  3390. try {
  3391. m_JobsEnabled = TRUE;
  3392. WsbAffirmHr(RestartSuspendedJobs());
  3393. } WsbCatch(hr);
  3394. LeaveCriticalSection(&m_JobDisableLock);
  3395. WsbTraceOut(OLESTR("CHsmServer::EnableAllJobs"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3396. return(hr);
  3397. }
  3398. HRESULT
  3399. CHsmServer::DisableAllJobs( void )
  3400. /*++
  3401. Implements:
  3402. IHsmServer::DisableAllJobs().
  3403. Notes:
  3404. The medthod tries to disable all jobs.
  3405. If any job is active or starting, it fails with HSM_E_DISABLE_RUNNING_JOBS and calls
  3406. RestartSuspendedJobs to restart any job that alreay became suspended beacuse of this
  3407. unsuccessful disabling attempt.
  3408. --*/
  3409. {
  3410. HRESULT hr = S_OK;
  3411. WsbTraceIn(OLESTR("CHsmServer::DisableAllJobs"), OLESTR(""));
  3412. EnterCriticalSection(&m_JobDisableLock);
  3413. try {
  3414. ULONG nJobs;
  3415. m_JobsEnabled = FALSE;
  3416. // Loop over jobs
  3417. WsbAffirmHr(m_pJobs->GetEntries(&nJobs));
  3418. for (ULONG i = 0; i < nJobs; i++) {
  3419. CComPtr<IHsmJob> pJob;
  3420. HSM_JOB_STATE state;
  3421. WsbAffirmHr(m_pJobs->At(i, IID_IHsmJob, (void**) &pJob));
  3422. // Check if this job is suspended
  3423. WsbAffirmHr(pJob->GetState(&state));
  3424. if ((HSM_JOB_STATE_ACTIVE == state) || (HSM_JOB_STATE_STARTING == state)) {
  3425. // Cannot disable jobs
  3426. m_JobsEnabled = TRUE;
  3427. hr = HSM_E_DISABLE_RUNNING_JOBS;
  3428. RestartSuspendedJobs();
  3429. break;
  3430. }
  3431. }
  3432. } WsbCatch(hr);
  3433. LeaveCriticalSection(&m_JobDisableLock);
  3434. WsbTraceOut(OLESTR("CHsmServer::DisableAllJobs"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3435. return(hr);
  3436. }
  3437. HRESULT
  3438. CHsmServer::RestartSuspendedJobs(
  3439. void
  3440. )
  3441. /*++
  3442. Implements:
  3443. IHsmServer::RestartSuspendedJobs().
  3444. --*/
  3445. {
  3446. HRESULT hr = S_OK;
  3447. WsbTraceIn(OLESTR("CHsmServer::RestartSuspendedJobs"), OLESTR(""));
  3448. try {
  3449. ULONG nJobs;
  3450. // Loop over jobs
  3451. // Note: this algorithm is unfair because jobs at the end of the
  3452. // list could "starve" because jobs at the beginning are more likely
  3453. // to get started. The assumption is that there should be very few
  3454. // jobs waiting to run. If this assumption proves to be false, some
  3455. WsbAffirmHr(m_pJobs->GetEntries(&nJobs));
  3456. // sort of priority scheme will be needed.
  3457. for (ULONG i = 0; i < nJobs; i++) {
  3458. CComPtr<IHsmJob> pJob;
  3459. HSM_JOB_STATE state;
  3460. WsbAffirmHr(m_pJobs->At(i, IID_IHsmJob, (void**) &pJob));
  3461. // Check if this job is suspended
  3462. WsbAffirmHr(pJob->GetState(&state));
  3463. if (HSM_JOB_STATE_SUSPENDED == state) {
  3464. // This may fail, but we don't care
  3465. pJob->Restart();
  3466. }
  3467. }
  3468. } WsbCatch(hr);
  3469. WsbTraceOut(OLESTR("CHsmServer::RestartSuspendedJobs"), OLESTR("hr = <%ls>"),
  3470. WsbHrAsString(hr));
  3471. return(hr);
  3472. }
  3473. HRESULT
  3474. CHsmServer::LockMountingMedias( void )
  3475. /*++
  3476. Implements:
  3477. IHsmServer::LockMountingMedias().
  3478. --*/
  3479. {
  3480. HRESULT hr = S_OK;
  3481. EnterCriticalSection(&m_MountingMediasLock);
  3482. return(hr);
  3483. }
  3484. HRESULT
  3485. CHsmServer::UnlockMountingMedias( void )
  3486. /*++
  3487. Implements:
  3488. IHsmServer::UnlockMountingMedias().
  3489. --*/
  3490. {
  3491. HRESULT hr = S_OK;
  3492. LeaveCriticalSection(&m_MountingMediasLock);
  3493. return(hr);
  3494. }
  3495. HRESULT
  3496. CHsmServer::ResetSegmentValidMark( void )
  3497. /*++
  3498. Implements:
  3499. IHsmServer::ResetSegmentValidMark().
  3500. --*/
  3501. {
  3502. HRESULT hr = S_OK;
  3503. BOOL bOpenDb = FALSE;
  3504. CComPtr<IWsbDbSession> pDbSession;
  3505. WsbTraceIn(OLESTR("CHsmServer::ResetSegmentValidMark"), OLESTR(""));
  3506. try {
  3507. CComPtr<ISegRec> pSegRec;
  3508. USHORT uSegFlags;
  3509. // open Engine's Segment database
  3510. WsbAffirmHr(m_pSegmentDatabase->Open(&pDbSession));
  3511. bOpenDb = TRUE;
  3512. // Traverse segment records
  3513. WsbAffirmHr(m_pSegmentDatabase->GetEntity(pDbSession, HSM_SEG_REC_TYPE,
  3514. IID_ISegRec, (void**)&pSegRec));
  3515. for (hr = pSegRec->First(); S_OK == hr; hr = pSegRec->Next()) {
  3516. WsbAffirmHr(pSegRec->GetSegmentFlags(&uSegFlags));
  3517. if (uSegFlags & SEG_REC_MARKED_AS_VALID) {
  3518. // Need to reset this bit
  3519. uSegFlags &= ~SEG_REC_MARKED_AS_VALID;
  3520. WsbAffirmHr(pSegRec->SetSegmentFlags(uSegFlags));
  3521. WsbAffirmHr(pSegRec->Write());
  3522. }
  3523. }
  3524. // If we fell out of the loop because we ran out of segments, reset the HRESULT
  3525. if (hr == WSB_E_NOTFOUND) {
  3526. hr = S_OK;
  3527. } else {
  3528. WsbAffirmHr(hr);
  3529. }
  3530. } WsbCatch(hr);
  3531. if (bOpenDb) {
  3532. hr = m_pSegmentDatabase->Close(pDbSession);
  3533. }
  3534. WsbTraceOut(OLESTR("CHsmServer::ResetSegmentValidMark"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3535. return(hr);
  3536. }
  3537. HRESULT
  3538. CHsmServer::ResetMediaValidBytes( void )
  3539. /*++
  3540. Implements:
  3541. IHsmServer::ResetMediaValidBytes().
  3542. --*/
  3543. {
  3544. HRESULT hr = S_OK;
  3545. BOOL bOpenDb = FALSE;
  3546. CComPtr<IWsbDbSession> pDbSession;
  3547. WsbTraceIn(OLESTR("CHsmServer::ResetMediaValidBytes"), OLESTR(""));
  3548. try {
  3549. CComPtr<IMediaInfo> pMediaInfo;
  3550. // open Engine's Segment database
  3551. WsbAffirmHr(m_pSegmentDatabase->Open(&pDbSession));
  3552. bOpenDb = TRUE;
  3553. // Traverse segment records
  3554. WsbAffirmHr(m_pSegmentDatabase->GetEntity(pDbSession, HSM_MEDIA_INFO_REC_TYPE,
  3555. IID_IMediaInfo, (void**)&pMediaInfo));
  3556. for (hr = pMediaInfo->First(); S_OK == hr; hr = pMediaInfo->Next()) {
  3557. WsbAffirmHr(pMediaInfo->SetLogicalValidBytes(0));
  3558. WsbAffirmHr(pMediaInfo->Write());
  3559. }
  3560. // If we fell out of the loop because we ran out of segments, reset the HRESULT
  3561. if (hr == WSB_E_NOTFOUND) {
  3562. hr = S_OK;
  3563. } else {
  3564. WsbAffirmHr(hr);
  3565. }
  3566. } WsbCatch(hr);
  3567. if (bOpenDb) {
  3568. hr = m_pSegmentDatabase->Close(pDbSession);
  3569. }
  3570. WsbTraceOut(OLESTR("CHsmServer::ResetMediaValidBytes"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3571. return(hr);
  3572. }
  3573. HRESULT
  3574. CHsmServer::GetSegmentPosition(
  3575. IN REFGUID bagId,
  3576. IN LONGLONG fileStart,
  3577. IN LONGLONG fileSize,
  3578. OUT GUID* pPosMedia,
  3579. OUT LONGLONG* pPosOffset)
  3580. /*++
  3581. Implements:
  3582. IHsmServer::GetSegmentPosition().
  3583. --*/
  3584. {
  3585. HRESULT hr = S_OK;
  3586. BOOL bOpenDb = FALSE;
  3587. CComPtr<IWsbDbSession> pDbSession;
  3588. CComPtr<ISegDb> pSegDb;
  3589. WsbTraceIn(OLESTR("CHsmServer::GetSegmentPosition"), OLESTR(""));
  3590. try {
  3591. CComPtr<ISegRec> pSegRec;
  3592. // open Engine's Segment database
  3593. WsbAffirmHr(m_pSegmentDatabase->Open(&pDbSession));
  3594. bOpenDb = TRUE;
  3595. // Find segemnt
  3596. WsbAffirmHr(m_pSegmentDatabase->QueryInterface(IID_ISegDb, (void**) &pSegDb));
  3597. WsbAffirmHr(pSegDb->SegFind(pDbSession, bagId, fileStart, fileSize, &pSegRec));
  3598. // Extract output
  3599. WsbAffirmHr(pSegRec->GetPrimPos(pPosMedia));
  3600. WsbAffirmHr(pSegRec->GetSecPos(pPosOffset));
  3601. } WsbCatch(hr);
  3602. if (bOpenDb) {
  3603. hr = m_pSegmentDatabase->Close(pDbSession);
  3604. }
  3605. WsbTraceOut(OLESTR("CHsmServer::GetSegmentPosition"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3606. return(hr);
  3607. }
  3608. void
  3609. CHsmServer::StopAutosaveThread(
  3610. void
  3611. )
  3612. /*++
  3613. Routine Description:
  3614. Stop the Autosave thread:
  3615. First try gracefully, using the termination event
  3616. If doesn't work, just terminate the thread
  3617. Arguments:
  3618. None.
  3619. Return Value:
  3620. S_OK - Success.
  3621. --*/
  3622. {
  3623. HRESULT hr = S_OK;
  3624. WsbTraceIn(OLESTR("CHsmServer::StopAutosaveThread"), OLESTR(""));
  3625. try {
  3626. // Terminate the autosave thread
  3627. if (m_autosaveThread) {
  3628. // Signal thread to terminate
  3629. SetEvent(m_terminateEvent);
  3630. // Wait for the thread, if it doesn't terminate gracefully - kill it
  3631. switch (WaitForSingleObject(m_autosaveThread, 20000)) {
  3632. case WAIT_FAILED: {
  3633. WsbTrace(OLESTR("CHsmServer::StopAutosaveThread: WaitForSingleObject returned error %lu\n"), GetLastError());
  3634. }
  3635. // fall through...
  3636. case WAIT_TIMEOUT: {
  3637. WsbTrace(OLESTR("CHsmServer::StopAutosaveThread: force terminating of autosave thread.\n"));
  3638. DWORD dwExitCode;
  3639. if (GetExitCodeThread( m_autosaveThread, &dwExitCode)) {
  3640. if (dwExitCode == STILL_ACTIVE) { // thread still active
  3641. if (!TerminateThread (m_autosaveThread, 0)) {
  3642. WsbTrace(OLESTR("CHsmServer::StopAutosaveThread: TerminateThread returned error %lu\n"), GetLastError());
  3643. }
  3644. }
  3645. } else {
  3646. WsbTrace(OLESTR("CHsmServer::StopAutosaveThread: GetExitCodeThread returned error %lu\n"), GetLastError());
  3647. }
  3648. break;
  3649. }
  3650. default:
  3651. // Thread terminated gracefully
  3652. WsbTrace(OLESTR("CHsmServer::StopAutosaveThread: Autosave thread terminated gracefully\n"));
  3653. break;
  3654. }
  3655. // Best effort done for terminating auto-backup thread
  3656. CloseHandle(m_autosaveThread);
  3657. m_autosaveThread = 0;
  3658. }
  3659. } WsbCatch(hr);
  3660. WsbTraceOut(OLESTR("CHsmServer::StopAutosaveThread"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3661. }
  3662. void
  3663. CHsmServer::StopCheckManagedResourcesThread(
  3664. void
  3665. )
  3666. /*++
  3667. Routine Description:
  3668. Stop the CheckManagedResources thread:
  3669. This thread should be running only for a short period of time during initialization,
  3670. so wait for thread to finish gracefully, then if it is hung for some reason, just terminate the thread
  3671. Arguments:
  3672. None.
  3673. Return Value:
  3674. S_OK - Success.
  3675. --*/
  3676. {
  3677. HRESULT hr = S_OK;
  3678. WsbTraceIn(OLESTR("CHsmServer::StopCheckManagedResourcesThread"), OLESTR(""));
  3679. try {
  3680. // Wait for the CheckManagedResources thread if it is still running
  3681. if (m_CheckManagedResourcesThread) {
  3682. switch (WaitForSingleObject(m_CheckManagedResourcesThread, 20000)) {
  3683. case WAIT_FAILED: {
  3684. WsbTrace(OLESTR("CHsmServer::StopCheckManagedResourcesThread: WaitForSingleObject returned error %lu\n"), GetLastError());
  3685. }
  3686. // fall through...
  3687. case WAIT_TIMEOUT: {
  3688. WsbTrace(OLESTR("CHsmServer::StopCheckManagedResourcesThread: force terminating of CheckManagedResources thread.\n"));
  3689. DWORD dwExitCode;
  3690. if (GetExitCodeThread( m_CheckManagedResourcesThread, &dwExitCode)) {
  3691. if (dwExitCode == STILL_ACTIVE) { // thread still active
  3692. if (!TerminateThread (m_CheckManagedResourcesThread, 0)) {
  3693. WsbTrace(OLESTR("CHsmServer::StopCheckManagedResourcesThread: TerminateThread returned error %lu\n"), GetLastError());
  3694. }
  3695. }
  3696. } else {
  3697. WsbTrace(OLESTR("CHsmServer::StopCheckManagedResourcesThread: GetExitCodeThread returned error %lu\n"), GetLastError());
  3698. }
  3699. break;
  3700. }
  3701. default:
  3702. // Thread terminated gracefully
  3703. WsbTrace(OLESTR("CHsmServer::StopCheckManagedResourcesThread: CheckManagedResources thread terminated gracefully\n"));
  3704. break;
  3705. }
  3706. // Best effort done for terminating auto-backup thread
  3707. CloseHandle(m_CheckManagedResourcesThread);
  3708. m_CheckManagedResourcesThread = 0;
  3709. }
  3710. } WsbCatch(hr);
  3711. WsbTraceOut(OLESTR("CHsmServer::StopCheckManagedResourcesThread"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3712. }
  3713. HRESULT
  3714. CHsmServer::InternalSavePersistData(
  3715. void
  3716. )
  3717. /*++
  3718. Implements:
  3719. CHsmServer::InternalSavePersistData().
  3720. --*/
  3721. {
  3722. HRESULT hr = S_OK;
  3723. WsbTraceIn(OLESTR("CHsmServer::InternalSavePersistData"), OLESTR(""));
  3724. try {
  3725. DWORD status, errWait;
  3726. CComPtr<IPersistFile> pPersistFile;
  3727. // Synchronize saving of persistent data with snapshot signaling event
  3728. status = WaitForSingleObject(m_savingEvent, EVENT_WAIT_TIMEOUT);
  3729. // Save anyway, then report if the Wait function returned an unexpected error
  3730. errWait = GetLastError();
  3731. // Note: Don't throw exception here because even if saving fails, we still need
  3732. // to set the saving event.
  3733. hr = (((IUnknown*) (IHsmServer*) this)->QueryInterface(IID_IPersistFile,
  3734. (void**) &pPersistFile));
  3735. if (SUCCEEDED(hr)) {
  3736. hr = WsbSafeSave(pPersistFile);
  3737. }
  3738. // Check Wait status... Note that hr remains OK because the saving itself completed fine
  3739. switch (status) {
  3740. case WAIT_OBJECT_0:
  3741. // The expected case
  3742. SetEvent(m_savingEvent);
  3743. break;
  3744. case WAIT_TIMEOUT:
  3745. // Don't log anything for now: This might happen if snapshot process takes
  3746. // too long for some reason, but logging seems to just confuse the user -
  3747. // he really can not (and should not) do anything...
  3748. WsbTraceAlways(OLESTR("CHsmServer::InternalSavePersistData: Wait for Single Object timed out after %lu ms\n"), EVENT_WAIT_TIMEOUT);
  3749. break;
  3750. case WAIT_FAILED:
  3751. WsbTraceAlways(OLESTR("CHsmServer::InternalSavePersistData: Wait for Single Object returned error %lu\n"), errWait);
  3752. break;
  3753. default:
  3754. WsbTraceAlways(OLESTR("CHsmServer::InternalSavePersistData: Wait for Single Object returned unexpected status %lu\n"), status);
  3755. break;
  3756. }
  3757. } WsbCatch(hr);
  3758. WsbTraceOut(OLESTR("CHsmServer::InternalSavePersistData"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3759. return(hr);
  3760. }
  3761. HRESULT
  3762. CHsmServer::CancelMountingMedias( void )
  3763. /*++
  3764. Implements:
  3765. CHsmServer::CancelMountingMedias().
  3766. --*/
  3767. {
  3768. HRESULT hr = S_OK;
  3769. CComPtr<IWsbEnum> pEnum;
  3770. CComPtr<IMountingMedia> pMountingMedia;
  3771. WsbTraceIn(OLESTR("CHsmServer::CancelMountingMedias"), OLESTR(""));
  3772. try {
  3773. WsbAffirmHr(m_pMountingMedias->Enum(&pEnum));
  3774. // Loop through all mounting media and release waiting mounting clients
  3775. for (hr = pEnum->First(IID_IMountingMedia, (void**) &pMountingMedia);
  3776. SUCCEEDED(hr);
  3777. hr = pEnum->Next(IID_IMountingMedia, (void**) &pMountingMedia)) {
  3778. pMountingMedia->MountDone();
  3779. pMountingMedia = 0;
  3780. }
  3781. if (hr == WSB_E_NOTFOUND) {
  3782. hr = S_OK;
  3783. }
  3784. } WsbCatch(hr);
  3785. WsbTraceOut(OLESTR("CHsmServer::CancelMountingMedias"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3786. return(hr);
  3787. }
  3788. //
  3789. // Methods of the class which uses to upgrade a Win2K rms to current rms
  3790. //
  3791. HRESULT
  3792. CHsmUpgradeRmsDb::FinalConstruct(
  3793. void
  3794. )
  3795. /*++
  3796. Implements:
  3797. CComObjectRoot::FinalConstruct
  3798. --*/
  3799. {
  3800. HRESULT hr = S_OK;
  3801. WsbTraceIn(OLESTR("CHsmUpgradeRmsDb::FinalConstruct"), OLESTR("") );
  3802. try {
  3803. WsbAffirmHr(CWsbPersistable::FinalConstruct());
  3804. m_pServer = NULL;
  3805. } WsbCatch(hr);
  3806. WsbTraceOut(OLESTR("CHsmUpgradeRmsDb::FinalConstruct"), OLESTR("hr =<%ls>"), WsbHrAsString(hr));
  3807. return(hr);
  3808. }
  3809. void
  3810. CHsmUpgradeRmsDb::FinalRelease(
  3811. void
  3812. )
  3813. /*++
  3814. Implements:
  3815. CComObjectRoot::FinalRelease
  3816. --*/
  3817. {
  3818. HRESULT hr = S_OK;
  3819. WsbTraceIn(OLESTR("CHsmUpgradeRmsDb::FinalRelease"), OLESTR(""));
  3820. CWsbPersistable::FinalRelease();
  3821. WsbTraceOut(OLESTR("CHsmUpgradeRmsDb::FinalRelease"), OLESTR("hr =<%ls>"), WsbHrAsString(hr));
  3822. }
  3823. HRESULT
  3824. CHsmUpgradeRmsDb::GetClassID(
  3825. OUT CLSID* pClsid)
  3826. /*++
  3827. Implements:
  3828. IPersist::GetClassId
  3829. --*/
  3830. {
  3831. HRESULT hr = S_OK;
  3832. WsbTraceIn(OLESTR("CHsmUpgradeRmsDb::GetClassID"), OLESTR(""));
  3833. try {
  3834. WsbAssert(0 != pClsid, E_POINTER);
  3835. // Return Rms class id since this is what the old col file represents
  3836. *pClsid = CLSID_CRmsServer;
  3837. } WsbCatch(hr);
  3838. WsbTraceOut(OLESTR("CHsmUpgradeRmsDb::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid));
  3839. return hr;
  3840. }
  3841. HRESULT
  3842. CHsmUpgradeRmsDb::Save(
  3843. IN IStream* /*pStream*/,
  3844. IN BOOL /*clearDirty*/
  3845. )
  3846. /*++
  3847. Implements:
  3848. IPersistStream::Save().
  3849. --*/
  3850. {
  3851. HRESULT hr = E_NOTIMPL;
  3852. WsbTraceIn(OLESTR("CHsmUpgradeRmsDb::Save"), OLESTR(""));
  3853. // Not implemented - this class should be used only for load
  3854. WsbTraceOut(OLESTR("CHsmUpgradeRmsDb::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3855. return(hr);
  3856. }
  3857. HRESULT
  3858. CHsmUpgradeRmsDb::Load(
  3859. IN IStream* pStream
  3860. )
  3861. /*++
  3862. Implements:
  3863. IPersistStream::Load().
  3864. --*/
  3865. {
  3866. HRESULT hr = S_OK;
  3867. WsbTraceIn(OLESTR("CHsmUpgradeRmsDb::Load"), OLESTR(""));
  3868. try {
  3869. ULONG buildVersion;
  3870. ULONG databaseVersion;
  3871. ULONG expectedVersion = RMS_WIN2K_DB_VERSION;
  3872. WsbAssert(0 != pStream, E_POINTER);
  3873. // Make sure this is the right version of the Rms database to load
  3874. WsbAffirmHr(WsbLoadFromStream(pStream, &databaseVersion));
  3875. if (databaseVersion != expectedVersion) {
  3876. WsbLogEvent( RMS_MESSAGE_DATABASE_VERSION_MISMATCH, 0, NULL, WsbQuickString(WsbPtrToUlongAsString(&expectedVersion)),
  3877. WsbQuickString(WsbPtrToUlongAsString(&databaseVersion)), NULL );
  3878. WsbThrow(RMS_E_DATABASE_VERSION_MISMATCH);
  3879. }
  3880. // Read in the build version but don't do anything with it.
  3881. WsbAffirmHr(WsbLoadFromStream(pStream, &buildVersion));
  3882. // Let Rms manager to this its load
  3883. CComPtr<IPersistStream> pIStream;
  3884. WsbAffirmHr(m_pServer->QueryInterface(IID_IPersistStream, (void **)&pIStream));
  3885. WsbAffirmHr(pIStream->Load(pStream));
  3886. } WsbCatch(hr);
  3887. WsbTraceOut(OLESTR("CHsmUpgradeRmsDb::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3888. return(hr);
  3889. }
  3890. HRESULT CHsmUpgradeRmsDb::Init(
  3891. IN IRmsServer *pHsmMediaMgr
  3892. )
  3893. /*++
  3894. Implements:
  3895. IHsmUpgradeRmsDb::Init().
  3896. --*/
  3897. {
  3898. HRESULT hr = S_OK;
  3899. WsbTraceIn(OLESTR("CHsmUpgradeRmsDb::Init"),OLESTR(""));
  3900. try {
  3901. WsbAssert(0 != pHsmMediaMgr, E_POINTER);
  3902. m_pServer = pHsmMediaMgr;
  3903. } WsbCatch(hr);
  3904. WsbTraceOut(OLESTR("CHsmUpgradeRmsDb::Init"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3905. return hr;
  3906. }
  3907. HRESULT
  3908. CHsmServer::UpdateMediaSizeLimit(
  3909. OUT DWORD* pdwNewLimit
  3910. )
  3911. /*++
  3912. Implements:
  3913. IHsmServer::UpdateMediaSizeLimit().
  3914. --*/
  3915. {
  3916. HRESULT hr = S_OK;
  3917. WsbTraceIn(OLESTR("CHsmServer::UpdateMediaSizeLimit"), OLESTR(""));
  3918. try {
  3919. LONGLONG llBytesCapacity = 0;
  3920. DWORD dwMBCapacity;
  3921. CComPtr<IHsmStoragePool> pStoragePool;
  3922. ULONG count;
  3923. GUID mediaSetId;
  3924. CWsbBstrPtr dummy;
  3925. WsbAssert(0 != pdwNewLimit, E_POINTER);
  3926. // Get current value from the Registry
  3927. if (WsbGetRegistryValueDWORD(NULL, HSM_ENGINE_REGISTRY_STRING, HSM_MAX_FILE_TO_MIGRATE, pdwNewLimit) != S_OK) {
  3928. *pdwNewLimit = 0;
  3929. }
  3930. WsbTrace(OLESTR("CHsmServer::UpdateMediaSizeLimit: Current limit is %lu\n"), *pdwNewLimit);
  3931. // Get relevant media set - assume only one pool !!
  3932. WsbAffirmHr(m_pStoragePools->GetEntries(&count));
  3933. WsbAffirm(1 == count, E_FAIL);
  3934. WsbAffirmHr(m_pStoragePools->At(0, IID_IHsmStoragePool, (void **)&pStoragePool));
  3935. WsbAffirmHr(pStoragePool->GetMediaSet(&mediaSetId, &dummy));
  3936. // Get currents media limit according to max media size
  3937. WsbAffirmHr(m_pHsmMediaMgr->GetMaxMediaCapacity(mediaSetId, &llBytesCapacity));
  3938. // Allow 95% of raw capacity
  3939. llBytesCapacity = (llBytesCapacity * 95) / 100;
  3940. dwMBCapacity = (DWORD)((llBytesCapacity / 1024) / 1024);
  3941. // Deteremine if to update limit
  3942. if (dwMBCapacity > *pdwNewLimit) {
  3943. *pdwNewLimit = dwMBCapacity;
  3944. WsbAffirmHr(WsbSetRegistryValueDWORD(NULL, HSM_ENGINE_REGISTRY_STRING, HSM_MAX_FILE_TO_MIGRATE, *pdwNewLimit));
  3945. WsbLogEvent(HSM_MESSAGE_NEW_MEDIA_LIMIT, 0, NULL, WsbPtrToUlongAsString(pdwNewLimit), NULL);
  3946. }
  3947. } WsbCatch(hr);
  3948. WsbTraceOut(OLESTR("CHsmServer::UpdateMediaSizeLimit"), OLESTR("hr = <%ls> , New limit = %lu MB"), WsbHrAsString(hr), *pdwNewLimit);
  3949. return(hr);
  3950. }