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.

1549 lines
47 KiB

  1. /*++
  2. 1998 Seagate Software, Inc. All rights reserved.
  3. Module Name:
  4. SegDb.cpp
  5. Abstract:
  6. This component is an provides the collection that contains the HSM segment records.
  7. Author:
  8. Cat Brant [cbrant] 12-Nov-1996
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #include "metaint.h"
  13. #include "metaLib.h"
  14. #include "engine.h"
  15. #include "segdb.h"
  16. #undef WSB_TRACE_IS
  17. #define WSB_TRACE_IS WSB_TRACE_BIT_SEG
  18. // SEG_APPEND_OK returns TRUE if bag segment 2 can be appended to
  19. // segment 1
  20. #define SEG_APPEND_OK(b1, s1, l1, b2, s2, l2) \
  21. (IsEqualGUID(b1, b2) && (s1 + l1 == s2))
  22. // SEG_EXPAND_OK returns TRUE if bag segment 2 can be added to
  23. // segment 1
  24. #define SEG_EXPAND_OK(b1, s1, l1, b2, s2, l2) \
  25. (IsEqualGUID(b1, b2) && (s1 + l1 <= s2))
  26. // SEG_CONTAINS returns TRUE if bag segment 1 contains (the first
  27. // part of) segment 2
  28. #define SEG_CONTAINS(b1, s1, l1, b2, s2, l2) \
  29. (IsEqualGUID(b1, b2) && (s1 <= s2) && ((s1 + l1) > s2))
  30. HRESULT
  31. CSegDb::BagHoleAdd
  32. (
  33. IN IWsbDbSession* pDbSession,
  34. IN GUID BagId,
  35. IN LONGLONG SegStartLoc,
  36. IN LONGLONG SegLen
  37. )
  38. /*++
  39. Implements:
  40. ISegDb::BagHoleAdd
  41. --*/
  42. {
  43. HRESULT hr = S_OK;
  44. WsbTraceIn(OLESTR("CSegDb::BagHoleAdd"),
  45. OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
  46. WsbGuidAsString(BagId), SegStartLoc,
  47. SegLen);
  48. try {
  49. BOOL found = FALSE;
  50. CComPtr<IBagHole> pBagHole;
  51. GUID l_BagId = GUID_NULL;
  52. LONGLONG l_SegStartLoc = 0;
  53. LONGLONG l_SegLen = 0;
  54. WsbAffirmHr(GetEntity(pDbSession, HSM_BAG_HOLE_REC_TYPE, IID_IBagHole,
  55. (void **)&pBagHole));
  56. WsbAffirmHr(pBagHole->SetBagHole(BagId, SegStartLoc, 0));
  57. // Look for a segment to which to append this one
  58. WsbTrace(OLESTR("Finding BagHole Record: <%ls>, <%I64u>, <%I64u>\n"),
  59. WsbGuidAsString(BagId),
  60. SegStartLoc,
  61. SegLen);
  62. hr = pBagHole->FindLTE();
  63. if (WSB_E_NOTFOUND == hr) {
  64. hr = S_OK;
  65. } else {
  66. WsbAffirmHr(pBagHole->GetBagHole(&l_BagId, &l_SegStartLoc, &l_SegLen));
  67. if (SEG_APPEND_OK(l_BagId, l_SegStartLoc, l_SegLen,
  68. BagId, SegStartLoc, SegLen)) {
  69. found = TRUE;
  70. }
  71. }
  72. if (found) {
  73. // Append this segment to the existing record
  74. l_SegLen += SegLen;
  75. } else {
  76. // Create a new record
  77. l_SegStartLoc = SegStartLoc;
  78. l_SegLen = SegLen;
  79. WsbAffirmHr(pBagHole->MarkAsNew());
  80. }
  81. WsbAffirmHr(pBagHole->SetBagHole(BagId, l_SegStartLoc, l_SegLen));
  82. WsbTrace(OLESTR("Writing BagHole Record: <%ls>, <%I64u>, <%I64u>\n"),
  83. WsbGuidAsString(BagId),
  84. l_SegStartLoc,
  85. l_SegLen);
  86. WsbAffirmHr(pBagHole->Write());
  87. } WsbCatch(hr);
  88. WsbTraceOut(OLESTR("CSegDb::BagHoleAdd"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
  89. return(hr);
  90. }
  91. HRESULT
  92. CSegDb::BagHoleFind
  93. (
  94. IN IWsbDbSession* pDbSession,
  95. IN GUID BagId,
  96. IN LONGLONG SegStartLoc,
  97. IN LONGLONG SegLen,
  98. OUT IBagHole** ppIBagHole
  99. )
  100. /*++
  101. Implements:
  102. ISegDb::BagHoleFind
  103. --*/
  104. {
  105. HRESULT hr = S_OK;
  106. WsbTraceIn(OLESTR("CSegDb::BagHoleFind"),
  107. OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
  108. WsbGuidAsString(BagId), SegStartLoc,
  109. SegLen);
  110. try {
  111. CComPtr<IBagHole> pBagHole;
  112. GUID l_BagId;
  113. LONGLONG l_SegStartLoc;
  114. LONGLONG l_SegLen;
  115. WsbAffirm(ppIBagHole != NULL, E_POINTER);
  116. WsbAffirmHr(GetEntity(pDbSession, HSM_BAG_HOLE_REC_TYPE, IID_IBagHole,
  117. (void **)&pBagHole));
  118. WsbAffirmHr(pBagHole->SetBagHole(BagId, SegStartLoc, 0));
  119. // Look for a segment that contains this one
  120. WsbTrace(OLESTR("Finding BagHole Record: <%ls>, <%I64u>, <%I64u>\n"),
  121. WsbGuidAsString(BagId),
  122. SegStartLoc,
  123. SegLen);
  124. WsbAffirmHr(pBagHole->FindLTE());
  125. // We found a record, see if it's the right one
  126. WsbAffirmHr(pBagHole->GetBagHole(&l_BagId, &l_SegStartLoc, &l_SegLen));
  127. if (SEG_CONTAINS(l_BagId, l_SegStartLoc, l_SegLen,
  128. BagId, SegStartLoc, SegLen)) {
  129. *ppIBagHole = pBagHole;
  130. pBagHole.p->AddRef();
  131. } else {
  132. hr = WSB_E_NOTFOUND;
  133. }
  134. } WsbCatch(hr);
  135. WsbTraceOut(OLESTR("CSegDb::BagHoleFind"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
  136. return(hr);
  137. }
  138. HRESULT
  139. CSegDb::BagHoleSubtract
  140. (
  141. IN IWsbDbSession* pDbSession,
  142. IN GUID BagId,
  143. IN LONGLONG SegStartLoc,
  144. IN LONGLONG SegLen
  145. )
  146. /*++
  147. Implements:
  148. ISegDb::BagHoleSubtract
  149. --*/
  150. {
  151. HRESULT hr = S_OK;
  152. WsbTraceIn(OLESTR("CSegDb::BagHoleSubtract"),
  153. OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
  154. WsbGuidAsString(BagId),
  155. SegStartLoc,
  156. SegLen);
  157. try {
  158. GUID l_BagId;
  159. LONGLONG l_SegStartLoc;
  160. LONGLONG l_SegLen;
  161. CComPtr<IBagHole> pBagHole;
  162. // Find the segment record
  163. WsbAffirmHr(BagHoleFind(pDbSession, BagId, SegStartLoc, SegLen, &pBagHole));
  164. // Get the current data
  165. WsbAffirmHr(pBagHole->GetBagHole(&l_BagId, &l_SegStartLoc, &l_SegLen));
  166. // Determine where the hole is
  167. if (l_SegStartLoc == SegStartLoc && l_SegLen == SegLen) {
  168. // Hole is the entire segment -- delete it
  169. WsbAffirmHr(pBagHole->Remove());
  170. } else if (l_SegStartLoc == SegStartLoc) {
  171. // Hole is at the beginning of the segment. Just update the
  172. // existing segment
  173. l_SegStartLoc += SegLen;
  174. WsbAffirmHr(pBagHole->SetBagHole(BagId, l_SegStartLoc, l_SegLen));
  175. WsbAffirmHr(pBagHole->Write());
  176. } else if ((l_SegStartLoc + l_SegLen) == (SegStartLoc + SegLen)) {
  177. // Hole is at the end of the segment. Just update the
  178. // existing segment
  179. l_SegLen -= SegLen;
  180. WsbAffirmHr(pBagHole->SetBagHole(BagId, l_SegStartLoc, l_SegLen));
  181. WsbAffirmHr(pBagHole->Write());
  182. } else {
  183. // Hole is in the middle of the segment. Update the
  184. // existing record to be the first part.
  185. LONGLONG oldLen = l_SegLen;
  186. LONGLONG offset = (SegStartLoc + SegLen) - l_SegStartLoc;
  187. l_SegLen = SegStartLoc - l_SegStartLoc;
  188. WsbAffirmHr(pBagHole->SetBagHole(BagId, l_SegStartLoc, l_SegLen));
  189. WsbAffirmHr(pBagHole->Write());
  190. // Create a new record for the second part.
  191. l_SegLen -= offset;
  192. l_SegStartLoc += offset;
  193. WsbAffirmHr(BagHoleAdd(pDbSession, BagId, l_SegStartLoc, l_SegLen));
  194. }
  195. } WsbCatch(hr);
  196. WsbTraceOut(OLESTR("CSegDb::BagHoleSubtract"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
  197. return(hr);
  198. }
  199. HRESULT
  200. CSegDb::FinalConstruct(
  201. void
  202. )
  203. /*++
  204. Routine Description:
  205. This method does some initialization of the object that is necessary
  206. after construction.
  207. Arguments:
  208. None.
  209. Return Value:
  210. S_OK
  211. --*/
  212. {
  213. HRESULT hr = S_OK;
  214. m_value = 0;
  215. try {
  216. WsbAssertHr(CWsbDb::FinalConstruct());
  217. m_version = 1;
  218. } WsbCatch(hr);
  219. return(hr);
  220. }
  221. HRESULT
  222. CSegDb::FinalRelease(
  223. void
  224. )
  225. /*++
  226. Routine Description:
  227. This method does some termination of the object that is necessary
  228. before destruction.
  229. Arguments:
  230. None.
  231. Return Value:
  232. S_OK
  233. Anything returned by CWsbCollection::FinalDestruct().
  234. --*/
  235. {
  236. HRESULT hr = S_OK;
  237. CWsbDb::FinalRelease();
  238. return(hr);
  239. }
  240. HRESULT
  241. CSegDb::Test
  242. (
  243. OUT USHORT * pTestsPassed,
  244. OUT USHORT* pTestsFailed
  245. )
  246. /*++
  247. Routine Description:
  248. See IWsbTestable::Test().
  249. Arguments:
  250. See IWsbTestable::Test().
  251. Return Value:
  252. See IWsbTestable::Test().
  253. --*/
  254. {
  255. HRESULT hr = S_OK;
  256. #ifdef THIS_CODE_IS_WRONG
  257. // This is mostly wrong now
  258. ULONG entries;
  259. GUID lastBagId;
  260. LONGLONG lastStartLoc;
  261. GUID startBagId;
  262. LONGLONG startSegStartLoc;
  263. LONGLONG startSegLen;
  264. USHORT startSegType;
  265. GUID startPrimLoc;
  266. LONGLONG startSecLoc;
  267. USHORT testsRun = 0;
  268. CComPtr<IWsbCollection> pColl;
  269. CComPtr<ISegRec> pSegRec1;
  270. CComPtr<ISegRec> pSegRec2;
  271. CComPtr<ISegRec> pSegRec3;
  272. CComPtr<ISegRec> pSegRec4;
  273. CComPtr<ISegRec> pSegRec5;
  274. CComPtr<ISegRec> pSegRec6;
  275. CComPtr<ISegRec> pSegRec7;
  276. CComPtr<ISegRec> pSegRec8;
  277. CComPtr<ISegRec> pSegRec9;
  278. CComPtr<ISegRec> pSegRec10;
  279. CComPtr<ISegRec> pSegRec11;
  280. WsbTraceIn(OLESTR("CSegDb::Test"), OLESTR(""));
  281. *pTestsPassed = *pTestsFailed = 0;
  282. try {
  283. // Clear out any entries that might be present.
  284. hr = S_OK;
  285. try {
  286. WsbAssertHr(Erase());
  287. } WsbCatch(hr);
  288. if (hr == S_OK) {
  289. (*pTestsPassed)++;
  290. } else {
  291. (*pTestsFailed)++;
  292. }
  293. // There shouldn't be any entries.
  294. hr = S_OK;
  295. try {
  296. WsbAssertHr(GetSegments(&pColl));
  297. WsbAssertHr(pColl->GetEntries(&entries));
  298. WsbAssert(0 == entries, E_FAIL);
  299. } WsbCatch(hr);
  300. if (hr == S_OK) {
  301. (*pTestsPassed)++;
  302. } else {
  303. (*pTestsFailed)++;
  304. }
  305. // It should be empty.
  306. hr = S_OK;
  307. try {
  308. WsbAssert(pColl->IsEmpty() == S_OK, E_FAIL);
  309. } WsbCatch(hr);
  310. if (hr == S_OK) {
  311. (*pTestsPassed)++;
  312. } else {
  313. (*pTestsFailed)++;
  314. }
  315. // We need some collectable items to exercise the collection.
  316. WsbAssertHr(GetEntity(pDbSession, HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec1));
  317. WsbAssertHr(pSegRec1->SetSegmentRecord(CLSID_CWsbBool, 0, 6, 0, CLSID_CSegRec,0 ));
  318. // Add the item to the collection.
  319. hr = S_OK;
  320. try {
  321. WsbAssertHr(pSegRec1->Write());
  322. } WsbCatch(hr);
  323. if (hr == S_OK) {
  324. (*pTestsPassed)++;
  325. } else {
  326. (*pTestsFailed)++;
  327. }
  328. // There should be 1 entry.
  329. hr = S_OK;
  330. try {
  331. WsbAssertHr(pColl->GetEntries(&entries));
  332. WsbAssert(1 == entries, E_FAIL);
  333. } WsbCatch(hr);
  334. if (hr == S_OK) {
  335. (*pTestsPassed)++;
  336. } else {
  337. (*pTestsFailed)++;
  338. }
  339. // It should not be empty.
  340. hr = S_OK;
  341. try {
  342. WsbAssert(pColl->IsEmpty() == S_FALSE, E_FAIL);
  343. } WsbCatch(hr);
  344. if (hr == S_OK) {
  345. (*pTestsPassed)++;
  346. } else {
  347. (*pTestsFailed)++;
  348. }
  349. // Does it think it has the item?
  350. hr = S_OK;
  351. try {
  352. WsbAssertHr(GetEntity(pDbSession, HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec2));
  353. WsbAssertHr(pSegRec2->SetSegmentRecord(CLSID_CWsbBool, 0, 6, 0, CLSID_CSegRec,0 ));
  354. WsbAssertHr(pSegRec2->FindEQ());
  355. WsbAssert(pSegRec1->CompareToISegmentRecord(pSegRec2, NULL) == S_OK, E_FAIL);
  356. } WsbCatch(hr);
  357. if (hr == S_OK) {
  358. (*pTestsPassed)++;
  359. } else {
  360. (*pTestsFailed)++;
  361. }
  362. // Add some more items
  363. WsbAssertHr(pSegRec2->SetSegmentRecord(CLSID_CWsbGuid, 0, 5, 0, CLSID_CSegRec,0 ));
  364. WsbAssertHr(GetEntity(pDbSession, HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec3));
  365. WsbAssertHr(pSegRec3->SetSegmentRecord(CLSID_CWsbGuid, 0, 5, 0, CLSID_CSegRec,0 ));
  366. // Add the items to the collection.
  367. hr = S_OK;
  368. try {
  369. WsbAssertHr(pSegRec2->Write());
  370. WsbAssertHr(pSegRec3->Write());
  371. } WsbCatch(hr);
  372. if (hr == S_OK) {
  373. (*pTestsPassed)++;
  374. } else {
  375. (*pTestsFailed)++;
  376. }
  377. // There should be 3 entries.
  378. hr = S_OK;
  379. try {
  380. WsbAssertHr(pColl->GetEntries(&entries));
  381. WsbAssert(3 == entries, E_FAIL);
  382. WsbAssertHr(pColl->OccurencesOf(pSegRec3, &entries));
  383. WsbAssert(2 == entries, E_FAIL);
  384. } WsbCatch(hr);
  385. if (hr == S_OK) {
  386. (*pTestsPassed)++;
  387. } else {
  388. (*pTestsFailed)++;
  389. }
  390. // Remove one of the two identical items.
  391. hr = S_OK;
  392. try {
  393. WsbAssertHr(pSegRec3->FindEQ());
  394. WsbAssertHr(pSegRec3->Remove());
  395. } WsbCatch(hr);
  396. if (hr == S_OK) {
  397. (*pTestsPassed)++;
  398. } else {
  399. (*pTestsFailed)++;
  400. }
  401. // There should be 2 entries.
  402. hr = S_OK;
  403. try {
  404. WsbAssertHr(pColl->GetEntries(&entries));
  405. WsbAssert(2 == entries, E_FAIL);
  406. } WsbCatch(hr);
  407. if (hr == S_OK) {
  408. (*pTestsPassed)++;
  409. } else {
  410. (*pTestsFailed)++;
  411. }
  412. // How many copies does it have?
  413. hr = S_OK;
  414. try {
  415. WsbAssertHr(pColl->OccurencesOf(pSegRec1, &entries));
  416. WsbAssert(1 == entries, E_FAIL);
  417. } WsbCatch(hr);
  418. if (hr == S_OK) {
  419. (*pTestsPassed)++;
  420. } else {
  421. (*pTestsFailed)++;
  422. }
  423. hr = S_OK;
  424. try {
  425. WsbAssertHr(pColl->OccurencesOf(pSegRec3, &entries));
  426. WsbAssert(1 == entries, E_FAIL);
  427. } WsbCatch(hr);
  428. if (hr == S_OK) {
  429. (*pTestsPassed)++;
  430. } else {
  431. (*pTestsFailed)++;
  432. }
  433. // Can we find an entry?
  434. hr = S_OK;
  435. try {
  436. WsbAssertHr(pSegRec3->FindEQ());
  437. } WsbCatch(hr);
  438. if (hr == S_OK) {
  439. (*pTestsPassed)++;
  440. } else {
  441. (*pTestsFailed)++;
  442. }
  443. // Does the collection still contain it?
  444. hr = S_OK;
  445. try {
  446. WsbAssert(pColl->Contains(pSegRec1) == S_OK, E_FAIL);
  447. } WsbCatch(hr);
  448. if (hr == S_OK) {
  449. (*pTestsPassed)++;
  450. } else {
  451. (*pTestsFailed)++;
  452. }
  453. // Remove the last of the record, and verify
  454. // that it can't be found. Then puit it back.
  455. hr = S_OK;
  456. try {
  457. WsbAssertHr(pSegRec1->FindEQ());
  458. WsbAssertHr(pSegRec1->Remove());
  459. WsbAssert(pColl->Contains(pSegRec1) == S_FALSE, E_FAIL);
  460. WsbAssertHr(pSegRec1->MarkAsNew());
  461. WsbAssertHr(pSegRec1->Write());
  462. } WsbCatch(hr);
  463. if (hr == S_OK) {
  464. (*pTestsPassed)++;
  465. } else {
  466. (*pTestsFailed)++;
  467. }
  468. try {
  469. WsbAssertHr(pColl->RemoveAllAndRelease());
  470. } WsbCatch(hr);
  471. if (hr == S_OK) {
  472. (*pTestsPassed)++;
  473. } else {
  474. (*pTestsFailed)++;
  475. }
  476. // It should be empty.
  477. hr = S_OK;
  478. try {
  479. WsbAssert(pColl->IsEmpty() == S_OK, E_FAIL);
  480. } WsbCatch(hr);
  481. if (hr == S_OK) {
  482. (*pTestsPassed)++;
  483. } else {
  484. (*pTestsFailed)++;
  485. }
  486. hr = S_OK;
  487. try {
  488. WsbAssertHr(Erase());
  489. } WsbCatch(hr);
  490. if (hr == S_OK) {
  491. (*pTestsPassed)++;
  492. } else {
  493. (*pTestsFailed)++;
  494. }
  495. try {
  496. WsbAssertHr(pSegRec1->SetSegmentRecord(CLSID_CWsbBool, 0, 6, 0, CLSID_CSegRec,0 ));
  497. WsbAssertHr(pSegRec2->SetSegmentRecord(CLSID_CWsbGuid, 0, 5, 0, CLSID_CSegRec,0 ));
  498. WsbAssertHr(pSegRec3->SetSegmentRecord(CLSID_CWsbGuid, 5, 5, 0, CLSID_CSegRec,0 ));
  499. WsbAssertHr(GetEntity(HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec4));
  500. WsbAssertHr(pSegRec4->SetSegmentRecord(CLSID_CWsbGuid, 10, 5, 0, CLSID_CSegRec,0 ));
  501. WsbAssertHr(GetEntity(HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec5));
  502. WsbAssertHr(pSegRec5->SetSegmentRecord(CLSID_CWsbGuid, 15, 5, 0, CLSID_CSegRec,0 ));
  503. WsbAssertHr(GetEntity(HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec6));
  504. WsbAssertHr(pSegRec6->SetSegmentRecord(CLSID_CWsbGuid, 20, 5, 0, CLSID_CSegRec,0 ));
  505. WsbAssertHr(GetEntity(HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec7));
  506. WsbAssertHr(pSegRec7->SetSegmentRecord(CLSID_CWsbGuid, 25, 5, 0, CLSID_CSegRec,0 ));
  507. WsbAssertHr(GetEntity(HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec8));
  508. WsbAssertHr(pSegRec8->SetSegmentRecord(CLSID_CWsbGuid, 30, 5, 0, CLSID_CSegRec,0 ));
  509. WsbAssertHr(GetEntity(HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec9));
  510. WsbAssertHr(pSegRec9->SetSegmentRecord(CLSID_CWsbGuid, 35, 5, 0, CLSID_CSegRec,0 ));
  511. WsbAssertHr(GetEntity(HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec10));
  512. WsbAssertHr(pSegRec10->SetSegmentRecord(CLSID_CWsbGuid, 40, 5, 0, CLSID_CSegRec,0 ));
  513. // Add them in random order
  514. WsbAssertHr(pColl->Add(pSegRec5));
  515. WsbAssertHr(pColl->Add(pSegRec4));
  516. WsbAssertHr(pColl->Add(pSegRec1));
  517. WsbAssertHr(pColl->Add(pSegRec6));
  518. WsbAssertHr(pColl->Add(pSegRec7));
  519. WsbAssertHr(pColl->Add(pSegRec8));
  520. WsbAssertHr(pColl->Add(pSegRec1));
  521. WsbAssertHr(pColl->Add(pSegRec2));
  522. WsbAssertHr(pColl->Add(pSegRec3));
  523. WsbAssertHr(pColl->Add(pSegRec9));
  524. WsbAssertHr(pColl->Add(pSegRec3));
  525. WsbAssertHr(pColl->Add(pSegRec4));
  526. WsbAssertHr(pColl->Add(pSegRec10));
  527. WsbAssertHr(pColl->Add(pSegRec5));
  528. WsbAssertHr(pColl->Add(pSegRec8));
  529. WsbAssertHr(pColl->Add(pSegRec1));
  530. WsbAssertHr(pColl->Add(pSegRec5));
  531. WsbAssertHr(pColl->Add(pSegRec6));
  532. WsbAssertHr(pColl->Add(pSegRec7));
  533. WsbAssertHr(pColl->Add(pSegRec1));
  534. WsbAssertHr(pColl->Add(pSegRec7));
  535. WsbAssertHr(pColl->Add(pSegRec2));
  536. WsbAssertHr(pColl->Add(pSegRec7));
  537. WsbAssertHr(pColl->Add(pSegRec8));
  538. WsbAssertHr(pColl->Add(pSegRec2));
  539. WsbAssertHr(pColl->Add(pSegRec8));
  540. WsbAssertHr(pColl->Add(pSegRec3));
  541. WsbAssertHr(pColl->Add(pSegRec6));
  542. WsbAssertHr(pColl->Add(pSegRec3));
  543. WsbAssertHr(pColl->Add(pSegRec9));
  544. WsbAssertHr(pColl->Add(pSegRec4));
  545. WsbAssertHr(pColl->Add(pSegRec6));
  546. WsbAssertHr(pColl->Add(pSegRec9));
  547. WsbAssertHr(pColl->Add(pSegRec9));
  548. WsbAssertHr(pColl->Add(pSegRec10));
  549. WsbAssertHr(pColl->Add(pSegRec4));
  550. WsbAssertHr(pColl->Add(pSegRec10));
  551. WsbAssertHr(pColl->Add(pSegRec5));
  552. WsbAssertHr(pColl->Add(pSegRec10));
  553. WsbAssertHr(pColl->Add(pSegRec2));
  554. } WsbCatch(hr);
  555. if (hr == S_OK) {
  556. (*pTestsPassed)++;
  557. } else {
  558. (*pTestsFailed)++;
  559. }
  560. try {
  561. // Check that they're sorted
  562. WsbAssertHr(GetEntity(HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec11));
  563. WsbAssertHr(pSegRec11->First());
  564. WsbAssertHr(pSegRec11->GetSegmentRecord(&startBagId, &startSegStartLoc, &startSegLen, &startSegType, &startPrimLoc, &startSecLoc));
  565. lastBagId = startBagId;
  566. lastStartLoc = startSegStartLoc;
  567. hr = S_OK;
  568. for ( ; ; ) {
  569. hr = pSegRec11->Next();
  570. if (hr != S_OK) break;
  571. WsbAssertHr(pSegRec11->GetSegmentRecord(&startBagId, &startSegStartLoc, &startSegLen, &startSegType, &startPrimLoc, &startSecLoc));
  572. WsbAssert(!IsEqualGUID(lastBagId, startBagId) ||
  573. lastStartLoc <= startSegStartLoc, E_FAIL);
  574. lastBagId = startBagId;
  575. lastStartLoc = startSegStartLoc;
  576. }
  577. WsbAssert(hr == WSB_E_NOTFOUND, E_FAIL);
  578. hr = S_OK;
  579. } WsbCatch(hr);
  580. if (hr == S_OK) {
  581. (*pTestsPassed)++;
  582. } else {
  583. (*pTestsFailed)++;
  584. }
  585. try {
  586. // Check that the last one is what we expect
  587. WsbAssertHr(pSegRec11->Last());
  588. WsbAssertHr(pSegRec11->CompareToISegmentRecord(pSegRec10, NULL));
  589. // Look for a specific record
  590. WsbAssertHr(pSegRec5->FindEQ());
  591. // Check for near misses
  592. WsbAssertHr(pSegRec11->SetSegmentRecord(CLSID_CWsbGuid, 23, 5, 0, CLSID_CSegRec,0 ));
  593. WsbAssertHr(pSegRec11->FindGT());
  594. WsbAssertHr(pSegRec11->CompareToISegmentRecord(pSegRec7, NULL));
  595. WsbAssertHr(pSegRec11->SetSegmentRecord(CLSID_CWsbGuid, 21, 5, 0, CLSID_CSegRec,0 ));
  596. WsbAssertHr(pSegRec11->FindLTE());
  597. WsbAssertHr(pSegRec11->CompareToISegmentRecord(pSegRec6, NULL));
  598. } WsbCatch(hr);
  599. if (hr == S_OK) {
  600. (*pTestsPassed)++;
  601. } else {
  602. (*pTestsFailed)++;
  603. }
  604. // Clear the DB so we can shut it down
  605. hr = S_OK;
  606. try {
  607. WsbAssertHr(Erase());
  608. WsbAssertHr(Close());
  609. } WsbCatch(hr);
  610. if (hr == S_OK) {
  611. (*pTestsPassed)++;
  612. } else {
  613. (*pTestsFailed)++;
  614. }
  615. } WsbCatch(hr);
  616. #else
  617. *pTestsPassed = *pTestsFailed = 0;
  618. #endif
  619. WsbTraceOut(OLESTR("CSegDb::Test"), OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  620. return(S_OK);
  621. }
  622. HRESULT
  623. CSegDb::Erase (
  624. void
  625. )
  626. /*++
  627. Routine Description:
  628. See ISegDb::Erase
  629. Arguments:
  630. See ISegDb::Erase
  631. Return Value:
  632. See ISegDb::Erase
  633. --*/
  634. {
  635. HRESULT hr = E_NOTIMPL;
  636. WsbTraceIn(OLESTR("CSegDb::Erase"),OLESTR(""));
  637. try {
  638. // To be done?
  639. } WsbCatch(hr);
  640. WsbTraceOut(OLESTR("CSegDb::Erase"), OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  641. return(hr);
  642. }
  643. HRESULT
  644. CSegDb::GetClassID(
  645. OUT CLSID* pClsid
  646. )
  647. /*++
  648. Implements:
  649. IPersist::GetClassID().
  650. --*/
  651. {
  652. HRESULT hr = S_OK;
  653. try {
  654. WsbAssert(0 != pClsid, E_POINTER);
  655. *pClsid = CLSID_CSegDb;
  656. } WsbCatch(hr);
  657. return(hr);
  658. }
  659. HRESULT
  660. CSegDb::Initialize(
  661. IN OLECHAR* root,
  662. IN IWsbDbSys* pDbSys,
  663. IN OUT BOOL* pCreateFlag
  664. )
  665. /*++
  666. Implements:
  667. ISegDb::Initialize().
  668. --*/
  669. {
  670. BOOL CreateFlag = FALSE;
  671. HRESULT hr = S_OK;
  672. CWsbStringPtr path;
  673. WsbTraceIn(OLESTR("CSegDb::Initialize"),
  674. OLESTR("root = <%ls>, CreateFlag = <%ls>"),
  675. WsbAbbreviatePath(root, 120), WsbPtrToBoolAsString(pCreateFlag));
  676. if (pCreateFlag) {
  677. CreateFlag = *pCreateFlag;
  678. }
  679. try {
  680. path = root;
  681. WsbAffirmHr(path.Append(OLESTR("\\SegDb")));
  682. m_pWsbDbSys = pDbSys;
  683. WsbAffirmPointer(m_pWsbDbSys);
  684. hr = Locate(path);
  685. if (hr == STG_E_FILENOTFOUND && CreateFlag){
  686. ULONG memSize;
  687. hr = S_OK;
  688. m_nRecTypes = 5;
  689. memSize = m_nRecTypes * sizeof(IDB_REC_INFO);
  690. m_RecInfo = (IDB_REC_INFO*)WsbAlloc(memSize);
  691. WsbAffirm(0 != m_RecInfo, E_FAIL);
  692. ZeroMemory(m_RecInfo, memSize);
  693. // Segment records
  694. m_RecInfo[0].Type = HSM_SEG_REC_TYPE;
  695. m_RecInfo[0].EntityClassId = CLSID_CSegRec;
  696. m_RecInfo[0].Flags = 0;
  697. m_RecInfo[0].MinSize = 2 * WSB_BYTE_SIZE_GUID +
  698. 3 * WSB_BYTE_SIZE_LONGLONG + WSB_BYTE_SIZE_USHORT;
  699. m_RecInfo[0].MaxSize = m_RecInfo[0].MinSize;
  700. m_RecInfo[0].nKeys = 1;
  701. memSize = m_RecInfo[0].nKeys * sizeof(IDB_KEY_INFO);
  702. m_RecInfo[0].Key = (IDB_KEY_INFO*)WsbAlloc(memSize);
  703. WsbAffirm(0 != m_RecInfo[0].Key, E_FAIL);
  704. ZeroMemory(m_RecInfo[0].Key, memSize);
  705. m_RecInfo[0].Key[0].Type = SEG_KEY_TYPE;
  706. m_RecInfo[0].Key[0].Size = WSB_BYTE_SIZE_GUID +
  707. WSB_BYTE_SIZE_LONGLONG;
  708. m_RecInfo[0].Key[0].Flags = IDB_KEY_FLAG_DUP_ALLOWED;
  709. // Media information
  710. m_RecInfo[1].Type = HSM_MEDIA_INFO_REC_TYPE;
  711. m_RecInfo[1].EntityClassId = CLSID_CMediaInfo;
  712. m_RecInfo[1].Flags = 0;
  713. m_RecInfo[1].MinSize = 2 * (WSB_BYTE_SIZE_GUID + //Id
  714. WSB_BYTE_SIZE_GUID + //ntmsId
  715. WSB_BYTE_SIZE_GUID + //soragePoolId
  716. 4 + //nme
  717. 4 + //brCode
  718. WSB_BYTE_SIZE_SHORT+ //tpe
  719. WSB_BYTE_SIZE_FILETIME + //lastUpdate
  720. WSB_BYTE_SIZE_LONG + //lastError
  721. WSB_BYTE_SIZE_BOOL + //m_RecallOnly
  722. WSB_BYTE_SIZE_LONGLONG + //m_freeBytes
  723. WSB_BYTE_SIZE_LONGLONG + //m_Capacity
  724. WSB_BYTE_SIZE_SHORT) + //nextRemoteDataSet
  725. WSB_BYTE_SIZE_BOOL + //m_Recreate
  726. WSB_BYTE_SIZE_LONGLONG + //m_LocicalFreeSpace
  727. 3 * (WSB_BYTE_SIZE_GUID + //m_RmsMediaId
  728. 4 + //m_Name
  729. 4 + //m_BarCode
  730. WSB_BYTE_SIZE_FILETIME + //m_Update
  731. WSB_BYTE_SIZE_LONG + //m_LastError
  732. WSB_BYTE_SIZE_SHORT ); //nextRemoteDataSet
  733. // NOTE:
  734. //
  735. // The next line that calculates the max record size for media info has a BAD bug in it - Windows Bugs 407340.
  736. // The macro SEG_DB_MAX_MEDIA_NAME_LEN and SEG_DB_MAX_MEDIA_BAR_CODE_LEN are defined without parenthesis - see in segdb.h
  737. // As a result, the max size is only 711 bytes instead of 1751 as it should be !!
  738. //
  739. // It is NOT fixed since there are too many existing installations with the wrong record size...
  740. // This bug has implications around the code - look for "Windows Bugs 407340" comments throughout the HSM code
  741. //
  742. m_RecInfo[1].MaxSize = m_RecInfo[1].MinSize + 5 * SEG_DB_MAX_MEDIA_NAME_LEN + 5 * SEG_DB_MAX_MEDIA_BAR_CODE_LEN;
  743. m_RecInfo[1].nKeys = 1;
  744. memSize = m_RecInfo[1].nKeys * sizeof(IDB_KEY_INFO);
  745. m_RecInfo[1].Key = (IDB_KEY_INFO*)WsbAlloc(memSize);
  746. WsbAffirm(0 != m_RecInfo[1].Key, E_FAIL);
  747. ZeroMemory(m_RecInfo[1].Key, memSize);
  748. m_RecInfo[1].Key[0].Type = MEDIA_INFO_KEY_TYPE;
  749. m_RecInfo[1].Key[0].Size = WSB_BYTE_SIZE_GUID;
  750. m_RecInfo[1].Key[0].Flags = IDB_KEY_FLAG_PRIMARY;
  751. // Bag information
  752. m_RecInfo[2].Type = HSM_BAG_INFO_REC_TYPE;
  753. m_RecInfo[2].EntityClassId = CLSID_CBagInfo;
  754. m_RecInfo[2].Flags = 0;
  755. m_RecInfo[2].MinSize = (2 * WSB_BYTE_SIZE_GUID) +
  756. (2 * WSB_BYTE_SIZE_LONGLONG) + (2 * WSB_BYTE_SIZE_USHORT) +
  757. WSB_BYTE_SIZE_FILETIME + WSB_BYTE_SIZE_SHORT;
  758. m_RecInfo[2].MaxSize = m_RecInfo[2].MinSize;
  759. m_RecInfo[2].nKeys = 1;
  760. memSize = m_RecInfo[2].nKeys * sizeof(IDB_KEY_INFO);
  761. m_RecInfo[2].Key = (IDB_KEY_INFO*)WsbAlloc(memSize);
  762. WsbAffirm(0 != m_RecInfo[2].Key, E_FAIL);
  763. ZeroMemory(m_RecInfo[2].Key, memSize);
  764. m_RecInfo[2].Key[0].Type = BAG_INFO_KEY_TYPE;
  765. m_RecInfo[2].Key[0].Size = WSB_BYTE_SIZE_GUID;
  766. m_RecInfo[2].Key[0].Flags = IDB_KEY_FLAG_PRIMARY;
  767. // Bag holes
  768. m_RecInfo[3].Type = HSM_BAG_HOLE_REC_TYPE;
  769. m_RecInfo[3].EntityClassId = CLSID_CBagHole;
  770. m_RecInfo[3].Flags = 0;
  771. m_RecInfo[3].MinSize = WSB_BYTE_SIZE_GUID +
  772. 2 * WSB_BYTE_SIZE_LONGLONG;
  773. m_RecInfo[3].MaxSize = m_RecInfo[3].MinSize;
  774. m_RecInfo[3].nKeys = 1;
  775. memSize = m_RecInfo[3].nKeys * sizeof(IDB_KEY_INFO);
  776. m_RecInfo[3].Key = (IDB_KEY_INFO*)WsbAlloc(memSize);
  777. WsbAffirm(0 != m_RecInfo[3].Key, E_FAIL);
  778. ZeroMemory(m_RecInfo[3].Key, memSize);
  779. m_RecInfo[3].Key[0].Type = BAG_HOLE_KEY_TYPE;
  780. m_RecInfo[3].Key[0].Size = WSB_BYTE_SIZE_GUID +
  781. WSB_BYTE_SIZE_LONGLONG;
  782. m_RecInfo[3].Key[0].Flags = IDB_KEY_FLAG_DUP_ALLOWED;
  783. // Volume assignment
  784. m_RecInfo[4].Type = HSM_VOL_ASSIGN_REC_TYPE;
  785. m_RecInfo[4].EntityClassId = CLSID_CVolAssign;
  786. m_RecInfo[4].Flags = 0;
  787. m_RecInfo[4].MinSize = 2 * WSB_BYTE_SIZE_GUID +
  788. 2 * WSB_BYTE_SIZE_LONGLONG;
  789. m_RecInfo[4].MaxSize = m_RecInfo[4].MinSize;
  790. m_RecInfo[4].nKeys = 1;
  791. memSize = m_RecInfo[4].nKeys * sizeof(IDB_KEY_INFO);
  792. m_RecInfo[4].Key = (IDB_KEY_INFO*)WsbAlloc(memSize);
  793. WsbAffirm(0 != m_RecInfo[4].Key, E_FAIL);
  794. ZeroMemory(m_RecInfo[4].Key, memSize);
  795. m_RecInfo[4].Key[0].Type = VOL_ASSIGN_KEY_TYPE;
  796. m_RecInfo[4].Key[0].Size = WSB_BYTE_SIZE_GUID +
  797. WSB_BYTE_SIZE_LONGLONG;
  798. m_RecInfo[4].Key[0].Flags = IDB_KEY_FLAG_DUP_ALLOWED;
  799. // Create the new DB
  800. WsbAssertHr(Create(path));
  801. CreateFlag = TRUE;
  802. } else if (hr == STG_E_FILENOTFOUND) {
  803. // DB doesn't exist, but we're not suppose to create it
  804. WsbLogEvent(WSB_MESSAGE_IDB_OPEN_FAILED, 0, NULL,
  805. WsbQuickString(WsbAbbreviatePath(path, 120)), NULL );
  806. hr = WSB_E_IDB_FILE_NOT_FOUND;
  807. }
  808. } WsbCatch(hr);
  809. if (pCreateFlag) {
  810. *pCreateFlag = CreateFlag;
  811. }
  812. WsbTraceOut(OLESTR("CSegDb::Initialize"),
  813. OLESTR("hr = %ls, path = <%ls>, CreateFlag = <%ls>"),
  814. WsbHrAsString(hr), WsbAbbreviatePath(path, 120),
  815. WsbPtrToBoolAsString(pCreateFlag));
  816. return(hr);
  817. }
  818. HRESULT
  819. CSegDb::Load(
  820. IN IStream* pStream
  821. )
  822. /*++
  823. Implements:
  824. IPersistStream::Load().
  825. --*/
  826. {
  827. HRESULT hr = S_OK;
  828. try {
  829. WsbAffirmHr(CWsbDb::Load(pStream));
  830. } WsbCatch(hr);
  831. return(hr);
  832. }
  833. HRESULT
  834. CSegDb::Save(
  835. IN IStream* pStream,
  836. IN BOOL clearDirty
  837. )
  838. /*++
  839. Implements:
  840. IPersistStream::Save().
  841. --*/
  842. {
  843. HRESULT hr = S_OK;
  844. try {
  845. WsbAffirmHr(CWsbDb::Save(pStream, clearDirty));
  846. } WsbCatch(hr);
  847. return(hr);
  848. }
  849. HRESULT
  850. CSegDb::SegAdd
  851. (
  852. IN IWsbDbSession* pDbSession,
  853. IN GUID BagId,
  854. IN LONGLONG SegStartLoc,
  855. IN LONGLONG SegLen,
  856. IN GUID MediaId,
  857. IN LONGLONG mediaStart,
  858. IN BOOL indirectRecord
  859. )
  860. /*++
  861. Implements:
  862. ISegDb::SegAdd
  863. --*/
  864. {
  865. HRESULT hr = S_OK;
  866. WsbTraceIn(OLESTR("CSegDb::SegAdd"),
  867. OLESTR("GUID = %ls, SegStartLoc = %I64u, SegLen = %I64u"),
  868. WsbGuidAsString(BagId), SegStartLoc, SegLen);
  869. try {
  870. BOOL found = FALSE;
  871. CComPtr<ISegRec> pSegRec;
  872. GUID l_BagId = GUID_NULL;
  873. LONGLONG l_SegStartLoc = 0;
  874. LONGLONG l_SegLen = 0;
  875. USHORT l_SegFlags = SEG_REC_NONE;
  876. GUID l_MediaId = GUID_NULL;
  877. LONGLONG l_MediaStart = 0;
  878. WsbAffirmHr(GetEntity(pDbSession, HSM_SEG_REC_TYPE, IID_ISegRec,
  879. (void **)&pSegRec));
  880. WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, SegStartLoc,
  881. 0, 0, GUID_NULL, 0 ));
  882. // Look for a segment to which to append this one
  883. hr = pSegRec->FindLTE();
  884. if (WSB_E_NOTFOUND == hr) {
  885. hr = S_OK;
  886. } else {
  887. WsbAffirmHr(pSegRec->GetSegmentRecord(&l_BagId, &l_SegStartLoc, &l_SegLen, &l_SegFlags,
  888. &l_MediaId, &l_MediaStart));
  889. if (SEG_EXPAND_OK(l_BagId, l_SegStartLoc, l_SegLen,
  890. BagId, SegStartLoc, SegLen) &&
  891. IsEqualGUID(MediaId, l_MediaId)) {
  892. WsbTrace(OLESTR("CSegDb::SegAdd: Found SegmentRecord: StartLoc = %I64u, Len = %I64u\n"),
  893. l_SegStartLoc, l_SegLen);
  894. found = TRUE;
  895. }
  896. }
  897. if (found) {
  898. // Append this segment to the existing record
  899. l_SegLen = (SegStartLoc - l_SegStartLoc) + SegLen;
  900. WsbTrace(OLESTR("CSegDb::SegAdd: new SegLen = %I64u\n"), l_SegLen);
  901. } else {
  902. // Create a new segment record
  903. l_SegStartLoc = SegStartLoc;
  904. l_SegLen = SegLen;
  905. if (indirectRecord) {
  906. l_SegFlags = SEG_REC_INDIRECT_RECORD;
  907. } else {
  908. l_SegFlags = SEG_REC_NONE;
  909. }
  910. l_MediaId = MediaId;
  911. l_MediaStart = mediaStart;
  912. WsbAffirmHr(pSegRec->MarkAsNew());
  913. WsbTrace(OLESTR("CSegDb::SegAdd: add new segment\n"));
  914. }
  915. WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, l_SegStartLoc,
  916. l_SegLen, l_SegFlags, l_MediaId, l_MediaStart ));
  917. WsbAffirmHr(pSegRec->Write());
  918. } WsbCatch(hr);
  919. WsbTraceOut(OLESTR("CSegDb::SegAdd"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
  920. return(hr);
  921. }
  922. HRESULT
  923. CSegDb::SegFind
  924. (
  925. IN IWsbDbSession* pDbSession,
  926. IN GUID BagId,
  927. IN LONGLONG SegStartLoc,
  928. IN LONGLONG SegLen,
  929. OUT ISegRec** ppISegRec
  930. )
  931. /*++
  932. Implements:
  933. ISegDb::SegFind
  934. --*/
  935. {
  936. HRESULT hr = S_OK;
  937. WsbTraceIn(OLESTR("CSegDb::SegFind"),
  938. OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
  939. WsbGuidAsString(BagId),
  940. SegStartLoc,
  941. SegLen);
  942. try {
  943. CComPtr<ISegRec> pSegRec;
  944. GUID l_BagId;
  945. LONGLONG l_SegStartLoc;
  946. LONGLONG l_SegLen;
  947. USHORT l_SegFlags;
  948. GUID l_MediaId;
  949. LONGLONG l_MediaStart;
  950. WsbAffirm(ppISegRec != NULL, E_POINTER);
  951. WsbAffirmHr(GetEntity(pDbSession, HSM_SEG_REC_TYPE, IID_ISegRec,
  952. (void **)&pSegRec));
  953. WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, SegStartLoc,
  954. 0, 0, GUID_NULL, 0 ));
  955. // Look for a segment that contains this one
  956. WsbTrace(OLESTR("Finding SegmentRecord: <%ls>, <%I64u>, <%I64u>\n"),
  957. WsbGuidAsString(BagId),
  958. SegStartLoc,
  959. SegLen);
  960. WsbAffirmHr(pSegRec->FindLTE());
  961. // We found a record, see if it's the right one
  962. WsbAffirmHr(pSegRec->GetSegmentRecord(&l_BagId, &l_SegStartLoc,
  963. &l_SegLen, &l_SegFlags, &l_MediaId, &l_MediaStart));
  964. if (SEG_CONTAINS(l_BagId, l_SegStartLoc, l_SegLen,
  965. BagId, SegStartLoc, SegLen)) {
  966. *ppISegRec = pSegRec;
  967. pSegRec.p->AddRef();
  968. } else {
  969. hr = WSB_E_NOTFOUND;
  970. }
  971. } WsbCatch(hr);
  972. WsbTraceOut(OLESTR("CSegDb::SegFind"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
  973. return(hr);
  974. }
  975. HRESULT
  976. CSegDb::SegSubtract
  977. (
  978. IN IWsbDbSession* pDbSession,
  979. IN GUID BagId,
  980. IN LONGLONG SegStartLoc,
  981. IN LONGLONG SegLen
  982. )
  983. /*++
  984. Implements:
  985. ISegDb::SegSubtract
  986. --*/
  987. {
  988. HRESULT hr = S_OK;
  989. WsbTraceIn(OLESTR("CSegDb::SegSubtract"),
  990. OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
  991. WsbGuidAsString(BagId),
  992. SegStartLoc,
  993. SegLen);
  994. try {
  995. GUID l_BagId;
  996. LONGLONG l_SegStartLoc;
  997. LONGLONG l_SegLen;
  998. USHORT l_SegFlags;
  999. GUID l_MediaId;
  1000. LONGLONG l_MediaStart;
  1001. CComPtr<ISegRec> pSegRec;
  1002. // Find the segment record
  1003. WsbAffirmHr(SegFind(pDbSession, BagId, SegStartLoc, SegLen, &pSegRec));
  1004. // Get the current data
  1005. WsbAffirmHr(pSegRec->GetSegmentRecord(&l_BagId, &l_SegStartLoc,
  1006. &l_SegLen, &l_SegFlags, &l_MediaId, &l_MediaStart));
  1007. // Determine where the hole is
  1008. if (l_SegStartLoc == SegStartLoc && l_SegLen == SegLen) {
  1009. // Hole is the entire segment -- delete it
  1010. WsbAffirmHr(pSegRec->Remove());
  1011. } else if (l_SegStartLoc == SegStartLoc) {
  1012. // Hole is at the beginning of the segment. Just update the
  1013. // existing segment
  1014. l_SegStartLoc += SegLen;
  1015. l_MediaStart += SegLen;
  1016. WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, l_SegStartLoc,
  1017. l_SegLen, l_SegFlags, l_MediaId, l_MediaStart ));
  1018. WsbAffirmHr(pSegRec->Write());
  1019. } else if ((l_SegStartLoc + l_SegLen) == (SegStartLoc + SegLen)) {
  1020. // Hole is at the end of the segment. Just update the
  1021. // existing segment
  1022. l_SegLen -= SegLen;
  1023. WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, l_SegStartLoc,
  1024. l_SegLen, l_SegFlags, l_MediaId, l_MediaStart ));
  1025. WsbAffirmHr(pSegRec->Write());
  1026. } else {
  1027. // Hole is in the middle of the segment. Update the
  1028. // existing record to be the first part.
  1029. LONGLONG oldLen = l_SegLen;
  1030. LONGLONG offset = (SegStartLoc + SegLen) - l_SegStartLoc;
  1031. BOOL bIndirect = FALSE;
  1032. l_SegLen = SegStartLoc - l_SegStartLoc;
  1033. WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, l_SegStartLoc,
  1034. l_SegLen, l_SegFlags, l_MediaId, l_MediaStart ));
  1035. WsbAffirmHr(pSegRec->Write());
  1036. // Create a new record for the second part.
  1037. l_SegLen -= offset;
  1038. l_SegStartLoc += offset;
  1039. l_MediaStart += offset;
  1040. if (l_SegFlags & SEG_REC_INDIRECT_RECORD) {
  1041. bIndirect = TRUE;
  1042. }
  1043. WsbAffirmHr(SegAdd(pDbSession, BagId, l_SegStartLoc, l_SegLen, l_MediaId,
  1044. l_MediaStart, bIndirect));
  1045. }
  1046. } WsbCatch(hr);
  1047. WsbTraceOut(OLESTR("CSegDb::SegSubtract"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
  1048. return(hr);
  1049. }
  1050. HRESULT
  1051. CSegDb::VolAssignAdd
  1052. (
  1053. IN IWsbDbSession* pDbSession,
  1054. IN GUID BagId,
  1055. IN LONGLONG SegStartLoc,
  1056. IN LONGLONG SegLen,
  1057. IN GUID VolId
  1058. )
  1059. /*++
  1060. Implements:
  1061. ISegDb::VolAssignAdd
  1062. --*/
  1063. {
  1064. HRESULT hr = S_OK;
  1065. WsbTraceIn(OLESTR("CSegDb::VolAssignAdd"),
  1066. OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
  1067. WsbGuidAsString(BagId),
  1068. SegStartLoc,
  1069. SegLen);
  1070. try {
  1071. BOOL found = FALSE;
  1072. CComPtr<IVolAssign> pVolAssign;
  1073. GUID l_BagId = GUID_NULL;
  1074. LONGLONG l_SegStartLoc = 0;
  1075. LONGLONG l_SegLen = 0;
  1076. GUID l_VolId = GUID_NULL;
  1077. WsbAffirmHr(GetEntity(pDbSession, HSM_VOL_ASSIGN_REC_TYPE, IID_IVolAssign,
  1078. (void **)&pVolAssign));
  1079. WsbAffirmHr(pVolAssign->SetVolAssign(BagId, SegStartLoc,
  1080. 0, GUID_NULL));
  1081. // Look for a segment to which to append this one
  1082. WsbTrace(OLESTR("Finding VolAssign Record: <%ls>, <%I64u>, <%I64u>\n"),
  1083. WsbGuidAsString(BagId),
  1084. SegStartLoc,
  1085. SegLen);
  1086. hr = pVolAssign->FindLTE();
  1087. if (WSB_E_NOTFOUND == hr) {
  1088. hr = S_OK;
  1089. } else {
  1090. WsbAffirmHr(pVolAssign->GetVolAssign(&l_BagId, &l_SegStartLoc,
  1091. &l_SegLen, &l_VolId));
  1092. if (SEG_APPEND_OK(l_BagId, l_SegStartLoc, l_SegLen,
  1093. BagId, SegStartLoc, SegLen) && IsEqualGUID(l_VolId, VolId)) {
  1094. found = TRUE;
  1095. }
  1096. }
  1097. if (found) {
  1098. // Append this segment to the existing record
  1099. l_SegLen += SegLen;
  1100. } else {
  1101. // Create a new record
  1102. l_SegStartLoc = SegStartLoc;
  1103. l_SegLen = SegLen;
  1104. l_VolId = VolId;
  1105. WsbAffirmHr(pVolAssign->MarkAsNew());
  1106. }
  1107. WsbAffirmHr(pVolAssign->SetVolAssign(BagId, l_SegStartLoc,
  1108. l_SegLen, l_VolId));
  1109. WsbTrace(OLESTR("Writing VolAssign Record: <%ls>, <%I64u>, <%I64u>\n"),
  1110. WsbGuidAsString(BagId),
  1111. l_SegStartLoc,
  1112. l_SegLen);
  1113. WsbAffirmHr(pVolAssign->Write());
  1114. } WsbCatch(hr);
  1115. WsbTraceOut(OLESTR("CSegDb::VolAssignAdd"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
  1116. return(hr);
  1117. }
  1118. HRESULT
  1119. CSegDb::VolAssignFind
  1120. (
  1121. IN IWsbDbSession* pDbSession,
  1122. IN GUID BagId,
  1123. IN LONGLONG SegStartLoc,
  1124. IN LONGLONG SegLen,
  1125. OUT IVolAssign** ppIVolAssign
  1126. )
  1127. /*++
  1128. Implements:
  1129. ISegDb::VolAssignFind
  1130. --*/
  1131. {
  1132. HRESULT hr = S_OK;
  1133. WsbTraceIn(OLESTR("CSegDb::VolAssignFind"),
  1134. OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
  1135. WsbGuidAsString(BagId),
  1136. SegStartLoc,
  1137. SegLen);
  1138. try {
  1139. CComPtr<IVolAssign> pVolAssign;
  1140. GUID l_BagId;
  1141. LONGLONG l_SegStartLoc;
  1142. LONGLONG l_SegLen;
  1143. GUID l_VolId;
  1144. WsbAffirm(ppIVolAssign != NULL, E_POINTER);
  1145. WsbAffirmHr(GetEntity(pDbSession, HSM_VOL_ASSIGN_REC_TYPE, IID_IVolAssign,
  1146. (void **)&pVolAssign));
  1147. WsbAffirmHr(pVolAssign->SetVolAssign(BagId, SegStartLoc, 0, GUID_NULL));
  1148. // Look for a segment that contains this one
  1149. WsbTrace(OLESTR("Finding VolAssign Record: <%ls>, <%I64u>, <%I64u>\n"),
  1150. WsbGuidAsString(BagId),
  1151. SegStartLoc,
  1152. SegLen);
  1153. WsbAffirmHr(pVolAssign->FindLTE());
  1154. // We found a record, see if it's the right one
  1155. WsbAffirmHr(pVolAssign->GetVolAssign(&l_BagId, &l_SegStartLoc,
  1156. &l_SegLen, &l_VolId));
  1157. if (SEG_CONTAINS(l_BagId, l_SegStartLoc, l_SegLen,
  1158. BagId, SegStartLoc, SegLen)) {
  1159. *ppIVolAssign = pVolAssign;
  1160. pVolAssign.p->AddRef();
  1161. } else {
  1162. hr = WSB_E_NOTFOUND;
  1163. }
  1164. } WsbCatch(hr);
  1165. WsbTraceOut(OLESTR("CSegDb::VolAssignFind"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
  1166. return(hr);
  1167. }
  1168. HRESULT
  1169. CSegDb::VolAssignSubtract
  1170. (
  1171. IN IWsbDbSession* pDbSession,
  1172. IN GUID BagId,
  1173. IN LONGLONG SegStartLoc,
  1174. IN LONGLONG SegLen
  1175. )
  1176. /*++
  1177. Implements:
  1178. ISegDb::VolAssignSubtract
  1179. --*/
  1180. {
  1181. HRESULT hr = S_OK;
  1182. WsbTraceIn(OLESTR("CSegDb::VolAssignSubtract"),
  1183. OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
  1184. WsbGuidAsString(BagId),
  1185. SegStartLoc,
  1186. SegLen);
  1187. try {
  1188. GUID l_BagId;
  1189. LONGLONG l_SegStartLoc;
  1190. LONGLONG l_SegLen;
  1191. GUID l_VolId;
  1192. CComPtr<IVolAssign> pVolAssign;
  1193. // Find the segment record
  1194. WsbAffirmHr(VolAssignFind(pDbSession, BagId, SegStartLoc, SegLen, &pVolAssign));
  1195. // Get the current data
  1196. WsbAffirmHr(pVolAssign->GetVolAssign(&l_BagId, &l_SegStartLoc,
  1197. &l_SegLen, &l_VolId));
  1198. // Determine where the hole is
  1199. if (l_SegStartLoc == SegStartLoc && l_SegLen == SegLen) {
  1200. // Hole is the entire segment -- delete it
  1201. WsbAffirmHr(pVolAssign->Remove());
  1202. } else if (l_SegStartLoc == SegStartLoc) {
  1203. // Hole is at the beginning of the segment. Just update the
  1204. // existing segment
  1205. l_SegStartLoc += SegLen;
  1206. WsbAffirmHr(pVolAssign->SetVolAssign(BagId, l_SegStartLoc,
  1207. l_SegLen, l_VolId));
  1208. WsbAffirmHr(pVolAssign->Write());
  1209. } else if ((l_SegStartLoc + l_SegLen) == (SegStartLoc + SegLen)) {
  1210. // Hole is at the end of the segment. Just update the
  1211. // existing segment
  1212. l_SegLen -= SegLen;
  1213. WsbAffirmHr(pVolAssign->SetVolAssign(BagId, l_SegStartLoc,
  1214. l_SegLen, l_VolId));
  1215. WsbAffirmHr(pVolAssign->Write());
  1216. } else {
  1217. // Hole is in the middle of the segment. Update the
  1218. // existing record to be the first part.
  1219. LONGLONG oldLen = l_SegLen;
  1220. LONGLONG offset = (SegStartLoc + SegLen) - l_SegStartLoc;
  1221. l_SegLen = SegStartLoc - l_SegStartLoc;
  1222. WsbAffirmHr(pVolAssign->SetVolAssign(BagId, l_SegStartLoc,
  1223. l_SegLen, l_VolId));
  1224. WsbAffirmHr(pVolAssign->Write());
  1225. // Create a new record for the second part.
  1226. l_SegLen -= offset;
  1227. l_SegStartLoc += offset;
  1228. WsbAffirmHr(VolAssignAdd(pDbSession, BagId, l_SegStartLoc, l_SegLen,
  1229. l_VolId));
  1230. }
  1231. } WsbCatch(hr);
  1232. WsbTraceOut(OLESTR("CSegDb::VolAssignSubtract"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
  1233. return(hr);
  1234. }