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.

871 lines
22 KiB

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