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.

900 lines
24 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992.
  5. //
  6. // File: DirP.CXX
  7. //
  8. // Contents: Private CDirectory child tree methods
  9. //
  10. // History: 17-Nov-92 AlexT Created
  11. //
  12. // Notes:
  13. //
  14. //--------------------------------------------------------------------------
  15. #include "msfhead.cxx"
  16. #pragma hdrstop
  17. #include <dirfunc.hxx>
  18. //+-------------------------------------------------------------------------
  19. //
  20. // Member: CDirectory::InsertEntry, private
  21. //
  22. // Synopsis: insert entry into child tree
  23. //
  24. // Arguments: [sidTree] -- storage entry in which to insert entry
  25. // [sidNew] -- new entry
  26. // [pdfnNew] -- new entry name
  27. //
  28. // Returns: S_OK, STG_E_FILEALREADYEXISTS, or other error
  29. //
  30. // Modifies: sidParent's child tree
  31. //
  32. // Algorithm: Search down the binary tree to find the leaf node to which
  33. // to add the new entry (failing if we find the name already
  34. // exists). Along the way we split nodes where needed to keep
  35. // the tree balanced.
  36. //
  37. // History: 16-Nov-92 AlexT Created
  38. // 18-Nov-92 AlexT Balanced tree
  39. //
  40. //--------------------------------------------------------------------------
  41. SCODE CDirectory::InsertEntry(
  42. SID sidTree,
  43. SID sidNew,
  44. CDfName const *pdfnNew)
  45. {
  46. SCODE sc = S_OK;
  47. SID sidCount = 0;
  48. const SID sidMax = (_cdsTable+1) * _cdeEntries;
  49. // To insert the key and keep the tree balanced, we need to know
  50. // the parent, grandparent, and greatgrandparent of the node we're
  51. // inserting.
  52. SID sidChild, sidParent, sidGrandParent, sidGreatGrandParent;
  53. CDirEntry *pdeParent;
  54. int iCmp = 0;
  55. // When we're ready to insert, sidParent will be the entry to which we
  56. // attach sidNew
  57. sidParent = sidGrandParent = sidGreatGrandParent = sidTree;
  58. // Begin the search with the root of the child tree
  59. msfChk(GetDirEntry(sidTree, FB_NONE, &pdeParent));
  60. sidChild = pdeParent->GetChild();
  61. // Search down the child tree to find the correct leaf entry
  62. while (sidChild != NOSTREAM)
  63. {
  64. // The sidParent entry has a child along the search path, so we
  65. // move down the tree (letting go of sidParent and taking hold of
  66. // its child)
  67. ReleaseEntry(sidParent);
  68. // Check to see if we need to split this node (nothing is held)
  69. do
  70. {
  71. SID sidLeft, sidRight;
  72. BOOL fRed;
  73. if (++sidCount > sidMax)
  74. msfChkTo (Err, STG_E_DOCFILECORRUPT);
  75. {
  76. CDirEntry *pdeChild;
  77. msfChk(GetDirEntry(sidChild, FB_NONE, &pdeChild));
  78. msfAssert(((sidTree != sidParent) ||
  79. (pdeChild->GetColor() == DE_BLACK)) &&
  80. aMsg("Dir tree corrupt - root child not black!"));
  81. sidLeft = pdeChild->GetLeftSib();
  82. sidRight = pdeChild->GetRightSib();
  83. ReleaseEntry(sidChild);
  84. }
  85. if (sidLeft == NOSTREAM || sidRight == NOSTREAM)
  86. break;
  87. {
  88. CDirEntry *pdeLeft;
  89. msfChk(GetDirEntry(sidLeft, FB_NONE, &pdeLeft));
  90. fRed = (pdeLeft->GetColor() == DE_RED);
  91. ReleaseEntry(sidLeft);
  92. }
  93. if (!fRed)
  94. break;
  95. {
  96. CDirEntry *pdeRight;
  97. msfChk(GetDirEntry(sidRight, FB_NONE, &pdeRight));
  98. fRed = (pdeRight->GetColor() == DE_RED);
  99. ReleaseEntry(sidRight);
  100. }
  101. if (fRed)
  102. msfChk(SplitEntry(pdfnNew, sidTree, sidGreatGrandParent,
  103. sidGrandParent, sidParent, sidChild,
  104. &sidChild));
  105. }
  106. while (FALSE);
  107. //
  108. msfAssert(sidChild != NOSTREAM);
  109. // Advance the search
  110. sidGreatGrandParent = sidGrandParent;
  111. sidGrandParent = sidParent;
  112. sidParent = sidChild;
  113. msfChk(GetDirEntry(sidParent, FB_NONE, &pdeParent));
  114. iCmp = NameCompare(pdfnNew, pdeParent->GetName());
  115. if (iCmp == 0)
  116. {
  117. // The new name exactly matched an existing name. Fail.
  118. msfChkTo(EH_RelParent, STG_E_FILEALREADYEXISTS);
  119. }
  120. // Move down the tree, left or right depending on the comparison
  121. if (iCmp < 0)
  122. sidChild = pdeParent->GetLeftSib();
  123. else
  124. sidChild = pdeParent->GetRightSib();
  125. }
  126. msfAssert(sidChild == NOSTREAM);
  127. // We've found the position to insert the new entry.
  128. // We're going to dirty sidParent, so we need to change our holding flags
  129. ReleaseEntry(sidParent);
  130. msfChk(GetDirEntry(sidParent, FB_DIRTY, &pdeParent));
  131. if (sidParent == sidTree)
  132. {
  133. // sidParent never made it past sidTree - we must be inserting the
  134. // first child into sidTree
  135. msfAssert(pdeParent->GetChild() == NOSTREAM);
  136. // The SplitInsert call below will make sidNew black.
  137. pdeParent->SetChild(sidNew);
  138. }
  139. else
  140. {
  141. msfAssert(iCmp != 0);
  142. // Use the comparison to determine which side to insert the new entry
  143. if (iCmp < 0)
  144. {
  145. msfAssert(pdeParent->GetLeftSib() == NOSTREAM);
  146. msfAssert(NameCompare(pdfnNew, pdeParent->GetName()) < 0);
  147. pdeParent->SetLeftSib(sidNew);
  148. }
  149. else
  150. {
  151. msfAssert(pdeParent->GetRightSib() == NOSTREAM);
  152. msfAssert(NameCompare(pdfnNew, pdeParent->GetName()) > 0);
  153. pdeParent->SetRightSib(sidNew);
  154. }
  155. }
  156. EH_RelParent:
  157. ReleaseEntry(sidParent);
  158. if (SUCCEEDED(sc))
  159. {
  160. SID sidTemp;
  161. sc = SplitEntry(pdfnNew, sidTree, sidGreatGrandParent, sidGrandParent,
  162. sidParent, sidNew, &sidTemp);
  163. }
  164. Err:
  165. return(sc);
  166. }
  167. //+-------------------------------------------------------------------------
  168. //
  169. // Member: CDirectory::SplitEntry, private
  170. //
  171. // Synopsis: Split 4-node
  172. //
  173. // Effects: Passes up red link to parent
  174. //
  175. // Arguments: [pdfn] -- search key
  176. // [sidTree] -- child tree sid
  177. // [sidGreat] -- greatgrandparent of child to split
  178. // [sidGrand] -- grandparent of child to split
  179. // [sidParent] -- parent of child to split
  180. // [sidChild] -- child to split
  181. // [psid] -- place holder for tree position
  182. //
  183. // Returns: S_OK, or error
  184. //
  185. // Modifies: psid, tree
  186. //
  187. // Algorithm:
  188. //
  189. // History: 18-Nov-92 AlexT Created
  190. //
  191. // Notes:
  192. //
  193. //--------------------------------------------------------------------------
  194. SCODE CDirectory::SplitEntry(
  195. CDfName const *pdfn,
  196. SID sidTree,
  197. SID sidGreat,
  198. SID sidGrand,
  199. SID sidParent,
  200. SID sidChild,
  201. SID *psid)
  202. {
  203. SCODE sc;
  204. CDirEntry *pdeChild;
  205. SID sidLeft, sidRight;
  206. // pn is a 4-node; start split by moving red link up
  207. // pn->GetLeft()->SetColor(BLACK);
  208. msfChk(GetDirEntry(sidChild, FB_DIRTY, &pdeChild));
  209. sidLeft = pdeChild->GetLeftSib();
  210. sidRight = pdeChild->GetRightSib();
  211. // The root must always be black; new non-root children are red
  212. pdeChild->SetColor((sidParent == sidTree) ? DE_BLACK : DE_RED);
  213. ReleaseEntry(sidChild);
  214. if (sidLeft != NOSTREAM)
  215. {
  216. msfChk(SetColorBlack(sidLeft));
  217. }
  218. // pn->GetRight()->SetColor(BLACK);
  219. if (sidRight != NOSTREAM)
  220. {
  221. msfChk(SetColorBlack(sidRight));
  222. }
  223. if (sidParent != sidTree)
  224. {
  225. CDirEntry *pdeParent;
  226. BOOL fRedParent;
  227. int iCmpParent = 0;
  228. msfChk(GetDirEntry(sidParent, FB_NONE, &pdeParent));
  229. fRedParent = (pdeParent->GetColor() == DE_RED);
  230. if (fRedParent)
  231. iCmpParent = NameCompare(pdfn, pdeParent->GetName());
  232. ReleaseEntry(sidParent);
  233. // if (pnp->IsRed())
  234. if (fRedParent)
  235. {
  236. int iCmpGrand;
  237. // parent is red - adjacent red links are not allowed
  238. // Note - grandparent may be sidTree
  239. if (sidGrand == sidTree)
  240. {
  241. iCmpGrand = 1;
  242. }
  243. else
  244. {
  245. CDirEntry *pdeGrand;
  246. msfChk(GetDirEntry(sidGrand, FB_DIRTY, &pdeGrand));
  247. iCmpGrand = NameCompare(pdfn, pdeGrand->GetName());
  248. // png->SetColor(RED);
  249. pdeGrand->SetColor(DE_RED);
  250. ReleaseEntry(sidGrand);
  251. }
  252. // if ((ikey < png->GetKey()) != (ikey < pnp->GetKey()))
  253. if ((iCmpGrand < 0) != (iCmpParent < 0))
  254. {
  255. /* two cases:
  256. //
  257. // | |
  258. // g g
  259. // / \
  260. // p p
  261. // \ /
  262. // x x
  263. //
  264. // the red links are oriented differently
  265. */
  266. // pn = Rotate(ikey, png);
  267. msfChk(RotateEntry(pdfn, sidTree, sidGrand, &sidChild));
  268. /*
  269. // | |
  270. // g g
  271. // / \
  272. // x x
  273. // / \
  274. // p p
  275. */
  276. }
  277. // the red links are now oriented the same - we balance the tree
  278. // by rotating
  279. // pn = Rotate(ikey, pngg);
  280. msfChk(RotateEntry(pdfn, sidTree, sidGreat, &sidChild));
  281. // pn->SetColor(BLACK);
  282. msfAssert(sidChild != sidTree);
  283. msfChk(SetColorBlack(sidChild));
  284. }
  285. }
  286. // return(pn);
  287. *psid = sidChild;
  288. // The first node's link must always be black.
  289. #if DBG == 1
  290. CDirEntry *pdeTree;
  291. msfChk(GetDirEntry(sidTree, FB_NONE, &pdeTree));
  292. sidChild = pdeTree->GetChild();
  293. ReleaseEntry(sidTree);
  294. msfChk(GetDirEntry(sidChild, FB_NONE, &pdeChild));
  295. msfAssert(pdeChild->GetColor() == DE_BLACK);
  296. ReleaseEntry(sidChild);
  297. #endif
  298. Err:
  299. return(sc);
  300. }
  301. //+-------------------------------------------------------------------------
  302. //
  303. // Member: CDirectory::RotateEntry
  304. //
  305. // Synopsis: rotation for balancing
  306. //
  307. // Effects: rotates localized portion of child tree
  308. //
  309. // Arguments: [pdfn] -- search key
  310. // [sidTree] -- child tree sid
  311. // [sidParent] -- root of rotation
  312. // [psid] -- placeholder for root after rotation
  313. //
  314. // Returns: S_OK, or error
  315. //
  316. // Modifies: child tree
  317. //
  318. // Algorithm:
  319. //
  320. // History: 17-Nov-92 AlexT Created
  321. //
  322. // Notes:
  323. //
  324. //--------------------------------------------------------------------------
  325. SCODE CDirectory::RotateEntry(
  326. CDfName const *pdfn,
  327. SID sidTree,
  328. SID sidParent,
  329. SID *psid)
  330. {
  331. SCODE sc;
  332. int iCmp;
  333. // PNODE pnc, pngc;
  334. SID sidChild, sidGrand;
  335. // find the child
  336. CDirEntry *pdeParent, *pdeChild, *pdeGrand;
  337. msfChk(GetDirEntry(sidParent, FB_DIRTY, &pdeParent));
  338. if (sidParent == sidTree)
  339. {
  340. sidChild = pdeParent->GetChild();
  341. }
  342. else
  343. {
  344. iCmp = NameCompare(pdfn, pdeParent->GetName());
  345. if (iCmp < 0)
  346. sidChild = pdeParent->GetLeftSib();
  347. else
  348. sidChild = pdeParent->GetRightSib();
  349. }
  350. // find the grandchild
  351. msfChkTo(EH_RelParent, GetDirEntry(sidChild, FB_DIRTY, &pdeChild));
  352. msfAssert(sidChild != sidTree);
  353. iCmp = NameCompare(pdfn, pdeChild->GetName());
  354. if (iCmp < 0)
  355. {
  356. // pngc = pnc->GetLeft();
  357. sidGrand = pdeChild->GetLeftSib();
  358. msfChkTo(EH_RelChild, GetDirEntry(sidGrand, FB_DIRTY, &pdeGrand));
  359. /*
  360. // |
  361. // c
  362. // / \
  363. // / \
  364. // g X
  365. // \
  366. // Y
  367. */
  368. // pnc->SetLeft(pngc->GetRight());
  369. pdeChild->SetLeftSib(pdeGrand->GetRightSib());
  370. /*
  371. // |
  372. // c
  373. // / \
  374. // | \
  375. // g | X
  376. // \|
  377. // Y
  378. */
  379. // pngc->SetRight(pnc);
  380. pdeGrand->SetRightSib(sidChild);
  381. /*
  382. // g
  383. // \
  384. // \|
  385. // c
  386. // / \
  387. // | \
  388. // | X
  389. // |
  390. // Y
  391. */
  392. }
  393. else
  394. {
  395. // pngc = pnc->GetRight();
  396. sidGrand = pdeChild->GetRightSib();
  397. msfChkTo(EH_RelChild, GetDirEntry(sidGrand, FB_DIRTY, &pdeGrand));
  398. // pnc->SetRight(pngc->GetLeft());
  399. pdeChild->SetRightSib(pdeGrand->GetLeftSib());
  400. // pngc->SetLeft(pnc);
  401. pdeGrand->SetLeftSib(sidChild);
  402. }
  403. // update parent
  404. if (sidParent == sidTree)
  405. {
  406. // The root must always be black
  407. pdeGrand->SetColor(DE_BLACK);
  408. pdeParent->SetChild(sidGrand);
  409. }
  410. else
  411. {
  412. iCmp = NameCompare(pdfn, pdeParent->GetName());
  413. if (iCmp < 0)
  414. {
  415. // pnp->SetLeft(pngc);
  416. pdeParent->SetLeftSib(sidGrand);
  417. }
  418. else
  419. {
  420. // pnp->SetRight(pngc);
  421. pdeParent->SetRightSib(sidGrand);
  422. }
  423. }
  424. ReleaseEntry(sidGrand);
  425. /*
  426. // |
  427. // g
  428. // \
  429. // \
  430. // c
  431. // / \
  432. // | \
  433. // | X
  434. // |
  435. // Y
  436. */
  437. // return(pngc);
  438. *psid = sidGrand;
  439. EH_RelChild:
  440. ReleaseEntry(sidChild);
  441. EH_RelParent:
  442. ReleaseEntry(sidParent);
  443. Err:
  444. return(sc);
  445. }
  446. //+-------------------------------------------------------------------------
  447. //
  448. // Member: CDirectory::FindEntry, private
  449. //
  450. // Synopsis: find entry info based on name (optionally removing it)
  451. //
  452. // Effects: find - none, remove - takes entry out of child list
  453. //
  454. // Arguments: [sidParent] -- sid of parent entry to search
  455. // [pdfn] -- name to search for
  456. // [deop] -- entry operation (find or remove)
  457. // [peb] -- entry information buffer
  458. //
  459. // Returns: S_OK, STG_E_FILENOTFOUND, or other error
  460. //
  461. // Modifies: peb
  462. //
  463. // Algorithm: To find the entry we search down the binary tree.
  464. // To remove the entry, we need to patch the tree to keep it
  465. // as a valid binary tree.
  466. //
  467. // History: 16-Nov-92 AlexT Created
  468. //
  469. //--------------------------------------------------------------------------
  470. SCODE CDirectory::FindEntry(
  471. SID sidParent,
  472. CDfName const *pdfn,
  473. DIRENTRYOP deop,
  474. SEntryBuffer *peb)
  475. {
  476. SCODE sc;
  477. SID sidPrev, sidFind;
  478. CDirEntry *pdePrev, *pdeFind;
  479. int iCmp = 0;
  480. SID sidCount = 0;
  481. const SID sidMax = (_cdsTable+1) * _cdeEntries;
  482. // Once we've found the right child, sidPrev will be that entry's parent
  483. // in the child tree
  484. sidPrev = sidParent;
  485. // Begin the search with the root of the child tree
  486. msfChk(GetDirEntry(sidPrev, FB_NONE, &pdePrev));
  487. sidFind = pdePrev->GetChild();
  488. // sidPrev is held
  489. for(;;)
  490. {
  491. if (++sidCount > sidMax)
  492. msfChkTo (EH_RelPrev, STG_E_DOCFILECORRUPT);
  493. if (sidFind == NOSTREAM)
  494. {
  495. // we didn't find the child. fail.
  496. sc = STG_E_FILENOTFOUND;
  497. goto EH_RelPrev;
  498. // Removed this line to supress the debug error print.
  499. // msfChkTo(EH_RelPrev, STG_E_FILENOTFOUND);
  500. }
  501. msfChkTo(EH_RelPrev, GetDirEntry(sidFind, FB_NONE, &pdeFind));
  502. // sidPrev and sidFind are held
  503. int tmpCmp = NameCompare(pdfn, pdeFind->GetName());
  504. if (tmpCmp == 0)
  505. {
  506. // We found the entry that matches our search name
  507. break;
  508. }
  509. // The names did not match. Advance the search down the tree.
  510. ReleaseEntry(sidPrev);
  511. pdePrev = pdeFind;
  512. sidPrev = sidFind;
  513. // sidPrev is held
  514. // remember the comparison with sidPrev so we can use it to insert
  515. // an entry when we patch the tree
  516. iCmp = tmpCmp;
  517. if (iCmp < 0)
  518. sidFind = pdePrev->GetLeftSib();
  519. else
  520. sidFind = pdePrev->GetRightSib();
  521. }
  522. msfAssert(sidFind != NOSTREAM);
  523. // sidFind is held
  524. // sidPrev is held
  525. msfAssert(NameCompare(pdfn, pdeFind->GetName()) == 0);
  526. // fill in entry information
  527. peb->sid = sidFind;
  528. peb->dwType = pdeFind->GetFlags();
  529. peb->luid = DF_NOLUID;
  530. if (deop == DEOP_REMOVE)
  531. {
  532. ReleaseEntry(sidFind);
  533. ReleaseEntry(sidPrev);
  534. msfChk(GetDirEntry(sidPrev, FB_DIRTY, &pdePrev));
  535. msfChkTo(EH_RelPrev, GetDirEntry(sidFind, FB_DIRTY, &pdeFind));
  536. // Remove the found child from tree (carefully!). We remove it by
  537. // finding another entry in the tree with which to replace it.
  538. // sidFind is the node we're removing
  539. // sidPrev is the parent of sidFind in the child tree
  540. // sidInsert is the entry which will replace sidFind
  541. SID sidInsert = pdeFind->GetRightSib();
  542. if (sidInsert == NOSTREAM)
  543. {
  544. // sidFind has no right child, so we can patch the tree by
  545. // replacing sidFind with the sidFind's left child
  546. sidInsert = pdeFind->GetLeftSib();
  547. // set the inserted to the right color
  548. if (sidInsert != NOSTREAM)
  549. {
  550. // we always set the inserted node to black (since the
  551. // parent may not exist (we could be inserting at the
  552. // root)
  553. msfChkTo(EH_RelPrev, SetColorBlack(sidInsert));
  554. }
  555. }
  556. else
  557. {
  558. CDirEntry *pdeInsert;
  559. // The node we're removing has a right child
  560. msfChkTo(EH_RelFind, GetDirEntry(sidInsert, FB_NONE, &pdeInsert));
  561. // sidPrev, sidFind, and sidInsert are all held
  562. if (pdeInsert->GetLeftSib() != NOSTREAM)
  563. {
  564. // sidFind's right child has a left child.
  565. // sidInsert will be the leftmost child of sidFind's right
  566. // child (which will keep the tree ordered)
  567. // sidPreInsert will be the leftmost child's parent int the
  568. // child tree
  569. SID sidPreInsert = sidInsert;
  570. CDirEntry *pdePreInsert = pdeInsert;
  571. // we wait to assign sidInsert so we can clean up
  572. msfChkTo(EH_RelIns, GetDirEntry(pdePreInsert->GetLeftSib(),
  573. FB_NONE, &pdeInsert));
  574. sidInsert = pdePreInsert->GetLeftSib();
  575. // sidPrev, sidFind, sidPreInsert, sidInsert are held
  576. // find the leftmost child of sidFind's right child
  577. SID sidLeft;
  578. while ((sidLeft = pdeInsert->GetLeftSib()) != NOSTREAM)
  579. {
  580. ReleaseEntry(sidPreInsert);
  581. // sidPrev, sidFind, sidInsert are held
  582. sidPreInsert = sidInsert;
  583. pdePreInsert = pdeInsert;
  584. // we wait to assign sidInsert to we can clean up
  585. msfChkTo(EH_RelIns, GetDirEntry(sidLeft,
  586. FB_NONE, &pdeInsert));
  587. sidInsert = sidLeft;
  588. }
  589. msfAssert(pdeInsert->GetLeftSib() == NOSTREAM);
  590. // sidPrev, sidFind, sidPreInsert, sidInsert are held
  591. // Remove sidInsert so we can reinsert it in place of sidFind.
  592. // We remove sidInsert (which has no left child) by making
  593. // sidPreInsert's left child point to sidInsert's right child
  594. ReleaseEntry(sidPreInsert);
  595. msfChkTo(EH_RelIns, GetDirEntry(sidPreInsert, FB_DIRTY,
  596. &pdePreInsert));
  597. pdePreInsert->SetLeftSib(pdeInsert->GetRightSib());
  598. ReleaseEntry(sidPreInsert);
  599. // sidPrev, sidFind, sidInsert is held
  600. // Begin to replace sidFind with sidInsert by setting the
  601. // right child of sidInsert to be the right child of sidFind
  602. ReleaseEntry(sidInsert);
  603. msfChkTo(EH_RelFind, GetDirEntry(sidInsert, FB_DIRTY,
  604. &pdeInsert));
  605. pdeInsert->SetRightSib(pdeFind->GetRightSib());
  606. }
  607. else
  608. {
  609. // sidFind's right child has no left child, so we can patch
  610. // the tree by making sidFind's right child's left child
  611. // point to sidFind's left child, and then replacing sidFind
  612. // with sidFind's right child.
  613. ReleaseEntry(sidInsert);
  614. msfChkTo(EH_RelFind, GetDirEntry(sidInsert, FB_DIRTY,
  615. &pdeInsert));
  616. // fall through to do the work
  617. }
  618. pdeInsert->SetColor(DE_BLACK);
  619. // Complete sidInsert's patching by setting its left child to be
  620. // the left child of sidFind
  621. pdeInsert->SetLeftSib(pdeFind->GetLeftSib());
  622. EH_RelIns:
  623. ReleaseEntry(sidInsert);
  624. }
  625. if (SUCCEEDED(sc))
  626. {
  627. if (sidPrev == sidParent)
  628. {
  629. // We're removing the first child; update sidParent.
  630. // We made sure sidInsert is black (above).
  631. pdePrev->SetChild(sidInsert);
  632. }
  633. else if (iCmp < 0)
  634. {
  635. pdePrev->SetLeftSib(sidInsert);
  636. }
  637. else
  638. pdePrev->SetRightSib(sidInsert);
  639. // make sure sidFind is clean
  640. pdeFind->SetLeftSib(NOSTREAM);
  641. pdeFind->SetRightSib(NOSTREAM);
  642. }
  643. }
  644. EH_RelFind:
  645. ReleaseEntry(sidFind);
  646. EH_RelPrev:
  647. ReleaseEntry(sidPrev);
  648. Err:
  649. return(sc);
  650. }
  651. //+-------------------------------------------------------------------------
  652. //
  653. // Member: CDirectory::NameCompare, private static
  654. //
  655. // Synopsis: name ordering function for child tree
  656. //
  657. // Arguments: [pdfn1] - name 1
  658. // [pdfn2] - name 2
  659. //
  660. // Requires: One but not both names cannot may have zero length.
  661. //
  662. // Returns: <0 if name 1 < name 2
  663. // 0 if name 1 = name 2
  664. // >0 if name 1 > name 2
  665. //
  666. // Algorithm: To speed the comparision (and to allow zero length names),
  667. // we first compare the name lengths. (Shorter names are "less"
  668. // than longer names). If the lengths are equal we compare the
  669. // strings.
  670. //
  671. // History: 16-Nov-92 AlexT Created
  672. //
  673. //
  674. //--------------------------------------------------------------------------
  675. int CDirectory::NameCompare(CDfName const *pdfn1, CDfName const *pdfn2)
  676. {
  677. int iCmp = pdfn1->GetLength() - pdfn2->GetLength();
  678. if (iCmp == 0)
  679. {
  680. msfAssert(pdfn1->GetLength() != 0);
  681. iCmp = dfwcsnicmp((WCHAR *)pdfn1->GetBuffer(),
  682. (WCHAR *)pdfn2->GetBuffer(),
  683. pdfn1->GetLength() / sizeof(WCHAR));
  684. }
  685. return(iCmp);
  686. }
  687. //+-------------------------------------------------------------------------
  688. //
  689. // Method: CDirectory::SetColorBlack, private
  690. //
  691. // Synopsis: Sets a directory entry to black
  692. //
  693. // Arguments: [sid] -- SID of entry to be modified
  694. //
  695. // Returns: S_OK or error
  696. //
  697. // History: 19-Jan-93 AlexT Created.
  698. //
  699. // Notes: Added to reduce code size
  700. //
  701. //--------------------------------------------------------------------------
  702. SCODE CDirectory::SetColorBlack(const SID sid)
  703. {
  704. SCODE sc;
  705. CDirEntry *pde;
  706. msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
  707. pde->SetColor(DE_BLACK);
  708. ReleaseEntry(sid);
  709. Err:
  710. return sc;
  711. }