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