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