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

1539 lines
45 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->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. m_RecInfo[1].MaxSize = m_RecInfo[1].MinSize + 5 * SEG_DB_MAX_MEDIA_NAME_LEN + 5 * SEG_DB_MAX_MEDIA_BAR_CODE_LEN;
  734. m_RecInfo[1].nKeys = 1;
  735. memSize = m_RecInfo[1].nKeys * sizeof(IDB_KEY_INFO);
  736. m_RecInfo[1].Key = (IDB_KEY_INFO*)WsbAlloc(memSize);
  737. WsbAffirm(0 != m_RecInfo[1].Key, E_FAIL);
  738. ZeroMemory(m_RecInfo[1].Key, memSize);
  739. m_RecInfo[1].Key[0].Type = MEDIA_INFO_KEY_TYPE;
  740. m_RecInfo[1].Key[0].Size = WSB_BYTE_SIZE_GUID;
  741. m_RecInfo[1].Key[0].Flags = IDB_KEY_FLAG_PRIMARY;
  742. // Bag information
  743. m_RecInfo[2].Type = HSM_BAG_INFO_REC_TYPE;
  744. m_RecInfo[2].EntityClassId = CLSID_CBagInfo;
  745. m_RecInfo[2].Flags = 0;
  746. m_RecInfo[2].MinSize = (2 * WSB_BYTE_SIZE_GUID) +
  747. (2 * WSB_BYTE_SIZE_LONGLONG) + (2 * WSB_BYTE_SIZE_USHORT) +
  748. WSB_BYTE_SIZE_FILETIME + WSB_BYTE_SIZE_SHORT;
  749. m_RecInfo[2].MaxSize = m_RecInfo[2].MinSize;
  750. m_RecInfo[2].nKeys = 1;
  751. memSize = m_RecInfo[2].nKeys * sizeof(IDB_KEY_INFO);
  752. m_RecInfo[2].Key = (IDB_KEY_INFO*)WsbAlloc(memSize);
  753. WsbAffirm(0 != m_RecInfo[2].Key, E_FAIL);
  754. ZeroMemory(m_RecInfo[2].Key, memSize);
  755. m_RecInfo[2].Key[0].Type = BAG_INFO_KEY_TYPE;
  756. m_RecInfo[2].Key[0].Size = WSB_BYTE_SIZE_GUID;
  757. m_RecInfo[2].Key[0].Flags = IDB_KEY_FLAG_PRIMARY;
  758. // Bag holes
  759. m_RecInfo[3].Type = HSM_BAG_HOLE_REC_TYPE;
  760. m_RecInfo[3].EntityClassId = CLSID_CBagHole;
  761. m_RecInfo[3].Flags = 0;
  762. m_RecInfo[3].MinSize = WSB_BYTE_SIZE_GUID +
  763. 2 * WSB_BYTE_SIZE_LONGLONG;
  764. m_RecInfo[3].MaxSize = m_RecInfo[3].MinSize;
  765. m_RecInfo[3].nKeys = 1;
  766. memSize = m_RecInfo[3].nKeys * sizeof(IDB_KEY_INFO);
  767. m_RecInfo[3].Key = (IDB_KEY_INFO*)WsbAlloc(memSize);
  768. WsbAffirm(0 != m_RecInfo[3].Key, E_FAIL);
  769. ZeroMemory(m_RecInfo[3].Key, memSize);
  770. m_RecInfo[3].Key[0].Type = BAG_HOLE_KEY_TYPE;
  771. m_RecInfo[3].Key[0].Size = WSB_BYTE_SIZE_GUID +
  772. WSB_BYTE_SIZE_LONGLONG;
  773. m_RecInfo[3].Key[0].Flags = IDB_KEY_FLAG_DUP_ALLOWED;
  774. // Volume assignment
  775. m_RecInfo[4].Type = HSM_VOL_ASSIGN_REC_TYPE;
  776. m_RecInfo[4].EntityClassId = CLSID_CVolAssign;
  777. m_RecInfo[4].Flags = 0;
  778. m_RecInfo[4].MinSize = 2 * WSB_BYTE_SIZE_GUID +
  779. 2 * WSB_BYTE_SIZE_LONGLONG;
  780. m_RecInfo[4].MaxSize = m_RecInfo[4].MinSize;
  781. m_RecInfo[4].nKeys = 1;
  782. memSize = m_RecInfo[4].nKeys * sizeof(IDB_KEY_INFO);
  783. m_RecInfo[4].Key = (IDB_KEY_INFO*)WsbAlloc(memSize);
  784. WsbAffirm(0 != m_RecInfo[4].Key, E_FAIL);
  785. ZeroMemory(m_RecInfo[4].Key, memSize);
  786. m_RecInfo[4].Key[0].Type = VOL_ASSIGN_KEY_TYPE;
  787. m_RecInfo[4].Key[0].Size = WSB_BYTE_SIZE_GUID +
  788. WSB_BYTE_SIZE_LONGLONG;
  789. m_RecInfo[4].Key[0].Flags = IDB_KEY_FLAG_DUP_ALLOWED;
  790. // Create the new DB
  791. WsbAssertHr(Create(path));
  792. CreateFlag = TRUE;
  793. } else if (hr == STG_E_FILENOTFOUND) {
  794. // DB doesn't exist, but we're not suppose to create it
  795. WsbLogEvent(WSB_MESSAGE_IDB_OPEN_FAILED, 0, NULL,
  796. WsbQuickString(WsbAbbreviatePath(path, 120)), NULL );
  797. hr = WSB_E_IDB_FILE_NOT_FOUND;
  798. }
  799. } WsbCatch(hr);
  800. if (pCreateFlag) {
  801. *pCreateFlag = CreateFlag;
  802. }
  803. WsbTraceOut(OLESTR("CSegDb::Initialize"),
  804. OLESTR("hr = %ls, path = <%ls>, CreateFlag = <%ls>"),
  805. WsbHrAsString(hr), WsbAbbreviatePath(path, 120),
  806. WsbPtrToBoolAsString(pCreateFlag));
  807. return(hr);
  808. }
  809. HRESULT
  810. CSegDb::Load(
  811. IN IStream* pStream
  812. )
  813. /*++
  814. Implements:
  815. IPersistStream::Load().
  816. --*/
  817. {
  818. HRESULT hr = S_OK;
  819. try {
  820. WsbAffirmHr(CWsbDb::Load(pStream));
  821. } WsbCatch(hr);
  822. return(hr);
  823. }
  824. HRESULT
  825. CSegDb::Save(
  826. IN IStream* pStream,
  827. IN BOOL clearDirty
  828. )
  829. /*++
  830. Implements:
  831. IPersistStream::Save().
  832. --*/
  833. {
  834. HRESULT hr = S_OK;
  835. try {
  836. WsbAffirmHr(CWsbDb::Save(pStream, clearDirty));
  837. } WsbCatch(hr);
  838. return(hr);
  839. }
  840. HRESULT
  841. CSegDb::SegAdd
  842. (
  843. IN IWsbDbSession* pDbSession,
  844. IN GUID BagId,
  845. IN LONGLONG SegStartLoc,
  846. IN LONGLONG SegLen,
  847. IN GUID MediaId,
  848. IN LONGLONG mediaStart,
  849. IN BOOL indirectRecord
  850. )
  851. /*++
  852. Implements:
  853. ISegDb::SegAdd
  854. --*/
  855. {
  856. HRESULT hr = S_OK;
  857. WsbTraceIn(OLESTR("CSegDb::SegAdd"),
  858. OLESTR("GUID = %ls, SegStartLoc = %I64u, SegLen = %I64u"),
  859. WsbGuidAsString(BagId), SegStartLoc, SegLen);
  860. try {
  861. BOOL found = FALSE;
  862. CComPtr<ISegRec> pSegRec;
  863. GUID l_BagId = GUID_NULL;
  864. LONGLONG l_SegStartLoc = 0;
  865. LONGLONG l_SegLen = 0;
  866. USHORT l_SegFlags = SEG_REC_NONE;
  867. GUID l_MediaId = GUID_NULL;
  868. LONGLONG l_MediaStart = 0;
  869. WsbAffirmHr(GetEntity(pDbSession, HSM_SEG_REC_TYPE, IID_ISegRec,
  870. (void **)&pSegRec));
  871. WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, SegStartLoc,
  872. 0, 0, GUID_NULL, 0 ));
  873. // Look for a segment to which to append this one
  874. hr = pSegRec->FindLTE();
  875. if (WSB_E_NOTFOUND == hr) {
  876. hr = S_OK;
  877. } else {
  878. WsbAffirmHr(pSegRec->GetSegmentRecord(&l_BagId, &l_SegStartLoc, &l_SegLen, &l_SegFlags,
  879. &l_MediaId, &l_MediaStart));
  880. if (SEG_EXPAND_OK(l_BagId, l_SegStartLoc, l_SegLen,
  881. BagId, SegStartLoc, SegLen) &&
  882. IsEqualGUID(MediaId, l_MediaId)) {
  883. WsbTrace(OLESTR("CSegDb::SegAdd: Found SegmentRecord: StartLoc = %I64u, Len = %I64u\n"),
  884. l_SegStartLoc, l_SegLen);
  885. found = TRUE;
  886. }
  887. }
  888. if (found) {
  889. // Append this segment to the existing record
  890. l_SegLen = (SegStartLoc - l_SegStartLoc) + SegLen;
  891. WsbTrace(OLESTR("CSegDb::SegAdd: new SegLen = %I64u\n"), l_SegLen);
  892. } else {
  893. // Create a new segment record
  894. l_SegStartLoc = SegStartLoc;
  895. l_SegLen = SegLen;
  896. if (indirectRecord) {
  897. l_SegFlags = SEG_REC_INDIRECT_RECORD;
  898. } else {
  899. l_SegFlags = SEG_REC_NONE;
  900. }
  901. l_MediaId = MediaId;
  902. l_MediaStart = mediaStart;
  903. WsbAffirmHr(pSegRec->MarkAsNew());
  904. WsbTrace(OLESTR("CSegDb::SegAdd: add new segment\n"));
  905. }
  906. WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, l_SegStartLoc,
  907. l_SegLen, l_SegFlags, l_MediaId, l_MediaStart ));
  908. WsbAffirmHr(pSegRec->Write());
  909. } WsbCatch(hr);
  910. WsbTraceOut(OLESTR("CSegDb::SegAdd"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
  911. return(hr);
  912. }
  913. HRESULT
  914. CSegDb::SegFind
  915. (
  916. IN IWsbDbSession* pDbSession,
  917. IN GUID BagId,
  918. IN LONGLONG SegStartLoc,
  919. IN LONGLONG SegLen,
  920. OUT ISegRec** ppISegRec
  921. )
  922. /*++
  923. Implements:
  924. ISegDb::SegFind
  925. --*/
  926. {
  927. HRESULT hr = S_OK;
  928. WsbTraceIn(OLESTR("CSegDb::SegFind"),
  929. OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
  930. WsbGuidAsString(BagId),
  931. SegStartLoc,
  932. SegLen);
  933. try {
  934. CComPtr<ISegRec> pSegRec;
  935. GUID l_BagId;
  936. LONGLONG l_SegStartLoc;
  937. LONGLONG l_SegLen;
  938. USHORT l_SegFlags;
  939. GUID l_MediaId;
  940. LONGLONG l_MediaStart;
  941. WsbAffirm(ppISegRec != NULL, E_POINTER);
  942. WsbAffirmHr(GetEntity(pDbSession, HSM_SEG_REC_TYPE, IID_ISegRec,
  943. (void **)&pSegRec));
  944. WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, SegStartLoc,
  945. 0, 0, GUID_NULL, 0 ));
  946. // Look for a segment that contains this one
  947. WsbTrace(OLESTR("Finding SegmentRecord: <%ls>, <%I64u>, <%I64u>\n"),
  948. WsbGuidAsString(BagId),
  949. SegStartLoc,
  950. SegLen);
  951. WsbAffirmHr(pSegRec->FindLTE());
  952. // We found a record, see if it's the right one
  953. WsbAffirmHr(pSegRec->GetSegmentRecord(&l_BagId, &l_SegStartLoc,
  954. &l_SegLen, &l_SegFlags, &l_MediaId, &l_MediaStart));
  955. if (SEG_CONTAINS(l_BagId, l_SegStartLoc, l_SegLen,
  956. BagId, SegStartLoc, SegLen)) {
  957. *ppISegRec = pSegRec;
  958. pSegRec->AddRef();
  959. } else {
  960. hr = WSB_E_NOTFOUND;
  961. }
  962. } WsbCatch(hr);
  963. WsbTraceOut(OLESTR("CSegDb::SegFind"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
  964. return(hr);
  965. }
  966. HRESULT
  967. CSegDb::SegSubtract
  968. (
  969. IN IWsbDbSession* pDbSession,
  970. IN GUID BagId,
  971. IN LONGLONG SegStartLoc,
  972. IN LONGLONG SegLen
  973. )
  974. /*++
  975. Implements:
  976. ISegDb::SegSubtract
  977. --*/
  978. {
  979. HRESULT hr = S_OK;
  980. WsbTraceIn(OLESTR("CSegDb::SegSubtract"),
  981. OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
  982. WsbGuidAsString(BagId),
  983. SegStartLoc,
  984. SegLen);
  985. try {
  986. GUID l_BagId;
  987. LONGLONG l_SegStartLoc;
  988. LONGLONG l_SegLen;
  989. USHORT l_SegFlags;
  990. GUID l_MediaId;
  991. LONGLONG l_MediaStart;
  992. CComPtr<ISegRec> pSegRec;
  993. // Find the segment record
  994. WsbAffirmHr(SegFind(pDbSession, BagId, SegStartLoc, SegLen, &pSegRec));
  995. // Get the current data
  996. WsbAffirmHr(pSegRec->GetSegmentRecord(&l_BagId, &l_SegStartLoc,
  997. &l_SegLen, &l_SegFlags, &l_MediaId, &l_MediaStart));
  998. // Determine where the hole is
  999. if (l_SegStartLoc == SegStartLoc && l_SegLen == SegLen) {
  1000. // Hole is the entire segment -- delete it
  1001. WsbAffirmHr(pSegRec->Remove());
  1002. } else if (l_SegStartLoc == SegStartLoc) {
  1003. // Hole is at the beginning of the segment. Just update the
  1004. // existing segment
  1005. l_SegStartLoc += SegLen;
  1006. l_MediaStart += SegLen;
  1007. WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, l_SegStartLoc,
  1008. l_SegLen, l_SegFlags, l_MediaId, l_MediaStart ));
  1009. WsbAffirmHr(pSegRec->Write());
  1010. } else if ((l_SegStartLoc + l_SegLen) == (SegStartLoc + SegLen)) {
  1011. // Hole is at the end of the segment. Just update the
  1012. // existing segment
  1013. l_SegLen -= SegLen;
  1014. WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, l_SegStartLoc,
  1015. l_SegLen, l_SegFlags, l_MediaId, l_MediaStart ));
  1016. WsbAffirmHr(pSegRec->Write());
  1017. } else {
  1018. // Hole is in the middle of the segment. Update the
  1019. // existing record to be the first part.
  1020. LONGLONG oldLen = l_SegLen;
  1021. LONGLONG offset = (SegStartLoc + SegLen) - l_SegStartLoc;
  1022. BOOL bIndirect = FALSE;
  1023. l_SegLen = SegStartLoc - l_SegStartLoc;
  1024. WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, l_SegStartLoc,
  1025. l_SegLen, l_SegFlags, l_MediaId, l_MediaStart ));
  1026. WsbAffirmHr(pSegRec->Write());
  1027. // Create a new record for the second part.
  1028. l_SegLen -= offset;
  1029. l_SegStartLoc += offset;
  1030. l_MediaStart += offset;
  1031. if (l_SegFlags & SEG_REC_INDIRECT_RECORD) {
  1032. bIndirect = TRUE;
  1033. }
  1034. WsbAffirmHr(SegAdd(pDbSession, BagId, l_SegStartLoc, l_SegLen, l_MediaId,
  1035. l_MediaStart, bIndirect));
  1036. }
  1037. } WsbCatch(hr);
  1038. WsbTraceOut(OLESTR("CSegDb::SegSubtract"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
  1039. return(hr);
  1040. }
  1041. HRESULT
  1042. CSegDb::VolAssignAdd
  1043. (
  1044. IN IWsbDbSession* pDbSession,
  1045. IN GUID BagId,
  1046. IN LONGLONG SegStartLoc,
  1047. IN LONGLONG SegLen,
  1048. IN GUID VolId
  1049. )
  1050. /*++
  1051. Implements:
  1052. ISegDb::VolAssignAdd
  1053. --*/
  1054. {
  1055. HRESULT hr = S_OK;
  1056. WsbTraceIn(OLESTR("CSegDb::VolAssignAdd"),
  1057. OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
  1058. WsbGuidAsString(BagId),
  1059. SegStartLoc,
  1060. SegLen);
  1061. try {
  1062. BOOL found = FALSE;
  1063. CComPtr<IVolAssign> pVolAssign;
  1064. GUID l_BagId = GUID_NULL;
  1065. LONGLONG l_SegStartLoc = 0;
  1066. LONGLONG l_SegLen = 0;
  1067. GUID l_VolId = GUID_NULL;
  1068. WsbAffirmHr(GetEntity(pDbSession, HSM_VOL_ASSIGN_REC_TYPE, IID_IVolAssign,
  1069. (void **)&pVolAssign));
  1070. WsbAffirmHr(pVolAssign->SetVolAssign(BagId, SegStartLoc,
  1071. 0, GUID_NULL));
  1072. // Look for a segment to which to append this one
  1073. WsbTrace(OLESTR("Finding VolAssign Record: <%ls>, <%I64u>, <%I64u>\n"),
  1074. WsbGuidAsString(BagId),
  1075. SegStartLoc,
  1076. SegLen);
  1077. hr = pVolAssign->FindLTE();
  1078. if (WSB_E_NOTFOUND == hr) {
  1079. hr = S_OK;
  1080. } else {
  1081. WsbAffirmHr(pVolAssign->GetVolAssign(&l_BagId, &l_SegStartLoc,
  1082. &l_SegLen, &l_VolId));
  1083. if (SEG_APPEND_OK(l_BagId, l_SegStartLoc, l_SegLen,
  1084. BagId, SegStartLoc, SegLen) && IsEqualGUID(l_VolId, VolId)) {
  1085. found = TRUE;
  1086. }
  1087. }
  1088. if (found) {
  1089. // Append this segment to the existing record
  1090. l_SegLen += SegLen;
  1091. } else {
  1092. // Create a new record
  1093. l_SegStartLoc = SegStartLoc;
  1094. l_SegLen = SegLen;
  1095. l_VolId = VolId;
  1096. WsbAffirmHr(pVolAssign->MarkAsNew());
  1097. }
  1098. WsbAffirmHr(pVolAssign->SetVolAssign(BagId, l_SegStartLoc,
  1099. l_SegLen, l_VolId));
  1100. WsbTrace(OLESTR("Writing VolAssign Record: <%ls>, <%I64u>, <%I64u>\n"),
  1101. WsbGuidAsString(BagId),
  1102. l_SegStartLoc,
  1103. l_SegLen);
  1104. WsbAffirmHr(pVolAssign->Write());
  1105. } WsbCatch(hr);
  1106. WsbTraceOut(OLESTR("CSegDb::VolAssignAdd"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
  1107. return(hr);
  1108. }
  1109. HRESULT
  1110. CSegDb::VolAssignFind
  1111. (
  1112. IN IWsbDbSession* pDbSession,
  1113. IN GUID BagId,
  1114. IN LONGLONG SegStartLoc,
  1115. IN LONGLONG SegLen,
  1116. OUT IVolAssign** ppIVolAssign
  1117. )
  1118. /*++
  1119. Implements:
  1120. ISegDb::VolAssignFind
  1121. --*/
  1122. {
  1123. HRESULT hr = S_OK;
  1124. WsbTraceIn(OLESTR("CSegDb::VolAssignFind"),
  1125. OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
  1126. WsbGuidAsString(BagId),
  1127. SegStartLoc,
  1128. SegLen);
  1129. try {
  1130. CComPtr<IVolAssign> pVolAssign;
  1131. GUID l_BagId;
  1132. LONGLONG l_SegStartLoc;
  1133. LONGLONG l_SegLen;
  1134. GUID l_VolId;
  1135. WsbAffirm(ppIVolAssign != NULL, E_POINTER);
  1136. WsbAffirmHr(GetEntity(pDbSession, HSM_VOL_ASSIGN_REC_TYPE, IID_IVolAssign,
  1137. (void **)&pVolAssign));
  1138. WsbAffirmHr(pVolAssign->SetVolAssign(BagId, SegStartLoc, 0, GUID_NULL));
  1139. // Look for a segment that contains this one
  1140. WsbTrace(OLESTR("Finding VolAssign Record: <%ls>, <%I64u>, <%I64u>\n"),
  1141. WsbGuidAsString(BagId),
  1142. SegStartLoc,
  1143. SegLen);
  1144. WsbAffirmHr(pVolAssign->FindLTE());
  1145. // We found a record, see if it's the right one
  1146. WsbAffirmHr(pVolAssign->GetVolAssign(&l_BagId, &l_SegStartLoc,
  1147. &l_SegLen, &l_VolId));
  1148. if (SEG_CONTAINS(l_BagId, l_SegStartLoc, l_SegLen,
  1149. BagId, SegStartLoc, SegLen)) {
  1150. *ppIVolAssign = pVolAssign;
  1151. pVolAssign->AddRef();
  1152. } else {
  1153. hr = WSB_E_NOTFOUND;
  1154. }
  1155. } WsbCatch(hr);
  1156. WsbTraceOut(OLESTR("CSegDb::VolAssignFind"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
  1157. return(hr);
  1158. }
  1159. HRESULT
  1160. CSegDb::VolAssignSubtract
  1161. (
  1162. IN IWsbDbSession* pDbSession,
  1163. IN GUID BagId,
  1164. IN LONGLONG SegStartLoc,
  1165. IN LONGLONG SegLen
  1166. )
  1167. /*++
  1168. Implements:
  1169. ISegDb::VolAssignSubtract
  1170. --*/
  1171. {
  1172. HRESULT hr = S_OK;
  1173. WsbTraceIn(OLESTR("CSegDb::VolAssignSubtract"),
  1174. OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
  1175. WsbGuidAsString(BagId),
  1176. SegStartLoc,
  1177. SegLen);
  1178. try {
  1179. GUID l_BagId;
  1180. LONGLONG l_SegStartLoc;
  1181. LONGLONG l_SegLen;
  1182. GUID l_VolId;
  1183. CComPtr<IVolAssign> pVolAssign;
  1184. // Find the segment record
  1185. WsbAffirmHr(VolAssignFind(pDbSession, BagId, SegStartLoc, SegLen, &pVolAssign));
  1186. // Get the current data
  1187. WsbAffirmHr(pVolAssign->GetVolAssign(&l_BagId, &l_SegStartLoc,
  1188. &l_SegLen, &l_VolId));
  1189. // Determine where the hole is
  1190. if (l_SegStartLoc == SegStartLoc && l_SegLen == SegLen) {
  1191. // Hole is the entire segment -- delete it
  1192. WsbAffirmHr(pVolAssign->Remove());
  1193. } else if (l_SegStartLoc == SegStartLoc) {
  1194. // Hole is at the beginning of the segment. Just update the
  1195. // existing segment
  1196. l_SegStartLoc += SegLen;
  1197. WsbAffirmHr(pVolAssign->SetVolAssign(BagId, l_SegStartLoc,
  1198. l_SegLen, l_VolId));
  1199. WsbAffirmHr(pVolAssign->Write());
  1200. } else if ((l_SegStartLoc + l_SegLen) == (SegStartLoc + SegLen)) {
  1201. // Hole is at the end of the segment. Just update the
  1202. // existing segment
  1203. l_SegLen -= SegLen;
  1204. WsbAffirmHr(pVolAssign->SetVolAssign(BagId, l_SegStartLoc,
  1205. l_SegLen, l_VolId));
  1206. WsbAffirmHr(pVolAssign->Write());
  1207. } else {
  1208. // Hole is in the middle of the segment. Update the
  1209. // existing record to be the first part.
  1210. LONGLONG oldLen = l_SegLen;
  1211. LONGLONG offset = (SegStartLoc + SegLen) - l_SegStartLoc;
  1212. l_SegLen = SegStartLoc - l_SegStartLoc;
  1213. WsbAffirmHr(pVolAssign->SetVolAssign(BagId, l_SegStartLoc,
  1214. l_SegLen, l_VolId));
  1215. WsbAffirmHr(pVolAssign->Write());
  1216. // Create a new record for the second part.
  1217. l_SegLen -= offset;
  1218. l_SegStartLoc += offset;
  1219. WsbAffirmHr(VolAssignAdd(pDbSession, BagId, l_SegStartLoc, l_SegLen,
  1220. l_VolId));
  1221. }
  1222. } WsbCatch(hr);
  1223. WsbTraceOut(OLESTR("CSegDb::VolAssignSubtract"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
  1224. return(hr);
  1225. }