1*23b7c7b8SHermès Bélusca-Maïto /*++
2*23b7c7b8SHermès Bélusca-Maïto 
3*23b7c7b8SHermès Bélusca-Maïto Copyright (c) 1989-2000 Microsoft Corporation
4*23b7c7b8SHermès Bélusca-Maïto 
5*23b7c7b8SHermès Bélusca-Maïto Module Name:
6*23b7c7b8SHermès Bélusca-Maïto 
7*23b7c7b8SHermès Bélusca-Maïto     DirSup.c
8*23b7c7b8SHermès Bélusca-Maïto 
9*23b7c7b8SHermès Bélusca-Maïto Abstract:
10*23b7c7b8SHermès Bélusca-Maïto 
11*23b7c7b8SHermès Bélusca-Maïto     This module implements the dirent support routines for Fat.
12*23b7c7b8SHermès Bélusca-Maïto 
13*23b7c7b8SHermès Bélusca-Maïto 
14*23b7c7b8SHermès Bélusca-Maïto --*/
15*23b7c7b8SHermès Bélusca-Maïto 
16*23b7c7b8SHermès Bélusca-Maïto #include "fatprocs.h"
17*23b7c7b8SHermès Bélusca-Maïto 
18*23b7c7b8SHermès Bélusca-Maïto //
19*23b7c7b8SHermès Bélusca-Maïto //  The Bug check file id for this module
20*23b7c7b8SHermès Bélusca-Maïto //
21*23b7c7b8SHermès Bélusca-Maïto 
22*23b7c7b8SHermès Bélusca-Maïto #define BugCheckFileId                   (FAT_BUG_CHECK_DIRSUP)
23*23b7c7b8SHermès Bélusca-Maïto 
24*23b7c7b8SHermès Bélusca-Maïto //
25*23b7c7b8SHermès Bélusca-Maïto //  Local debug trace level
26*23b7c7b8SHermès Bélusca-Maïto //
27*23b7c7b8SHermès Bélusca-Maïto 
28*23b7c7b8SHermès Bélusca-Maïto #define Dbg                              (DEBUG_TRACE_DIRSUP)
29*23b7c7b8SHermès Bélusca-Maïto 
30*23b7c7b8SHermès Bélusca-Maïto //
31*23b7c7b8SHermès Bélusca-Maïto //  The following three macro all assume the input dirent has been zeroed.
32*23b7c7b8SHermès Bélusca-Maïto //
33*23b7c7b8SHermès Bélusca-Maïto 
34*23b7c7b8SHermès Bélusca-Maïto //
35*23b7c7b8SHermès Bélusca-Maïto //  VOID
36*23b7c7b8SHermès Bélusca-Maïto //  FatConstructDot (
37*23b7c7b8SHermès Bélusca-Maïto //      IN PIRP_CONTEXT IrpContext,
38*23b7c7b8SHermès Bélusca-Maïto //      IN PDCB Directory,
39*23b7c7b8SHermès Bélusca-Maïto //      IN PDIRENT ParentDirent,
40*23b7c7b8SHermès Bélusca-Maïto //      IN OUT PDIRENT Dirent
41*23b7c7b8SHermès Bélusca-Maïto //      );
42*23b7c7b8SHermès Bélusca-Maïto //
43*23b7c7b8SHermès Bélusca-Maïto //  The following macro is called to initalize the "." dirent.
44*23b7c7b8SHermès Bélusca-Maïto //
45*23b7c7b8SHermès Bélusca-Maïto //  Always setting FirstClusterOfFileHi is OK because it will be zero
46*23b7c7b8SHermès Bélusca-Maïto //  unless we're working on a FAT 32 disk.
47*23b7c7b8SHermès Bélusca-Maïto //
48*23b7c7b8SHermès Bélusca-Maïto 
49*23b7c7b8SHermès Bélusca-Maïto #define FatConstructDot(IRPCONTEXT,DCB,PARENT,DIRENT) {                  \
50*23b7c7b8SHermès Bélusca-Maïto                                                                          \
51*23b7c7b8SHermès Bélusca-Maïto     RtlCopyMemory( (PUCHAR)(DIRENT), ".          ", 11 );                \
52*23b7c7b8SHermès Bélusca-Maïto     (DIRENT)->Attributes = FAT_DIRENT_ATTR_DIRECTORY;                    \
53*23b7c7b8SHermès Bélusca-Maïto     (DIRENT)->LastWriteTime = (PARENT)->LastWriteTime;                   \
54*23b7c7b8SHermès Bélusca-Maïto     if (FatData.ChicagoMode) {                                           \
55*23b7c7b8SHermès Bélusca-Maïto         (DIRENT)->CreationTime = (PARENT)->CreationTime;                 \
56*23b7c7b8SHermès Bélusca-Maïto         (DIRENT)->CreationMSec = (PARENT)->CreationMSec;                 \
57*23b7c7b8SHermès Bélusca-Maïto         (DIRENT)->LastAccessDate = (PARENT)->LastAccessDate;             \
58*23b7c7b8SHermès Bélusca-Maïto     }                                                                    \
59*23b7c7b8SHermès Bélusca-Maïto     (DIRENT)->FirstClusterOfFile =                                       \
60*23b7c7b8SHermès Bélusca-Maïto             (USHORT)(DCB)->FirstClusterOfFile;                           \
61*23b7c7b8SHermès Bélusca-Maïto     (DIRENT)->FirstClusterOfFileHi =                                     \
62*23b7c7b8SHermès Bélusca-Maïto             (USHORT)((DCB)->FirstClusterOfFile/0x10000);                 \
63*23b7c7b8SHermès Bélusca-Maïto }
64*23b7c7b8SHermès Bélusca-Maïto 
65*23b7c7b8SHermès Bélusca-Maïto //
66*23b7c7b8SHermès Bélusca-Maïto //  VOID
67*23b7c7b8SHermès Bélusca-Maïto //  FatConstructDotDot (
68*23b7c7b8SHermès Bélusca-Maïto //      IN PIRP_CONTEXT IrpContext,
69*23b7c7b8SHermès Bélusca-Maïto //      IN PDCB Directory,
70*23b7c7b8SHermès Bélusca-Maïto //      IN PDIRENT ParentDirent,
71*23b7c7b8SHermès Bélusca-Maïto //      IN OUT PDIRENT Dirent
72*23b7c7b8SHermès Bélusca-Maïto //      );
73*23b7c7b8SHermès Bélusca-Maïto //
74*23b7c7b8SHermès Bélusca-Maïto //  The following macro is called to initalize the ".." dirent.
75*23b7c7b8SHermès Bélusca-Maïto //
76*23b7c7b8SHermès Bélusca-Maïto //  Always setting FirstClusterOfFileHi is OK because it will be zero
77*23b7c7b8SHermès Bélusca-Maïto //  unless we're working on a FAT 32 disk.
78*23b7c7b8SHermès Bélusca-Maïto //
79*23b7c7b8SHermès Bélusca-Maïto 
80*23b7c7b8SHermès Bélusca-Maïto #define FatConstructDotDot(IRPCONTEXT,DCB,PARENT,DIRENT) {   \
81*23b7c7b8SHermès Bélusca-Maïto                                                              \
82*23b7c7b8SHermès Bélusca-Maïto     RtlCopyMemory( (PUCHAR)(DIRENT), "..         ", 11 );    \
83*23b7c7b8SHermès Bélusca-Maïto     (DIRENT)->Attributes = FAT_DIRENT_ATTR_DIRECTORY;        \
84*23b7c7b8SHermès Bélusca-Maïto     (DIRENT)->LastWriteTime = (PARENT)->LastWriteTime;       \
85*23b7c7b8SHermès Bélusca-Maïto     if (FatData.ChicagoMode) {                               \
86*23b7c7b8SHermès Bélusca-Maïto         (DIRENT)->CreationTime = (PARENT)->CreationTime;     \
87*23b7c7b8SHermès Bélusca-Maïto         (DIRENT)->CreationMSec = (PARENT)->CreationMSec;     \
88*23b7c7b8SHermès Bélusca-Maïto         (DIRENT)->LastAccessDate = (PARENT)->LastAccessDate; \
89*23b7c7b8SHermès Bélusca-Maïto     }                                                        \
90*23b7c7b8SHermès Bélusca-Maïto     if (NodeType((DCB)->ParentDcb) == FAT_NTC_ROOT_DCB) {    \
91*23b7c7b8SHermès Bélusca-Maïto         (DIRENT)->FirstClusterOfFile = 0;                    \
92*23b7c7b8SHermès Bélusca-Maïto         (DIRENT)->FirstClusterOfFileHi = 0;                  \
93*23b7c7b8SHermès Bélusca-Maïto     } else {                                                 \
94*23b7c7b8SHermès Bélusca-Maïto         (DIRENT)->FirstClusterOfFile = (USHORT)              \
95*23b7c7b8SHermès Bélusca-Maïto             ((DCB)->ParentDcb->FirstClusterOfFile);          \
96*23b7c7b8SHermès Bélusca-Maïto         (DIRENT)->FirstClusterOfFileHi = (USHORT)            \
97*23b7c7b8SHermès Bélusca-Maïto             ((DCB)->ParentDcb->FirstClusterOfFile/0x10000);  \
98*23b7c7b8SHermès Bélusca-Maïto     }                                                        \
99*23b7c7b8SHermès Bélusca-Maïto }
100*23b7c7b8SHermès Bélusca-Maïto 
101*23b7c7b8SHermès Bélusca-Maïto //
102*23b7c7b8SHermès Bélusca-Maïto //  VOID
103*23b7c7b8SHermès Bélusca-Maïto //  FatConstructEndDirent (
104*23b7c7b8SHermès Bélusca-Maïto //      IN PIRP_CONTEXT IrpContext,
105*23b7c7b8SHermès Bélusca-Maïto //      IN OUT PDIRENT Dirent
106*23b7c7b8SHermès Bélusca-Maïto //      );
107*23b7c7b8SHermès Bélusca-Maïto //
108*23b7c7b8SHermès Bélusca-Maïto //  The following macro created the end dirent.  Note that since the
109*23b7c7b8SHermès Bélusca-Maïto //  dirent was zeroed, the first byte of the name already contains 0x0,
110*23b7c7b8SHermès Bélusca-Maïto //  so there is nothing to do.
111*23b7c7b8SHermès Bélusca-Maïto //
112*23b7c7b8SHermès Bélusca-Maïto 
113*23b7c7b8SHermès Bélusca-Maïto #define FatConstructEndDirent(IRPCONTEXT,DIRENT) NOTHING
114*23b7c7b8SHermès Bélusca-Maïto 
115*23b7c7b8SHermès Bélusca-Maïto //
116*23b7c7b8SHermès Bélusca-Maïto //  VOID
117*23b7c7b8SHermès Bélusca-Maïto //  FatReadDirent (
118*23b7c7b8SHermès Bélusca-Maïto //      IN PIRP_CONTEXT IrpContext,
119*23b7c7b8SHermès Bélusca-Maïto //      IN PDCB Dcb,
120*23b7c7b8SHermès Bélusca-Maïto //      IN VBO Vbo,
121*23b7c7b8SHermès Bélusca-Maïto //      OUT PBCB *Bcb,
122*23b7c7b8SHermès Bélusca-Maïto //      OUT PVOID *Dirent,
123*23b7c7b8SHermès Bélusca-Maïto //      OUT PNTSTATUS Status
124*23b7c7b8SHermès Bélusca-Maïto //      );
125*23b7c7b8SHermès Bélusca-Maïto //
126*23b7c7b8SHermès Bélusca-Maïto 
127*23b7c7b8SHermès Bélusca-Maïto //
128*23b7c7b8SHermès Bélusca-Maïto //  This macro reads in a page of dirents when we step onto a new page,
129*23b7c7b8SHermès Bélusca-Maïto //  or this is the first iteration of a loop and Bcb is NULL.
130*23b7c7b8SHermès Bélusca-Maïto //
131*23b7c7b8SHermès Bélusca-Maïto 
132*23b7c7b8SHermès Bélusca-Maïto #define FatReadDirent(IRPCONTEXT,DCB,VBO,BCB,DIRENT,STATUS)       \
133*23b7c7b8SHermès Bélusca-Maïto if ((VBO) >= (DCB)->Header.AllocationSize.LowPart) {              \
134*23b7c7b8SHermès Bélusca-Maïto     *(STATUS) = STATUS_END_OF_FILE;                               \
135*23b7c7b8SHermès Bélusca-Maïto     FatUnpinBcb( (IRPCONTEXT), *(BCB) );                          \
136*23b7c7b8SHermès Bélusca-Maïto } else if ( ((VBO) % PAGE_SIZE == 0) || (*(BCB) == NULL) ) {      \
137*23b7c7b8SHermès Bélusca-Maïto     FatUnpinBcb( (IRPCONTEXT), *(BCB) );                          \
138*23b7c7b8SHermès Bélusca-Maïto     FatReadDirectoryFile( (IRPCONTEXT),                           \
139*23b7c7b8SHermès Bélusca-Maïto                           (DCB),                                  \
140*23b7c7b8SHermès Bélusca-Maïto                           (VBO) & ~(PAGE_SIZE - 1),               \
141*23b7c7b8SHermès Bélusca-Maïto                           PAGE_SIZE,                              \
142*23b7c7b8SHermès Bélusca-Maïto                           FALSE,                                  \
143*23b7c7b8SHermès Bélusca-Maïto                           (BCB),                                  \
144*23b7c7b8SHermès Bélusca-Maïto                           (PVOID *)(DIRENT),                      \
145*23b7c7b8SHermès Bélusca-Maïto                           (STATUS) );                             \
146*23b7c7b8SHermès Bélusca-Maïto     *(DIRENT) = (PVOID)((PUCHAR)*(DIRENT) + ((VBO) % PAGE_SIZE)); \
147*23b7c7b8SHermès Bélusca-Maïto }
148*23b7c7b8SHermès Bélusca-Maïto 
149*23b7c7b8SHermès Bélusca-Maïto //
150*23b7c7b8SHermès Bélusca-Maïto //  Internal support routines
151*23b7c7b8SHermès Bélusca-Maïto //
152*23b7c7b8SHermès Bélusca-Maïto 
153*23b7c7b8SHermès Bélusca-Maïto UCHAR
154*23b7c7b8SHermès Bélusca-Maïto FatComputeLfnChecksum (
155*23b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent
156*23b7c7b8SHermès Bélusca-Maïto     );
157*23b7c7b8SHermès Bélusca-Maïto 
158*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
159*23b7c7b8SHermès Bélusca-Maïto VOID
160*23b7c7b8SHermès Bélusca-Maïto FatRescanDirectory (
161*23b7c7b8SHermès Bélusca-Maïto     PIRP_CONTEXT IrpContext,
162*23b7c7b8SHermès Bélusca-Maïto     PDCB Dcb
163*23b7c7b8SHermès Bélusca-Maïto     );
164*23b7c7b8SHermès Bélusca-Maïto 
165*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
166*23b7c7b8SHermès Bélusca-Maïto ULONG
167*23b7c7b8SHermès Bélusca-Maïto FatDefragDirectory (
168*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
169*23b7c7b8SHermès Bélusca-Maïto     IN PDCB Dcb,
170*23b7c7b8SHermès Bélusca-Maïto     IN ULONG DirentsNeeded
171*23b7c7b8SHermès Bélusca-Maïto     );
172*23b7c7b8SHermès Bélusca-Maïto 
173*23b7c7b8SHermès Bélusca-Maïto 
174*23b7c7b8SHermès Bélusca-Maïto #ifdef ALLOC_PRAGMA
175*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatComputeLfnChecksum)
176*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatConstructDirent)
177*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatConstructLabelDirent)
178*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatCreateNewDirent)
179*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatDefragDirectory)
180*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatDeleteDirent)
181*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatGetDirentFromFcbOrDcb)
182*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatInitializeDirectoryDirent)
183*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatIsDirectoryEmpty)
184*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatLfnDirentExists)
185*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatLocateDirent)
186*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatLocateSimpleOemDirent)
187*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatLocateVolumeLabel)
188*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatRescanDirectory)
189*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatSetFileSizeInDirent)
190*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatSetFileSizeInDirentNoRaise)
191*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatTunnelFcbOrDcb)
192*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatUpdateDirentFromFcb)
193*23b7c7b8SHermès Bélusca-Maïto 
194*23b7c7b8SHermès Bélusca-Maïto 
195*23b7c7b8SHermès Bélusca-Maïto #endif
196*23b7c7b8SHermès Bélusca-Maïto 
197*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)198*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
199*23b7c7b8SHermès Bélusca-Maïto ULONG
200*23b7c7b8SHermès Bélusca-Maïto FatCreateNewDirent (
201*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
202*23b7c7b8SHermès Bélusca-Maïto     IN PDCB ParentDirectory,
203*23b7c7b8SHermès Bélusca-Maïto     IN ULONG DirentsNeeded,
204*23b7c7b8SHermès Bélusca-Maïto     IN BOOLEAN RescanDir
205*23b7c7b8SHermès Bélusca-Maïto     )
206*23b7c7b8SHermès Bélusca-Maïto 
207*23b7c7b8SHermès Bélusca-Maïto /*++
208*23b7c7b8SHermès Bélusca-Maïto 
209*23b7c7b8SHermès Bélusca-Maïto Routine Description:
210*23b7c7b8SHermès Bélusca-Maïto 
211*23b7c7b8SHermès Bélusca-Maïto     This routine allocates on the disk a new dirent inside of the
212*23b7c7b8SHermès Bélusca-Maïto     parent directory.  If a new dirent cannot be allocated (i.e.,
213*23b7c7b8SHermès Bélusca-Maïto     because the disk is full or the root directory is full) then
214*23b7c7b8SHermès Bélusca-Maïto     it raises the appropriate status.  The dirent itself is
215*23b7c7b8SHermès Bélusca-Maïto     neither initialized nor pinned by this procedure.
216*23b7c7b8SHermès Bélusca-Maïto 
217*23b7c7b8SHermès Bélusca-Maïto Arguments:
218*23b7c7b8SHermès Bélusca-Maïto 
219*23b7c7b8SHermès Bélusca-Maïto     ParentDirectory - Supplies the DCB for the directory in which
220*23b7c7b8SHermès Bélusca-Maïto         to create the new dirent
221*23b7c7b8SHermès Bélusca-Maïto 
222*23b7c7b8SHermès Bélusca-Maïto     DirentsNeeded - This is the number of continginous dirents required
223*23b7c7b8SHermès Bélusca-Maïto 
224*23b7c7b8SHermès Bélusca-Maïto Return Value:
225*23b7c7b8SHermès Bélusca-Maïto 
226*23b7c7b8SHermès Bélusca-Maïto     ByteOffset - Returns the VBO within the Parent directory where
227*23b7c7b8SHermès Bélusca-Maïto         the dirent has been allocated
228*23b7c7b8SHermès Bélusca-Maïto 
229*23b7c7b8SHermès Bélusca-Maïto --*/
230*23b7c7b8SHermès Bélusca-Maïto 
231*23b7c7b8SHermès Bélusca-Maïto {
232*23b7c7b8SHermès Bélusca-Maïto     VBO UnusedVbo;
233*23b7c7b8SHermès Bélusca-Maïto     VBO DeletedHint;
234*23b7c7b8SHermès Bélusca-Maïto     ULONG ByteOffset;
235*23b7c7b8SHermès Bélusca-Maïto 
236*23b7c7b8SHermès Bélusca-Maïto     PBCB Bcb = NULL;
237*23b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent = NULL;
238*23b7c7b8SHermès Bélusca-Maïto     NTSTATUS Status = STATUS_SUCCESS;
239*23b7c7b8SHermès Bélusca-Maïto 
240*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
241*23b7c7b8SHermès Bélusca-Maïto 
242*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatCreateNewDirent\n", 0);
243*23b7c7b8SHermès Bélusca-Maïto 
244*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  ParentDirectory = %p\n", ParentDirectory);
245*23b7c7b8SHermès Bélusca-Maïto 
246*23b7c7b8SHermès Bélusca-Maïto     //
247*23b7c7b8SHermès Bélusca-Maïto     //  If UnusedDirentVbo is within our current file allocation then we
248*23b7c7b8SHermès Bélusca-Maïto     //  don't have to search through the directory at all; we know just
249*23b7c7b8SHermès Bélusca-Maïto     //  where to put it.
250*23b7c7b8SHermès Bélusca-Maïto     //
251*23b7c7b8SHermès Bélusca-Maïto     //  If UnusedDirentVbo is beyond the current file allocation then
252*23b7c7b8SHermès Bélusca-Maïto     //  there are no more unused dirents in the current allocation, though
253*23b7c7b8SHermès Bélusca-Maïto     //  upon adding another cluster of allocation UnusedDirentVbo
254*23b7c7b8SHermès Bélusca-Maïto     //  will point to an unused dirent.  Haveing found no unused dirents
255*23b7c7b8SHermès Bélusca-Maïto     //  we use the DeletedDirentHint to try and find a deleted dirent in
256*23b7c7b8SHermès Bélusca-Maïto     //  the current allocation.  In this also runs off the end of the file,
257*23b7c7b8SHermès Bélusca-Maïto     //  we finally have to break down and allocate another sector.  Note
258*23b7c7b8SHermès Bélusca-Maïto     //  that simply writing beyond the current allocation will automatically
259*23b7c7b8SHermès Bélusca-Maïto     //  do just this.
260*23b7c7b8SHermès Bélusca-Maïto     //
261*23b7c7b8SHermès Bélusca-Maïto     //  We also must deal with the special case where UnusedDirentVbo and
262*23b7c7b8SHermès Bélusca-Maïto     //  DeletedDirentHint have yet to be initialized.  In this case we must
263*23b7c7b8SHermès Bélusca-Maïto     //  first walk through the directory looking for the first deleted entry
264*23b7c7b8SHermès Bélusca-Maïto     //  first unused dirent.  After this point we continue as before.
265*23b7c7b8SHermès Bélusca-Maïto     //  This initial state is denoted by the special value of 0xffffffff.
266*23b7c7b8SHermès Bélusca-Maïto     //
267*23b7c7b8SHermès Bélusca-Maïto 
268*23b7c7b8SHermès Bélusca-Maïto     UnusedVbo = ParentDirectory->Specific.Dcb.UnusedDirentVbo;
269*23b7c7b8SHermès Bélusca-Maïto     DeletedHint = ParentDirectory->Specific.Dcb.DeletedDirentHint;
270*23b7c7b8SHermès Bélusca-Maïto 
271*23b7c7b8SHermès Bélusca-Maïto     //
272*23b7c7b8SHermès Bélusca-Maïto     //  Check for our first call to this routine with this Dcb.  If so
273*23b7c7b8SHermès Bélusca-Maïto     //  we have to correctly set the two hints in the Dcb.
274*23b7c7b8SHermès Bélusca-Maïto     //
275*23b7c7b8SHermès Bélusca-Maïto 
276*23b7c7b8SHermès Bélusca-Maïto     if (UnusedVbo == 0xffffffff || RescanDir) {
277*23b7c7b8SHermès Bélusca-Maïto 
278*23b7c7b8SHermès Bélusca-Maïto         FatRescanDirectory( IrpContext, ParentDirectory );
279*23b7c7b8SHermès Bélusca-Maïto 
280*23b7c7b8SHermès Bélusca-Maïto         UnusedVbo = ParentDirectory->Specific.Dcb.UnusedDirentVbo;
281*23b7c7b8SHermès Bélusca-Maïto         DeletedHint = ParentDirectory->Specific.Dcb.DeletedDirentHint;
282*23b7c7b8SHermès Bélusca-Maïto     }
283*23b7c7b8SHermès Bélusca-Maïto 
284*23b7c7b8SHermès Bélusca-Maïto     //
285*23b7c7b8SHermès Bélusca-Maïto     //  Now we know that UnusedDirentVbo and DeletedDirentHint are correctly
286*23b7c7b8SHermès Bélusca-Maïto     //  set so we check if there is already an unused dirent in the the
287*23b7c7b8SHermès Bélusca-Maïto     //  current allocation.  This is the easy case.
288*23b7c7b8SHermès Bélusca-Maïto     //
289*23b7c7b8SHermès Bélusca-Maïto 
290*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  UnusedVbo   = %08lx\n", UnusedVbo);
291*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  DeletedHint = %08lx\n", DeletedHint);
292*23b7c7b8SHermès Bélusca-Maïto 
293*23b7c7b8SHermès Bélusca-Maïto     if (!RescanDir && ( UnusedVbo + (DirentsNeeded * sizeof(DIRENT)) <=
294*23b7c7b8SHermès Bélusca-Maïto          ParentDirectory->Header.AllocationSize.LowPart )) {
295*23b7c7b8SHermès Bélusca-Maïto 
296*23b7c7b8SHermès Bélusca-Maïto         //
297*23b7c7b8SHermès Bélusca-Maïto         //  Get this unused dirent for the caller.  We have a
298*23b7c7b8SHermès Bélusca-Maïto         //  sporting chance that we won't have to wait.
299*23b7c7b8SHermès Bélusca-Maïto         //
300*23b7c7b8SHermès Bélusca-Maïto 
301*23b7c7b8SHermès Bélusca-Maïto         DebugTrace( 0, Dbg, "There is a never used entry.\n", 0);
302*23b7c7b8SHermès Bélusca-Maïto 
303*23b7c7b8SHermès Bélusca-Maïto         ByteOffset = UnusedVbo;
304*23b7c7b8SHermès Bélusca-Maïto 
305*23b7c7b8SHermès Bélusca-Maïto         UnusedVbo += DirentsNeeded * sizeof(DIRENT);
306*23b7c7b8SHermès Bélusca-Maïto 
307*23b7c7b8SHermès Bélusca-Maïto     } else {
308*23b7c7b8SHermès Bélusca-Maïto 
309*23b7c7b8SHermès Bélusca-Maïto         //
310*23b7c7b8SHermès Bélusca-Maïto         //  Life is tough.  We have to march from the DeletedDirentHint
311*23b7c7b8SHermès Bélusca-Maïto         //  looking for a deleted dirent.  If we get to EOF without finding
312*23b7c7b8SHermès Bélusca-Maïto         //  one, we will have to allocate a new cluster.
313*23b7c7b8SHermès Bélusca-Maïto         //
314*23b7c7b8SHermès Bélusca-Maïto 
315*23b7c7b8SHermès Bélusca-Maïto         ByteOffset =
316*23b7c7b8SHermès Bélusca-Maïto             RtlFindClearBits( &ParentDirectory->Specific.Dcb.FreeDirentBitmap,
317*23b7c7b8SHermès Bélusca-Maïto                               DirentsNeeded,
318*23b7c7b8SHermès Bélusca-Maïto                               DeletedHint / sizeof(DIRENT) );
319*23b7c7b8SHermès Bélusca-Maïto 
320*23b7c7b8SHermès Bélusca-Maïto         //
321*23b7c7b8SHermès Bélusca-Maïto         //  Do a quick check for a root directory allocation that failed
322*23b7c7b8SHermès Bélusca-Maïto         //  simply because of fragmentation.  Also, only attempt to defrag
323*23b7c7b8SHermès Bélusca-Maïto         //  if the length is less that 0x40000.  This is to avoid
324*23b7c7b8SHermès Bélusca-Maïto         //  complications arising from crossing a MM view boundary (256kb).
325*23b7c7b8SHermès Bélusca-Maïto         //  By default on DOS the root directory is only 0x2000 long.
326*23b7c7b8SHermès Bélusca-Maïto         //
327*23b7c7b8SHermès Bélusca-Maïto         //  Don't try to defrag fat32 root dirs.
328*23b7c7b8SHermès Bélusca-Maïto         //
329*23b7c7b8SHermès Bélusca-Maïto 
330*23b7c7b8SHermès Bélusca-Maïto         if (!FatIsFat32(ParentDirectory->Vcb) &&
331*23b7c7b8SHermès Bélusca-Maïto             (ByteOffset == -1) &&
332*23b7c7b8SHermès Bélusca-Maïto             (NodeType(ParentDirectory) == FAT_NTC_ROOT_DCB) &&
333*23b7c7b8SHermès Bélusca-Maïto             (ParentDirectory->Header.AllocationSize.LowPart <= 0x40000)) {
334*23b7c7b8SHermès Bélusca-Maïto 
335*23b7c7b8SHermès Bélusca-Maïto             ByteOffset = FatDefragDirectory( IrpContext, ParentDirectory, DirentsNeeded );
336*23b7c7b8SHermès Bélusca-Maïto         }
337*23b7c7b8SHermès Bélusca-Maïto 
338*23b7c7b8SHermès Bélusca-Maïto         if (ByteOffset != -1) {
339*23b7c7b8SHermès Bélusca-Maïto 
340*23b7c7b8SHermès Bélusca-Maïto             //
341*23b7c7b8SHermès Bélusca-Maïto             //  If we consuemed deleted dirents at Deleted Hint, update.
342*23b7c7b8SHermès Bélusca-Maïto             //  We also may have consumed some un-used dirents as well,
343*23b7c7b8SHermès Bélusca-Maïto             //  so be sure to check for that as well.
344*23b7c7b8SHermès Bélusca-Maïto             //
345*23b7c7b8SHermès Bélusca-Maïto 
346*23b7c7b8SHermès Bélusca-Maïto             ByteOffset *= sizeof(DIRENT);
347*23b7c7b8SHermès Bélusca-Maïto 
348*23b7c7b8SHermès Bélusca-Maïto             if (ByteOffset == DeletedHint) {
349*23b7c7b8SHermès Bélusca-Maïto 
350*23b7c7b8SHermès Bélusca-Maïto                 DeletedHint += DirentsNeeded * sizeof(DIRENT);
351*23b7c7b8SHermès Bélusca-Maïto             }
352*23b7c7b8SHermès Bélusca-Maïto 
353*23b7c7b8SHermès Bélusca-Maïto             if (ByteOffset + DirentsNeeded * sizeof(DIRENT) > UnusedVbo) {
354*23b7c7b8SHermès Bélusca-Maïto 
355*23b7c7b8SHermès Bélusca-Maïto                 UnusedVbo = ByteOffset + DirentsNeeded * sizeof(DIRENT);
356*23b7c7b8SHermès Bélusca-Maïto             }
357*23b7c7b8SHermès Bélusca-Maïto 
358*23b7c7b8SHermès Bélusca-Maïto         } else {
359*23b7c7b8SHermès Bélusca-Maïto 
360*23b7c7b8SHermès Bélusca-Maïto             //
361*23b7c7b8SHermès Bélusca-Maïto             //  We are going to have to allocate another cluster.  Do
362*23b7c7b8SHermès Bélusca-Maïto             //  so, update both the UnusedVbo and the DeletedHint and bail.
363*23b7c7b8SHermès Bélusca-Maïto             //
364*23b7c7b8SHermès Bélusca-Maïto 
365*23b7c7b8SHermès Bélusca-Maïto             DebugTrace( 0, Dbg, "We have to allocate another cluster.\n", 0);
366*23b7c7b8SHermès Bélusca-Maïto 
367*23b7c7b8SHermès Bélusca-Maïto             //
368*23b7c7b8SHermès Bélusca-Maïto             //  A reason why we might fail, unrelated to physical reasons,
369*23b7c7b8SHermès Bélusca-Maïto             //  is that we constrain to 64k directory entries to match the
370*23b7c7b8SHermès Bélusca-Maïto             //  restriction on Win95.  There are fundamental reasons to do
371*23b7c7b8SHermès Bélusca-Maïto             //  this since searching a FAT directory is a linear operation
372*23b7c7b8SHermès Bélusca-Maïto             //  and to allow FAT32 to toss us over the cliff is not permissable.
373*23b7c7b8SHermès Bélusca-Maïto             //
374*23b7c7b8SHermès Bélusca-Maïto 
375*23b7c7b8SHermès Bélusca-Maïto             if (ParentDirectory->Header.AllocationSize.LowPart >= (64 * 1024 * sizeof(DIRENT)) ||
376*23b7c7b8SHermès Bélusca-Maïto 
377*23b7c7b8SHermès Bélusca-Maïto                 //
378*23b7c7b8SHermès Bélusca-Maïto                 //  Make sure we are not trying to expand the root directory on non
379*23b7c7b8SHermès Bélusca-Maïto                 //  FAT32.  FAT16 and FAT12 have fixed size allocations.
380*23b7c7b8SHermès Bélusca-Maïto                 //
381*23b7c7b8SHermès Bélusca-Maïto 
382*23b7c7b8SHermès Bélusca-Maïto                 (!FatIsFat32(ParentDirectory->Vcb) &&
383*23b7c7b8SHermès Bélusca-Maïto                  NodeType(ParentDirectory) == FAT_NTC_ROOT_DCB)) {
384*23b7c7b8SHermès Bélusca-Maïto 
385*23b7c7b8SHermès Bélusca-Maïto                 DebugTrace(0, Dbg, "Full root directory or too big on FAT32.  Raise Status.\n", 0);
386*23b7c7b8SHermès Bélusca-Maïto 
387*23b7c7b8SHermès Bélusca-Maïto                 FatRaiseStatus( IrpContext, STATUS_CANNOT_MAKE );
388*23b7c7b8SHermès Bélusca-Maïto             }
389*23b7c7b8SHermès Bélusca-Maïto 
390*23b7c7b8SHermès Bélusca-Maïto             //
391*23b7c7b8SHermès Bélusca-Maïto             //  Take the last dirent(s) in this cluster.  We will allocate
392*23b7c7b8SHermès Bélusca-Maïto             //  more clusters below.
393*23b7c7b8SHermès Bélusca-Maïto             //
394*23b7c7b8SHermès Bélusca-Maïto 
395*23b7c7b8SHermès Bélusca-Maïto             ByteOffset = UnusedVbo;
396*23b7c7b8SHermès Bélusca-Maïto             UnusedVbo += DirentsNeeded * sizeof(DIRENT);
397*23b7c7b8SHermès Bélusca-Maïto 
398*23b7c7b8SHermès Bélusca-Maïto             //
399*23b7c7b8SHermès Bélusca-Maïto             //  Touch the directory file to cause space for the new dirents
400*23b7c7b8SHermès Bélusca-Maïto             //  to be allocated.
401*23b7c7b8SHermès Bélusca-Maïto             //
402*23b7c7b8SHermès Bélusca-Maïto 
403*23b7c7b8SHermès Bélusca-Maïto             Bcb = NULL;
404*23b7c7b8SHermès Bélusca-Maïto 
405*23b7c7b8SHermès Bélusca-Maïto             _SEH2_TRY {
406*23b7c7b8SHermès Bélusca-Maïto 
407*23b7c7b8SHermès Bélusca-Maïto                 PVOID Buffer;
408*23b7c7b8SHermès Bélusca-Maïto 
409*23b7c7b8SHermès Bélusca-Maïto                 FatPrepareWriteDirectoryFile( IrpContext,
410*23b7c7b8SHermès Bélusca-Maïto                                               ParentDirectory,
411*23b7c7b8SHermès Bélusca-Maïto                                               UnusedVbo,
412*23b7c7b8SHermès Bélusca-Maïto                                               1,
413*23b7c7b8SHermès Bélusca-Maïto                                               &Bcb,
414*23b7c7b8SHermès Bélusca-Maïto                                               &Buffer,
415*23b7c7b8SHermès Bélusca-Maïto                                               FALSE,
416*23b7c7b8SHermès Bélusca-Maïto                                               TRUE,
417*23b7c7b8SHermès Bélusca-Maïto                                               &Status );
418*23b7c7b8SHermès Bélusca-Maïto 
419*23b7c7b8SHermès Bélusca-Maïto             } _SEH2_FINALLY {
420*23b7c7b8SHermès Bélusca-Maïto 
421*23b7c7b8SHermès Bélusca-Maïto                 FatUnpinBcb( IrpContext, Bcb );
422*23b7c7b8SHermès Bélusca-Maïto             } _SEH2_END;
423*23b7c7b8SHermès Bélusca-Maïto         }
424*23b7c7b8SHermès Bélusca-Maïto     }
425*23b7c7b8SHermès Bélusca-Maïto 
426*23b7c7b8SHermès Bélusca-Maïto     //
427*23b7c7b8SHermès Bélusca-Maïto     //  If we are only requesting a single dirent, and we did not get the
428*23b7c7b8SHermès Bélusca-Maïto     //  first dirent in a directory, then check that the preceding dirent
429*23b7c7b8SHermès Bélusca-Maïto     //  is not an orphaned LFN.  If it is, then mark it deleted.  Thus
430*23b7c7b8SHermès Bélusca-Maïto     //  reducing the possibility of an accidental pairing.
431*23b7c7b8SHermès Bélusca-Maïto     //
432*23b7c7b8SHermès Bélusca-Maïto     //  Only do this when we are in Chicago Mode.
433*23b7c7b8SHermès Bélusca-Maïto     //
434*23b7c7b8SHermès Bélusca-Maïto 
435*23b7c7b8SHermès Bélusca-Maïto     Bcb = NULL;
436*23b7c7b8SHermès Bélusca-Maïto 
437*23b7c7b8SHermès Bélusca-Maïto     if (FatData.ChicagoMode &&
438*23b7c7b8SHermès Bélusca-Maïto         (DirentsNeeded == 1) &&
439*23b7c7b8SHermès Bélusca-Maïto         (ByteOffset > (NodeType(ParentDirectory) == FAT_NTC_ROOT_DCB ?
440*23b7c7b8SHermès Bélusca-Maïto                        0 : 2 * sizeof(DIRENT)))) {
441*23b7c7b8SHermès Bélusca-Maïto         _SEH2_TRY {
442*23b7c7b8SHermès Bélusca-Maïto 
443*23b7c7b8SHermès Bélusca-Maïto             FatReadDirent( IrpContext,
444*23b7c7b8SHermès Bélusca-Maïto                            ParentDirectory,
445*23b7c7b8SHermès Bélusca-Maïto                            ByteOffset - sizeof(DIRENT),
446*23b7c7b8SHermès Bélusca-Maïto                            &Bcb,
447*23b7c7b8SHermès Bélusca-Maïto                            &Dirent,
448*23b7c7b8SHermès Bélusca-Maïto                            &Status );
449*23b7c7b8SHermès Bélusca-Maïto 
450*23b7c7b8SHermès Bélusca-Maïto             if ((Status != STATUS_SUCCESS) ||
451*23b7c7b8SHermès Bélusca-Maïto                 (Dirent->FileName[0] == FAT_DIRENT_NEVER_USED)) {
452*23b7c7b8SHermès Bélusca-Maïto 
453*23b7c7b8SHermès Bélusca-Maïto                 FatPopUpFileCorrupt( IrpContext, ParentDirectory );
454*23b7c7b8SHermès Bélusca-Maïto 
455*23b7c7b8SHermès Bélusca-Maïto                 FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
456*23b7c7b8SHermès Bélusca-Maïto             }
457*23b7c7b8SHermès Bélusca-Maïto 
458*23b7c7b8SHermès Bélusca-Maïto             if ((Dirent->Attributes == FAT_DIRENT_ATTR_LFN) &&
459*23b7c7b8SHermès Bélusca-Maïto                 (Dirent->FileName[0] != FAT_DIRENT_DELETED)) {
460*23b7c7b8SHermès Bélusca-Maïto 
461*23b7c7b8SHermès Bélusca-Maïto                 //
462*23b7c7b8SHermès Bélusca-Maïto                 //  Pin it, mark it, and set it dirty.
463*23b7c7b8SHermès Bélusca-Maïto                 //
464*23b7c7b8SHermès Bélusca-Maïto 
465*23b7c7b8SHermès Bélusca-Maïto                 FatPinMappedData( IrpContext,
466*23b7c7b8SHermès Bélusca-Maïto                                   ParentDirectory,
467*23b7c7b8SHermès Bélusca-Maïto                                   ByteOffset - sizeof(DIRENT),
468*23b7c7b8SHermès Bélusca-Maïto                                   sizeof(DIRENT),
469*23b7c7b8SHermès Bélusca-Maïto                                   &Bcb );
470*23b7c7b8SHermès Bélusca-Maïto 
471*23b7c7b8SHermès Bélusca-Maïto                 Dirent->FileName[0] = FAT_DIRENT_DELETED;
472*23b7c7b8SHermès Bélusca-Maïto 
473*23b7c7b8SHermès Bélusca-Maïto                 FatSetDirtyBcb( IrpContext, Bcb, ParentDirectory->Vcb, TRUE );
474*23b7c7b8SHermès Bélusca-Maïto 
475*23b7c7b8SHermès Bélusca-Maïto                 NT_ASSERT( RtlAreBitsSet( &ParentDirectory->Specific.Dcb.FreeDirentBitmap,
476*23b7c7b8SHermès Bélusca-Maïto                                        (ByteOffset - sizeof(DIRENT))/ sizeof(DIRENT),
477*23b7c7b8SHermès Bélusca-Maïto                                        DirentsNeeded ) );
478*23b7c7b8SHermès Bélusca-Maïto 
479*23b7c7b8SHermès Bélusca-Maïto                 RtlClearBits( &ParentDirectory->Specific.Dcb.FreeDirentBitmap,
480*23b7c7b8SHermès Bélusca-Maïto                               (ByteOffset - sizeof(DIRENT))/ sizeof(DIRENT),
481*23b7c7b8SHermès Bélusca-Maïto                               DirentsNeeded );
482*23b7c7b8SHermès Bélusca-Maïto 
483*23b7c7b8SHermès Bélusca-Maïto             }
484*23b7c7b8SHermès Bélusca-Maïto 
485*23b7c7b8SHermès Bélusca-Maïto         } _SEH2_FINALLY {
486*23b7c7b8SHermès Bélusca-Maïto 
487*23b7c7b8SHermès Bélusca-Maïto             FatUnpinBcb( IrpContext, Bcb );
488*23b7c7b8SHermès Bélusca-Maïto         } _SEH2_END;
489*23b7c7b8SHermès Bélusca-Maïto     }
490*23b7c7b8SHermès Bélusca-Maïto 
491*23b7c7b8SHermès Bélusca-Maïto     //
492*23b7c7b8SHermès Bélusca-Maïto     //  Assert that the dirents are in fact unused
493*23b7c7b8SHermès Bélusca-Maïto     //
494*23b7c7b8SHermès Bélusca-Maïto 
495*23b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
496*23b7c7b8SHermès Bélusca-Maïto 
497*23b7c7b8SHermès Bélusca-Maïto         ULONG i;
498*23b7c7b8SHermès Bélusca-Maïto 
499*23b7c7b8SHermès Bélusca-Maïto         Bcb = NULL;
500*23b7c7b8SHermès Bélusca-Maïto 
501*23b7c7b8SHermès Bélusca-Maïto         for (i = 0; i < DirentsNeeded; i++) {
502*23b7c7b8SHermès Bélusca-Maïto 
503*23b7c7b8SHermès Bélusca-Maïto             FatReadDirent( IrpContext,
504*23b7c7b8SHermès Bélusca-Maïto                            ParentDirectory,
505*23b7c7b8SHermès Bélusca-Maïto                            ByteOffset + i*sizeof(DIRENT),
506*23b7c7b8SHermès Bélusca-Maïto                            &Bcb,
507*23b7c7b8SHermès Bélusca-Maïto                            &Dirent,
508*23b7c7b8SHermès Bélusca-Maïto                            &Status );
509*23b7c7b8SHermès Bélusca-Maïto 
510*23b7c7b8SHermès Bélusca-Maïto             if ((Status != STATUS_SUCCESS) ||
511*23b7c7b8SHermès Bélusca-Maïto                 ((Dirent->FileName[0] != FAT_DIRENT_NEVER_USED) &&
512*23b7c7b8SHermès Bélusca-Maïto                  (Dirent->FileName[0] != FAT_DIRENT_DELETED))) {
513*23b7c7b8SHermès Bélusca-Maïto 
514*23b7c7b8SHermès Bélusca-Maïto                 FatPopUpFileCorrupt( IrpContext, ParentDirectory );
515*23b7c7b8SHermès Bélusca-Maïto                 FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
516*23b7c7b8SHermès Bélusca-Maïto             }
517*23b7c7b8SHermès Bélusca-Maïto         }
518*23b7c7b8SHermès Bélusca-Maïto 
519*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
520*23b7c7b8SHermès Bélusca-Maïto 
521*23b7c7b8SHermès Bélusca-Maïto         FatUnpinBcb( IrpContext, Bcb );
522*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
523*23b7c7b8SHermès Bélusca-Maïto 
524*23b7c7b8SHermès Bélusca-Maïto     //
525*23b7c7b8SHermès Bélusca-Maïto     //  Set the Bits in the bitmap and move the Unused Dirent Vbo.
526*23b7c7b8SHermès Bélusca-Maïto     //
527*23b7c7b8SHermès Bélusca-Maïto 
528*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( RtlAreBitsClear( &ParentDirectory->Specific.Dcb.FreeDirentBitmap,
529*23b7c7b8SHermès Bélusca-Maïto                              ByteOffset / sizeof(DIRENT),
530*23b7c7b8SHermès Bélusca-Maïto                              DirentsNeeded ) );
531*23b7c7b8SHermès Bélusca-Maïto 
532*23b7c7b8SHermès Bélusca-Maïto     RtlSetBits( &ParentDirectory->Specific.Dcb.FreeDirentBitmap,
533*23b7c7b8SHermès Bélusca-Maïto                 ByteOffset / sizeof(DIRENT),
534*23b7c7b8SHermès Bélusca-Maïto                 DirentsNeeded );
535*23b7c7b8SHermès Bélusca-Maïto 
536*23b7c7b8SHermès Bélusca-Maïto     //
537*23b7c7b8SHermès Bélusca-Maïto     //  Save the newly computed values in the Parent Directory Fcb
538*23b7c7b8SHermès Bélusca-Maïto     //
539*23b7c7b8SHermès Bélusca-Maïto 
540*23b7c7b8SHermès Bélusca-Maïto     ParentDirectory->Specific.Dcb.UnusedDirentVbo = UnusedVbo;
541*23b7c7b8SHermès Bélusca-Maïto     ParentDirectory->Specific.Dcb.DeletedDirentHint = DeletedHint;
542*23b7c7b8SHermès Bélusca-Maïto 
543*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatCreateNewDirent -> (VOID)\n", 0);
544*23b7c7b8SHermès Bélusca-Maïto 
545*23b7c7b8SHermès Bélusca-Maïto     return ByteOffset;
546*23b7c7b8SHermès Bélusca-Maïto }
547*23b7c7b8SHermès Bélusca-Maïto 
548*23b7c7b8SHermès Bélusca-Maïto 
549*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)550*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
551*23b7c7b8SHermès Bélusca-Maïto VOID
552*23b7c7b8SHermès Bélusca-Maïto FatInitializeDirectoryDirent (
553*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
554*23b7c7b8SHermès Bélusca-Maïto     IN PDCB Dcb,
555*23b7c7b8SHermès Bélusca-Maïto     IN PDIRENT ParentDirent
556*23b7c7b8SHermès Bélusca-Maïto     )
557*23b7c7b8SHermès Bélusca-Maïto 
558*23b7c7b8SHermès Bélusca-Maïto /*++
559*23b7c7b8SHermès Bélusca-Maïto 
560*23b7c7b8SHermès Bélusca-Maïto Routine Description:
561*23b7c7b8SHermès Bélusca-Maïto 
562*23b7c7b8SHermès Bélusca-Maïto     This routine converts a dirent into a directory on the disk.  It does this
563*23b7c7b8SHermès Bélusca-Maïto     setting the directory flag in the dirent, and by allocating the necessary
564*23b7c7b8SHermès Bélusca-Maïto     space for the "." and ".." dirents and initializing them.
565*23b7c7b8SHermès Bélusca-Maïto 
566*23b7c7b8SHermès Bélusca-Maïto     If a new dirent cannot be allocated (i.e., because the disk is full) then
567*23b7c7b8SHermès Bélusca-Maïto     it raises the appropriate status.
568*23b7c7b8SHermès Bélusca-Maïto 
569*23b7c7b8SHermès Bélusca-Maïto Arguments:
570*23b7c7b8SHermès Bélusca-Maïto 
571*23b7c7b8SHermès Bélusca-Maïto     Dcb - Supplies the Dcb denoting the file that is to be made into a
572*23b7c7b8SHermès Bélusca-Maïto         directory.  This must be input a completely empty file with
573*23b7c7b8SHermès Bélusca-Maïto         an allocation size of zero.
574*23b7c7b8SHermès Bélusca-Maïto 
575*23b7c7b8SHermès Bélusca-Maïto     ParentDirent - Provides the parent Dirent for a time-stamp model.
576*23b7c7b8SHermès Bélusca-Maïto 
577*23b7c7b8SHermès Bélusca-Maïto Return Value:
578*23b7c7b8SHermès Bélusca-Maïto 
579*23b7c7b8SHermès Bélusca-Maïto     None.
580*23b7c7b8SHermès Bélusca-Maïto 
581*23b7c7b8SHermès Bélusca-Maïto --*/
582*23b7c7b8SHermès Bélusca-Maïto 
583*23b7c7b8SHermès Bélusca-Maïto {
584*23b7c7b8SHermès Bélusca-Maïto     PBCB Bcb;
585*23b7c7b8SHermès Bélusca-Maïto     PVOID Buffer;
586*23b7c7b8SHermès Bélusca-Maïto     NTSTATUS DontCare = STATUS_SUCCESS;
587*23b7c7b8SHermès Bélusca-Maïto 
588*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
589*23b7c7b8SHermès Bélusca-Maïto 
590*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatInitializeDirectoryDirent\n", 0);
591*23b7c7b8SHermès Bélusca-Maïto 
592*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  Dcb = %p\n", Dcb);
593*23b7c7b8SHermès Bélusca-Maïto 
594*23b7c7b8SHermès Bélusca-Maïto     //
595*23b7c7b8SHermès Bélusca-Maïto     //  Assert that we are not attempting this on the root directory.
596*23b7c7b8SHermès Bélusca-Maïto     //
597*23b7c7b8SHermès Bélusca-Maïto 
598*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( NodeType(Dcb) != FAT_NTC_ROOT_DCB );
599*23b7c7b8SHermès Bélusca-Maïto 
600*23b7c7b8SHermès Bélusca-Maïto     //
601*23b7c7b8SHermès Bélusca-Maïto     //  Assert that this is only attempted on newly created directories.
602*23b7c7b8SHermès Bélusca-Maïto     //
603*23b7c7b8SHermès Bélusca-Maïto 
604*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( Dcb->Header.AllocationSize.LowPart == 0 );
605*23b7c7b8SHermès Bélusca-Maïto 
606*23b7c7b8SHermès Bélusca-Maïto     //
607*23b7c7b8SHermès Bélusca-Maïto     //  Prepare the directory file for writing.  Note that we can use a single
608*23b7c7b8SHermès Bélusca-Maïto     //  Bcb for these two entries because we know they are the first two in
609*23b7c7b8SHermès Bélusca-Maïto     //  the directory, and thus together do not span a page boundry.  Also
610*23b7c7b8SHermès Bélusca-Maïto     //  note that we prepare write 2 entries: one for "." and one for "..".
611*23b7c7b8SHermès Bélusca-Maïto     //  The end of directory marker is automatically set since the whole
612*23b7c7b8SHermès Bélusca-Maïto     //  directory is initially zero (DIRENT_NEVER_USED).
613*23b7c7b8SHermès Bélusca-Maïto     //
614*23b7c7b8SHermès Bélusca-Maïto 
615*23b7c7b8SHermès Bélusca-Maïto     FatPrepareWriteDirectoryFile( IrpContext,
616*23b7c7b8SHermès Bélusca-Maïto                                   Dcb,
617*23b7c7b8SHermès Bélusca-Maïto                                   0,
618*23b7c7b8SHermès Bélusca-Maïto                                   2 * sizeof(DIRENT),
619*23b7c7b8SHermès Bélusca-Maïto                                   &Bcb,
620*23b7c7b8SHermès Bélusca-Maïto                                   &Buffer,
621*23b7c7b8SHermès Bélusca-Maïto                                   FALSE,
622*23b7c7b8SHermès Bélusca-Maïto                                   TRUE,
623*23b7c7b8SHermès Bélusca-Maïto                                   &DontCare );
624*23b7c7b8SHermès Bélusca-Maïto 
625*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( NT_SUCCESS( DontCare ));
626*23b7c7b8SHermès Bélusca-Maïto 
627*23b7c7b8SHermès Bélusca-Maïto     //
628*23b7c7b8SHermès Bélusca-Maïto     //  Add the . and .. entries
629*23b7c7b8SHermès Bélusca-Maïto     //
630*23b7c7b8SHermès Bélusca-Maïto 
631*23b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
632*23b7c7b8SHermès Bélusca-Maïto 
633*23b7c7b8SHermès Bélusca-Maïto         FatConstructDot( IrpContext, Dcb, ParentDirent, (PDIRENT)Buffer + 0);
634*23b7c7b8SHermès Bélusca-Maïto 
635*23b7c7b8SHermès Bélusca-Maïto         FatConstructDotDot( IrpContext, Dcb, ParentDirent, (PDIRENT)Buffer + 1);
636*23b7c7b8SHermès Bélusca-Maïto 
637*23b7c7b8SHermès Bélusca-Maïto     //
638*23b7c7b8SHermès Bélusca-Maïto     //  Unpin the buffer and return to the caller.
639*23b7c7b8SHermès Bélusca-Maïto     //
640*23b7c7b8SHermès Bélusca-Maïto 
641*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
642*23b7c7b8SHermès Bélusca-Maïto 
643*23b7c7b8SHermès Bélusca-Maïto         FatUnpinBcb( IrpContext, Bcb );
644*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
645*23b7c7b8SHermès Bélusca-Maïto 
646*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatInitializeDirectoryDirent -> (VOID)\n", 0);
647*23b7c7b8SHermès Bélusca-Maïto     return;
648*23b7c7b8SHermès Bélusca-Maïto }
649*23b7c7b8SHermès Bélusca-Maïto 
650*23b7c7b8SHermès Bélusca-Maïto 
651*23b7c7b8SHermès Bélusca-Maïto VOID
FatTunnelFcbOrDcb(IN PFCB FcbOrDcb,IN PCCB Ccb OPTIONAL)652*23b7c7b8SHermès Bélusca-Maïto FatTunnelFcbOrDcb (
653*23b7c7b8SHermès Bélusca-Maïto     IN PFCB FcbOrDcb,
654*23b7c7b8SHermès Bélusca-Maïto     IN PCCB Ccb OPTIONAL
655*23b7c7b8SHermès Bélusca-Maïto     )
656*23b7c7b8SHermès Bélusca-Maïto /*++
657*23b7c7b8SHermès Bélusca-Maïto 
658*23b7c7b8SHermès Bélusca-Maïto Routine Description:
659*23b7c7b8SHermès Bélusca-Maïto 
660*23b7c7b8SHermès Bélusca-Maïto     This routine handles tunneling of an Fcb or Dcb associated with
661*23b7c7b8SHermès Bélusca-Maïto     an object whose name is disappearing from a directory.
662*23b7c7b8SHermès Bélusca-Maïto 
663*23b7c7b8SHermès Bélusca-Maïto Arguments:
664*23b7c7b8SHermès Bélusca-Maïto 
665*23b7c7b8SHermès Bélusca-Maïto     FcbOrDcb - Supplies the Fcb/Dcb whose name will be going away
666*23b7c7b8SHermès Bélusca-Maïto 
667*23b7c7b8SHermès Bélusca-Maïto     Ccb - Supplies the Ccb for the Fcb (not reqired for a Dcb) so
668*23b7c7b8SHermès Bélusca-Maïto         that we know which name the Fcb was opened by
669*23b7c7b8SHermès Bélusca-Maïto 
670*23b7c7b8SHermès Bélusca-Maïto Return Value:
671*23b7c7b8SHermès Bélusca-Maïto 
672*23b7c7b8SHermès Bélusca-Maïto     None.
673*23b7c7b8SHermès Bélusca-Maïto 
674*23b7c7b8SHermès Bélusca-Maïto --*/
675*23b7c7b8SHermès Bélusca-Maïto {
676*23b7c7b8SHermès Bélusca-Maïto     UNICODE_STRING ShortNameWithCase = {0};
677*23b7c7b8SHermès Bélusca-Maïto     UNICODE_STRING DownCaseSeg;
678*23b7c7b8SHermès Bélusca-Maïto     WCHAR ShortNameBuffer[8+1+3];
679*23b7c7b8SHermès Bélusca-Maïto     NTSTATUS Status;
680*23b7c7b8SHermès Bélusca-Maïto     USHORT i;
681*23b7c7b8SHermès Bélusca-Maïto 
682*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
683*23b7c7b8SHermès Bélusca-Maïto 
684*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatTunnelFcbOrDcb\n", 0);
685*23b7c7b8SHermès Bélusca-Maïto 
686*23b7c7b8SHermès Bélusca-Maïto     if (NodeType(FcbOrDcb) == FAT_NTC_DCB) {
687*23b7c7b8SHermès Bélusca-Maïto 
688*23b7c7b8SHermès Bélusca-Maïto         //
689*23b7c7b8SHermès Bélusca-Maïto         //  Directory deletion. Flush all entries from this directory in
690*23b7c7b8SHermès Bélusca-Maïto         //  the cache for this volume
691*23b7c7b8SHermès Bélusca-Maïto         //
692*23b7c7b8SHermès Bélusca-Maïto 
693*23b7c7b8SHermès Bélusca-Maïto         FsRtlDeleteKeyFromTunnelCache( &FcbOrDcb->Vcb->Tunnel,
694*23b7c7b8SHermès Bélusca-Maïto                                        FatDirectoryKey(FcbOrDcb) );
695*23b7c7b8SHermès Bélusca-Maïto 
696*23b7c7b8SHermès Bélusca-Maïto     } else {
697*23b7c7b8SHermès Bélusca-Maïto 
698*23b7c7b8SHermès Bélusca-Maïto         //
699*23b7c7b8SHermès Bélusca-Maïto         //  Was a file, so throw it into the tunnel cache
700*23b7c7b8SHermès Bélusca-Maïto         //
701*23b7c7b8SHermès Bélusca-Maïto 
702*23b7c7b8SHermès Bélusca-Maïto         //
703*23b7c7b8SHermès Bélusca-Maïto         //  Get the short name into UNICODE
704*23b7c7b8SHermès Bélusca-Maïto         //
705*23b7c7b8SHermès Bélusca-Maïto 
706*23b7c7b8SHermès Bélusca-Maïto         ShortNameWithCase.Length = 0;
707*23b7c7b8SHermès Bélusca-Maïto         ShortNameWithCase.MaximumLength = sizeof(ShortNameBuffer);
708*23b7c7b8SHermès Bélusca-Maïto         ShortNameWithCase.Buffer = ShortNameBuffer;
709*23b7c7b8SHermès Bélusca-Maïto 
710*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
711*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress:28931, "needed for debug build" )
712*23b7c7b8SHermès Bélusca-Maïto #endif
713*23b7c7b8SHermès Bélusca-Maïto         Status = RtlOemStringToCountedUnicodeString( &ShortNameWithCase,
714*23b7c7b8SHermès Bélusca-Maïto                                                      &FcbOrDcb->ShortName.Name.Oem,
715*23b7c7b8SHermès Bélusca-Maïto                                                      FALSE);
716*23b7c7b8SHermès Bélusca-Maïto 
717*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT(ShortNameWithCase.Length != 0);
718*23b7c7b8SHermès Bélusca-Maïto 
719*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT(NT_SUCCESS(Status));
720*23b7c7b8SHermès Bélusca-Maïto 
721*23b7c7b8SHermès Bélusca-Maïto         if (FlagOn(FcbOrDcb->FcbState, FCB_STATE_8_LOWER_CASE | FCB_STATE_3_LOWER_CASE)) {
722*23b7c7b8SHermès Bélusca-Maïto 
723*23b7c7b8SHermès Bélusca-Maïto             //
724*23b7c7b8SHermès Bélusca-Maïto             //  Have to repair the case of the short name
725*23b7c7b8SHermès Bélusca-Maïto             //
726*23b7c7b8SHermès Bélusca-Maïto 
727*23b7c7b8SHermès Bélusca-Maïto             for (i = 0; i < (ShortNameWithCase.Length/sizeof(WCHAR)) &&
728*23b7c7b8SHermès Bélusca-Maïto                         ShortNameWithCase.Buffer[i] != L'.'; i++);
729*23b7c7b8SHermès Bélusca-Maïto 
730*23b7c7b8SHermès Bélusca-Maïto             //
731*23b7c7b8SHermès Bélusca-Maïto             //  Now pointing at the '.', or otherwise the end of name component
732*23b7c7b8SHermès Bélusca-Maïto             //
733*23b7c7b8SHermès Bélusca-Maïto 
734*23b7c7b8SHermès Bélusca-Maïto             if (FlagOn(FcbOrDcb->FcbState, FCB_STATE_8_LOWER_CASE)) {
735*23b7c7b8SHermès Bélusca-Maïto 
736*23b7c7b8SHermès Bélusca-Maïto                 DownCaseSeg.Buffer = ShortNameWithCase.Buffer;
737*23b7c7b8SHermès Bélusca-Maïto                 DownCaseSeg.MaximumLength = DownCaseSeg.Length = i*sizeof(WCHAR);
738*23b7c7b8SHermès Bélusca-Maïto 
739*23b7c7b8SHermès Bélusca-Maïto                 RtlDowncaseUnicodeString(&DownCaseSeg, &DownCaseSeg, FALSE);
740*23b7c7b8SHermès Bélusca-Maïto             }
741*23b7c7b8SHermès Bélusca-Maïto 
742*23b7c7b8SHermès Bélusca-Maïto             i++;
743*23b7c7b8SHermès Bélusca-Maïto 
744*23b7c7b8SHermès Bélusca-Maïto             //
745*23b7c7b8SHermès Bélusca-Maïto             //  Now pointing at first wchar of the extension.
746*23b7c7b8SHermès Bélusca-Maïto             //
747*23b7c7b8SHermès Bélusca-Maïto 
748*23b7c7b8SHermès Bélusca-Maïto             if (FlagOn(FcbOrDcb->FcbState, FCB_STATE_3_LOWER_CASE)) {
749*23b7c7b8SHermès Bélusca-Maïto 
750*23b7c7b8SHermès Bélusca-Maïto                 //
751*23b7c7b8SHermès Bélusca-Maïto                 //  It is not neccesarily the case that we can rely on the flag
752*23b7c7b8SHermès Bélusca-Maïto                 //  indicating that we really have an extension.
753*23b7c7b8SHermès Bélusca-Maïto                 //
754*23b7c7b8SHermès Bélusca-Maïto 
755*23b7c7b8SHermès Bélusca-Maïto                 if ((i*sizeof(WCHAR)) < ShortNameWithCase.Length) {
756*23b7c7b8SHermès Bélusca-Maïto                     DownCaseSeg.Buffer = &ShortNameWithCase.Buffer[i];
757*23b7c7b8SHermès Bélusca-Maïto                     DownCaseSeg.MaximumLength = DownCaseSeg.Length = ShortNameWithCase.Length - i*sizeof(WCHAR);
758*23b7c7b8SHermès Bélusca-Maïto 
759*23b7c7b8SHermès Bélusca-Maïto                     RtlDowncaseUnicodeString(&DownCaseSeg, &DownCaseSeg, FALSE);
760*23b7c7b8SHermès Bélusca-Maïto                 }
761*23b7c7b8SHermès Bélusca-Maïto             }
762*23b7c7b8SHermès Bélusca-Maïto         }
763*23b7c7b8SHermès Bélusca-Maïto 
764*23b7c7b8SHermès Bélusca-Maïto         //
765*23b7c7b8SHermès Bélusca-Maïto         //  ... and add it in
766*23b7c7b8SHermès Bélusca-Maïto         //
767*23b7c7b8SHermès Bélusca-Maïto 
768*23b7c7b8SHermès Bélusca-Maïto         FsRtlAddToTunnelCache( &FcbOrDcb->Vcb->Tunnel,
769*23b7c7b8SHermès Bélusca-Maïto                                FatDirectoryKey(FcbOrDcb->ParentDcb),
770*23b7c7b8SHermès Bélusca-Maïto                                &ShortNameWithCase,
771*23b7c7b8SHermès Bélusca-Maïto                                &FcbOrDcb->ExactCaseLongName,
772*23b7c7b8SHermès Bélusca-Maïto                                BooleanFlagOn(Ccb->Flags, CCB_FLAG_OPENED_BY_SHORTNAME),
773*23b7c7b8SHermès Bélusca-Maïto                                sizeof(LARGE_INTEGER),
774*23b7c7b8SHermès Bélusca-Maïto                                &FcbOrDcb->CreationTime );
775*23b7c7b8SHermès Bélusca-Maïto     }
776*23b7c7b8SHermès Bélusca-Maïto 
777*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatTunnelFcbOrDcb -> (VOID)\n", 0);
778*23b7c7b8SHermès Bélusca-Maïto 
779*23b7c7b8SHermès Bélusca-Maïto     return;
780*23b7c7b8SHermès Bélusca-Maïto }
781*23b7c7b8SHermès Bélusca-Maïto 
782*23b7c7b8SHermès Bélusca-Maïto 
783*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)784*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
785*23b7c7b8SHermès Bélusca-Maïto VOID
786*23b7c7b8SHermès Bélusca-Maïto FatDeleteDirent (
787*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
788*23b7c7b8SHermès Bélusca-Maïto     IN PFCB FcbOrDcb,
789*23b7c7b8SHermès Bélusca-Maïto     IN PDELETE_CONTEXT DeleteContext OPTIONAL,
790*23b7c7b8SHermès Bélusca-Maïto     IN BOOLEAN DeleteEa
791*23b7c7b8SHermès Bélusca-Maïto     )
792*23b7c7b8SHermès Bélusca-Maïto 
793*23b7c7b8SHermès Bélusca-Maïto /*++
794*23b7c7b8SHermès Bélusca-Maïto 
795*23b7c7b8SHermès Bélusca-Maïto Routine Description:
796*23b7c7b8SHermès Bélusca-Maïto 
797*23b7c7b8SHermès Bélusca-Maïto     This routine Deletes on the disk the indicated dirent.  It does
798*23b7c7b8SHermès Bélusca-Maïto     this by marking the dirent as deleted.
799*23b7c7b8SHermès Bélusca-Maïto 
800*23b7c7b8SHermès Bélusca-Maïto Arguments:
801*23b7c7b8SHermès Bélusca-Maïto 
802*23b7c7b8SHermès Bélusca-Maïto     FcbOrDcb - Supplies the FCB/DCB for the file/directory being
803*23b7c7b8SHermès Bélusca-Maïto         deleted.  For a file the file size and allocation must be zero.
804*23b7c7b8SHermès Bélusca-Maïto         (Zero allocation is implied by a zero cluster index).
805*23b7c7b8SHermès Bélusca-Maïto         For a directory the allocation must be zero.
806*23b7c7b8SHermès Bélusca-Maïto 
807*23b7c7b8SHermès Bélusca-Maïto     DeleteContext - This variable, if speicified, may be used to preserve
808*23b7c7b8SHermès Bélusca-Maïto         the file size and first cluster of file information in the dirent
809*23b7c7b8SHermès Bélusca-Maïto         fot the benefit of unerase utilities.
810*23b7c7b8SHermès Bélusca-Maïto 
811*23b7c7b8SHermès Bélusca-Maïto     DeleteEa - Tells us whether to delete the EA and whether to check
812*23b7c7b8SHermès Bélusca-Maïto         for no allocation/  Mainly TRUE.  FALSE passed in from rename.
813*23b7c7b8SHermès Bélusca-Maïto 
814*23b7c7b8SHermès Bélusca-Maïto Return Value:
815*23b7c7b8SHermès Bélusca-Maïto 
816*23b7c7b8SHermès Bélusca-Maïto     None.
817*23b7c7b8SHermès Bélusca-Maïto 
818*23b7c7b8SHermès Bélusca-Maïto --*/
819*23b7c7b8SHermès Bélusca-Maïto 
820*23b7c7b8SHermès Bélusca-Maïto {
821*23b7c7b8SHermès Bélusca-Maïto     PBCB Bcb = NULL;
822*23b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent = NULL;
823*23b7c7b8SHermès Bélusca-Maïto     NTSTATUS DontCare;
824*23b7c7b8SHermès Bélusca-Maïto     ULONG Offset;
825*23b7c7b8SHermès Bélusca-Maïto     ULONG DirentsToDelete;
826*23b7c7b8SHermès Bélusca-Maïto 
827*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
828*23b7c7b8SHermès Bélusca-Maïto 
829*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatDeleteDirent\n", 0);
830*23b7c7b8SHermès Bélusca-Maïto 
831*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  FcbOrDcb = %p\n", FcbOrDcb);
832*23b7c7b8SHermès Bélusca-Maïto 
833*23b7c7b8SHermès Bélusca-Maïto     //
834*23b7c7b8SHermès Bélusca-Maïto     //  We must be holding the vcb exclusive here to deal with the locate dirent
835*23b7c7b8SHermès Bélusca-Maïto     //  cases where it cannot be holding the parent simply.  This is actually
836*23b7c7b8SHermès Bélusca-Maïto     //  a true statement from olden daze, lets just wire in our assertion.
837*23b7c7b8SHermès Bélusca-Maïto     //
838*23b7c7b8SHermès Bélusca-Maïto     //  Among other reasons, it'd be unfortunate if this raced with the
839*23b7c7b8SHermès Bélusca-Maïto     //  rename path.
840*23b7c7b8SHermès Bélusca-Maïto     //
841*23b7c7b8SHermès Bélusca-Maïto 
842*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( ExIsResourceAcquiredExclusiveLite( &FcbOrDcb->Vcb->Resource ));
843*23b7c7b8SHermès Bélusca-Maïto 
844*23b7c7b8SHermès Bélusca-Maïto     //
845*23b7c7b8SHermès Bélusca-Maïto     //  Assert that we are not attempting this on the root directory.
846*23b7c7b8SHermès Bélusca-Maïto     //
847*23b7c7b8SHermès Bélusca-Maïto 
848*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( NodeType(FcbOrDcb) != FAT_NTC_ROOT_DCB );
849*23b7c7b8SHermès Bélusca-Maïto 
850*23b7c7b8SHermès Bélusca-Maïto     //
851*23b7c7b8SHermès Bélusca-Maïto     //  Make sure all requests have zero allocation/file size
852*23b7c7b8SHermès Bélusca-Maïto     //
853*23b7c7b8SHermès Bélusca-Maïto 
854*23b7c7b8SHermès Bélusca-Maïto     if (DeleteEa &&
855*23b7c7b8SHermès Bélusca-Maïto         ((FcbOrDcb->Header.AllocationSize.LowPart != 0) ||
856*23b7c7b8SHermès Bélusca-Maïto          ((NodeType(FcbOrDcb) == FAT_NTC_FCB) &&
857*23b7c7b8SHermès Bélusca-Maïto           (FcbOrDcb->Header.FileSize.LowPart != 0)))) {
858*23b7c7b8SHermès Bélusca-Maïto 
859*23b7c7b8SHermès Bélusca-Maïto         DebugTrace( 0, Dbg, "Called with non zero allocation/file size.\n", 0);
860*23b7c7b8SHermès Bélusca-Maïto 
861*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
862*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
863*23b7c7b8SHermès Bélusca-Maïto #endif
864*23b7c7b8SHermès Bélusca-Maïto         FatBugCheck( 0, 0, 0 );
865*23b7c7b8SHermès Bélusca-Maïto     }
866*23b7c7b8SHermès Bélusca-Maïto 
867*23b7c7b8SHermès Bélusca-Maïto     //
868*23b7c7b8SHermès Bélusca-Maïto     //  Now, mark the dirents deleted, unpin the Bcb, and return to the caller.
869*23b7c7b8SHermès Bélusca-Maïto     //  Assert that there isn't any allocation associated with this dirent.
870*23b7c7b8SHermès Bélusca-Maïto     //
871*23b7c7b8SHermès Bélusca-Maïto     //  Note that this loop will end with Dirent pointing to the short name.
872*23b7c7b8SHermès Bélusca-Maïto     //
873*23b7c7b8SHermès Bélusca-Maïto 
874*23b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
875*23b7c7b8SHermès Bélusca-Maïto 
876*23b7c7b8SHermès Bélusca-Maïto         //
877*23b7c7b8SHermès Bélusca-Maïto         //  We must acquire our parent exclusive to synchronize with enumerators
878*23b7c7b8SHermès Bélusca-Maïto         //  who do not hold the vcb (ex: dirctrl).
879*23b7c7b8SHermès Bélusca-Maïto         //
880*23b7c7b8SHermès Bélusca-Maïto         //  This relies on our bottom up lockorder.
881*23b7c7b8SHermès Bélusca-Maïto         //
882*23b7c7b8SHermès Bélusca-Maïto 
883*23b7c7b8SHermès Bélusca-Maïto         ExAcquireResourceExclusiveLite( FcbOrDcb->ParentDcb->Header.Resource, TRUE );
884*23b7c7b8SHermès Bélusca-Maïto 
885*23b7c7b8SHermès Bélusca-Maïto         for ( Offset = FcbOrDcb->LfnOffsetWithinDirectory;
886*23b7c7b8SHermès Bélusca-Maïto               Offset <= FcbOrDcb->DirentOffsetWithinDirectory;
887*23b7c7b8SHermès Bélusca-Maïto               Offset += sizeof(DIRENT), Dirent += 1 ) {
888*23b7c7b8SHermès Bélusca-Maïto 
889*23b7c7b8SHermès Bélusca-Maïto             //
890*23b7c7b8SHermès Bélusca-Maïto             //  If we stepped onto a new page, or this is the first iteration,
891*23b7c7b8SHermès Bélusca-Maïto             //  unpin the old page, and pin the new one.
892*23b7c7b8SHermès Bélusca-Maïto             //
893*23b7c7b8SHermès Bélusca-Maïto 
894*23b7c7b8SHermès Bélusca-Maïto             if ((Offset == FcbOrDcb->LfnOffsetWithinDirectory) ||
895*23b7c7b8SHermès Bélusca-Maïto                 ((Offset & (PAGE_SIZE - 1)) == 0)) {
896*23b7c7b8SHermès Bélusca-Maïto 
897*23b7c7b8SHermès Bélusca-Maïto                 FatUnpinBcb( IrpContext, Bcb );
898*23b7c7b8SHermès Bélusca-Maïto 
899*23b7c7b8SHermès Bélusca-Maïto                 FatPrepareWriteDirectoryFile( IrpContext,
900*23b7c7b8SHermès Bélusca-Maïto                                               FcbOrDcb->ParentDcb,
901*23b7c7b8SHermès Bélusca-Maïto                                               Offset,
902*23b7c7b8SHermès Bélusca-Maïto                                               sizeof(DIRENT),
903*23b7c7b8SHermès Bélusca-Maïto                                               &Bcb,
904*23b7c7b8SHermès Bélusca-Maïto                                               (PVOID *)&Dirent,
905*23b7c7b8SHermès Bélusca-Maïto                                               FALSE,
906*23b7c7b8SHermès Bélusca-Maïto                                               TRUE,
907*23b7c7b8SHermès Bélusca-Maïto                                               &DontCare );
908*23b7c7b8SHermès Bélusca-Maïto             }
909*23b7c7b8SHermès Bélusca-Maïto 
910*23b7c7b8SHermès Bélusca-Maïto             NT_ASSERT( (Dirent->FirstClusterOfFile == 0) || !DeleteEa );
911*23b7c7b8SHermès Bélusca-Maïto             Dirent->FileName[0] = FAT_DIRENT_DELETED;
912*23b7c7b8SHermès Bélusca-Maïto         }
913*23b7c7b8SHermès Bélusca-Maïto 
914*23b7c7b8SHermès Bélusca-Maïto         //
915*23b7c7b8SHermès Bélusca-Maïto         //  Back Dirent off by one to point back to the short dirent.
916*23b7c7b8SHermès Bélusca-Maïto         //
917*23b7c7b8SHermès Bélusca-Maïto 
918*23b7c7b8SHermès Bélusca-Maïto         Dirent -= 1;
919*23b7c7b8SHermès Bélusca-Maïto 
920*23b7c7b8SHermès Bélusca-Maïto         //
921*23b7c7b8SHermès Bélusca-Maïto         //  If there are extended attributes for this dirent, we will attempt
922*23b7c7b8SHermès Bélusca-Maïto         //  to remove them.  We ignore any errors in removing Eas.
923*23b7c7b8SHermès Bélusca-Maïto         //
924*23b7c7b8SHermès Bélusca-Maïto 
925*23b7c7b8SHermès Bélusca-Maïto         if (!FatIsFat32(FcbOrDcb->Vcb) &&
926*23b7c7b8SHermès Bélusca-Maïto             DeleteEa && (Dirent->ExtendedAttributes != 0)) {
927*23b7c7b8SHermès Bélusca-Maïto 
928*23b7c7b8SHermès Bélusca-Maïto             _SEH2_TRY {
929*23b7c7b8SHermès Bélusca-Maïto 
930*23b7c7b8SHermès Bélusca-Maïto                 FatDeleteEa( IrpContext,
931*23b7c7b8SHermès Bélusca-Maïto                              FcbOrDcb->Vcb,
932*23b7c7b8SHermès Bélusca-Maïto                              Dirent->ExtendedAttributes,
933*23b7c7b8SHermès Bélusca-Maïto                              &FcbOrDcb->ShortName.Name.Oem );
934*23b7c7b8SHermès Bélusca-Maïto 
935*23b7c7b8SHermès Bélusca-Maïto             } _SEH2_EXCEPT(FatExceptionFilter( IrpContext, _SEH2_GetExceptionInformation() )) {
936*23b7c7b8SHermès Bélusca-Maïto 
937*23b7c7b8SHermès Bélusca-Maïto                 //
938*23b7c7b8SHermès Bélusca-Maïto                 //  We catch all exceptions that Fat catches, but don't do
939*23b7c7b8SHermès Bélusca-Maïto                 //  anything with them.
940*23b7c7b8SHermès Bélusca-Maïto                 //
941*23b7c7b8SHermès Bélusca-Maïto             } _SEH2_END;
942*23b7c7b8SHermès Bélusca-Maïto         }
943*23b7c7b8SHermès Bélusca-Maïto 
944*23b7c7b8SHermès Bélusca-Maïto         //
945*23b7c7b8SHermès Bélusca-Maïto         //  Now clear the bits in the free dirent mask.
946*23b7c7b8SHermès Bélusca-Maïto         //
947*23b7c7b8SHermès Bélusca-Maïto 
948*23b7c7b8SHermès Bélusca-Maïto         DirentsToDelete = (FcbOrDcb->DirentOffsetWithinDirectory -
949*23b7c7b8SHermès Bélusca-Maïto                            FcbOrDcb->LfnOffsetWithinDirectory) / sizeof(DIRENT) + 1;
950*23b7c7b8SHermès Bélusca-Maïto 
951*23b7c7b8SHermès Bélusca-Maïto 
952*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( (FcbOrDcb->ParentDcb->Specific.Dcb.UnusedDirentVbo == 0xffffffff) ||
953*23b7c7b8SHermès Bélusca-Maïto                 RtlAreBitsSet( &FcbOrDcb->ParentDcb->Specific.Dcb.FreeDirentBitmap,
954*23b7c7b8SHermès Bélusca-Maïto                                FcbOrDcb->LfnOffsetWithinDirectory / sizeof(DIRENT),
955*23b7c7b8SHermès Bélusca-Maïto                                DirentsToDelete ) );
956*23b7c7b8SHermès Bélusca-Maïto 
957*23b7c7b8SHermès Bélusca-Maïto         RtlClearBits( &FcbOrDcb->ParentDcb->Specific.Dcb.FreeDirentBitmap,
958*23b7c7b8SHermès Bélusca-Maïto                       FcbOrDcb->LfnOffsetWithinDirectory / sizeof(DIRENT),
959*23b7c7b8SHermès Bélusca-Maïto                       DirentsToDelete );
960*23b7c7b8SHermès Bélusca-Maïto 
961*23b7c7b8SHermès Bélusca-Maïto         //
962*23b7c7b8SHermès Bélusca-Maïto         //  Now, if the caller specified a DeleteContext, use it.
963*23b7c7b8SHermès Bélusca-Maïto         //
964*23b7c7b8SHermès Bélusca-Maïto 
965*23b7c7b8SHermès Bélusca-Maïto         if ( ARGUMENT_PRESENT( DeleteContext ) ) {
966*23b7c7b8SHermès Bélusca-Maïto 
967*23b7c7b8SHermès Bélusca-Maïto             Dirent->FileSize = DeleteContext->FileSize;
968*23b7c7b8SHermès Bélusca-Maïto 
969*23b7c7b8SHermès Bélusca-Maïto 
970*23b7c7b8SHermès Bélusca-Maïto             Dirent->FirstClusterOfFile = (USHORT)DeleteContext->FirstClusterOfFile;
971*23b7c7b8SHermès Bélusca-Maïto         }
972*23b7c7b8SHermès Bélusca-Maïto 
973*23b7c7b8SHermès Bélusca-Maïto         //
974*23b7c7b8SHermès Bélusca-Maïto         //  If this newly deleted dirent is before the DeletedDirentHint, change
975*23b7c7b8SHermès Bélusca-Maïto         //  the DeletedDirentHint to point here.
976*23b7c7b8SHermès Bélusca-Maïto         //
977*23b7c7b8SHermès Bélusca-Maïto 
978*23b7c7b8SHermès Bélusca-Maïto         if (FcbOrDcb->DirentOffsetWithinDirectory <
979*23b7c7b8SHermès Bélusca-Maïto                             FcbOrDcb->ParentDcb->Specific.Dcb.DeletedDirentHint) {
980*23b7c7b8SHermès Bélusca-Maïto 
981*23b7c7b8SHermès Bélusca-Maïto             FcbOrDcb->ParentDcb->Specific.Dcb.DeletedDirentHint =
982*23b7c7b8SHermès Bélusca-Maïto                                             FcbOrDcb->LfnOffsetWithinDirectory;
983*23b7c7b8SHermès Bélusca-Maïto         }
984*23b7c7b8SHermès Bélusca-Maïto 
985*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
986*23b7c7b8SHermès Bélusca-Maïto 
987*23b7c7b8SHermès Bélusca-Maïto         FatUnpinBcb( IrpContext, Bcb );
988*23b7c7b8SHermès Bélusca-Maïto 
989*23b7c7b8SHermès Bélusca-Maïto         //
990*23b7c7b8SHermès Bélusca-Maïto         //  Release our parent.
991*23b7c7b8SHermès Bélusca-Maïto         //
992*23b7c7b8SHermès Bélusca-Maïto 
993*23b7c7b8SHermès Bélusca-Maïto         ExReleaseResourceLite( FcbOrDcb->ParentDcb->Header.Resource );
994*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
995*23b7c7b8SHermès Bélusca-Maïto 
996*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatDeleteDirent -> (VOID)\n", 0);
997*23b7c7b8SHermès Bélusca-Maïto     return;
998*23b7c7b8SHermès Bélusca-Maïto }
999*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)1000*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
1001*23b7c7b8SHermès Bélusca-Maïto BOOLEAN
1002*23b7c7b8SHermès Bélusca-Maïto FatLfnDirentExists (
1003*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
1004*23b7c7b8SHermès Bélusca-Maïto     IN PDCB Dcb,
1005*23b7c7b8SHermès Bélusca-Maïto     IN PUNICODE_STRING Lfn,
1006*23b7c7b8SHermès Bélusca-Maïto     IN PUNICODE_STRING LfnTmp
1007*23b7c7b8SHermès Bélusca-Maïto     )
1008*23b7c7b8SHermès Bélusca-Maïto /*++
1009*23b7c7b8SHermès Bélusca-Maïto 
1010*23b7c7b8SHermès Bélusca-Maïto Routine Description:
1011*23b7c7b8SHermès Bélusca-Maïto 
1012*23b7c7b8SHermès Bélusca-Maïto     This routine looks for a given Lfn in a directory
1013*23b7c7b8SHermès Bélusca-Maïto 
1014*23b7c7b8SHermès Bélusca-Maïto Arguments:
1015*23b7c7b8SHermès Bélusca-Maïto 
1016*23b7c7b8SHermès Bélusca-Maïto     Dcb - The directory to search
1017*23b7c7b8SHermès Bélusca-Maïto 
1018*23b7c7b8SHermès Bélusca-Maïto     Lfn - The Lfn to look for
1019*23b7c7b8SHermès Bélusca-Maïto 
1020*23b7c7b8SHermès Bélusca-Maïto     Lfn - Temporary buffer to use to search for Lfn with (if < MAX_LFN then this
1021*23b7c7b8SHermès Bélusca-Maïto         function may cause it to be allocated from pool if not large enough.
1022*23b7c7b8SHermès Bélusca-Maïto 
1023*23b7c7b8SHermès Bélusca-Maïto Retrn Value:
1024*23b7c7b8SHermès Bélusca-Maïto 
1025*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN TRUE if it exists, FALSE if not
1026*23b7c7b8SHermès Bélusca-Maïto 
1027*23b7c7b8SHermès Bélusca-Maïto --*/
1028*23b7c7b8SHermès Bélusca-Maïto {
1029*23b7c7b8SHermès Bélusca-Maïto     CCB Ccb;
1030*23b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent;
1031*23b7c7b8SHermès Bélusca-Maïto     PBCB DirentBcb = NULL;
1032*23b7c7b8SHermès Bélusca-Maïto     VBO DirentByteOffset;
1033*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN Result = FALSE;
1034*23b7c7b8SHermès Bélusca-Maïto     ULONG Flags = 0;
1035*23b7c7b8SHermès Bélusca-Maïto 
1036*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
1037*23b7c7b8SHermès Bélusca-Maïto 
1038*23b7c7b8SHermès Bélusca-Maïto     //
1039*23b7c7b8SHermès Bélusca-Maïto     //  Pay performance penalty by forcing the compares to be case insensitive as
1040*23b7c7b8SHermès Bélusca-Maïto     //  opposed to grabbing more pool for a monocased copy of the Lfn. This is slight.
1041*23b7c7b8SHermès Bélusca-Maïto     //
1042*23b7c7b8SHermès Bélusca-Maïto 
1043*23b7c7b8SHermès Bélusca-Maïto     Ccb.UnicodeQueryTemplate =  *Lfn;
1044*23b7c7b8SHermès Bélusca-Maïto     Ccb.ContainsWildCards = FALSE;
1045*23b7c7b8SHermès Bélusca-Maïto     Ccb.Flags = CCB_FLAG_SKIP_SHORT_NAME_COMPARE | CCB_FLAG_QUERY_TEMPLATE_MIXED;
1046*23b7c7b8SHermès Bélusca-Maïto 
1047*23b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
1048*23b7c7b8SHermès Bélusca-Maïto 
1049*23b7c7b8SHermès Bélusca-Maïto         FatLocateDirent( IrpContext,
1050*23b7c7b8SHermès Bélusca-Maïto                          Dcb,
1051*23b7c7b8SHermès Bélusca-Maïto                          &Ccb,
1052*23b7c7b8SHermès Bélusca-Maïto                          0,
1053*23b7c7b8SHermès Bélusca-Maïto                          &Flags,
1054*23b7c7b8SHermès Bélusca-Maïto                          &Dirent,
1055*23b7c7b8SHermès Bélusca-Maïto                          &DirentBcb,
1056*23b7c7b8SHermès Bélusca-Maïto                          &DirentByteOffset,
1057*23b7c7b8SHermès Bélusca-Maïto                          NULL,
1058*23b7c7b8SHermès Bélusca-Maïto                          LfnTmp,
1059*23b7c7b8SHermès Bélusca-Maïto                          NULL );
1060*23b7c7b8SHermès Bélusca-Maïto 
1061*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
1062*23b7c7b8SHermès Bélusca-Maïto 
1063*23b7c7b8SHermès Bélusca-Maïto         if (DirentBcb) {
1064*23b7c7b8SHermès Bélusca-Maïto 
1065*23b7c7b8SHermès Bélusca-Maïto             Result = TRUE;
1066*23b7c7b8SHermès Bélusca-Maïto         }
1067*23b7c7b8SHermès Bélusca-Maïto 
1068*23b7c7b8SHermès Bélusca-Maïto         FatUnpinBcb(IrpContext, DirentBcb);
1069*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
1070*23b7c7b8SHermès Bélusca-Maïto 
1071*23b7c7b8SHermès Bélusca-Maïto     return Result;
1072*23b7c7b8SHermès Bélusca-Maïto }
1073*23b7c7b8SHermès Bélusca-Maïto 
1074*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)1075*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
1076*23b7c7b8SHermès Bélusca-Maïto VOID
1077*23b7c7b8SHermès Bélusca-Maïto FatLocateDirent (
1078*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
1079*23b7c7b8SHermès Bélusca-Maïto     IN PDCB ParentDirectory,
1080*23b7c7b8SHermès Bélusca-Maïto     IN PCCB Ccb,
1081*23b7c7b8SHermès Bélusca-Maïto     IN VBO OffsetToStartSearchFrom,
1082*23b7c7b8SHermès Bélusca-Maïto     IN OUT PULONG Flags,
1083*23b7c7b8SHermès Bélusca-Maïto     OUT PDIRENT *Dirent,
1084*23b7c7b8SHermès Bélusca-Maïto     OUT PBCB *Bcb,
1085*23b7c7b8SHermès Bélusca-Maïto     OUT PVBO ByteOffset,
1086*23b7c7b8SHermès Bélusca-Maïto     OUT PBOOLEAN FileNameDos OPTIONAL,
1087*23b7c7b8SHermès Bélusca-Maïto     IN OUT PUNICODE_STRING LongFileName OPTIONAL,
1088*23b7c7b8SHermès Bélusca-Maïto     IN OUT PUNICODE_STRING OrigLongFileName OPTIONAL
1089*23b7c7b8SHermès Bélusca-Maïto     )
1090*23b7c7b8SHermès Bélusca-Maïto 
1091*23b7c7b8SHermès Bélusca-Maïto /*++
1092*23b7c7b8SHermès Bélusca-Maïto 
1093*23b7c7b8SHermès Bélusca-Maïto Routine Description:
1094*23b7c7b8SHermès Bélusca-Maïto 
1095*23b7c7b8SHermès Bélusca-Maïto     This routine locates on the disk an undeleted dirent matching a given name.
1096*23b7c7b8SHermès Bélusca-Maïto 
1097*23b7c7b8SHermès Bélusca-Maïto Arguments:
1098*23b7c7b8SHermès Bélusca-Maïto 
1099*23b7c7b8SHermès Bélusca-Maïto     ParentDirectory - Supplies the DCB for the directory to search
1100*23b7c7b8SHermès Bélusca-Maïto 
1101*23b7c7b8SHermès Bélusca-Maïto     Ccb - Contains a context control block with all matching information.
1102*23b7c7b8SHermès Bélusca-Maïto 
1103*23b7c7b8SHermès Bélusca-Maïto     OffsetToStartSearchFrom - Supplies the VBO within the parent directory
1104*23b7c7b8SHermès Bélusca-Maïto         from which to start looking for another real dirent.
1105*23b7c7b8SHermès Bélusca-Maïto 
1106*23b7c7b8SHermès Bélusca-Maïto     Dirent - Receives a pointer to the located dirent if one was found
1107*23b7c7b8SHermès Bélusca-Maïto         or NULL otherwise.
1108*23b7c7b8SHermès Bélusca-Maïto 
1109*23b7c7b8SHermès Bélusca-Maïto     Bcb - Receives the Bcb for the located dirent if one was found or
1110*23b7c7b8SHermès Bélusca-Maïto         NULL otherwise.
1111*23b7c7b8SHermès Bélusca-Maïto 
1112*23b7c7b8SHermès Bélusca-Maïto     ByteOffset - Receives the VBO within the Parent directory for
1113*23b7c7b8SHermès Bélusca-Maïto         the located dirent if one was found, or 0 otherwise.
1114*23b7c7b8SHermès Bélusca-Maïto 
1115*23b7c7b8SHermès Bélusca-Maïto     FileNameDos - Receives TRUE if the element of the dirent we hit on
1116*23b7c7b8SHermès Bélusca-Maïto         was the short (non LFN) side
1117*23b7c7b8SHermès Bélusca-Maïto 
1118*23b7c7b8SHermès Bélusca-Maïto     LongFileName - If specified, this parameter returns the long file name
1119*23b7c7b8SHermès Bélusca-Maïto         associated with the returned dirent.  Note that it is the caller's
1120*23b7c7b8SHermès Bélusca-Maïto         responsibility to provide the buffer (and set MaximumLength
1121*23b7c7b8SHermès Bélusca-Maïto         accordingly) for this unicode string.  The Length field is reset
1122*23b7c7b8SHermès Bélusca-Maïto         to 0 by this routine on invocation.  If the supplied buffer is not
1123*23b7c7b8SHermès Bélusca-Maïto         large enough,  a new one will be allocated from pool.
1124*23b7c7b8SHermès Bélusca-Maïto 
1125*23b7c7b8SHermès Bélusca-Maïto Return Value:
1126*23b7c7b8SHermès Bélusca-Maïto 
1127*23b7c7b8SHermès Bélusca-Maïto     None.
1128*23b7c7b8SHermès Bélusca-Maïto 
1129*23b7c7b8SHermès Bélusca-Maïto --*/
1130*23b7c7b8SHermès Bélusca-Maïto 
1131*23b7c7b8SHermès Bélusca-Maïto {
1132*23b7c7b8SHermès Bélusca-Maïto     NTSTATUS Status = STATUS_SUCCESS;
1133*23b7c7b8SHermès Bélusca-Maïto 
1134*23b7c7b8SHermès Bélusca-Maïto     OEM_STRING Name;
1135*23b7c7b8SHermès Bélusca-Maïto     UCHAR NameBuffer[12];
1136*23b7c7b8SHermès Bélusca-Maïto 
1137*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN UpcasedLfnValid = FALSE;
1138*23b7c7b8SHermès Bélusca-Maïto     UNICODE_STRING UpcasedLfn = {0};
1139*23b7c7b8SHermès Bélusca-Maïto     WCHAR LocalLfnBuffer[32];
1140*23b7c7b8SHermès Bélusca-Maïto 
1141*23b7c7b8SHermès Bélusca-Maïto 
1142*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN LfnInProgress = FALSE;
1143*23b7c7b8SHermès Bélusca-Maïto     UCHAR LfnChecksum = 0;
1144*23b7c7b8SHermès Bélusca-Maïto     ULONG LfnSize = 0;
1145*23b7c7b8SHermès Bélusca-Maïto     ULONG LfnIndex = 0;
1146*23b7c7b8SHermès Bélusca-Maïto     UCHAR Ordinal = 0;
1147*23b7c7b8SHermès Bélusca-Maïto     VBO LfnByteOffset = 0;
1148*23b7c7b8SHermès Bélusca-Maïto 
1149*23b7c7b8SHermès Bélusca-Maïto     TimerStart(Dbg);
1150*23b7c7b8SHermès Bélusca-Maïto 
1151*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
1152*23b7c7b8SHermès Bélusca-Maïto 
1153*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatLocateDirent\n", 0);
1154*23b7c7b8SHermès Bélusca-Maïto 
1155*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  ParentDirectory         = %p\n", ParentDirectory);
1156*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  OffsetToStartSearchFrom = %08lx\n", OffsetToStartSearchFrom);
1157*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  Dirent                  = %p\n", Dirent);
1158*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  Bcb                     = %p\n", Bcb);
1159*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  ByteOffset              = %08lx\n", *ByteOffset);
1160*23b7c7b8SHermès Bélusca-Maïto 
1161*23b7c7b8SHermès Bélusca-Maïto     //
1162*23b7c7b8SHermès Bélusca-Maïto     //  We must have acquired the parent or the vcb to synchronize with deletion.  This
1163*23b7c7b8SHermès Bélusca-Maïto     //  is important since we can't survive racing a thread marking a series of lfn
1164*23b7c7b8SHermès Bélusca-Maïto     //  dirents deleted - we'd get a bogus ordinal, and otherwise get really messed up.
1165*23b7c7b8SHermès Bélusca-Maïto     //
1166*23b7c7b8SHermès Bélusca-Maïto     //  This routine cannot do the acquire since it would be out-of-order with respect
1167*23b7c7b8SHermès Bélusca-Maïto     //  to the Bcb resources on iterative calls.  Our order has Bcbs as the inferior resource.
1168*23b7c7b8SHermès Bélusca-Maïto     //
1169*23b7c7b8SHermès Bélusca-Maïto     //  Deletion always grabs the parent (safely - this used to not be possible until the
1170*23b7c7b8SHermès Bélusca-Maïto     //  multiple fcb lockorder was fixed to be bottom up!).  Deletion always occurs with
1171*23b7c7b8SHermès Bélusca-Maïto     //  the vcb held exclusive as well, and this will cover the cases where we can't easily
1172*23b7c7b8SHermès Bélusca-Maïto     //  hold the parent here, see above.
1173*23b7c7b8SHermès Bélusca-Maïto     //
1174*23b7c7b8SHermès Bélusca-Maïto 
1175*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( ExIsResourceAcquiredSharedLite( ParentDirectory->Header.Resource ) ||
1176*23b7c7b8SHermès Bélusca-Maïto             ExIsResourceAcquiredExclusiveLite( ParentDirectory->Header.Resource ) ||
1177*23b7c7b8SHermès Bélusca-Maïto             ExIsResourceAcquiredSharedLite( &ParentDirectory->Vcb->Resource ) ||
1178*23b7c7b8SHermès Bélusca-Maïto             ExIsResourceAcquiredExclusiveLite( &ParentDirectory->Vcb->Resource ));
1179*23b7c7b8SHermès Bélusca-Maïto 
1180*23b7c7b8SHermès Bélusca-Maïto     //
1181*23b7c7b8SHermès Bélusca-Maïto     //  The algorithm here is pretty simple.  We just walk through the
1182*23b7c7b8SHermès Bélusca-Maïto     //  parent directory until we:
1183*23b7c7b8SHermès Bélusca-Maïto     //
1184*23b7c7b8SHermès Bélusca-Maïto     //      A)  Find a matching entry.
1185*23b7c7b8SHermès Bélusca-Maïto     //      B)  Can't Wait
1186*23b7c7b8SHermès Bélusca-Maïto     //      C)  Hit the End of Directory
1187*23b7c7b8SHermès Bélusca-Maïto     //      D)  Hit Eof
1188*23b7c7b8SHermès Bélusca-Maïto     //
1189*23b7c7b8SHermès Bélusca-Maïto     //  In the first case we found it, in the latter three cases we did not.
1190*23b7c7b8SHermès Bélusca-Maïto     //
1191*23b7c7b8SHermès Bélusca-Maïto 
1192*23b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( Flags ); // future use
1193*23b7c7b8SHermès Bélusca-Maïto 
1194*23b7c7b8SHermès Bélusca-Maïto 
1195*23b7c7b8SHermès Bélusca-Maïto     Name.MaximumLength = 12;
1196*23b7c7b8SHermès Bélusca-Maïto     Name.Buffer = (PCHAR)NameBuffer;
1197*23b7c7b8SHermès Bélusca-Maïto 
1198*23b7c7b8SHermès Bélusca-Maïto     UpcasedLfn.Length = 0;
1199*23b7c7b8SHermès Bélusca-Maïto     UpcasedLfn.MaximumLength = sizeof( LocalLfnBuffer);
1200*23b7c7b8SHermès Bélusca-Maïto     UpcasedLfn.Buffer = LocalLfnBuffer;
1201*23b7c7b8SHermès Bélusca-Maïto 
1202*23b7c7b8SHermès Bélusca-Maïto 
1203*23b7c7b8SHermès Bélusca-Maïto     //
1204*23b7c7b8SHermès Bélusca-Maïto     //  If we were given a non-NULL Bcb, compute the new Dirent address
1205*23b7c7b8SHermès Bélusca-Maïto     //  from the prior one, or unpin the Bcb if the new Dirent is not pinned.
1206*23b7c7b8SHermès Bélusca-Maïto     //
1207*23b7c7b8SHermès Bélusca-Maïto 
1208*23b7c7b8SHermès Bélusca-Maïto     if (*Bcb != NULL) {
1209*23b7c7b8SHermès Bélusca-Maïto 
1210*23b7c7b8SHermès Bélusca-Maïto         if ((OffsetToStartSearchFrom / PAGE_SIZE) == (*ByteOffset / PAGE_SIZE)) {
1211*23b7c7b8SHermès Bélusca-Maïto 
1212*23b7c7b8SHermès Bélusca-Maïto             *Dirent += (OffsetToStartSearchFrom - *ByteOffset) / sizeof(DIRENT);
1213*23b7c7b8SHermès Bélusca-Maïto 
1214*23b7c7b8SHermès Bélusca-Maïto         } else {
1215*23b7c7b8SHermès Bélusca-Maïto 
1216*23b7c7b8SHermès Bélusca-Maïto             FatUnpinBcb( IrpContext, *Bcb );
1217*23b7c7b8SHermès Bélusca-Maïto         }
1218*23b7c7b8SHermès Bélusca-Maïto     }
1219*23b7c7b8SHermès Bélusca-Maïto 
1220*23b7c7b8SHermès Bélusca-Maïto     //
1221*23b7c7b8SHermès Bélusca-Maïto     //  Init the Lfn if we were given one.
1222*23b7c7b8SHermès Bélusca-Maïto     //
1223*23b7c7b8SHermès Bélusca-Maïto 
1224*23b7c7b8SHermès Bélusca-Maïto     if (ARGUMENT_PRESENT(LongFileName)) {
1225*23b7c7b8SHermès Bélusca-Maïto 
1226*23b7c7b8SHermès Bélusca-Maïto         LongFileName->Length = 0;
1227*23b7c7b8SHermès Bélusca-Maïto     }
1228*23b7c7b8SHermès Bélusca-Maïto 
1229*23b7c7b8SHermès Bélusca-Maïto     if (ARGUMENT_PRESENT(OrigLongFileName)) {
1230*23b7c7b8SHermès Bélusca-Maïto 
1231*23b7c7b8SHermès Bélusca-Maïto         OrigLongFileName->Length = 0;
1232*23b7c7b8SHermès Bélusca-Maïto     }
1233*23b7c7b8SHermès Bélusca-Maïto 
1234*23b7c7b8SHermès Bélusca-Maïto     //
1235*23b7c7b8SHermès Bélusca-Maïto     //  Init the FileNameDos flag
1236*23b7c7b8SHermès Bélusca-Maïto     //
1237*23b7c7b8SHermès Bélusca-Maïto 
1238*23b7c7b8SHermès Bélusca-Maïto     if (FileNameDos) {
1239*23b7c7b8SHermès Bélusca-Maïto 
1240*23b7c7b8SHermès Bélusca-Maïto         *FileNameDos = FALSE;
1241*23b7c7b8SHermès Bélusca-Maïto     }
1242*23b7c7b8SHermès Bélusca-Maïto 
1243*23b7c7b8SHermès Bélusca-Maïto     //
1244*23b7c7b8SHermès Bélusca-Maïto     //  Round up OffsetToStartSearchFrom to the nearest Dirent, and store
1245*23b7c7b8SHermès Bélusca-Maïto     //  in ByteOffset.  Note that this wipes out the prior value.
1246*23b7c7b8SHermès Bélusca-Maïto     //
1247*23b7c7b8SHermès Bélusca-Maïto 
1248*23b7c7b8SHermès Bélusca-Maïto     *ByteOffset = (OffsetToStartSearchFrom +  (sizeof(DIRENT) - 1))
1249*23b7c7b8SHermès Bélusca-Maïto                                            & ~(sizeof(DIRENT) - 1);
1250*23b7c7b8SHermès Bélusca-Maïto 
1251*23b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
1252*23b7c7b8SHermès Bélusca-Maïto 
1253*23b7c7b8SHermès Bélusca-Maïto         while ( TRUE ) {
1254*23b7c7b8SHermès Bélusca-Maïto 
1255*23b7c7b8SHermès Bélusca-Maïto             BOOLEAN FoundValidLfn;
1256*23b7c7b8SHermès Bélusca-Maïto 
1257*23b7c7b8SHermès Bélusca-Maïto             UpcasedLfnValid = FALSE;
1258*23b7c7b8SHermès Bélusca-Maïto 
1259*23b7c7b8SHermès Bélusca-Maïto 
1260*23b7c7b8SHermès Bélusca-Maïto             //
1261*23b7c7b8SHermès Bélusca-Maïto             //  Try to read in the dirent
1262*23b7c7b8SHermès Bélusca-Maïto             //
1263*23b7c7b8SHermès Bélusca-Maïto 
1264*23b7c7b8SHermès Bélusca-Maïto             FatReadDirent( IrpContext,
1265*23b7c7b8SHermès Bélusca-Maïto                            ParentDirectory,
1266*23b7c7b8SHermès Bélusca-Maïto                            *ByteOffset,
1267*23b7c7b8SHermès Bélusca-Maïto                            Bcb,
1268*23b7c7b8SHermès Bélusca-Maïto                            Dirent,
1269*23b7c7b8SHermès Bélusca-Maïto                            &Status );
1270*23b7c7b8SHermès Bélusca-Maïto 
1271*23b7c7b8SHermès Bélusca-Maïto             //
1272*23b7c7b8SHermès Bélusca-Maïto             //  If End Directory dirent or EOF, set all out parameters to
1273*23b7c7b8SHermès Bélusca-Maïto             //  indicate entry not found and, like, bail.
1274*23b7c7b8SHermès Bélusca-Maïto             //
1275*23b7c7b8SHermès Bélusca-Maïto             //  Note that the order of evaluation here is important since we
1276*23b7c7b8SHermès Bélusca-Maïto             //  cannot check the first character of the dirent until after we
1277*23b7c7b8SHermès Bélusca-Maïto             //  know we are not beyond EOF
1278*23b7c7b8SHermès Bélusca-Maïto             //
1279*23b7c7b8SHermès Bélusca-Maïto 
1280*23b7c7b8SHermès Bélusca-Maïto             if ((Status == STATUS_END_OF_FILE) ||
1281*23b7c7b8SHermès Bélusca-Maïto                 ((*Dirent)->FileName[0] == FAT_DIRENT_NEVER_USED)) {
1282*23b7c7b8SHermès Bélusca-Maïto 
1283*23b7c7b8SHermès Bélusca-Maïto                 DebugTrace( 0, Dbg, "End of directory: entry not found.\n", 0);
1284*23b7c7b8SHermès Bélusca-Maïto 
1285*23b7c7b8SHermès Bélusca-Maïto                 //
1286*23b7c7b8SHermès Bélusca-Maïto                 //  If there is a Bcb, unpin it and set it to null
1287*23b7c7b8SHermès Bélusca-Maïto                 //
1288*23b7c7b8SHermès Bélusca-Maïto 
1289*23b7c7b8SHermès Bélusca-Maïto                 FatUnpinBcb( IrpContext, *Bcb );
1290*23b7c7b8SHermès Bélusca-Maïto 
1291*23b7c7b8SHermès Bélusca-Maïto                 *Dirent = NULL;
1292*23b7c7b8SHermès Bélusca-Maïto                 *ByteOffset = 0;
1293*23b7c7b8SHermès Bélusca-Maïto                 break;
1294*23b7c7b8SHermès Bélusca-Maïto             }
1295*23b7c7b8SHermès Bélusca-Maïto 
1296*23b7c7b8SHermès Bélusca-Maïto             //
1297*23b7c7b8SHermès Bélusca-Maïto             //  If the entry is marked deleted, skip.  If there was an Lfn in
1298*23b7c7b8SHermès Bélusca-Maïto             //  progress we throw it out at this point.
1299*23b7c7b8SHermès Bélusca-Maïto             //
1300*23b7c7b8SHermès Bélusca-Maïto 
1301*23b7c7b8SHermès Bélusca-Maïto             if ((*Dirent)->FileName[0] == FAT_DIRENT_DELETED) {
1302*23b7c7b8SHermès Bélusca-Maïto 
1303*23b7c7b8SHermès Bélusca-Maïto                 LfnInProgress = FALSE;
1304*23b7c7b8SHermès Bélusca-Maïto                 goto GetNextDirent;
1305*23b7c7b8SHermès Bélusca-Maïto             }
1306*23b7c7b8SHermès Bélusca-Maïto 
1307*23b7c7b8SHermès Bélusca-Maïto             //
1308*23b7c7b8SHermès Bélusca-Maïto             //  If we have wandered onto an LFN entry, try to interpret it.
1309*23b7c7b8SHermès Bélusca-Maïto             //
1310*23b7c7b8SHermès Bélusca-Maïto 
1311*23b7c7b8SHermès Bélusca-Maïto             if (FatData.ChicagoMode &&
1312*23b7c7b8SHermès Bélusca-Maïto                 ARGUMENT_PRESENT(LongFileName) &&
1313*23b7c7b8SHermès Bélusca-Maïto                 ((*Dirent)->Attributes == FAT_DIRENT_ATTR_LFN)) {
1314*23b7c7b8SHermès Bélusca-Maïto 
1315*23b7c7b8SHermès Bélusca-Maïto                 PLFN_DIRENT Lfn;
1316*23b7c7b8SHermès Bélusca-Maïto 
1317*23b7c7b8SHermès Bélusca-Maïto                 Lfn = (PLFN_DIRENT)*Dirent;
1318*23b7c7b8SHermès Bélusca-Maïto 
1319*23b7c7b8SHermès Bélusca-Maïto                 if (LfnInProgress) {
1320*23b7c7b8SHermès Bélusca-Maïto 
1321*23b7c7b8SHermès Bélusca-Maïto                     //
1322*23b7c7b8SHermès Bélusca-Maïto                     //  Check for a proper continuation of the Lfn in progress.
1323*23b7c7b8SHermès Bélusca-Maïto                     //
1324*23b7c7b8SHermès Bélusca-Maïto 
1325*23b7c7b8SHermès Bélusca-Maïto                     if ((Lfn->Ordinal & FAT_LAST_LONG_ENTRY) ||
1326*23b7c7b8SHermès Bélusca-Maïto                         (Lfn->Ordinal == 0) ||
1327*23b7c7b8SHermès Bélusca-Maïto                         (Lfn->Ordinal != Ordinal - 1) ||
1328*23b7c7b8SHermès Bélusca-Maïto                         (Lfn->Checksum != LfnChecksum) ||
1329*23b7c7b8SHermès Bélusca-Maïto                         (Lfn->MustBeZero != 0)) {
1330*23b7c7b8SHermès Bélusca-Maïto 
1331*23b7c7b8SHermès Bélusca-Maïto                         //
1332*23b7c7b8SHermès Bélusca-Maïto                         //  The Lfn is not proper, stop constructing it.
1333*23b7c7b8SHermès Bélusca-Maïto                         //
1334*23b7c7b8SHermès Bélusca-Maïto 
1335*23b7c7b8SHermès Bélusca-Maïto                         LfnInProgress = FALSE;
1336*23b7c7b8SHermès Bélusca-Maïto 
1337*23b7c7b8SHermès Bélusca-Maïto                     } else {
1338*23b7c7b8SHermès Bélusca-Maïto 
1339*23b7c7b8SHermès Bélusca-Maïto                         NT_ASSERT( ((LfnIndex % 13) == 0) && LfnIndex );
1340*23b7c7b8SHermès Bélusca-Maïto 
1341*23b7c7b8SHermès Bélusca-Maïto                         LfnIndex -= 13;
1342*23b7c7b8SHermès Bélusca-Maïto 
1343*23b7c7b8SHermès Bélusca-Maïto                         RtlCopyMemory( &LongFileName->Buffer[LfnIndex+0],
1344*23b7c7b8SHermès Bélusca-Maïto                                        &Lfn->Name1[0],
1345*23b7c7b8SHermès Bélusca-Maïto                                        5*sizeof(WCHAR) );
1346*23b7c7b8SHermès Bélusca-Maïto 
1347*23b7c7b8SHermès Bélusca-Maïto                         RtlCopyMemory( &LongFileName->Buffer[LfnIndex+5],
1348*23b7c7b8SHermès Bélusca-Maïto                                        &Lfn->Name2[0],
1349*23b7c7b8SHermès Bélusca-Maïto                                        6 * sizeof(WCHAR) );
1350*23b7c7b8SHermès Bélusca-Maïto 
1351*23b7c7b8SHermès Bélusca-Maïto                         RtlCopyMemory( &LongFileName->Buffer[LfnIndex+11],
1352*23b7c7b8SHermès Bélusca-Maïto                                        &Lfn->Name3[0],
1353*23b7c7b8SHermès Bélusca-Maïto                                        2 * sizeof(WCHAR) );
1354*23b7c7b8SHermès Bélusca-Maïto 
1355*23b7c7b8SHermès Bélusca-Maïto                         Ordinal = Lfn->Ordinal;
1356*23b7c7b8SHermès Bélusca-Maïto                         LfnByteOffset = *ByteOffset;
1357*23b7c7b8SHermès Bélusca-Maïto                     }
1358*23b7c7b8SHermès Bélusca-Maïto                 }
1359*23b7c7b8SHermès Bélusca-Maïto 
1360*23b7c7b8SHermès Bélusca-Maïto                 //
1361*23b7c7b8SHermès Bélusca-Maïto                 //  Now check (maybe again) if we should analyze this entry
1362*23b7c7b8SHermès Bélusca-Maïto                 //  for a possible last entry.
1363*23b7c7b8SHermès Bélusca-Maïto                 //
1364*23b7c7b8SHermès Bélusca-Maïto 
1365*23b7c7b8SHermès Bélusca-Maïto                 if ((!LfnInProgress) &&
1366*23b7c7b8SHermès Bélusca-Maïto                     (Lfn->Ordinal & FAT_LAST_LONG_ENTRY) &&
1367*23b7c7b8SHermès Bélusca-Maïto                     ((Lfn->Ordinal & ~FAT_LAST_LONG_ENTRY) <= MAX_LFN_DIRENTS) &&
1368*23b7c7b8SHermès Bélusca-Maïto                     (Lfn->MustBeZero == 0)) {
1369*23b7c7b8SHermès Bélusca-Maïto 
1370*23b7c7b8SHermès Bélusca-Maïto                     BOOLEAN CheckTail = FALSE;
1371*23b7c7b8SHermès Bélusca-Maïto 
1372*23b7c7b8SHermès Bélusca-Maïto                     Ordinal = Lfn->Ordinal & ~FAT_LAST_LONG_ENTRY;
1373*23b7c7b8SHermès Bélusca-Maïto 
1374*23b7c7b8SHermès Bélusca-Maïto                     //
1375*23b7c7b8SHermès Bélusca-Maïto                     //  We're usually permissive (following the lead of Win9x) when we find
1376*23b7c7b8SHermès Bélusca-Maïto                     //  malformation of the LFN dirent pile.  I'm not sure this is a good idea,
1377*23b7c7b8SHermès Bélusca-Maïto                     //  so I'm going to trigger corruption on this particularly ugly one.  Perhaps
1378*23b7c7b8SHermès Bélusca-Maïto                     //  we should come back and redo the original code here with this in mind in the
1379*23b7c7b8SHermès Bélusca-Maïto                     //  future.
1380*23b7c7b8SHermès Bélusca-Maïto                     //
1381*23b7c7b8SHermès Bélusca-Maïto 
1382*23b7c7b8SHermès Bélusca-Maïto                     if (Ordinal == 0) {
1383*23b7c7b8SHermès Bélusca-Maïto 
1384*23b7c7b8SHermès Bélusca-Maïto                         //
1385*23b7c7b8SHermès Bélusca-Maïto                         //  First LFN in the pile was zero marked as the last. This is never
1386*23b7c7b8SHermès Bélusca-Maïto                         //  possible since oridinals are 1-based.
1387*23b7c7b8SHermès Bélusca-Maïto                         //
1388*23b7c7b8SHermès Bélusca-Maïto 
1389*23b7c7b8SHermès Bélusca-Maïto                         FatPopUpFileCorrupt( IrpContext, ParentDirectory );
1390*23b7c7b8SHermès Bélusca-Maïto                         FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
1391*23b7c7b8SHermès Bélusca-Maïto                     }
1392*23b7c7b8SHermès Bélusca-Maïto 
1393*23b7c7b8SHermès Bélusca-Maïto                     LfnIndex = (Ordinal - 1) * 13;
1394*23b7c7b8SHermès Bélusca-Maïto 
1395*23b7c7b8SHermès Bélusca-Maïto                     FatEnsureStringBufferEnough( LongFileName,
1396*23b7c7b8SHermès Bélusca-Maïto                                                  (USHORT)((LfnIndex + 13) << 1));
1397*23b7c7b8SHermès Bélusca-Maïto 
1398*23b7c7b8SHermès Bélusca-Maïto                     RtlCopyMemory( &LongFileName->Buffer[LfnIndex+0],
1399*23b7c7b8SHermès Bélusca-Maïto                                    &Lfn->Name1[0],
1400*23b7c7b8SHermès Bélusca-Maïto                                    5*sizeof(WCHAR));
1401*23b7c7b8SHermès Bélusca-Maïto 
1402*23b7c7b8SHermès Bélusca-Maïto                     RtlCopyMemory( &LongFileName->Buffer[LfnIndex+5],
1403*23b7c7b8SHermès Bélusca-Maïto                                    &Lfn->Name2[0],
1404*23b7c7b8SHermès Bélusca-Maïto                                    6 * sizeof(WCHAR) );
1405*23b7c7b8SHermès Bélusca-Maïto 
1406*23b7c7b8SHermès Bélusca-Maïto                     RtlCopyMemory( &LongFileName->Buffer[LfnIndex+11],
1407*23b7c7b8SHermès Bélusca-Maïto                                    &Lfn->Name3[0],
1408*23b7c7b8SHermès Bélusca-Maïto                                    2 * sizeof(WCHAR) );
1409*23b7c7b8SHermès Bélusca-Maïto 
1410*23b7c7b8SHermès Bélusca-Maïto                     //
1411*23b7c7b8SHermès Bélusca-Maïto                     //  Now compute the Lfn size and make sure that the tail
1412*23b7c7b8SHermès Bélusca-Maïto                     //  bytes are correct.
1413*23b7c7b8SHermès Bélusca-Maïto                     //
1414*23b7c7b8SHermès Bélusca-Maïto 
1415*23b7c7b8SHermès Bélusca-Maïto                     while (LfnIndex != (ULONG)Ordinal * 13) {
1416*23b7c7b8SHermès Bélusca-Maïto 
1417*23b7c7b8SHermès Bélusca-Maïto                         if (!CheckTail) {
1418*23b7c7b8SHermès Bélusca-Maïto 
1419*23b7c7b8SHermès Bélusca-Maïto                             if (LongFileName->Buffer[LfnIndex] == 0x0000) {
1420*23b7c7b8SHermès Bélusca-Maïto 
1421*23b7c7b8SHermès Bélusca-Maïto                                 LfnSize = LfnIndex;
1422*23b7c7b8SHermès Bélusca-Maïto                                 CheckTail = TRUE;
1423*23b7c7b8SHermès Bélusca-Maïto                             }
1424*23b7c7b8SHermès Bélusca-Maïto 
1425*23b7c7b8SHermès Bélusca-Maïto                         } else {
1426*23b7c7b8SHermès Bélusca-Maïto 
1427*23b7c7b8SHermès Bélusca-Maïto                             if (LongFileName->Buffer[LfnIndex] != 0xffff) {
1428*23b7c7b8SHermès Bélusca-Maïto 
1429*23b7c7b8SHermès Bélusca-Maïto                                 break;
1430*23b7c7b8SHermès Bélusca-Maïto                             }
1431*23b7c7b8SHermès Bélusca-Maïto                         }
1432*23b7c7b8SHermès Bélusca-Maïto 
1433*23b7c7b8SHermès Bélusca-Maïto                         LfnIndex += 1;
1434*23b7c7b8SHermès Bélusca-Maïto                     }
1435*23b7c7b8SHermès Bélusca-Maïto 
1436*23b7c7b8SHermès Bélusca-Maïto                     //
1437*23b7c7b8SHermès Bélusca-Maïto                     //  If we exited this loop prematurely, the LFN is not valid.
1438*23b7c7b8SHermès Bélusca-Maïto                     //
1439*23b7c7b8SHermès Bélusca-Maïto 
1440*23b7c7b8SHermès Bélusca-Maïto                     if (LfnIndex == (ULONG)Ordinal * 13) {
1441*23b7c7b8SHermès Bélusca-Maïto 
1442*23b7c7b8SHermès Bélusca-Maïto                         //
1443*23b7c7b8SHermès Bélusca-Maïto                         //  If we didn't find the NULL terminator, then the size
1444*23b7c7b8SHermès Bélusca-Maïto                         //  is LfnIndex.
1445*23b7c7b8SHermès Bélusca-Maïto                         //
1446*23b7c7b8SHermès Bélusca-Maïto 
1447*23b7c7b8SHermès Bélusca-Maïto                         if (!CheckTail) {
1448*23b7c7b8SHermès Bélusca-Maïto 
1449*23b7c7b8SHermès Bélusca-Maïto                             LfnSize = LfnIndex;
1450*23b7c7b8SHermès Bélusca-Maïto                         }
1451*23b7c7b8SHermès Bélusca-Maïto 
1452*23b7c7b8SHermès Bélusca-Maïto                         LfnIndex -= 13;
1453*23b7c7b8SHermès Bélusca-Maïto                         LfnInProgress = TRUE;
1454*23b7c7b8SHermès Bélusca-Maïto                         LfnChecksum = Lfn->Checksum;
1455*23b7c7b8SHermès Bélusca-Maïto                         LfnByteOffset = *ByteOffset;
1456*23b7c7b8SHermès Bélusca-Maïto                     }
1457*23b7c7b8SHermès Bélusca-Maïto                 }
1458*23b7c7b8SHermès Bélusca-Maïto 
1459*23b7c7b8SHermès Bélusca-Maïto                 //
1460*23b7c7b8SHermès Bélusca-Maïto                 //  Move on to the next dirent.
1461*23b7c7b8SHermès Bélusca-Maïto                 //
1462*23b7c7b8SHermès Bélusca-Maïto 
1463*23b7c7b8SHermès Bélusca-Maïto                 goto GetNextDirent;
1464*23b7c7b8SHermès Bélusca-Maïto             }
1465*23b7c7b8SHermès Bélusca-Maïto 
1466*23b7c7b8SHermès Bélusca-Maïto             //
1467*23b7c7b8SHermès Bélusca-Maïto             //  If this is the volume label, skip.  Note that we never arrive here
1468*23b7c7b8SHermès Bélusca-Maïto             //  while building the LFN.  If we did, we weren't asked to find LFNs
1469*23b7c7b8SHermès Bélusca-Maïto             //  and that is another good reason to skip this LFN fragment.
1470*23b7c7b8SHermès Bélusca-Maïto             //
1471*23b7c7b8SHermès Bélusca-Maïto 
1472*23b7c7b8SHermès Bélusca-Maïto             if (FlagOn((*Dirent)->Attributes, FAT_DIRENT_ATTR_VOLUME_ID)) {
1473*23b7c7b8SHermès Bélusca-Maïto 
1474*23b7c7b8SHermès Bélusca-Maïto                 //
1475*23b7c7b8SHermès Bélusca-Maïto                 //  If we actually were asked to hand back volume labels,
1476*23b7c7b8SHermès Bélusca-Maïto                 //  do it.
1477*23b7c7b8SHermès Bélusca-Maïto                 //
1478*23b7c7b8SHermès Bélusca-Maïto 
1479*23b7c7b8SHermès Bélusca-Maïto                 if (FlagOn(Ccb->Flags, CCB_FLAG_MATCH_VOLUME_ID)) {
1480*23b7c7b8SHermès Bélusca-Maïto 
1481*23b7c7b8SHermès Bélusca-Maïto                     break;
1482*23b7c7b8SHermès Bélusca-Maïto                 }
1483*23b7c7b8SHermès Bélusca-Maïto 
1484*23b7c7b8SHermès Bélusca-Maïto                 goto GetNextDirent;
1485*23b7c7b8SHermès Bélusca-Maïto             }
1486*23b7c7b8SHermès Bélusca-Maïto 
1487*23b7c7b8SHermès Bélusca-Maïto             //
1488*23b7c7b8SHermès Bélusca-Maïto             //  We may have just stepped off a valid Lfn run.  Check to see if
1489*23b7c7b8SHermès Bélusca-Maïto             //  it is indeed valid for the following dirent.
1490*23b7c7b8SHermès Bélusca-Maïto             //
1491*23b7c7b8SHermès Bélusca-Maïto 
1492*23b7c7b8SHermès Bélusca-Maïto             if (LfnInProgress &&
1493*23b7c7b8SHermès Bélusca-Maïto                 (*ByteOffset == LfnByteOffset + sizeof(DIRENT)) &&
1494*23b7c7b8SHermès Bélusca-Maïto                 (LfnIndex == 0) &&
1495*23b7c7b8SHermès Bélusca-Maïto                 (FatComputeLfnChecksum(*Dirent) == LfnChecksum)) {
1496*23b7c7b8SHermès Bélusca-Maïto 
1497*23b7c7b8SHermès Bélusca-Maïto                 NT_ASSERT( Ordinal == 1);
1498*23b7c7b8SHermès Bélusca-Maïto 
1499*23b7c7b8SHermès Bélusca-Maïto                 FoundValidLfn = TRUE;
1500*23b7c7b8SHermès Bélusca-Maïto                 LongFileName->Length = (USHORT)(LfnSize * sizeof(WCHAR));
1501*23b7c7b8SHermès Bélusca-Maïto 
1502*23b7c7b8SHermès Bélusca-Maïto 
1503*23b7c7b8SHermès Bélusca-Maïto                 if (ARGUMENT_PRESENT(OrigLongFileName)) {
1504*23b7c7b8SHermès Bélusca-Maïto                     *OrigLongFileName = *LongFileName;
1505*23b7c7b8SHermès Bélusca-Maïto                 }
1506*23b7c7b8SHermès Bélusca-Maïto 
1507*23b7c7b8SHermès Bélusca-Maïto             } else {
1508*23b7c7b8SHermès Bélusca-Maïto 
1509*23b7c7b8SHermès Bélusca-Maïto                 FoundValidLfn = FALSE;
1510*23b7c7b8SHermès Bélusca-Maïto             }
1511*23b7c7b8SHermès Bélusca-Maïto 
1512*23b7c7b8SHermès Bélusca-Maïto 
1513*23b7c7b8SHermès Bélusca-Maïto 
1514*23b7c7b8SHermès Bélusca-Maïto             //
1515*23b7c7b8SHermès Bélusca-Maïto             //  If we are supposed to match all entries, then match this entry.
1516*23b7c7b8SHermès Bélusca-Maïto             //
1517*23b7c7b8SHermès Bélusca-Maïto 
1518*23b7c7b8SHermès Bélusca-Maïto             if (FlagOn(Ccb->Flags, CCB_FLAG_MATCH_ALL)) {
1519*23b7c7b8SHermès Bélusca-Maïto 
1520*23b7c7b8SHermès Bélusca-Maïto                 break;
1521*23b7c7b8SHermès Bélusca-Maïto             }
1522*23b7c7b8SHermès Bélusca-Maïto 
1523*23b7c7b8SHermès Bélusca-Maïto             //
1524*23b7c7b8SHermès Bélusca-Maïto             //  Check against the short name given if one was.
1525*23b7c7b8SHermès Bélusca-Maïto             //
1526*23b7c7b8SHermès Bélusca-Maïto 
1527*23b7c7b8SHermès Bélusca-Maïto             if (!FlagOn( Ccb->Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE )) {
1528*23b7c7b8SHermès Bélusca-Maïto 
1529*23b7c7b8SHermès Bélusca-Maïto                 if (Ccb->ContainsWildCards) {
1530*23b7c7b8SHermès Bélusca-Maïto 
1531*23b7c7b8SHermès Bélusca-Maïto                     //
1532*23b7c7b8SHermès Bélusca-Maïto                     //  If we get one, note that all out parameters are already set.
1533*23b7c7b8SHermès Bélusca-Maïto                     //
1534*23b7c7b8SHermès Bélusca-Maïto 
1535*23b7c7b8SHermès Bélusca-Maïto                     (VOID)Fat8dot3ToString( IrpContext, (*Dirent), FALSE, &Name );
1536*23b7c7b8SHermès Bélusca-Maïto 
1537*23b7c7b8SHermès Bélusca-Maïto                     //
1538*23b7c7b8SHermès Bélusca-Maïto                     //  For fat we special case the ".." dirent because we want it to
1539*23b7c7b8SHermès Bélusca-Maïto                     //  match ????????.??? and to do that we change ".." to "." before
1540*23b7c7b8SHermès Bélusca-Maïto                     //  calling the Fsrtl routine.  But only do this if the expression
1541*23b7c7b8SHermès Bélusca-Maïto                     //  is greater than one character long.
1542*23b7c7b8SHermès Bélusca-Maïto                     //
1543*23b7c7b8SHermès Bélusca-Maïto 
1544*23b7c7b8SHermès Bélusca-Maïto                     if ((Name.Length == 2) &&
1545*23b7c7b8SHermès Bélusca-Maïto                         (Name.Buffer[0] == '.') &&
1546*23b7c7b8SHermès Bélusca-Maïto                         (Name.Buffer[1] == '.') &&
1547*23b7c7b8SHermès Bélusca-Maïto                         (Ccb->OemQueryTemplate.Wild.Length > 1)) {
1548*23b7c7b8SHermès Bélusca-Maïto 
1549*23b7c7b8SHermès Bélusca-Maïto                         Name.Length = 1;
1550*23b7c7b8SHermès Bélusca-Maïto                     }
1551*23b7c7b8SHermès Bélusca-Maïto 
1552*23b7c7b8SHermès Bélusca-Maïto                     if (FatIsNameInExpression( IrpContext,
1553*23b7c7b8SHermès Bélusca-Maïto                                                Ccb->OemQueryTemplate.Wild,
1554*23b7c7b8SHermès Bélusca-Maïto                                                Name)) {
1555*23b7c7b8SHermès Bélusca-Maïto 
1556*23b7c7b8SHermès Bélusca-Maïto                         DebugTrace( 0, Dbg, "Entry found: Name = \"%Z\"\n", &Name);
1557*23b7c7b8SHermès Bélusca-Maïto                         DebugTrace( 0, Dbg, "             VBO  = %08lx\n", *ByteOffset);
1558*23b7c7b8SHermès Bélusca-Maïto 
1559*23b7c7b8SHermès Bélusca-Maïto                         if (FileNameDos) {
1560*23b7c7b8SHermès Bélusca-Maïto 
1561*23b7c7b8SHermès Bélusca-Maïto                             *FileNameDos = TRUE;
1562*23b7c7b8SHermès Bélusca-Maïto                         }
1563*23b7c7b8SHermès Bélusca-Maïto 
1564*23b7c7b8SHermès Bélusca-Maïto                         SetFlag( Ccb->Flags, CCB_FLAG_OPENED_BY_SHORTNAME );
1565*23b7c7b8SHermès Bélusca-Maïto 
1566*23b7c7b8SHermès Bélusca-Maïto                         break;
1567*23b7c7b8SHermès Bélusca-Maïto                     }
1568*23b7c7b8SHermès Bélusca-Maïto 
1569*23b7c7b8SHermès Bélusca-Maïto                 } else {
1570*23b7c7b8SHermès Bélusca-Maïto 
1571*23b7c7b8SHermès Bélusca-Maïto                     //
1572*23b7c7b8SHermès Bélusca-Maïto                     //  Do the quickest 8.3 equivalency check possible
1573*23b7c7b8SHermès Bélusca-Maïto                     //
1574*23b7c7b8SHermès Bélusca-Maïto 
1575*23b7c7b8SHermès Bélusca-Maïto                     if (!FlagOn((*Dirent)->Attributes, FAT_DIRENT_ATTR_VOLUME_ID) &&
1576*23b7c7b8SHermès Bélusca-Maïto                         (*(PULONG)&(Ccb->OemQueryTemplate.Constant[0]) == *(PULONG)&((*Dirent)->FileName[0])) &&
1577*23b7c7b8SHermès Bélusca-Maïto                         (*(PULONG)&(Ccb->OemQueryTemplate.Constant[4]) == *(PULONG)&((*Dirent)->FileName[4])) &&
1578*23b7c7b8SHermès Bélusca-Maïto                         (*(PUSHORT)&(Ccb->OemQueryTemplate.Constant[8]) == *(PUSHORT)&((*Dirent)->FileName[8])) &&
1579*23b7c7b8SHermès Bélusca-Maïto                         (*(PUCHAR)&(Ccb->OemQueryTemplate.Constant[10]) == *(PUCHAR)&((*Dirent)->FileName[10]))) {
1580*23b7c7b8SHermès Bélusca-Maïto 
1581*23b7c7b8SHermès Bélusca-Maïto                         DebugTrace( 0, Dbg, "Entry found.\n", 0);
1582*23b7c7b8SHermès Bélusca-Maïto 
1583*23b7c7b8SHermès Bélusca-Maïto                         if (FileNameDos) {
1584*23b7c7b8SHermès Bélusca-Maïto 
1585*23b7c7b8SHermès Bélusca-Maïto                             *FileNameDos = TRUE;
1586*23b7c7b8SHermès Bélusca-Maïto                         }
1587*23b7c7b8SHermès Bélusca-Maïto 
1588*23b7c7b8SHermès Bélusca-Maïto                         SetFlag( Ccb->Flags, CCB_FLAG_OPENED_BY_SHORTNAME );
1589*23b7c7b8SHermès Bélusca-Maïto 
1590*23b7c7b8SHermès Bélusca-Maïto                         break;
1591*23b7c7b8SHermès Bélusca-Maïto                     }
1592*23b7c7b8SHermès Bélusca-Maïto                 }
1593*23b7c7b8SHermès Bélusca-Maïto             }
1594*23b7c7b8SHermès Bélusca-Maïto 
1595*23b7c7b8SHermès Bélusca-Maïto             //
1596*23b7c7b8SHermès Bélusca-Maïto             //  No matches were found with the short name.  If an LFN exists,
1597*23b7c7b8SHermès Bélusca-Maïto             //  use it for the search.
1598*23b7c7b8SHermès Bélusca-Maïto             //
1599*23b7c7b8SHermès Bélusca-Maïto 
1600*23b7c7b8SHermès Bélusca-Maïto             if (FoundValidLfn) {
1601*23b7c7b8SHermès Bélusca-Maïto 
1602*23b7c7b8SHermès Bélusca-Maïto 
1603*23b7c7b8SHermès Bélusca-Maïto                 //
1604*23b7c7b8SHermès Bélusca-Maïto                 //  First do a quick check here for different sized constant
1605*23b7c7b8SHermès Bélusca-Maïto                 //  name and expression before upcasing.
1606*23b7c7b8SHermès Bélusca-Maïto                 //
1607*23b7c7b8SHermès Bélusca-Maïto 
1608*23b7c7b8SHermès Bélusca-Maïto                 if (!Ccb->ContainsWildCards &&
1609*23b7c7b8SHermès Bélusca-Maïto                     (Ccb->UnicodeQueryTemplate.Length != (USHORT)(LfnSize * sizeof(WCHAR)))) {
1610*23b7c7b8SHermès Bélusca-Maïto 
1611*23b7c7b8SHermès Bélusca-Maïto                     //
1612*23b7c7b8SHermès Bélusca-Maïto                     //  Move on to the next dirent.
1613*23b7c7b8SHermès Bélusca-Maïto                     //
1614*23b7c7b8SHermès Bélusca-Maïto 
1615*23b7c7b8SHermès Bélusca-Maïto                     FoundValidLfn = FALSE;
1616*23b7c7b8SHermès Bélusca-Maïto                     LongFileName->Length = 0;
1617*23b7c7b8SHermès Bélusca-Maïto                     if (OrigLongFileName) {
1618*23b7c7b8SHermès Bélusca-Maïto                         OrigLongFileName->Length = 0;
1619*23b7c7b8SHermès Bélusca-Maïto                     }
1620*23b7c7b8SHermès Bélusca-Maïto 
1621*23b7c7b8SHermès Bélusca-Maïto                     goto GetNextDirent;
1622*23b7c7b8SHermès Bélusca-Maïto                 }
1623*23b7c7b8SHermès Bélusca-Maïto 
1624*23b7c7b8SHermès Bélusca-Maïto 
1625*23b7c7b8SHermès Bélusca-Maïto 
1626*23b7c7b8SHermès Bélusca-Maïto                 if (!UpcasedLfnValid) {
1627*23b7c7b8SHermès Bélusca-Maïto 
1628*23b7c7b8SHermès Bélusca-Maïto                     //
1629*23b7c7b8SHermès Bélusca-Maïto                     //  We need to upcase the name we found on disk.
1630*23b7c7b8SHermès Bélusca-Maïto                     //  We need a buffer.  Try to avoid doing an allocation.
1631*23b7c7b8SHermès Bélusca-Maïto                     //
1632*23b7c7b8SHermès Bélusca-Maïto 
1633*23b7c7b8SHermès Bélusca-Maïto                     FatEnsureStringBufferEnough( &UpcasedLfn,
1634*23b7c7b8SHermès Bélusca-Maïto                                                  LongFileName->Length);
1635*23b7c7b8SHermès Bélusca-Maïto 
1636*23b7c7b8SHermès Bélusca-Maïto                     Status = RtlUpcaseUnicodeString( &UpcasedLfn,
1637*23b7c7b8SHermès Bélusca-Maïto                                                      LongFileName,
1638*23b7c7b8SHermès Bélusca-Maïto                                                      FALSE );
1639*23b7c7b8SHermès Bélusca-Maïto 
1640*23b7c7b8SHermès Bélusca-Maïto                     if (!NT_SUCCESS(Status)) {
1641*23b7c7b8SHermès Bélusca-Maïto 
1642*23b7c7b8SHermès Bélusca-Maïto                         FatNormalizeAndRaiseStatus( IrpContext, Status );
1643*23b7c7b8SHermès Bélusca-Maïto                     }
1644*23b7c7b8SHermès Bélusca-Maïto 
1645*23b7c7b8SHermès Bélusca-Maïto 
1646*23b7c7b8SHermès Bélusca-Maïto                     UpcasedLfnValid = TRUE;
1647*23b7c7b8SHermès Bélusca-Maïto 
1648*23b7c7b8SHermès Bélusca-Maïto                 }
1649*23b7c7b8SHermès Bélusca-Maïto 
1650*23b7c7b8SHermès Bélusca-Maïto                 //
1651*23b7c7b8SHermès Bélusca-Maïto                 //  Do the compare
1652*23b7c7b8SHermès Bélusca-Maïto                 //
1653*23b7c7b8SHermès Bélusca-Maïto 
1654*23b7c7b8SHermès Bélusca-Maïto                 if (Ccb->ContainsWildCards) {
1655*23b7c7b8SHermès Bélusca-Maïto 
1656*23b7c7b8SHermès Bélusca-Maïto                     if (FsRtlIsNameInExpression( &Ccb->UnicodeQueryTemplate,
1657*23b7c7b8SHermès Bélusca-Maïto                                                  &UpcasedLfn,
1658*23b7c7b8SHermès Bélusca-Maïto                                                  TRUE,
1659*23b7c7b8SHermès Bélusca-Maïto                                                  NULL )) {
1660*23b7c7b8SHermès Bélusca-Maïto 
1661*23b7c7b8SHermès Bélusca-Maïto                         break;
1662*23b7c7b8SHermès Bélusca-Maïto                     }
1663*23b7c7b8SHermès Bélusca-Maïto 
1664*23b7c7b8SHermès Bélusca-Maïto                 } else {
1665*23b7c7b8SHermès Bélusca-Maïto 
1666*23b7c7b8SHermès Bélusca-Maïto                     if (FsRtlAreNamesEqual( &Ccb->UnicodeQueryTemplate,
1667*23b7c7b8SHermès Bélusca-Maïto                                             &UpcasedLfn,
1668*23b7c7b8SHermès Bélusca-Maïto                                             BooleanFlagOn( Ccb->Flags, CCB_FLAG_QUERY_TEMPLATE_MIXED ),
1669*23b7c7b8SHermès Bélusca-Maïto                                             NULL )) {
1670*23b7c7b8SHermès Bélusca-Maïto 
1671*23b7c7b8SHermès Bélusca-Maïto                         break;
1672*23b7c7b8SHermès Bélusca-Maïto                     }
1673*23b7c7b8SHermès Bélusca-Maïto 
1674*23b7c7b8SHermès Bélusca-Maïto 
1675*23b7c7b8SHermès Bélusca-Maïto                 }
1676*23b7c7b8SHermès Bélusca-Maïto 
1677*23b7c7b8SHermès Bélusca-Maïto             }
1678*23b7c7b8SHermès Bélusca-Maïto 
1679*23b7c7b8SHermès Bélusca-Maïto             //
1680*23b7c7b8SHermès Bélusca-Maïto             //  This long name was not a match.  Zero out the Length field.
1681*23b7c7b8SHermès Bélusca-Maïto             //
1682*23b7c7b8SHermès Bélusca-Maïto 
1683*23b7c7b8SHermès Bélusca-Maïto             if (FoundValidLfn) {
1684*23b7c7b8SHermès Bélusca-Maïto 
1685*23b7c7b8SHermès Bélusca-Maïto                 FoundValidLfn = FALSE;
1686*23b7c7b8SHermès Bélusca-Maïto                 LongFileName->Length = 0;
1687*23b7c7b8SHermès Bélusca-Maïto 
1688*23b7c7b8SHermès Bélusca-Maïto 
1689*23b7c7b8SHermès Bélusca-Maïto                 if (OrigLongFileName) {
1690*23b7c7b8SHermès Bélusca-Maïto                     OrigLongFileName->Length = 0;
1691*23b7c7b8SHermès Bélusca-Maïto                 }
1692*23b7c7b8SHermès Bélusca-Maïto             }
1693*23b7c7b8SHermès Bélusca-Maïto 
1694*23b7c7b8SHermès Bélusca-Maïto GetNextDirent:
1695*23b7c7b8SHermès Bélusca-Maïto 
1696*23b7c7b8SHermès Bélusca-Maïto             //
1697*23b7c7b8SHermès Bélusca-Maïto             //  Move on to the next dirent.
1698*23b7c7b8SHermès Bélusca-Maïto             //
1699*23b7c7b8SHermès Bélusca-Maïto 
1700*23b7c7b8SHermès Bélusca-Maïto             *ByteOffset += sizeof(DIRENT);
1701*23b7c7b8SHermès Bélusca-Maïto             *Dirent += 1;
1702*23b7c7b8SHermès Bélusca-Maïto         }
1703*23b7c7b8SHermès Bélusca-Maïto 
1704*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
1705*23b7c7b8SHermès Bélusca-Maïto 
1706*23b7c7b8SHermès Bélusca-Maïto         FatFreeStringBuffer( &UpcasedLfn );
1707*23b7c7b8SHermès Bélusca-Maïto 
1708*23b7c7b8SHermès Bélusca-Maïto 
1709*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
1710*23b7c7b8SHermès Bélusca-Maïto 
1711*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatLocateDirent -> (VOID)\n", 0);
1712*23b7c7b8SHermès Bélusca-Maïto 
1713*23b7c7b8SHermès Bélusca-Maïto     TimerStop(Dbg,"FatLocateDirent");
1714*23b7c7b8SHermès Bélusca-Maïto 
1715*23b7c7b8SHermès Bélusca-Maïto     return;
1716*23b7c7b8SHermès Bélusca-Maïto }
1717*23b7c7b8SHermès Bélusca-Maïto 
1718*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)1719*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
1720*23b7c7b8SHermès Bélusca-Maïto VOID
1721*23b7c7b8SHermès Bélusca-Maïto FatLocateSimpleOemDirent (
1722*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
1723*23b7c7b8SHermès Bélusca-Maïto     IN PDCB ParentDirectory,
1724*23b7c7b8SHermès Bélusca-Maïto     IN POEM_STRING FileName,
1725*23b7c7b8SHermès Bélusca-Maïto     OUT PDIRENT *Dirent,
1726*23b7c7b8SHermès Bélusca-Maïto     OUT PBCB *Bcb,
1727*23b7c7b8SHermès Bélusca-Maïto     OUT PVBO ByteOffset
1728*23b7c7b8SHermès Bélusca-Maïto     )
1729*23b7c7b8SHermès Bélusca-Maïto 
1730*23b7c7b8SHermès Bélusca-Maïto /*++
1731*23b7c7b8SHermès Bélusca-Maïto 
1732*23b7c7b8SHermès Bélusca-Maïto Routine Description:
1733*23b7c7b8SHermès Bélusca-Maïto 
1734*23b7c7b8SHermès Bélusca-Maïto     This routine locates on the disk an undelted simple Oem dirent.  By simple
1735*23b7c7b8SHermès Bélusca-Maïto     I mean that FileName cannot contain any extended characters, and we do
1736*23b7c7b8SHermès Bélusca-Maïto     not search LFNs or return them.
1737*23b7c7b8SHermès Bélusca-Maïto 
1738*23b7c7b8SHermès Bélusca-Maïto Arguments:
1739*23b7c7b8SHermès Bélusca-Maïto 
1740*23b7c7b8SHermès Bélusca-Maïto     ParentDirectory - Supplies the DCB for the directory in which
1741*23b7c7b8SHermès Bélusca-Maïto         to search
1742*23b7c7b8SHermès Bélusca-Maïto 
1743*23b7c7b8SHermès Bélusca-Maïto     FileName - Supplies the filename to search for.  The name may contain
1744*23b7c7b8SHermès Bélusca-Maïto         wild cards
1745*23b7c7b8SHermès Bélusca-Maïto 
1746*23b7c7b8SHermès Bélusca-Maïto     OffsetToStartSearchFrom - Supplies the VBO within the parent directory
1747*23b7c7b8SHermès Bélusca-Maïto         from which to start looking for another real dirent.
1748*23b7c7b8SHermès Bélusca-Maïto 
1749*23b7c7b8SHermès Bélusca-Maïto     Dirent - Receives a pointer to the located dirent if one was found
1750*23b7c7b8SHermès Bélusca-Maïto         or NULL otherwise.
1751*23b7c7b8SHermès Bélusca-Maïto 
1752*23b7c7b8SHermès Bélusca-Maïto     Bcb - Receives the Bcb for the located dirent if one was found or
1753*23b7c7b8SHermès Bélusca-Maïto         NULL otherwise.
1754*23b7c7b8SHermès Bélusca-Maïto 
1755*23b7c7b8SHermès Bélusca-Maïto     ByteOffset - Receives the VBO within the Parent directory for
1756*23b7c7b8SHermès Bélusca-Maïto         the located dirent if one was found, or 0 otherwise.
1757*23b7c7b8SHermès Bélusca-Maïto 
1758*23b7c7b8SHermès Bélusca-Maïto Return Value:
1759*23b7c7b8SHermès Bélusca-Maïto 
1760*23b7c7b8SHermès Bélusca-Maïto     None.
1761*23b7c7b8SHermès Bélusca-Maïto 
1762*23b7c7b8SHermès Bélusca-Maïto --*/
1763*23b7c7b8SHermès Bélusca-Maïto 
1764*23b7c7b8SHermès Bélusca-Maïto {
1765*23b7c7b8SHermès Bélusca-Maïto     CCB LocalCcb;
1766*23b7c7b8SHermès Bélusca-Maïto 
1767*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
1768*23b7c7b8SHermès Bélusca-Maïto 
1769*23b7c7b8SHermès Bélusca-Maïto     //
1770*23b7c7b8SHermès Bélusca-Maïto     //  Note, this routine is called rarely, so performance is not critical.
1771*23b7c7b8SHermès Bélusca-Maïto     //  Just fill in a Ccb structure on my stack with the values that are
1772*23b7c7b8SHermès Bélusca-Maïto     //  required.
1773*23b7c7b8SHermès Bélusca-Maïto     //
1774*23b7c7b8SHermès Bélusca-Maïto 
1775*23b7c7b8SHermès Bélusca-Maïto     FatStringTo8dot3( IrpContext,
1776*23b7c7b8SHermès Bélusca-Maïto                       *FileName,
1777*23b7c7b8SHermès Bélusca-Maïto                       &LocalCcb.OemQueryTemplate.Constant );
1778*23b7c7b8SHermès Bélusca-Maïto     LocalCcb.ContainsWildCards = FALSE;
1779*23b7c7b8SHermès Bélusca-Maïto     LocalCcb.Flags = 0;
1780*23b7c7b8SHermès Bélusca-Maïto 
1781*23b7c7b8SHermès Bélusca-Maïto     FatLocateDirent( IrpContext,
1782*23b7c7b8SHermès Bélusca-Maïto                      ParentDirectory,
1783*23b7c7b8SHermès Bélusca-Maïto                      &LocalCcb,
1784*23b7c7b8SHermès Bélusca-Maïto                      0,
1785*23b7c7b8SHermès Bélusca-Maïto                      NULL,
1786*23b7c7b8SHermès Bélusca-Maïto                      Dirent,
1787*23b7c7b8SHermès Bélusca-Maïto                      Bcb,
1788*23b7c7b8SHermès Bélusca-Maïto                      ByteOffset,
1789*23b7c7b8SHermès Bélusca-Maïto                      NULL,
1790*23b7c7b8SHermès Bélusca-Maïto                      NULL,
1791*23b7c7b8SHermès Bélusca-Maïto                      NULL );
1792*23b7c7b8SHermès Bélusca-Maïto 
1793*23b7c7b8SHermès Bélusca-Maïto     return;
1794*23b7c7b8SHermès Bélusca-Maïto }
1795*23b7c7b8SHermès Bélusca-Maïto 
1796*23b7c7b8SHermès Bélusca-Maïto 
1797*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)1798*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
1799*23b7c7b8SHermès Bélusca-Maïto VOID
1800*23b7c7b8SHermès Bélusca-Maïto FatLocateVolumeLabel (
1801*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
1802*23b7c7b8SHermès Bélusca-Maïto     IN PVCB Vcb,
1803*23b7c7b8SHermès Bélusca-Maïto     OUT PDIRENT *Dirent,
1804*23b7c7b8SHermès Bélusca-Maïto     OUT PBCB *Bcb,
1805*23b7c7b8SHermès Bélusca-Maïto     OUT PVBO ByteOffset
1806*23b7c7b8SHermès Bélusca-Maïto     )
1807*23b7c7b8SHermès Bélusca-Maïto 
1808*23b7c7b8SHermès Bélusca-Maïto /*++
1809*23b7c7b8SHermès Bélusca-Maïto 
1810*23b7c7b8SHermès Bélusca-Maïto Routine Description:
1811*23b7c7b8SHermès Bélusca-Maïto 
1812*23b7c7b8SHermès Bélusca-Maïto     This routine locates on the disk a dirent representing the volume
1813*23b7c7b8SHermès Bélusca-Maïto     label.  It does this by searching the root directory for a special
1814*23b7c7b8SHermès Bélusca-Maïto     volume label dirent.
1815*23b7c7b8SHermès Bélusca-Maïto 
1816*23b7c7b8SHermès Bélusca-Maïto Arguments:
1817*23b7c7b8SHermès Bélusca-Maïto 
1818*23b7c7b8SHermès Bélusca-Maïto     Vcb - Supplies the VCB for the volume to search
1819*23b7c7b8SHermès Bélusca-Maïto 
1820*23b7c7b8SHermès Bélusca-Maïto     Dirent - Receives a pointer to the located dirent if one was found
1821*23b7c7b8SHermès Bélusca-Maïto         or NULL otherwise.
1822*23b7c7b8SHermès Bélusca-Maïto 
1823*23b7c7b8SHermès Bélusca-Maïto     Bcb - Receives the Bcb for the located dirent if one was found or
1824*23b7c7b8SHermès Bélusca-Maïto         NULL otherwise.
1825*23b7c7b8SHermès Bélusca-Maïto 
1826*23b7c7b8SHermès Bélusca-Maïto     ByteOffset - Receives the VBO within the Parent directory for
1827*23b7c7b8SHermès Bélusca-Maïto         the located dirent if one was found, or 0 otherwise.
1828*23b7c7b8SHermès Bélusca-Maïto 
1829*23b7c7b8SHermès Bélusca-Maïto Return Value:
1830*23b7c7b8SHermès Bélusca-Maïto 
1831*23b7c7b8SHermès Bélusca-Maïto     None.
1832*23b7c7b8SHermès Bélusca-Maïto 
1833*23b7c7b8SHermès Bélusca-Maïto --*/
1834*23b7c7b8SHermès Bélusca-Maïto 
1835*23b7c7b8SHermès Bélusca-Maïto {
1836*23b7c7b8SHermès Bélusca-Maïto     NTSTATUS Status = STATUS_SUCCESS;
1837*23b7c7b8SHermès Bélusca-Maïto 
1838*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
1839*23b7c7b8SHermès Bélusca-Maïto 
1840*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatLocateVolumeLabel\n", 0);
1841*23b7c7b8SHermès Bélusca-Maïto 
1842*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  Vcb        = %p\n", Vcb);
1843*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  Dirent     = %p\n", Dirent);
1844*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  Bcb        = %p\n", Bcb);
1845*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  ByteOffset = %08lx\n", *ByteOffset);
1846*23b7c7b8SHermès Bélusca-Maïto 
1847*23b7c7b8SHermès Bélusca-Maïto     //
1848*23b7c7b8SHermès Bélusca-Maïto     //  The algorithm here is really simple.  We just walk through the
1849*23b7c7b8SHermès Bélusca-Maïto     //  root directory until we:
1850*23b7c7b8SHermès Bélusca-Maïto     //
1851*23b7c7b8SHermès Bélusca-Maïto     //      A)  Find the non-deleted volume label
1852*23b7c7b8SHermès Bélusca-Maïto     //      B)  Can't Wait
1853*23b7c7b8SHermès Bélusca-Maïto     //      C)  Hit the End of Directory
1854*23b7c7b8SHermès Bélusca-Maïto     //      D)  Hit Eof
1855*23b7c7b8SHermès Bélusca-Maïto     //
1856*23b7c7b8SHermès Bélusca-Maïto     //  In the first case we found it, in the latter three cases we did not.
1857*23b7c7b8SHermès Bélusca-Maïto     //
1858*23b7c7b8SHermès Bélusca-Maïto 
1859*23b7c7b8SHermès Bélusca-Maïto     *Bcb = NULL;
1860*23b7c7b8SHermès Bélusca-Maïto     *ByteOffset = 0;
1861*23b7c7b8SHermès Bélusca-Maïto 
1862*23b7c7b8SHermès Bélusca-Maïto     while ( TRUE ) {
1863*23b7c7b8SHermès Bélusca-Maïto 
1864*23b7c7b8SHermès Bélusca-Maïto         //
1865*23b7c7b8SHermès Bélusca-Maïto         //  Try to read in the dirent
1866*23b7c7b8SHermès Bélusca-Maïto         //
1867*23b7c7b8SHermès Bélusca-Maïto 
1868*23b7c7b8SHermès Bélusca-Maïto         FatReadDirent( IrpContext,
1869*23b7c7b8SHermès Bélusca-Maïto                        Vcb->RootDcb,
1870*23b7c7b8SHermès Bélusca-Maïto                        *ByteOffset,
1871*23b7c7b8SHermès Bélusca-Maïto                        Bcb,
1872*23b7c7b8SHermès Bélusca-Maïto                        Dirent,
1873*23b7c7b8SHermès Bélusca-Maïto                        &Status );
1874*23b7c7b8SHermès Bélusca-Maïto 
1875*23b7c7b8SHermès Bélusca-Maïto         //
1876*23b7c7b8SHermès Bélusca-Maïto         //  If End Directory dirent or EOF, set all out parameters to
1877*23b7c7b8SHermès Bélusca-Maïto         //  indicate volume label not found and, like, bail.
1878*23b7c7b8SHermès Bélusca-Maïto         //
1879*23b7c7b8SHermès Bélusca-Maïto         //  Note that the order of evaluation here is important since we cannot
1880*23b7c7b8SHermès Bélusca-Maïto         //  check the first character of the dirent until after we know we
1881*23b7c7b8SHermès Bélusca-Maïto         //  are not beyond EOF
1882*23b7c7b8SHermès Bélusca-Maïto         //
1883*23b7c7b8SHermès Bélusca-Maïto 
1884*23b7c7b8SHermès Bélusca-Maïto         if ((Status == STATUS_END_OF_FILE) ||
1885*23b7c7b8SHermès Bélusca-Maïto             ((*Dirent)->FileName[0] == FAT_DIRENT_NEVER_USED)) {
1886*23b7c7b8SHermès Bélusca-Maïto 
1887*23b7c7b8SHermès Bélusca-Maïto             DebugTrace( 0, Dbg, "Volume label not found.\n", 0);
1888*23b7c7b8SHermès Bélusca-Maïto 
1889*23b7c7b8SHermès Bélusca-Maïto             //
1890*23b7c7b8SHermès Bélusca-Maïto             //  If there is a Bcb, unpin it and set it to null
1891*23b7c7b8SHermès Bélusca-Maïto             //
1892*23b7c7b8SHermès Bélusca-Maïto 
1893*23b7c7b8SHermès Bélusca-Maïto             FatUnpinBcb( IrpContext, *Bcb );
1894*23b7c7b8SHermès Bélusca-Maïto 
1895*23b7c7b8SHermès Bélusca-Maïto             *Dirent = NULL;
1896*23b7c7b8SHermès Bélusca-Maïto             *ByteOffset = 0;
1897*23b7c7b8SHermès Bélusca-Maïto             break;
1898*23b7c7b8SHermès Bélusca-Maïto         }
1899*23b7c7b8SHermès Bélusca-Maïto 
1900*23b7c7b8SHermès Bélusca-Maïto         //
1901*23b7c7b8SHermès Bélusca-Maïto         //  If the entry is the non-deleted volume label break from the loop.
1902*23b7c7b8SHermès Bélusca-Maïto         //
1903*23b7c7b8SHermès Bélusca-Maïto         //  Note that all out parameters are already correctly set.
1904*23b7c7b8SHermès Bélusca-Maïto         //
1905*23b7c7b8SHermès Bélusca-Maïto 
1906*23b7c7b8SHermès Bélusca-Maïto         if ((((*Dirent)->Attributes & ~FAT_DIRENT_ATTR_ARCHIVE) == FAT_DIRENT_ATTR_VOLUME_ID) &&
1907*23b7c7b8SHermès Bélusca-Maïto             ((*Dirent)->FileName[0] != FAT_DIRENT_DELETED)) {
1908*23b7c7b8SHermès Bélusca-Maïto 
1909*23b7c7b8SHermès Bélusca-Maïto             DebugTrace( 0, Dbg, "Volume label found at VBO = %08lx\n", *ByteOffset);
1910*23b7c7b8SHermès Bélusca-Maïto 
1911*23b7c7b8SHermès Bélusca-Maïto             //
1912*23b7c7b8SHermès Bélusca-Maïto             //  We may set this dirty, so pin it.
1913*23b7c7b8SHermès Bélusca-Maïto             //
1914*23b7c7b8SHermès Bélusca-Maïto 
1915*23b7c7b8SHermès Bélusca-Maïto             FatPinMappedData( IrpContext,
1916*23b7c7b8SHermès Bélusca-Maïto                               Vcb->RootDcb,
1917*23b7c7b8SHermès Bélusca-Maïto                               *ByteOffset,
1918*23b7c7b8SHermès Bélusca-Maïto                               sizeof(DIRENT),
1919*23b7c7b8SHermès Bélusca-Maïto                               Bcb );
1920*23b7c7b8SHermès Bélusca-Maïto 
1921*23b7c7b8SHermès Bélusca-Maïto             break;
1922*23b7c7b8SHermès Bélusca-Maïto         }
1923*23b7c7b8SHermès Bélusca-Maïto 
1924*23b7c7b8SHermès Bélusca-Maïto         //
1925*23b7c7b8SHermès Bélusca-Maïto         //  Move on to the next dirent.
1926*23b7c7b8SHermès Bélusca-Maïto         //
1927*23b7c7b8SHermès Bélusca-Maïto 
1928*23b7c7b8SHermès Bélusca-Maïto         *ByteOffset += sizeof(DIRENT);
1929*23b7c7b8SHermès Bélusca-Maïto         *Dirent += 1;
1930*23b7c7b8SHermès Bélusca-Maïto     }
1931*23b7c7b8SHermès Bélusca-Maïto 
1932*23b7c7b8SHermès Bélusca-Maïto 
1933*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatLocateVolumeLabel -> (VOID)\n", 0);
1934*23b7c7b8SHermès Bélusca-Maïto 
1935*23b7c7b8SHermès Bélusca-Maïto     return;
1936*23b7c7b8SHermès Bélusca-Maïto }
1937*23b7c7b8SHermès Bélusca-Maïto 
1938*23b7c7b8SHermès Bélusca-Maïto 
1939*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)1940*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
1941*23b7c7b8SHermès Bélusca-Maïto VOID
1942*23b7c7b8SHermès Bélusca-Maïto FatGetDirentFromFcbOrDcb (
1943*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
1944*23b7c7b8SHermès Bélusca-Maïto     IN PFCB FcbOrDcb,
1945*23b7c7b8SHermès Bélusca-Maïto     IN BOOLEAN ReturnOnFailure,
1946*23b7c7b8SHermès Bélusca-Maïto     OUT PDIRENT *Dirent,
1947*23b7c7b8SHermès Bélusca-Maïto     OUT PBCB *Bcb
1948*23b7c7b8SHermès Bélusca-Maïto     )
1949*23b7c7b8SHermès Bélusca-Maïto 
1950*23b7c7b8SHermès Bélusca-Maïto /*++
1951*23b7c7b8SHermès Bélusca-Maïto 
1952*23b7c7b8SHermès Bélusca-Maïto Routine Description:
1953*23b7c7b8SHermès Bélusca-Maïto 
1954*23b7c7b8SHermès Bélusca-Maïto     This routine reads locates on the disk the dirent denoted by the
1955*23b7c7b8SHermès Bélusca-Maïto     specified Fcb/Dcb.
1956*23b7c7b8SHermès Bélusca-Maïto 
1957*23b7c7b8SHermès Bélusca-Maïto Arguments:
1958*23b7c7b8SHermès Bélusca-Maïto 
1959*23b7c7b8SHermès Bélusca-Maïto     FcbOrDcb - Supplies the FCB/DCB for the file/directory whose dirent
1960*23b7c7b8SHermès Bélusca-Maïto         we are trying to read in.  This must not be the root dcb.
1961*23b7c7b8SHermès Bélusca-Maïto 
1962*23b7c7b8SHermès Bélusca-Maïto     Dirent - Receives a pointer to the dirent
1963*23b7c7b8SHermès Bélusca-Maïto 
1964*23b7c7b8SHermès Bélusca-Maïto     Bcb - Receives the Bcb for the dirent
1965*23b7c7b8SHermès Bélusca-Maïto 
1966*23b7c7b8SHermès Bélusca-Maïto Return Value:
1967*23b7c7b8SHermès Bélusca-Maïto 
1968*23b7c7b8SHermès Bélusca-Maïto     None.
1969*23b7c7b8SHermès Bélusca-Maïto 
1970*23b7c7b8SHermès Bélusca-Maïto --*/
1971*23b7c7b8SHermès Bélusca-Maïto 
1972*23b7c7b8SHermès Bélusca-Maïto {
1973*23b7c7b8SHermès Bélusca-Maïto     NTSTATUS DontCare = STATUS_SUCCESS;
1974*23b7c7b8SHermès Bélusca-Maïto 
1975*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
1976*23b7c7b8SHermès Bélusca-Maïto 
1977*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatGetDirentFromFcbOrDcb\n", 0);
1978*23b7c7b8SHermès Bélusca-Maïto 
1979*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  FcbOrDcb = %p\n", FcbOrDcb);
1980*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  Dirent   = %p\n", Dirent);
1981*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  Bcb      = %p\n", Bcb);
1982*23b7c7b8SHermès Bélusca-Maïto 
1983*23b7c7b8SHermès Bélusca-Maïto     //
1984*23b7c7b8SHermès Bélusca-Maïto     //  Assert that we are not attempting this on the root directory.
1985*23b7c7b8SHermès Bélusca-Maïto     //
1986*23b7c7b8SHermès Bélusca-Maïto 
1987*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( NodeType(FcbOrDcb) != FAT_NTC_ROOT_DCB );
1988*23b7c7b8SHermès Bélusca-Maïto 
1989*23b7c7b8SHermès Bélusca-Maïto     //
1990*23b7c7b8SHermès Bélusca-Maïto     //  We know the offset of the dirent within the directory file,
1991*23b7c7b8SHermès Bélusca-Maïto     //  so we just read it (with pinning).
1992*23b7c7b8SHermès Bélusca-Maïto     //
1993*23b7c7b8SHermès Bélusca-Maïto 
1994*23b7c7b8SHermès Bélusca-Maïto     FatReadDirectoryFile( IrpContext,
1995*23b7c7b8SHermès Bélusca-Maïto                           FcbOrDcb->ParentDcb,
1996*23b7c7b8SHermès Bélusca-Maïto                           FcbOrDcb->DirentOffsetWithinDirectory,
1997*23b7c7b8SHermès Bélusca-Maïto                           sizeof(DIRENT),
1998*23b7c7b8SHermès Bélusca-Maïto                           TRUE,
1999*23b7c7b8SHermès Bélusca-Maïto                           Bcb,
2000*23b7c7b8SHermès Bélusca-Maïto                           (PVOID *)Dirent,
2001*23b7c7b8SHermès Bélusca-Maïto                           &DontCare );
2002*23b7c7b8SHermès Bélusca-Maïto 
2003*23b7c7b8SHermès Bélusca-Maïto     //
2004*23b7c7b8SHermès Bélusca-Maïto     //  Previous call can fail.  We used to assert success, but we use this
2005*23b7c7b8SHermès Bélusca-Maïto     //  as part of volume verification (DetermineAndMarkFcbCondition) after
2006*23b7c7b8SHermès Bélusca-Maïto     //  media has been removed.  Clearly the directory could shrink and we
2007*23b7c7b8SHermès Bélusca-Maïto     //  would try to read beyond filesize.
2008*23b7c7b8SHermès Bélusca-Maïto     //
2009*23b7c7b8SHermès Bélusca-Maïto     //  The caller will note this via NULL pointers for Bcb/Buffer.  Note that
2010*23b7c7b8SHermès Bélusca-Maïto     //  both asserts below are OK since this should never happen fixed media.
2011*23b7c7b8SHermès Bélusca-Maïto     //
2012*23b7c7b8SHermès Bélusca-Maïto     //  This was a Prefix catch.
2013*23b7c7b8SHermès Bélusca-Maïto     //
2014*23b7c7b8SHermès Bélusca-Maïto 
2015*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( FlagOn( FcbOrDcb->Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA) ||
2016*23b7c7b8SHermès Bélusca-Maïto             NT_SUCCESS( DontCare ));
2017*23b7c7b8SHermès Bélusca-Maïto 
2018*23b7c7b8SHermès Bélusca-Maïto     //
2019*23b7c7b8SHermès Bélusca-Maïto     //  Note also that the only way this could fail is if the Fcb was being
2020*23b7c7b8SHermès Bélusca-Maïto     //  verified.  This can't happen if the Fcb is in good condition.
2021*23b7c7b8SHermès Bélusca-Maïto     //
2022*23b7c7b8SHermès Bélusca-Maïto     //  Also a Prefix catch.
2023*23b7c7b8SHermès Bélusca-Maïto     //
2024*23b7c7b8SHermès Bélusca-Maïto 
2025*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( NT_SUCCESS( DontCare ) || FcbOrDcb->FcbCondition == FcbNeedsToBeVerified );
2026*23b7c7b8SHermès Bélusca-Maïto 
2027*23b7c7b8SHermès Bélusca-Maïto     //
2028*23b7c7b8SHermès Bélusca-Maïto     //  This should never happen except in very specific cases (during volume
2029*23b7c7b8SHermès Bélusca-Maïto     //  verify) but we'll handle and raise here to save all callers checking the
2030*23b7c7b8SHermès Bélusca-Maïto     //  pointers.
2031*23b7c7b8SHermès Bélusca-Maïto     //
2032*23b7c7b8SHermès Bélusca-Maïto 
2033*23b7c7b8SHermès Bélusca-Maïto     if ((NULL == *Dirent) && !ReturnOnFailure) {
2034*23b7c7b8SHermès Bélusca-Maïto 
2035*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( FALSE);
2036*23b7c7b8SHermès Bélusca-Maïto         FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR);
2037*23b7c7b8SHermès Bélusca-Maïto     }
2038*23b7c7b8SHermès Bélusca-Maïto 
2039*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatGetDirentFromFcbOrDcb -> (VOID)\n", 0);
2040*23b7c7b8SHermès Bélusca-Maïto }
2041*23b7c7b8SHermès Bélusca-Maïto 
2042*23b7c7b8SHermès Bélusca-Maïto 
2043*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)2044*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
2045*23b7c7b8SHermès Bélusca-Maïto BOOLEAN
2046*23b7c7b8SHermès Bélusca-Maïto FatIsDirectoryEmpty (
2047*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
2048*23b7c7b8SHermès Bélusca-Maïto     IN PDCB Dcb
2049*23b7c7b8SHermès Bélusca-Maïto     )
2050*23b7c7b8SHermès Bélusca-Maïto 
2051*23b7c7b8SHermès Bélusca-Maïto /*++
2052*23b7c7b8SHermès Bélusca-Maïto 
2053*23b7c7b8SHermès Bélusca-Maïto Routine Description:
2054*23b7c7b8SHermès Bélusca-Maïto 
2055*23b7c7b8SHermès Bélusca-Maïto     This routine indicates to the caller if the specified directory
2056*23b7c7b8SHermès Bélusca-Maïto     is empty.  (i.e., it is not the root dcb and it only contains
2057*23b7c7b8SHermès Bélusca-Maïto     the "." and ".." entries, or deleted files).
2058*23b7c7b8SHermès Bélusca-Maïto 
2059*23b7c7b8SHermès Bélusca-Maïto Arguments:
2060*23b7c7b8SHermès Bélusca-Maïto 
2061*23b7c7b8SHermès Bélusca-Maïto     Dcb - Supplies the DCB for the directory being queried.
2062*23b7c7b8SHermès Bélusca-Maïto 
2063*23b7c7b8SHermès Bélusca-Maïto Return Value:
2064*23b7c7b8SHermès Bélusca-Maïto 
2065*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN - Returns TRUE if the directory is empty and
2066*23b7c7b8SHermès Bélusca-Maïto         FALSE if the directory and is not empty.
2067*23b7c7b8SHermès Bélusca-Maïto 
2068*23b7c7b8SHermès Bélusca-Maïto --*/
2069*23b7c7b8SHermès Bélusca-Maïto 
2070*23b7c7b8SHermès Bélusca-Maïto {
2071*23b7c7b8SHermès Bélusca-Maïto     PBCB Bcb;
2072*23b7c7b8SHermès Bélusca-Maïto     ULONG ByteOffset;
2073*23b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent = NULL;
2074*23b7c7b8SHermès Bélusca-Maïto 
2075*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN IsDirectoryEmpty = FALSE;
2076*23b7c7b8SHermès Bélusca-Maïto 
2077*23b7c7b8SHermès Bélusca-Maïto     NTSTATUS Status = STATUS_SUCCESS;
2078*23b7c7b8SHermès Bélusca-Maïto 
2079*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
2080*23b7c7b8SHermès Bélusca-Maïto 
2081*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatIsDirectoryEmpty\n", 0);
2082*23b7c7b8SHermès Bélusca-Maïto 
2083*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  Dcb              = %p\n", Dcb);
2084*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  IsDirectoryEmpty = %08lx\n", IsDirectoryEmpty);
2085*23b7c7b8SHermès Bélusca-Maïto 
2086*23b7c7b8SHermès Bélusca-Maïto     //
2087*23b7c7b8SHermès Bélusca-Maïto     //  Check to see if the first entry is an and of directory marker.
2088*23b7c7b8SHermès Bélusca-Maïto     //  For the root directory we check at Vbo = 0, for normal directories
2089*23b7c7b8SHermès Bélusca-Maïto     //  we check after the "." and ".." entries.
2090*23b7c7b8SHermès Bélusca-Maïto     //
2091*23b7c7b8SHermès Bélusca-Maïto 
2092*23b7c7b8SHermès Bélusca-Maïto     ByteOffset = (NodeType(Dcb) == FAT_NTC_ROOT_DCB) ? 0 : 2*sizeof(DIRENT);
2093*23b7c7b8SHermès Bélusca-Maïto 
2094*23b7c7b8SHermès Bélusca-Maïto     //
2095*23b7c7b8SHermès Bélusca-Maïto     //  We just march through the directory looking for anything other
2096*23b7c7b8SHermès Bélusca-Maïto     //  than deleted files, LFNs, an EOF, or end of directory marker.
2097*23b7c7b8SHermès Bélusca-Maïto     //
2098*23b7c7b8SHermès Bélusca-Maïto 
2099*23b7c7b8SHermès Bélusca-Maïto     Bcb = NULL;
2100*23b7c7b8SHermès Bélusca-Maïto 
2101*23b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
2102*23b7c7b8SHermès Bélusca-Maïto 
2103*23b7c7b8SHermès Bélusca-Maïto         while ( TRUE ) {
2104*23b7c7b8SHermès Bélusca-Maïto 
2105*23b7c7b8SHermès Bélusca-Maïto             //
2106*23b7c7b8SHermès Bélusca-Maïto             //  Try to read in the dirent
2107*23b7c7b8SHermès Bélusca-Maïto             //
2108*23b7c7b8SHermès Bélusca-Maïto 
2109*23b7c7b8SHermès Bélusca-Maïto             FatReadDirent( IrpContext,
2110*23b7c7b8SHermès Bélusca-Maïto                            Dcb,
2111*23b7c7b8SHermès Bélusca-Maïto                            ByteOffset,
2112*23b7c7b8SHermès Bélusca-Maïto                            &Bcb,
2113*23b7c7b8SHermès Bélusca-Maïto                            &Dirent,
2114*23b7c7b8SHermès Bélusca-Maïto                            &Status );
2115*23b7c7b8SHermès Bélusca-Maïto 
2116*23b7c7b8SHermès Bélusca-Maïto             //
2117*23b7c7b8SHermès Bélusca-Maïto             //  If End Directory dirent or EOF, set IsDirectoryEmpty to TRUE and,
2118*23b7c7b8SHermès Bélusca-Maïto             //  like, bail.
2119*23b7c7b8SHermès Bélusca-Maïto             //
2120*23b7c7b8SHermès Bélusca-Maïto             //  Note that the order of evaluation here is important since we cannot
2121*23b7c7b8SHermès Bélusca-Maïto             //  check the first character of the dirent until after we know we
2122*23b7c7b8SHermès Bélusca-Maïto             //  are not beyond EOF
2123*23b7c7b8SHermès Bélusca-Maïto             //
2124*23b7c7b8SHermès Bélusca-Maïto 
2125*23b7c7b8SHermès Bélusca-Maïto             if ((Status == STATUS_END_OF_FILE) ||
2126*23b7c7b8SHermès Bélusca-Maïto                 (Dirent->FileName[0] == FAT_DIRENT_NEVER_USED)) {
2127*23b7c7b8SHermès Bélusca-Maïto 
2128*23b7c7b8SHermès Bélusca-Maïto                 DebugTrace( 0, Dbg, "Empty.  Last exempt entry at VBO = %08lx\n", ByteOffset);
2129*23b7c7b8SHermès Bélusca-Maïto 
2130*23b7c7b8SHermès Bélusca-Maïto                 IsDirectoryEmpty = TRUE;
2131*23b7c7b8SHermès Bélusca-Maïto                 break;
2132*23b7c7b8SHermès Bélusca-Maïto             }
2133*23b7c7b8SHermès Bélusca-Maïto 
2134*23b7c7b8SHermès Bélusca-Maïto             //
2135*23b7c7b8SHermès Bélusca-Maïto             //  If this dirent is NOT deleted or an LFN set IsDirectoryEmpty to
2136*23b7c7b8SHermès Bélusca-Maïto             //  FALSE and, like, bail.
2137*23b7c7b8SHermès Bélusca-Maïto             //
2138*23b7c7b8SHermès Bélusca-Maïto 
2139*23b7c7b8SHermès Bélusca-Maïto             if ((Dirent->FileName[0] != FAT_DIRENT_DELETED) &&
2140*23b7c7b8SHermès Bélusca-Maïto                 (Dirent->Attributes != FAT_DIRENT_ATTR_LFN)) {
2141*23b7c7b8SHermès Bélusca-Maïto 
2142*23b7c7b8SHermès Bélusca-Maïto 
2143*23b7c7b8SHermès Bélusca-Maïto                     break;
2144*23b7c7b8SHermès Bélusca-Maïto 
2145*23b7c7b8SHermès Bélusca-Maïto 
2146*23b7c7b8SHermès Bélusca-Maïto             }
2147*23b7c7b8SHermès Bélusca-Maïto 
2148*23b7c7b8SHermès Bélusca-Maïto             //
2149*23b7c7b8SHermès Bélusca-Maïto             //  Move on to the next dirent.
2150*23b7c7b8SHermès Bélusca-Maïto             //
2151*23b7c7b8SHermès Bélusca-Maïto 
2152*23b7c7b8SHermès Bélusca-Maïto             ByteOffset += sizeof(DIRENT);
2153*23b7c7b8SHermès Bélusca-Maïto             Dirent += 1;
2154*23b7c7b8SHermès Bélusca-Maïto         }
2155*23b7c7b8SHermès Bélusca-Maïto 
2156*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
2157*23b7c7b8SHermès Bélusca-Maïto 
2158*23b7c7b8SHermès Bélusca-Maïto         FatUnpinBcb( IrpContext, Bcb );
2159*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
2160*23b7c7b8SHermès Bélusca-Maïto 
2161*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatIsDirectoryEmpty -> %ld\n", IsDirectoryEmpty);
2162*23b7c7b8SHermès Bélusca-Maïto 
2163*23b7c7b8SHermès Bélusca-Maïto     return IsDirectoryEmpty;
2164*23b7c7b8SHermès Bélusca-Maïto }
2165*23b7c7b8SHermès Bélusca-Maïto 
2166*23b7c7b8SHermès Bélusca-Maïto 
2167*23b7c7b8SHermès Bélusca-Maïto 
2168*23b7c7b8SHermès Bélusca-Maïto 
2169*23b7c7b8SHermès Bélusca-Maïto 
2170*23b7c7b8SHermès Bélusca-Maïto VOID
FatConstructDirent(IN PIRP_CONTEXT IrpContext,IN OUT PDIRENT Dirent,IN POEM_STRING FileName,IN BOOLEAN ComponentReallyLowercase,IN BOOLEAN ExtensionReallyLowercase,IN PUNICODE_STRING Lfn OPTIONAL,IN USHORT Attributes,IN BOOLEAN ZeroAndSetTimeFields,IN PLARGE_INTEGER SetCreationTime OPTIONAL)2171*23b7c7b8SHermès Bélusca-Maïto FatConstructDirent (
2172*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
2173*23b7c7b8SHermès Bélusca-Maïto     IN OUT PDIRENT Dirent,
2174*23b7c7b8SHermès Bélusca-Maïto     IN POEM_STRING FileName,
2175*23b7c7b8SHermès Bélusca-Maïto     IN BOOLEAN ComponentReallyLowercase,
2176*23b7c7b8SHermès Bélusca-Maïto     IN BOOLEAN ExtensionReallyLowercase,
2177*23b7c7b8SHermès Bélusca-Maïto     IN PUNICODE_STRING Lfn OPTIONAL,
2178*23b7c7b8SHermès Bélusca-Maïto     IN USHORT Attributes,
2179*23b7c7b8SHermès Bélusca-Maïto     IN BOOLEAN ZeroAndSetTimeFields,
2180*23b7c7b8SHermès Bélusca-Maïto     IN PLARGE_INTEGER SetCreationTime OPTIONAL
2181*23b7c7b8SHermès Bélusca-Maïto     )
2182*23b7c7b8SHermès Bélusca-Maïto 
2183*23b7c7b8SHermès Bélusca-Maïto /*++
2184*23b7c7b8SHermès Bélusca-Maïto 
2185*23b7c7b8SHermès Bélusca-Maïto Routine Description:
2186*23b7c7b8SHermès Bélusca-Maïto 
2187*23b7c7b8SHermès Bélusca-Maïto     This routine modifies the fields of a dirent.
2188*23b7c7b8SHermès Bélusca-Maïto 
2189*23b7c7b8SHermès Bélusca-Maïto Arguments:
2190*23b7c7b8SHermès Bélusca-Maïto 
2191*23b7c7b8SHermès Bélusca-Maïto     Dirent - Supplies the dirent being modified.
2192*23b7c7b8SHermès Bélusca-Maïto 
2193*23b7c7b8SHermès Bélusca-Maïto     FileName - Supplies the name to store in the Dirent.  This
2194*23b7c7b8SHermès Bélusca-Maïto         name must not contain wildcards.
2195*23b7c7b8SHermès Bélusca-Maïto 
2196*23b7c7b8SHermès Bélusca-Maïto     ComponentReallyLowercase - This boolean indicates that the User Specified
2197*23b7c7b8SHermès Bélusca-Maïto         compoent name was really all a-z and < 0x80 characters.  We set the
2198*23b7c7b8SHermès Bélusca-Maïto         magic bit in this case.
2199*23b7c7b8SHermès Bélusca-Maïto 
2200*23b7c7b8SHermès Bélusca-Maïto     ExtensionReallyLowercase - Same as above, but for the extension.
2201*23b7c7b8SHermès Bélusca-Maïto 
2202*23b7c7b8SHermès Bélusca-Maïto     Lfn - May supply a long file name.
2203*23b7c7b8SHermès Bélusca-Maïto 
2204*23b7c7b8SHermès Bélusca-Maïto     Attributes - Supplies the attributes to store in the dirent
2205*23b7c7b8SHermès Bélusca-Maïto 
2206*23b7c7b8SHermès Bélusca-Maïto     ZeroAndSetTimeFields - Tells whether or not to initially zero the dirent
2207*23b7c7b8SHermès Bélusca-Maïto         and update the time fields.
2208*23b7c7b8SHermès Bélusca-Maïto 
2209*23b7c7b8SHermès Bélusca-Maïto     SetCreationTime - If specified, contains a timestamp to use as the creation
2210*23b7c7b8SHermès Bélusca-Maïto         time of this dirent
2211*23b7c7b8SHermès Bélusca-Maïto 
2212*23b7c7b8SHermès Bélusca-Maïto Return Value:
2213*23b7c7b8SHermès Bélusca-Maïto 
2214*23b7c7b8SHermès Bélusca-Maïto     None.
2215*23b7c7b8SHermès Bélusca-Maïto 
2216*23b7c7b8SHermès Bélusca-Maïto --*/
2217*23b7c7b8SHermès Bélusca-Maïto 
2218*23b7c7b8SHermès Bélusca-Maïto {
2219*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
2220*23b7c7b8SHermès Bélusca-Maïto 
2221*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatConstructDirent\n", 0);
2222*23b7c7b8SHermès Bélusca-Maïto 
2223*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  Dirent             = %p\n", Dirent);
2224*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  FileName           = %Z\n", FileName);
2225*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  Attributes         = %08lx\n", Attributes);
2226*23b7c7b8SHermès Bélusca-Maïto 
2227*23b7c7b8SHermès Bélusca-Maïto     if (ZeroAndSetTimeFields) {
2228*23b7c7b8SHermès Bélusca-Maïto 
2229*23b7c7b8SHermès Bélusca-Maïto         RtlZeroMemory( Dirent, sizeof(DIRENT) );
2230*23b7c7b8SHermès Bélusca-Maïto     }
2231*23b7c7b8SHermès Bélusca-Maïto 
2232*23b7c7b8SHermès Bélusca-Maïto     //
2233*23b7c7b8SHermès Bélusca-Maïto     //  We just merrily go and fill up the dirent with the fields given.
2234*23b7c7b8SHermès Bélusca-Maïto     //
2235*23b7c7b8SHermès Bélusca-Maïto 
2236*23b7c7b8SHermès Bélusca-Maïto     FatStringTo8dot3( IrpContext, *FileName, (PFAT8DOT3)&Dirent->FileName[0] );
2237*23b7c7b8SHermès Bélusca-Maïto 
2238*23b7c7b8SHermès Bélusca-Maïto     if (ZeroAndSetTimeFields || SetCreationTime) {
2239*23b7c7b8SHermès Bélusca-Maïto 
2240*23b7c7b8SHermès Bélusca-Maïto         LARGE_INTEGER Time, SaveTime;
2241*23b7c7b8SHermès Bélusca-Maïto 
2242*23b7c7b8SHermès Bélusca-Maïto         KeQuerySystemTime( &Time );
2243*23b7c7b8SHermès Bélusca-Maïto 
2244*23b7c7b8SHermès Bélusca-Maïto         if (FatData.ChicagoMode) {
2245*23b7c7b8SHermès Bélusca-Maïto 
2246*23b7c7b8SHermès Bélusca-Maïto             if (!SetCreationTime || !FatNtTimeToFatTime( IrpContext,
2247*23b7c7b8SHermès Bélusca-Maïto                                                          SetCreationTime,
2248*23b7c7b8SHermès Bélusca-Maïto                                                          FALSE,
2249*23b7c7b8SHermès Bélusca-Maïto                                                          &Dirent->CreationTime,
2250*23b7c7b8SHermès Bélusca-Maïto                                                          &Dirent->CreationMSec )) {
2251*23b7c7b8SHermès Bélusca-Maïto 
2252*23b7c7b8SHermès Bélusca-Maïto                 //
2253*23b7c7b8SHermès Bélusca-Maïto                 //  No tunneled time or the tunneled time was bogus. Since we aren't
2254*23b7c7b8SHermès Bélusca-Maïto                 //  responsible for initializing the to-be-created Fcb with creation
2255*23b7c7b8SHermès Bélusca-Maïto                 //  time, we can't do the usual thing and let NtTimeToFatTime perform
2256*23b7c7b8SHermès Bélusca-Maïto                 //  rounding on the timestamp - this would mess up converting to the
2257*23b7c7b8SHermès Bélusca-Maïto                 //  LastWriteTime below.
2258*23b7c7b8SHermès Bélusca-Maïto                 //
2259*23b7c7b8SHermès Bélusca-Maïto 
2260*23b7c7b8SHermès Bélusca-Maïto                 SaveTime = Time;
2261*23b7c7b8SHermès Bélusca-Maïto 
2262*23b7c7b8SHermès Bélusca-Maïto                 if (!FatNtTimeToFatTime( IrpContext,
2263*23b7c7b8SHermès Bélusca-Maïto                                          &SaveTime,
2264*23b7c7b8SHermès Bélusca-Maïto                                          FALSE,
2265*23b7c7b8SHermès Bélusca-Maïto                                          &Dirent->CreationTime,
2266*23b7c7b8SHermès Bélusca-Maïto                                          &Dirent->CreationMSec )) {
2267*23b7c7b8SHermès Bélusca-Maïto 
2268*23b7c7b8SHermès Bélusca-Maïto                     //
2269*23b7c7b8SHermès Bélusca-Maïto                     //  Failed again. Wow.
2270*23b7c7b8SHermès Bélusca-Maïto                     //
2271*23b7c7b8SHermès Bélusca-Maïto 
2272*23b7c7b8SHermès Bélusca-Maïto                     RtlZeroMemory( &Dirent->CreationTime, sizeof(FAT_TIME_STAMP));
2273*23b7c7b8SHermès Bélusca-Maïto                     Dirent->CreationMSec = 0;
2274*23b7c7b8SHermès Bélusca-Maïto                 }
2275*23b7c7b8SHermès Bélusca-Maïto             }
2276*23b7c7b8SHermès Bélusca-Maïto         }
2277*23b7c7b8SHermès Bélusca-Maïto 
2278*23b7c7b8SHermès Bélusca-Maïto         if (ZeroAndSetTimeFields) {
2279*23b7c7b8SHermès Bélusca-Maïto 
2280*23b7c7b8SHermès Bélusca-Maïto             //
2281*23b7c7b8SHermès Bélusca-Maïto             //  We only touch the other timestamps if we are initializing the dirent
2282*23b7c7b8SHermès Bélusca-Maïto             //
2283*23b7c7b8SHermès Bélusca-Maïto 
2284*23b7c7b8SHermès Bélusca-Maïto             if (!FatNtTimeToFatTime( IrpContext,
2285*23b7c7b8SHermès Bélusca-Maïto                                      &Time,
2286*23b7c7b8SHermès Bélusca-Maïto                                      TRUE,
2287*23b7c7b8SHermès Bélusca-Maïto                                      &Dirent->LastWriteTime,
2288*23b7c7b8SHermès Bélusca-Maïto                                      NULL )) {
2289*23b7c7b8SHermès Bélusca-Maïto 
2290*23b7c7b8SHermès Bélusca-Maïto                 DebugTrace( 0, Dbg, "Current time invalid.\n", 0);
2291*23b7c7b8SHermès Bélusca-Maïto 
2292*23b7c7b8SHermès Bélusca-Maïto                 RtlZeroMemory( &Dirent->LastWriteTime, sizeof(FAT_TIME_STAMP) );
2293*23b7c7b8SHermès Bélusca-Maïto             }
2294*23b7c7b8SHermès Bélusca-Maïto 
2295*23b7c7b8SHermès Bélusca-Maïto             if (FatData.ChicagoMode) {
2296*23b7c7b8SHermès Bélusca-Maïto 
2297*23b7c7b8SHermès Bélusca-Maïto                 Dirent->LastAccessDate = Dirent->LastWriteTime.Date;
2298*23b7c7b8SHermès Bélusca-Maïto             }
2299*23b7c7b8SHermès Bélusca-Maïto         }
2300*23b7c7b8SHermès Bélusca-Maïto     }
2301*23b7c7b8SHermès Bélusca-Maïto 
2302*23b7c7b8SHermès Bélusca-Maïto     //
2303*23b7c7b8SHermès Bélusca-Maïto     //  Copy the attributes
2304*23b7c7b8SHermès Bélusca-Maïto     //
2305*23b7c7b8SHermès Bélusca-Maïto 
2306*23b7c7b8SHermès Bélusca-Maïto     Dirent->Attributes = (UCHAR)Attributes;
2307*23b7c7b8SHermès Bélusca-Maïto 
2308*23b7c7b8SHermès Bélusca-Maïto     //
2309*23b7c7b8SHermès Bélusca-Maïto     //  Set the magic bit here, to tell dirctrl.c that this name is really
2310*23b7c7b8SHermès Bélusca-Maïto     //  lowercase.
2311*23b7c7b8SHermès Bélusca-Maïto     //
2312*23b7c7b8SHermès Bélusca-Maïto 
2313*23b7c7b8SHermès Bélusca-Maïto     Dirent->NtByte = 0;
2314*23b7c7b8SHermès Bélusca-Maïto 
2315*23b7c7b8SHermès Bélusca-Maïto     if (ComponentReallyLowercase) {
2316*23b7c7b8SHermès Bélusca-Maïto 
2317*23b7c7b8SHermès Bélusca-Maïto         SetFlag( Dirent->NtByte, FAT_DIRENT_NT_BYTE_8_LOWER_CASE );
2318*23b7c7b8SHermès Bélusca-Maïto     }
2319*23b7c7b8SHermès Bélusca-Maïto 
2320*23b7c7b8SHermès Bélusca-Maïto     if (ExtensionReallyLowercase) {
2321*23b7c7b8SHermès Bélusca-Maïto 
2322*23b7c7b8SHermès Bélusca-Maïto         SetFlag( Dirent->NtByte, FAT_DIRENT_NT_BYTE_3_LOWER_CASE );
2323*23b7c7b8SHermès Bélusca-Maïto     }
2324*23b7c7b8SHermès Bélusca-Maïto 
2325*23b7c7b8SHermès Bélusca-Maïto     //
2326*23b7c7b8SHermès Bélusca-Maïto     //  See if we have to create an Lfn entry
2327*23b7c7b8SHermès Bélusca-Maïto     //
2328*23b7c7b8SHermès Bélusca-Maïto 
2329*23b7c7b8SHermès Bélusca-Maïto     if (ARGUMENT_PRESENT(Lfn)) {
2330*23b7c7b8SHermès Bélusca-Maïto 
2331*23b7c7b8SHermès Bélusca-Maïto         UCHAR DirentChecksum;
2332*23b7c7b8SHermès Bélusca-Maïto         UCHAR DirentsInLfn;
2333*23b7c7b8SHermès Bélusca-Maïto         UCHAR LfnOrdinal;
2334*23b7c7b8SHermès Bélusca-Maïto         PWCHAR LfnBuffer;
2335*23b7c7b8SHermès Bélusca-Maïto         PLFN_DIRENT LfnDirent;
2336*23b7c7b8SHermès Bélusca-Maïto 
2337*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( FatData.ChicagoMode );
2338*23b7c7b8SHermès Bélusca-Maïto 
2339*23b7c7b8SHermès Bélusca-Maïto         DirentChecksum = FatComputeLfnChecksum( Dirent );
2340*23b7c7b8SHermès Bélusca-Maïto 
2341*23b7c7b8SHermès Bélusca-Maïto         LfnOrdinal =
2342*23b7c7b8SHermès Bélusca-Maïto         DirentsInLfn = (UCHAR)FAT_LFN_DIRENTS_NEEDED(Lfn);
2343*23b7c7b8SHermès Bélusca-Maïto 
2344*23b7c7b8SHermès Bélusca-Maïto         LfnBuffer = &Lfn->Buffer[(DirentsInLfn - 1) * 13];
2345*23b7c7b8SHermès Bélusca-Maïto 
2346*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( DirentsInLfn <= MAX_LFN_DIRENTS );
2347*23b7c7b8SHermès Bélusca-Maïto 
2348*23b7c7b8SHermès Bélusca-Maïto         for (LfnDirent = (PLFN_DIRENT)Dirent - DirentsInLfn;
2349*23b7c7b8SHermès Bélusca-Maïto              LfnDirent < (PLFN_DIRENT)Dirent;
2350*23b7c7b8SHermès Bélusca-Maïto              LfnDirent += 1, LfnOrdinal -= 1, LfnBuffer -= 13) {
2351*23b7c7b8SHermès Bélusca-Maïto 
2352*23b7c7b8SHermès Bélusca-Maïto             WCHAR FinalLfnBuffer[13];
2353*23b7c7b8SHermès Bélusca-Maïto             PWCHAR Buffer;
2354*23b7c7b8SHermès Bélusca-Maïto 
2355*23b7c7b8SHermès Bélusca-Maïto             //
2356*23b7c7b8SHermès Bélusca-Maïto             //  We need to special case the "final" dirent.
2357*23b7c7b8SHermès Bélusca-Maïto             //
2358*23b7c7b8SHermès Bélusca-Maïto 
2359*23b7c7b8SHermès Bélusca-Maïto             if (LfnOrdinal == DirentsInLfn) {
2360*23b7c7b8SHermès Bélusca-Maïto 
2361*23b7c7b8SHermès Bélusca-Maïto                 ULONG i;
2362*23b7c7b8SHermès Bélusca-Maïto                 ULONG RemainderChars;
2363*23b7c7b8SHermès Bélusca-Maïto 
2364*23b7c7b8SHermès Bélusca-Maïto                 RemainderChars = (Lfn->Length / sizeof(WCHAR)) % 13;
2365*23b7c7b8SHermès Bélusca-Maïto 
2366*23b7c7b8SHermès Bélusca-Maïto                 LfnDirent->Ordinal = LfnOrdinal | FAT_LAST_LONG_ENTRY;
2367*23b7c7b8SHermès Bélusca-Maïto 
2368*23b7c7b8SHermès Bélusca-Maïto                 if (RemainderChars != 0) {
2369*23b7c7b8SHermès Bélusca-Maïto 
2370*23b7c7b8SHermès Bélusca-Maïto                     RtlCopyMemory( FinalLfnBuffer,
2371*23b7c7b8SHermès Bélusca-Maïto                                    LfnBuffer,
2372*23b7c7b8SHermès Bélusca-Maïto                                    RemainderChars * sizeof(WCHAR) );
2373*23b7c7b8SHermès Bélusca-Maïto 
2374*23b7c7b8SHermès Bélusca-Maïto                     for (i = RemainderChars; i < 13; i++) {
2375*23b7c7b8SHermès Bélusca-Maïto 
2376*23b7c7b8SHermès Bélusca-Maïto                         //
2377*23b7c7b8SHermès Bélusca-Maïto                         //  Figure out which character to use.
2378*23b7c7b8SHermès Bélusca-Maïto                         //
2379*23b7c7b8SHermès Bélusca-Maïto 
2380*23b7c7b8SHermès Bélusca-Maïto                         if (i == RemainderChars) {
2381*23b7c7b8SHermès Bélusca-Maïto 
2382*23b7c7b8SHermès Bélusca-Maïto                             FinalLfnBuffer[i] = 0x0000;
2383*23b7c7b8SHermès Bélusca-Maïto 
2384*23b7c7b8SHermès Bélusca-Maïto                         } else {
2385*23b7c7b8SHermès Bélusca-Maïto 
2386*23b7c7b8SHermès Bélusca-Maïto                             FinalLfnBuffer[i] = 0xffff;
2387*23b7c7b8SHermès Bélusca-Maïto                         }
2388*23b7c7b8SHermès Bélusca-Maïto                     }
2389*23b7c7b8SHermès Bélusca-Maïto 
2390*23b7c7b8SHermès Bélusca-Maïto                     Buffer = FinalLfnBuffer;
2391*23b7c7b8SHermès Bélusca-Maïto 
2392*23b7c7b8SHermès Bélusca-Maïto                 } else {
2393*23b7c7b8SHermès Bélusca-Maïto 
2394*23b7c7b8SHermès Bélusca-Maïto                     Buffer = LfnBuffer;
2395*23b7c7b8SHermès Bélusca-Maïto                 }
2396*23b7c7b8SHermès Bélusca-Maïto 
2397*23b7c7b8SHermès Bélusca-Maïto             } else {
2398*23b7c7b8SHermès Bélusca-Maïto 
2399*23b7c7b8SHermès Bélusca-Maïto                 LfnDirent->Ordinal = LfnOrdinal;
2400*23b7c7b8SHermès Bélusca-Maïto 
2401*23b7c7b8SHermès Bélusca-Maïto                 Buffer = LfnBuffer;
2402*23b7c7b8SHermès Bélusca-Maïto             }
2403*23b7c7b8SHermès Bélusca-Maïto 
2404*23b7c7b8SHermès Bélusca-Maïto             //
2405*23b7c7b8SHermès Bélusca-Maïto             //  Now fill in the name.
2406*23b7c7b8SHermès Bélusca-Maïto             //
2407*23b7c7b8SHermès Bélusca-Maïto 
2408*23b7c7b8SHermès Bélusca-Maïto             RtlCopyMemory( &LfnDirent->Name1[0],
2409*23b7c7b8SHermès Bélusca-Maïto                            &Buffer[0],
2410*23b7c7b8SHermès Bélusca-Maïto                            5 * sizeof(WCHAR) );
2411*23b7c7b8SHermès Bélusca-Maïto 
2412*23b7c7b8SHermès Bélusca-Maïto             RtlCopyMemory( &LfnDirent->Name2[0],
2413*23b7c7b8SHermès Bélusca-Maïto                            &Buffer[5],
2414*23b7c7b8SHermès Bélusca-Maïto                            6 * sizeof(WCHAR) );
2415*23b7c7b8SHermès Bélusca-Maïto 
2416*23b7c7b8SHermès Bélusca-Maïto             RtlCopyMemory( &LfnDirent->Name3[0],
2417*23b7c7b8SHermès Bélusca-Maïto                            &Buffer[11],
2418*23b7c7b8SHermès Bélusca-Maïto                            2 * sizeof(WCHAR) );
2419*23b7c7b8SHermès Bélusca-Maïto 
2420*23b7c7b8SHermès Bélusca-Maïto             //
2421*23b7c7b8SHermès Bélusca-Maïto             //  And the other fields
2422*23b7c7b8SHermès Bélusca-Maïto             //
2423*23b7c7b8SHermès Bélusca-Maïto 
2424*23b7c7b8SHermès Bélusca-Maïto             LfnDirent->Attributes = FAT_DIRENT_ATTR_LFN;
2425*23b7c7b8SHermès Bélusca-Maïto 
2426*23b7c7b8SHermès Bélusca-Maïto             LfnDirent->Type = 0;
2427*23b7c7b8SHermès Bélusca-Maïto 
2428*23b7c7b8SHermès Bélusca-Maïto             LfnDirent->Checksum = DirentChecksum;
2429*23b7c7b8SHermès Bélusca-Maïto 
2430*23b7c7b8SHermès Bélusca-Maïto             LfnDirent->MustBeZero = 0;
2431*23b7c7b8SHermès Bélusca-Maïto         }
2432*23b7c7b8SHermès Bélusca-Maïto     }
2433*23b7c7b8SHermès Bélusca-Maïto 
2434*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatConstructDirent -> (VOID)\n", 0);
2435*23b7c7b8SHermès Bélusca-Maïto     return;
2436*23b7c7b8SHermès Bélusca-Maïto }
2437*23b7c7b8SHermès Bélusca-Maïto 
2438*23b7c7b8SHermès Bélusca-Maïto 
2439*23b7c7b8SHermès Bélusca-Maïto VOID
FatConstructLabelDirent(IN PIRP_CONTEXT IrpContext,IN OUT PDIRENT Dirent,IN POEM_STRING Label)2440*23b7c7b8SHermès Bélusca-Maïto FatConstructLabelDirent (
2441*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
2442*23b7c7b8SHermès Bélusca-Maïto     IN OUT PDIRENT Dirent,
2443*23b7c7b8SHermès Bélusca-Maïto     IN POEM_STRING Label
2444*23b7c7b8SHermès Bélusca-Maïto     )
2445*23b7c7b8SHermès Bélusca-Maïto 
2446*23b7c7b8SHermès Bélusca-Maïto /*++
2447*23b7c7b8SHermès Bélusca-Maïto 
2448*23b7c7b8SHermès Bélusca-Maïto Routine Description:
2449*23b7c7b8SHermès Bélusca-Maïto 
2450*23b7c7b8SHermès Bélusca-Maïto     This routine modifies the fields of a dirent to be used for a label.
2451*23b7c7b8SHermès Bélusca-Maïto 
2452*23b7c7b8SHermès Bélusca-Maïto Arguments:
2453*23b7c7b8SHermès Bélusca-Maïto 
2454*23b7c7b8SHermès Bélusca-Maïto     Dirent - Supplies the dirent being modified.
2455*23b7c7b8SHermès Bélusca-Maïto 
2456*23b7c7b8SHermès Bélusca-Maïto     Label - Supplies the name to store in the Dirent.  This
2457*23b7c7b8SHermès Bélusca-Maïto             name must not contain wildcards.
2458*23b7c7b8SHermès Bélusca-Maïto 
2459*23b7c7b8SHermès Bélusca-Maïto Return Value:
2460*23b7c7b8SHermès Bélusca-Maïto 
2461*23b7c7b8SHermès Bélusca-Maïto     None.
2462*23b7c7b8SHermès Bélusca-Maïto 
2463*23b7c7b8SHermès Bélusca-Maïto --*/
2464*23b7c7b8SHermès Bélusca-Maïto 
2465*23b7c7b8SHermès Bélusca-Maïto {
2466*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
2467*23b7c7b8SHermès Bélusca-Maïto 
2468*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatConstructLabelDirent\n", 0);
2469*23b7c7b8SHermès Bélusca-Maïto 
2470*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  Dirent             = %p\n", Dirent);
2471*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "  Label              = %Z\n", Label);
2472*23b7c7b8SHermès Bélusca-Maïto 
2473*23b7c7b8SHermès Bélusca-Maïto     RtlZeroMemory( Dirent, sizeof(DIRENT) );
2474*23b7c7b8SHermès Bélusca-Maïto 
2475*23b7c7b8SHermès Bélusca-Maïto     //
2476*23b7c7b8SHermès Bélusca-Maïto     //  We just merrily go and fill up the dirent with the fields given.
2477*23b7c7b8SHermès Bélusca-Maïto     //
2478*23b7c7b8SHermès Bélusca-Maïto 
2479*23b7c7b8SHermès Bélusca-Maïto     RtlCopyMemory( Dirent->FileName, Label->Buffer, Label->Length );
2480*23b7c7b8SHermès Bélusca-Maïto 
2481*23b7c7b8SHermès Bélusca-Maïto     //
2482*23b7c7b8SHermès Bélusca-Maïto     // Pad the label with spaces, not nulls.
2483*23b7c7b8SHermès Bélusca-Maïto     //
2484*23b7c7b8SHermès Bélusca-Maïto 
2485*23b7c7b8SHermès Bélusca-Maïto     RtlFillMemory( &Dirent->FileName[Label->Length], 11 - Label->Length, ' ');
2486*23b7c7b8SHermès Bélusca-Maïto 
2487*23b7c7b8SHermès Bélusca-Maïto     Dirent->LastWriteTime = FatGetCurrentFatTime( IrpContext );
2488*23b7c7b8SHermès Bélusca-Maïto 
2489*23b7c7b8SHermès Bélusca-Maïto     Dirent->Attributes = FAT_DIRENT_ATTR_VOLUME_ID;
2490*23b7c7b8SHermès Bélusca-Maïto     Dirent->ExtendedAttributes = 0;
2491*23b7c7b8SHermès Bélusca-Maïto     Dirent->FileSize = 0;
2492*23b7c7b8SHermès Bélusca-Maïto 
2493*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatConstructLabelDirent -> (VOID)\n", 0);
2494*23b7c7b8SHermès Bélusca-Maïto     return;
2495*23b7c7b8SHermès Bélusca-Maïto }
2496*23b7c7b8SHermès Bélusca-Maïto 
2497*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)2498*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
2499*23b7c7b8SHermès Bélusca-Maïto VOID
2500*23b7c7b8SHermès Bélusca-Maïto FatSetFileSizeInDirent (
2501*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
2502*23b7c7b8SHermès Bélusca-Maïto     IN PFCB Fcb,
2503*23b7c7b8SHermès Bélusca-Maïto     IN PULONG AlternativeFileSize OPTIONAL
2504*23b7c7b8SHermès Bélusca-Maïto     )
2505*23b7c7b8SHermès Bélusca-Maïto 
2506*23b7c7b8SHermès Bélusca-Maïto /*++
2507*23b7c7b8SHermès Bélusca-Maïto 
2508*23b7c7b8SHermès Bélusca-Maïto Routine Description:
2509*23b7c7b8SHermès Bélusca-Maïto 
2510*23b7c7b8SHermès Bélusca-Maïto     This routine saves the file size in an fcb into its dirent.
2511*23b7c7b8SHermès Bélusca-Maïto 
2512*23b7c7b8SHermès Bélusca-Maïto Arguments:
2513*23b7c7b8SHermès Bélusca-Maïto 
2514*23b7c7b8SHermès Bélusca-Maïto     Fcb - Supplies the Fcb being referenced
2515*23b7c7b8SHermès Bélusca-Maïto 
2516*23b7c7b8SHermès Bélusca-Maïto     AlternativeFileSize - If non-null we use the ULONG it points to as
2517*23b7c7b8SHermès Bélusca-Maïto         the new file size.  Otherwise we use the one in the Fcb.
2518*23b7c7b8SHermès Bélusca-Maïto 
2519*23b7c7b8SHermès Bélusca-Maïto Return Value:
2520*23b7c7b8SHermès Bélusca-Maïto 
2521*23b7c7b8SHermès Bélusca-Maïto     None.
2522*23b7c7b8SHermès Bélusca-Maïto 
2523*23b7c7b8SHermès Bélusca-Maïto --*/
2524*23b7c7b8SHermès Bélusca-Maïto 
2525*23b7c7b8SHermès Bélusca-Maïto {
2526*23b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent;
2527*23b7c7b8SHermès Bélusca-Maïto     PBCB DirentBcb;
2528*23b7c7b8SHermès Bélusca-Maïto 
2529*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
2530*23b7c7b8SHermès Bélusca-Maïto 
2531*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( Fcb->FcbCondition == FcbGood );
2532*23b7c7b8SHermès Bélusca-Maïto 
2533*23b7c7b8SHermès Bélusca-Maïto     FatGetDirentFromFcbOrDcb( IrpContext,
2534*23b7c7b8SHermès Bélusca-Maïto                               Fcb,
2535*23b7c7b8SHermès Bélusca-Maïto                               FALSE,
2536*23b7c7b8SHermès Bélusca-Maïto                               &Dirent,
2537*23b7c7b8SHermès Bélusca-Maïto                               &DirentBcb );
2538*23b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
2539*23b7c7b8SHermès Bélusca-Maïto 
2540*23b7c7b8SHermès Bélusca-Maïto         Dirent->FileSize = ARGUMENT_PRESENT( AlternativeFileSize ) ?
2541*23b7c7b8SHermès Bélusca-Maïto                            *AlternativeFileSize : Fcb->Header.FileSize.LowPart;
2542*23b7c7b8SHermès Bélusca-Maïto 
2543*23b7c7b8SHermès Bélusca-Maïto 
2544*23b7c7b8SHermès Bélusca-Maïto         FatSetDirtyBcb( IrpContext, DirentBcb, Fcb->Vcb, TRUE );
2545*23b7c7b8SHermès Bélusca-Maïto 
2546*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
2547*23b7c7b8SHermès Bélusca-Maïto 
2548*23b7c7b8SHermès Bélusca-Maïto         FatUnpinBcb( IrpContext, DirentBcb );
2549*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
2550*23b7c7b8SHermès Bélusca-Maïto }
2551*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)2552*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
2553*23b7c7b8SHermès Bélusca-Maïto VOID
2554*23b7c7b8SHermès Bélusca-Maïto FatSetFileSizeInDirentNoRaise (
2555*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
2556*23b7c7b8SHermès Bélusca-Maïto     IN PFCB Fcb,
2557*23b7c7b8SHermès Bélusca-Maïto     IN PULONG AlternativeFileSize OPTIONAL
2558*23b7c7b8SHermès Bélusca-Maïto     )
2559*23b7c7b8SHermès Bélusca-Maïto 
2560*23b7c7b8SHermès Bélusca-Maïto /*++
2561*23b7c7b8SHermès Bélusca-Maïto 
2562*23b7c7b8SHermès Bélusca-Maïto Routine Description:
2563*23b7c7b8SHermès Bélusca-Maïto 
2564*23b7c7b8SHermès Bélusca-Maïto     This routine saves the file size in an fcb into its dirent.
2565*23b7c7b8SHermès Bélusca-Maïto     All exceptions thrown from FatSetFileSizeInDirent are
2566*23b7c7b8SHermès Bélusca-Maïto     silently swallowed.
2567*23b7c7b8SHermès Bélusca-Maïto 
2568*23b7c7b8SHermès Bélusca-Maïto Arguments:
2569*23b7c7b8SHermès Bélusca-Maïto 
2570*23b7c7b8SHermès Bélusca-Maïto     Fcb - Supplies the Fcb being referenced
2571*23b7c7b8SHermès Bélusca-Maïto 
2572*23b7c7b8SHermès Bélusca-Maïto     AlternativeFileSize - If non-null we use the ULONG it points to as
2573*23b7c7b8SHermès Bélusca-Maïto         the new file size.  Otherwise we use the one in the Fcb.
2574*23b7c7b8SHermès Bélusca-Maïto 
2575*23b7c7b8SHermès Bélusca-Maïto Return Value:
2576*23b7c7b8SHermès Bélusca-Maïto 
2577*23b7c7b8SHermès Bélusca-Maïto     None.
2578*23b7c7b8SHermès Bélusca-Maïto 
2579*23b7c7b8SHermès Bélusca-Maïto --*/
2580*23b7c7b8SHermès Bélusca-Maïto 
2581*23b7c7b8SHermès Bélusca-Maïto {
2582*23b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
2583*23b7c7b8SHermès Bélusca-Maïto 
2584*23b7c7b8SHermès Bélusca-Maïto         FatSetFileSizeInDirent( IrpContext, Fcb, AlternativeFileSize );
2585*23b7c7b8SHermès Bélusca-Maïto 
2586*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_EXCEPT(FatExceptionFilter( IrpContext, _SEH2_GetExceptionInformation() )) {
2587*23b7c7b8SHermès Bélusca-Maïto 
2588*23b7c7b8SHermès Bélusca-Maïto         NOTHING;
2589*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
2590*23b7c7b8SHermès Bélusca-Maïto }
2591*23b7c7b8SHermès Bélusca-Maïto 
2592*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)2593*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
2594*23b7c7b8SHermès Bélusca-Maïto VOID
2595*23b7c7b8SHermès Bélusca-Maïto FatUpdateDirentFromFcb (
2596*23b7c7b8SHermès Bélusca-Maïto    IN PIRP_CONTEXT IrpContext,
2597*23b7c7b8SHermès Bélusca-Maïto    IN PFILE_OBJECT FileObject,
2598*23b7c7b8SHermès Bélusca-Maïto    IN PFCB FcbOrDcb,
2599*23b7c7b8SHermès Bélusca-Maïto    IN PCCB Ccb
2600*23b7c7b8SHermès Bélusca-Maïto    )
2601*23b7c7b8SHermès Bélusca-Maïto 
2602*23b7c7b8SHermès Bélusca-Maïto 
2603*23b7c7b8SHermès Bélusca-Maïto /*++
2604*23b7c7b8SHermès Bélusca-Maïto 
2605*23b7c7b8SHermès Bélusca-Maïto Routine Description:
2606*23b7c7b8SHermès Bélusca-Maïto 
2607*23b7c7b8SHermès Bélusca-Maïto     This routine modifies an objects directory entry based on the hints
2608*23b7c7b8SHermès Bélusca-Maïto     that have been built up over previous operations on a handle.  Notify
2609*23b7c7b8SHermès Bélusca-Maïto     change filters are built and fired as a result of these updates.
2610*23b7c7b8SHermès Bélusca-Maïto 
2611*23b7c7b8SHermès Bélusca-Maïto Arguments:
2612*23b7c7b8SHermès Bélusca-Maïto 
2613*23b7c7b8SHermès Bélusca-Maïto     FileObject - Fileobject representing the handle involved
2614*23b7c7b8SHermès Bélusca-Maïto 
2615*23b7c7b8SHermès Bélusca-Maïto     FcbOrDcb - File/Dir involved
2616*23b7c7b8SHermès Bélusca-Maïto 
2617*23b7c7b8SHermès Bélusca-Maïto     Ccb - User context involved
2618*23b7c7b8SHermès Bélusca-Maïto 
2619*23b7c7b8SHermès Bélusca-Maïto Return Value:
2620*23b7c7b8SHermès Bélusca-Maïto 
2621*23b7c7b8SHermès Bélusca-Maïto     None.
2622*23b7c7b8SHermès Bélusca-Maïto 
2623*23b7c7b8SHermès Bélusca-Maïto --*/
2624*23b7c7b8SHermès Bélusca-Maïto 
2625*23b7c7b8SHermès Bélusca-Maïto {
2626*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN SetArchiveBit;
2627*23b7c7b8SHermès Bélusca-Maïto 
2628*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN UpdateFileSize;
2629*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN UpdateLastWriteTime;
2630*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN UpdateLastAccessTime;
2631*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN UpdateDirent = FALSE;
2632*23b7c7b8SHermès Bélusca-Maïto 
2633*23b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent;
2634*23b7c7b8SHermès Bélusca-Maïto     PBCB DirentBcb = NULL;
2635*23b7c7b8SHermès Bélusca-Maïto     ULONG NotifyFilter = 0;
2636*23b7c7b8SHermès Bélusca-Maïto     FAT_TIME_STAMP CurrentFatTime = {0};
2637*23b7c7b8SHermès Bélusca-Maïto 
2638*23b7c7b8SHermès Bélusca-Maïto     LARGE_INTEGER CurrentTime;
2639*23b7c7b8SHermès Bélusca-Maïto     LARGE_INTEGER CurrentDay = {0};
2640*23b7c7b8SHermès Bélusca-Maïto     LARGE_INTEGER LastAccessDay;
2641*23b7c7b8SHermès Bélusca-Maïto 
2642*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
2643*23b7c7b8SHermès Bélusca-Maïto 
2644*23b7c7b8SHermès Bélusca-Maïto     //
2645*23b7c7b8SHermès Bélusca-Maïto     //  Nothing to do if the fcb is bad, volume is readonly or we got the
2646*23b7c7b8SHermès Bélusca-Maïto     //  root dir.
2647*23b7c7b8SHermès Bélusca-Maïto     //
2648*23b7c7b8SHermès Bélusca-Maïto 
2649*23b7c7b8SHermès Bélusca-Maïto     if (FcbOrDcb->FcbCondition != FcbGood ||
2650*23b7c7b8SHermès Bélusca-Maïto         NodeType(FcbOrDcb) == FAT_NTC_ROOT_DCB ||
2651*23b7c7b8SHermès Bélusca-Maïto         FlagOn(FcbOrDcb->Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
2652*23b7c7b8SHermès Bélusca-Maïto 
2653*23b7c7b8SHermès Bélusca-Maïto         return;
2654*23b7c7b8SHermès Bélusca-Maïto     }
2655*23b7c7b8SHermès Bélusca-Maïto 
2656*23b7c7b8SHermès Bélusca-Maïto     //
2657*23b7c7b8SHermès Bélusca-Maïto     //  Check if we should be changing the time or file size and set
2658*23b7c7b8SHermès Bélusca-Maïto     //  the archive bit on the file.
2659*23b7c7b8SHermès Bélusca-Maïto     //
2660*23b7c7b8SHermès Bélusca-Maïto 
2661*23b7c7b8SHermès Bélusca-Maïto     KeQuerySystemTime( &CurrentTime );
2662*23b7c7b8SHermès Bélusca-Maïto 
2663*23b7c7b8SHermès Bélusca-Maïto     //
2664*23b7c7b8SHermès Bélusca-Maïto     //  Note that we HAVE to use BooleanFlagOn() here because
2665*23b7c7b8SHermès Bélusca-Maïto     //  FO_FILE_SIZE_CHANGED > 0x80 (i.e., not in the first byte).
2666*23b7c7b8SHermès Bélusca-Maïto     //
2667*23b7c7b8SHermès Bélusca-Maïto 
2668*23b7c7b8SHermès Bélusca-Maïto     SetArchiveBit = BooleanFlagOn(FileObject->Flags, FO_FILE_MODIFIED);
2669*23b7c7b8SHermès Bélusca-Maïto 
2670*23b7c7b8SHermès Bélusca-Maïto     UpdateLastWriteTime = FlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
2671*23b7c7b8SHermès Bélusca-Maïto                           !FlagOn(Ccb->Flags, CCB_FLAG_USER_SET_LAST_WRITE);
2672*23b7c7b8SHermès Bélusca-Maïto 
2673*23b7c7b8SHermès Bélusca-Maïto     UpdateFileSize = NodeType(FcbOrDcb) == FAT_NTC_FCB &&
2674*23b7c7b8SHermès Bélusca-Maïto                      BooleanFlagOn(FileObject->Flags, FO_FILE_SIZE_CHANGED);
2675*23b7c7b8SHermès Bélusca-Maïto 
2676*23b7c7b8SHermès Bélusca-Maïto     //
2677*23b7c7b8SHermès Bélusca-Maïto     //  Do one further check here of access time.  Only update it if
2678*23b7c7b8SHermès Bélusca-Maïto     //  the current version is at least one day old.  We know that
2679*23b7c7b8SHermès Bélusca-Maïto     //  the current FcbOrDcb->LastAccessTime corresponds to 12 midnight local
2680*23b7c7b8SHermès Bélusca-Maïto     //  time, so just see if the current time is on the same day.
2681*23b7c7b8SHermès Bélusca-Maïto     //
2682*23b7c7b8SHermès Bélusca-Maïto 
2683*23b7c7b8SHermès Bélusca-Maïto     if (FatData.ChicagoMode &&
2684*23b7c7b8SHermès Bélusca-Maïto         (UpdateLastWriteTime ||
2685*23b7c7b8SHermès Bélusca-Maïto          FlagOn(FileObject->Flags, FO_FILE_FAST_IO_READ)) &&
2686*23b7c7b8SHermès Bélusca-Maïto         !FlagOn(Ccb->Flags, CCB_FLAG_USER_SET_LAST_ACCESS)) {
2687*23b7c7b8SHermès Bélusca-Maïto 
2688*23b7c7b8SHermès Bélusca-Maïto         ExSystemTimeToLocalTime( &FcbOrDcb->LastAccessTime, &LastAccessDay );
2689*23b7c7b8SHermès Bélusca-Maïto         ExSystemTimeToLocalTime( &CurrentTime, &CurrentDay );
2690*23b7c7b8SHermès Bélusca-Maïto 
2691*23b7c7b8SHermès Bélusca-Maïto         LastAccessDay.QuadPart /= FatOneDay.QuadPart;
2692*23b7c7b8SHermès Bélusca-Maïto         CurrentDay.QuadPart /= FatOneDay.QuadPart;
2693*23b7c7b8SHermès Bélusca-Maïto 
2694*23b7c7b8SHermès Bélusca-Maïto         if (LastAccessDay.LowPart != CurrentDay.LowPart) {
2695*23b7c7b8SHermès Bélusca-Maïto 
2696*23b7c7b8SHermès Bélusca-Maïto             UpdateLastAccessTime = TRUE;
2697*23b7c7b8SHermès Bélusca-Maïto 
2698*23b7c7b8SHermès Bélusca-Maïto         } else {
2699*23b7c7b8SHermès Bélusca-Maïto 
2700*23b7c7b8SHermès Bélusca-Maïto             UpdateLastAccessTime = FALSE;
2701*23b7c7b8SHermès Bélusca-Maïto         }
2702*23b7c7b8SHermès Bélusca-Maïto 
2703*23b7c7b8SHermès Bélusca-Maïto     } else {
2704*23b7c7b8SHermès Bélusca-Maïto 
2705*23b7c7b8SHermès Bélusca-Maïto         UpdateLastAccessTime = FALSE;
2706*23b7c7b8SHermès Bélusca-Maïto     }
2707*23b7c7b8SHermès Bélusca-Maïto 
2708*23b7c7b8SHermès Bélusca-Maïto     if (SetArchiveBit ||
2709*23b7c7b8SHermès Bélusca-Maïto         UpdateFileSize ||
2710*23b7c7b8SHermès Bélusca-Maïto         UpdateLastWriteTime ||
2711*23b7c7b8SHermès Bélusca-Maïto         UpdateLastAccessTime
2712*23b7c7b8SHermès Bélusca-Maïto         ) {
2713*23b7c7b8SHermès Bélusca-Maïto 
2714*23b7c7b8SHermès Bélusca-Maïto         DebugTrace(0, Dbg, "Update Time and/or file size on File/Dir\n", 0);
2715*23b7c7b8SHermès Bélusca-Maïto 
2716*23b7c7b8SHermès Bélusca-Maïto         _SEH2_TRY {
2717*23b7c7b8SHermès Bélusca-Maïto 
2718*23b7c7b8SHermès Bélusca-Maïto             _SEH2_TRY {
2719*23b7c7b8SHermès Bélusca-Maïto 
2720*23b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN8)
2721*23b7c7b8SHermès Bélusca-Maïto                 //
2722*23b7c7b8SHermès Bélusca-Maïto                 //  Break parent directory oplock.  Directory oplock breaks are
2723*23b7c7b8SHermès Bélusca-Maïto                 //  always advisory, so we will never block/get STATUS_PENDING here.
2724*23b7c7b8SHermès Bélusca-Maïto                 //
2725*23b7c7b8SHermès Bélusca-Maïto 
2726*23b7c7b8SHermès Bélusca-Maïto                 if (FcbOrDcb->ParentDcb != NULL) {
2727*23b7c7b8SHermès Bélusca-Maïto 
2728*23b7c7b8SHermès Bélusca-Maïto                     FsRtlCheckOplockEx( FatGetFcbOplock(FcbOrDcb->ParentDcb),
2729*23b7c7b8SHermès Bélusca-Maïto                                         IrpContext->OriginatingIrp,
2730*23b7c7b8SHermès Bélusca-Maïto                                         OPLOCK_FLAG_PARENT_OBJECT,
2731*23b7c7b8SHermès Bélusca-Maïto                                         NULL,
2732*23b7c7b8SHermès Bélusca-Maïto                                         NULL,
2733*23b7c7b8SHermès Bélusca-Maïto                                         NULL );
2734*23b7c7b8SHermès Bélusca-Maïto                 }
2735*23b7c7b8SHermès Bélusca-Maïto #endif
2736*23b7c7b8SHermès Bélusca-Maïto 
2737*23b7c7b8SHermès Bélusca-Maïto                 //
2738*23b7c7b8SHermès Bélusca-Maïto                 //  Get the dirent
2739*23b7c7b8SHermès Bélusca-Maïto                 //
2740*23b7c7b8SHermès Bélusca-Maïto 
2741*23b7c7b8SHermès Bélusca-Maïto                 FatGetDirentFromFcbOrDcb( IrpContext,
2742*23b7c7b8SHermès Bélusca-Maïto                                           FcbOrDcb,
2743*23b7c7b8SHermès Bélusca-Maïto                                           FALSE,
2744*23b7c7b8SHermès Bélusca-Maïto                                           &Dirent,
2745*23b7c7b8SHermès Bélusca-Maïto                                           &DirentBcb );
2746*23b7c7b8SHermès Bélusca-Maïto 
2747*23b7c7b8SHermès Bélusca-Maïto                 if (UpdateLastWriteTime || UpdateLastAccessTime) {
2748*23b7c7b8SHermès Bélusca-Maïto 
2749*23b7c7b8SHermès Bélusca-Maïto                     (VOID)FatNtTimeToFatTime( IrpContext,
2750*23b7c7b8SHermès Bélusca-Maïto                                               &CurrentTime,
2751*23b7c7b8SHermès Bélusca-Maïto                                               TRUE,
2752*23b7c7b8SHermès Bélusca-Maïto                                               &CurrentFatTime,
2753*23b7c7b8SHermès Bélusca-Maïto                                               NULL );
2754*23b7c7b8SHermès Bélusca-Maïto                 }
2755*23b7c7b8SHermès Bélusca-Maïto 
2756*23b7c7b8SHermès Bélusca-Maïto                 if (SetArchiveBit) {
2757*23b7c7b8SHermès Bélusca-Maïto 
2758*23b7c7b8SHermès Bélusca-Maïto                     Dirent->Attributes |= FILE_ATTRIBUTE_ARCHIVE;
2759*23b7c7b8SHermès Bélusca-Maïto                     FcbOrDcb->DirentFatFlags |= FILE_ATTRIBUTE_ARCHIVE;
2760*23b7c7b8SHermès Bélusca-Maïto 
2761*23b7c7b8SHermès Bélusca-Maïto                     NotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
2762*23b7c7b8SHermès Bélusca-Maïto                     UpdateDirent = TRUE;
2763*23b7c7b8SHermès Bélusca-Maïto                 }
2764*23b7c7b8SHermès Bélusca-Maïto 
2765*23b7c7b8SHermès Bélusca-Maïto                 if (UpdateLastWriteTime) {
2766*23b7c7b8SHermès Bélusca-Maïto 
2767*23b7c7b8SHermès Bélusca-Maïto                     //
2768*23b7c7b8SHermès Bélusca-Maïto                     //  Update its time of last write
2769*23b7c7b8SHermès Bélusca-Maïto                     //
2770*23b7c7b8SHermès Bélusca-Maïto 
2771*23b7c7b8SHermès Bélusca-Maïto                     FcbOrDcb->LastWriteTime = CurrentTime;
2772*23b7c7b8SHermès Bélusca-Maïto                     Dirent->LastWriteTime = CurrentFatTime;
2773*23b7c7b8SHermès Bélusca-Maïto 
2774*23b7c7b8SHermès Bélusca-Maïto                     //
2775*23b7c7b8SHermès Bélusca-Maïto                     //  We call the notify package to report that the
2776*23b7c7b8SHermès Bélusca-Maïto                     //  last modification time has changed.
2777*23b7c7b8SHermès Bélusca-Maïto                     //
2778*23b7c7b8SHermès Bélusca-Maïto 
2779*23b7c7b8SHermès Bélusca-Maïto                     NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
2780*23b7c7b8SHermès Bélusca-Maïto                     UpdateDirent = TRUE;
2781*23b7c7b8SHermès Bélusca-Maïto                 }
2782*23b7c7b8SHermès Bélusca-Maïto 
2783*23b7c7b8SHermès Bélusca-Maïto                 if (UpdateLastAccessTime) {
2784*23b7c7b8SHermès Bélusca-Maïto 
2785*23b7c7b8SHermès Bélusca-Maïto                     //
2786*23b7c7b8SHermès Bélusca-Maïto                     //  Now we have to truncate the local time down
2787*23b7c7b8SHermès Bélusca-Maïto                     //  to the current day, then convert back to UTC.
2788*23b7c7b8SHermès Bélusca-Maïto                     //
2789*23b7c7b8SHermès Bélusca-Maïto 
2790*23b7c7b8SHermès Bélusca-Maïto                     FcbOrDcb->LastAccessTime.QuadPart =
2791*23b7c7b8SHermès Bélusca-Maïto                         CurrentDay.QuadPart * FatOneDay.QuadPart;
2792*23b7c7b8SHermès Bélusca-Maïto 
2793*23b7c7b8SHermès Bélusca-Maïto                     ExLocalTimeToSystemTime( &FcbOrDcb->LastAccessTime,
2794*23b7c7b8SHermès Bélusca-Maïto                                              &FcbOrDcb->LastAccessTime );
2795*23b7c7b8SHermès Bélusca-Maïto 
2796*23b7c7b8SHermès Bélusca-Maïto                     Dirent->LastAccessDate = CurrentFatTime.Date;
2797*23b7c7b8SHermès Bélusca-Maïto 
2798*23b7c7b8SHermès Bélusca-Maïto                     //
2799*23b7c7b8SHermès Bélusca-Maïto                     //  We call the notify package to report that the
2800*23b7c7b8SHermès Bélusca-Maïto                     //  last access time has changed.
2801*23b7c7b8SHermès Bélusca-Maïto                     //
2802*23b7c7b8SHermès Bélusca-Maïto 
2803*23b7c7b8SHermès Bélusca-Maïto                     NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
2804*23b7c7b8SHermès Bélusca-Maïto                     UpdateDirent = TRUE;
2805*23b7c7b8SHermès Bélusca-Maïto                 }
2806*23b7c7b8SHermès Bélusca-Maïto 
2807*23b7c7b8SHermès Bélusca-Maïto                 if (UpdateFileSize) {
2808*23b7c7b8SHermès Bélusca-Maïto 
2809*23b7c7b8SHermès Bélusca-Maïto                     //
2810*23b7c7b8SHermès Bélusca-Maïto                     //  Perhaps we were called to make certain that the
2811*23b7c7b8SHermès Bélusca-Maïto                     //  filesize on disc was updated - don't bother updating
2812*23b7c7b8SHermès Bélusca-Maïto                     //  and firing the filter if nothing changed.
2813*23b7c7b8SHermès Bélusca-Maïto                     //
2814*23b7c7b8SHermès Bélusca-Maïto 
2815*23b7c7b8SHermès Bélusca-Maïto                     NT_ASSERT( NodeType(FcbOrDcb) == FAT_NTC_FCB );
2816*23b7c7b8SHermès Bélusca-Maïto 
2817*23b7c7b8SHermès Bélusca-Maïto                     if (Dirent->FileSize != FcbOrDcb->Header.FileSize.LowPart) {
2818*23b7c7b8SHermès Bélusca-Maïto 
2819*23b7c7b8SHermès Bélusca-Maïto                         //
2820*23b7c7b8SHermès Bélusca-Maïto                         //  Update the dirent file size
2821*23b7c7b8SHermès Bélusca-Maïto                         //
2822*23b7c7b8SHermès Bélusca-Maïto 
2823*23b7c7b8SHermès Bélusca-Maïto                         Dirent->FileSize = FcbOrDcb->Header.FileSize.LowPart;
2824*23b7c7b8SHermès Bélusca-Maïto 
2825*23b7c7b8SHermès Bélusca-Maïto                         //
2826*23b7c7b8SHermès Bélusca-Maïto                         //  We call the notify package to report that the
2827*23b7c7b8SHermès Bélusca-Maïto                         //  size has changed.
2828*23b7c7b8SHermès Bélusca-Maïto                         //
2829*23b7c7b8SHermès Bélusca-Maïto 
2830*23b7c7b8SHermès Bélusca-Maïto                         NotifyFilter |= FILE_NOTIFY_CHANGE_SIZE;
2831*23b7c7b8SHermès Bélusca-Maïto                         UpdateDirent = TRUE;
2832*23b7c7b8SHermès Bélusca-Maïto                     }
2833*23b7c7b8SHermès Bélusca-Maïto 
2834*23b7c7b8SHermès Bélusca-Maïto 
2835*23b7c7b8SHermès Bélusca-Maïto                 }
2836*23b7c7b8SHermès Bélusca-Maïto 
2837*23b7c7b8SHermès Bélusca-Maïto 
2838*23b7c7b8SHermès Bélusca-Maïto                 FatNotifyReportChange( IrpContext,
2839*23b7c7b8SHermès Bélusca-Maïto                                        FcbOrDcb->Vcb,
2840*23b7c7b8SHermès Bélusca-Maïto                                        FcbOrDcb,
2841*23b7c7b8SHermès Bélusca-Maïto                                        NotifyFilter,
2842*23b7c7b8SHermès Bélusca-Maïto                                        FILE_ACTION_MODIFIED );
2843*23b7c7b8SHermès Bélusca-Maïto 
2844*23b7c7b8SHermès Bélusca-Maïto                 if (UpdateDirent) {
2845*23b7c7b8SHermès Bélusca-Maïto 
2846*23b7c7b8SHermès Bélusca-Maïto                     //
2847*23b7c7b8SHermès Bélusca-Maïto                     //  If all we did was update last access time,
2848*23b7c7b8SHermès Bélusca-Maïto                     //  don't mark the volume dirty.
2849*23b7c7b8SHermès Bélusca-Maïto                     //
2850*23b7c7b8SHermès Bélusca-Maïto 
2851*23b7c7b8SHermès Bélusca-Maïto                     FatSetDirtyBcb( IrpContext,
2852*23b7c7b8SHermès Bélusca-Maïto                                     DirentBcb,
2853*23b7c7b8SHermès Bélusca-Maïto                                     NotifyFilter == FILE_NOTIFY_CHANGE_LAST_ACCESS ?
2854*23b7c7b8SHermès Bélusca-Maïto                                     NULL : FcbOrDcb->Vcb,
2855*23b7c7b8SHermès Bélusca-Maïto                                     TRUE );
2856*23b7c7b8SHermès Bélusca-Maïto                 }
2857*23b7c7b8SHermès Bélusca-Maïto 
2858*23b7c7b8SHermès Bélusca-Maïto             } _SEH2_EXCEPT( FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
2859*23b7c7b8SHermès Bélusca-Maïto                       EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) {
2860*23b7c7b8SHermès Bélusca-Maïto 
2861*23b7c7b8SHermès Bélusca-Maïto                   FatResetExceptionState( IrpContext );
2862*23b7c7b8SHermès Bélusca-Maïto             } _SEH2_END;
2863*23b7c7b8SHermès Bélusca-Maïto 
2864*23b7c7b8SHermès Bélusca-Maïto         } _SEH2_FINALLY {
2865*23b7c7b8SHermès Bélusca-Maïto 
2866*23b7c7b8SHermès Bélusca-Maïto             FatUnpinBcb( IrpContext, DirentBcb );
2867*23b7c7b8SHermès Bélusca-Maïto         } _SEH2_END;
2868*23b7c7b8SHermès Bélusca-Maïto     }
2869*23b7c7b8SHermès Bélusca-Maïto 
2870*23b7c7b8SHermès Bélusca-Maïto }
2871*23b7c7b8SHermès Bélusca-Maïto 
2872*23b7c7b8SHermès Bélusca-Maïto 
2873*23b7c7b8SHermès Bélusca-Maïto //
2874*23b7c7b8SHermès Bélusca-Maïto //  Internal support routine
2875*23b7c7b8SHermès Bélusca-Maïto //
2876*23b7c7b8SHermès Bélusca-Maïto 
2877*23b7c7b8SHermès Bélusca-Maïto UCHAR
FatComputeLfnChecksum(PDIRENT Dirent)2878*23b7c7b8SHermès Bélusca-Maïto FatComputeLfnChecksum (
2879*23b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent
2880*23b7c7b8SHermès Bélusca-Maïto     )
2881*23b7c7b8SHermès Bélusca-Maïto 
2882*23b7c7b8SHermès Bélusca-Maïto /*++
2883*23b7c7b8SHermès Bélusca-Maïto 
2884*23b7c7b8SHermès Bélusca-Maïto Routine Description:
2885*23b7c7b8SHermès Bélusca-Maïto 
2886*23b7c7b8SHermès Bélusca-Maïto     This routine computes the Chicago long file name checksum.
2887*23b7c7b8SHermès Bélusca-Maïto 
2888*23b7c7b8SHermès Bélusca-Maïto Arguments:
2889*23b7c7b8SHermès Bélusca-Maïto 
2890*23b7c7b8SHermès Bélusca-Maïto     Dirent - Specifies the dirent that we are to compute a checksum for.
2891*23b7c7b8SHermès Bélusca-Maïto 
2892*23b7c7b8SHermès Bélusca-Maïto Return Value:
2893*23b7c7b8SHermès Bélusca-Maïto 
2894*23b7c7b8SHermès Bélusca-Maïto     The checksum.
2895*23b7c7b8SHermès Bélusca-Maïto 
2896*23b7c7b8SHermès Bélusca-Maïto --*/
2897*23b7c7b8SHermès Bélusca-Maïto 
2898*23b7c7b8SHermès Bélusca-Maïto {
2899*23b7c7b8SHermès Bélusca-Maïto     ULONG i;
2900*23b7c7b8SHermès Bélusca-Maïto     UCHAR Checksum;
2901*23b7c7b8SHermès Bélusca-Maïto 
2902*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
2903*23b7c7b8SHermès Bélusca-Maïto 
2904*23b7c7b8SHermès Bélusca-Maïto     Checksum = Dirent->FileName[0];
2905*23b7c7b8SHermès Bélusca-Maïto 
2906*23b7c7b8SHermès Bélusca-Maïto     for (i=1; i < 11; i++) {
2907*23b7c7b8SHermès Bélusca-Maïto 
2908*23b7c7b8SHermès Bélusca-Maïto         Checksum = ((Checksum & 1) ? 0x80 : 0) +
2909*23b7c7b8SHermès Bélusca-Maïto                     (Checksum >> 1) +
2910*23b7c7b8SHermès Bélusca-Maïto                     Dirent->FileName[i];
2911*23b7c7b8SHermès Bélusca-Maïto     }
2912*23b7c7b8SHermès Bélusca-Maïto 
2913*23b7c7b8SHermès Bélusca-Maïto     return Checksum;
2914*23b7c7b8SHermès Bélusca-Maïto }
2915*23b7c7b8SHermès Bélusca-Maïto 
2916*23b7c7b8SHermès Bélusca-Maïto 
2917*23b7c7b8SHermès Bélusca-Maïto 
2918*23b7c7b8SHermès Bélusca-Maïto #if 0 // It turns out Win95 is still creating short names without a ~
2919*23b7c7b8SHermès Bélusca-Maïto 
2920*23b7c7b8SHermès Bélusca-Maïto //
2921*23b7c7b8SHermès Bélusca-Maïto //  Internal support routine
2922*23b7c7b8SHermès Bélusca-Maïto //
2923*23b7c7b8SHermès Bélusca-Maïto 
2924*23b7c7b8SHermès Bélusca-Maïto BOOLEAN
2925*23b7c7b8SHermès Bélusca-Maïto FatIsLfnPairValid (
2926*23b7c7b8SHermès Bélusca-Maïto     PWCHAR Lfn,
2927*23b7c7b8SHermès Bélusca-Maïto     ULONG LfnSize,
2928*23b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent
2929*23b7c7b8SHermès Bélusca-Maïto     )
2930*23b7c7b8SHermès Bélusca-Maïto 
2931*23b7c7b8SHermès Bélusca-Maïto /*++
2932*23b7c7b8SHermès Bélusca-Maïto 
2933*23b7c7b8SHermès Bélusca-Maïto Routine Description:
2934*23b7c7b8SHermès Bélusca-Maïto 
2935*23b7c7b8SHermès Bélusca-Maïto     This routine does a few more checks to make sure that a LFN/short
2936*23b7c7b8SHermès Bélusca-Maïto     name pairing is legitimate.  Basically this is the test:
2937*23b7c7b8SHermès Bélusca-Maïto 
2938*23b7c7b8SHermès Bélusca-Maïto         Pairing is valid if:
2939*23b7c7b8SHermès Bélusca-Maïto 
2940*23b7c7b8SHermès Bélusca-Maïto         DIRENT has a ~ character ||
2941*23b7c7b8SHermès Bélusca-Maïto         (LFN is 8.3 compliant &&
2942*23b7c7b8SHermès Bélusca-Maïto          (LFN has extended character(s) ? TRUE :
2943*23b7c7b8SHermès Bélusca-Maïto           LFN upcases to DIRENT))
2944*23b7c7b8SHermès Bélusca-Maïto 
2945*23b7c7b8SHermès Bélusca-Maïto     When checking for the presence of a tilda character in the short
2946*23b7c7b8SHermès Bélusca-Maïto     name, note that we purposely do a single byte search instead of
2947*23b7c7b8SHermès Bélusca-Maïto     converting the name to UNICODE and looking there for the tilda.
2948*23b7c7b8SHermès Bélusca-Maïto     This protects us from accidently missing the tilda if the
2949*23b7c7b8SHermès Bélusca-Maïto     preceding byte is a lead byte in the current Oem code page,
2950*23b7c7b8SHermès Bélusca-Maïto     but wasn't in the Oem code page that created the file.
2951*23b7c7b8SHermès Bélusca-Maïto 
2952*23b7c7b8SHermès Bélusca-Maïto     Also note that if the LFN is longer than 12 characters, then the
2953*23b7c7b8SHermès Bélusca-Maïto     second clause of the OR must be false.
2954*23b7c7b8SHermès Bélusca-Maïto 
2955*23b7c7b8SHermès Bélusca-Maïto Arguments:
2956*23b7c7b8SHermès Bélusca-Maïto 
2957*23b7c7b8SHermès Bélusca-Maïto     Lfn - Points to a buffer of UNICODE chars.
2958*23b7c7b8SHermès Bélusca-Maïto 
2959*23b7c7b8SHermès Bélusca-Maïto     LfnSize - This is the size of the LFN in characters.
2960*23b7c7b8SHermès Bélusca-Maïto 
2961*23b7c7b8SHermès Bélusca-Maïto     Dirent - Specifies the dirent we are to consider.
2962*23b7c7b8SHermès Bélusca-Maïto 
2963*23b7c7b8SHermès Bélusca-Maïto Return Value:
2964*23b7c7b8SHermès Bélusca-Maïto 
2965*23b7c7b8SHermès Bélusca-Maïto     TRUE if the Lfn/DIRENT form a legitimate pair, FALSE otherwise.
2966*23b7c7b8SHermès Bélusca-Maïto 
2967*23b7c7b8SHermès Bélusca-Maïto --*/
2968*23b7c7b8SHermès Bélusca-Maïto 
2969*23b7c7b8SHermès Bélusca-Maïto {
2970*23b7c7b8SHermès Bélusca-Maïto     ULONG i;
2971*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN ExtendedChars;
2972*23b7c7b8SHermès Bélusca-Maïto     ULONG DirentBuffer[3];
2973*23b7c7b8SHermès Bélusca-Maïto     PUCHAR DirentName;
2974*23b7c7b8SHermès Bélusca-Maïto     ULONG DirentIndex;
2975*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN DotEncountered;
2976*23b7c7b8SHermès Bélusca-Maïto 
2977*23b7c7b8SHermès Bélusca-Maïto     //
2978*23b7c7b8SHermès Bélusca-Maïto     //  First, look for a tilda
2979*23b7c7b8SHermès Bélusca-Maïto     //
2980*23b7c7b8SHermès Bélusca-Maïto 
2981*23b7c7b8SHermès Bélusca-Maïto     for (i=0; i<11; i++) {
2982*23b7c7b8SHermès Bélusca-Maïto         if (Dirent->FileName[i] == '~') {
2983*23b7c7b8SHermès Bélusca-Maïto             return TRUE;
2984*23b7c7b8SHermès Bélusca-Maïto         }
2985*23b7c7b8SHermès Bélusca-Maïto     }
2986*23b7c7b8SHermès Bélusca-Maïto 
2987*23b7c7b8SHermès Bélusca-Maïto     //
2988*23b7c7b8SHermès Bélusca-Maïto     //  No tilda.  If the LFN is longer than 12 characters, then it can
2989*23b7c7b8SHermès Bélusca-Maïto     //  neither upcase to the DIRENT nor be 8.3 complient.
2990*23b7c7b8SHermès Bélusca-Maïto     //
2991*23b7c7b8SHermès Bélusca-Maïto 
2992*23b7c7b8SHermès Bélusca-Maïto     if (LfnSize > 12) {
2993*23b7c7b8SHermès Bélusca-Maïto         return FALSE;
2994*23b7c7b8SHermès Bélusca-Maïto     }
2995*23b7c7b8SHermès Bélusca-Maïto 
2996*23b7c7b8SHermès Bélusca-Maïto     //
2997*23b7c7b8SHermès Bélusca-Maïto     //  Now see if the name is 8.3, and build an upcased DIRENT as well.
2998*23b7c7b8SHermès Bélusca-Maïto     //
2999*23b7c7b8SHermès Bélusca-Maïto 
3000*23b7c7b8SHermès Bélusca-Maïto     DirentBuffer[0] = 0x20202020;
3001*23b7c7b8SHermès Bélusca-Maïto     DirentBuffer[1] = 0x20202020;
3002*23b7c7b8SHermès Bélusca-Maïto     DirentBuffer[2] = 0x20202020;
3003*23b7c7b8SHermès Bélusca-Maïto 
3004*23b7c7b8SHermès Bélusca-Maïto     DirentName = (PUCHAR)DirentBuffer;
3005*23b7c7b8SHermès Bélusca-Maïto 
3006*23b7c7b8SHermès Bélusca-Maïto     ExtendedChars = FALSE;
3007*23b7c7b8SHermès Bélusca-Maïto     DirentIndex = 0;
3008*23b7c7b8SHermès Bélusca-Maïto     DotEncountered = FALSE;
3009*23b7c7b8SHermès Bélusca-Maïto 
3010*23b7c7b8SHermès Bélusca-Maïto     for (i=0; i < LfnSize; i++) {
3011*23b7c7b8SHermès Bélusca-Maïto 
3012*23b7c7b8SHermès Bélusca-Maïto         //
3013*23b7c7b8SHermès Bélusca-Maïto         //  Do dot transition work
3014*23b7c7b8SHermès Bélusca-Maïto         //
3015*23b7c7b8SHermès Bélusca-Maïto 
3016*23b7c7b8SHermès Bélusca-Maïto         if (Lfn[i] == L'.') {
3017*23b7c7b8SHermès Bélusca-Maïto             if (DotEncountered ||
3018*23b7c7b8SHermès Bélusca-Maïto                 (i > 8) ||
3019*23b7c7b8SHermès Bélusca-Maïto                 ((LfnSize - i) > 4) ||
3020*23b7c7b8SHermès Bélusca-Maïto                 (i && Lfn[i-1] == L' ')) {
3021*23b7c7b8SHermès Bélusca-Maïto                 return FALSE;
3022*23b7c7b8SHermès Bélusca-Maïto             }
3023*23b7c7b8SHermès Bélusca-Maïto             DotEncountered = TRUE;
3024*23b7c7b8SHermès Bélusca-Maïto             DirentIndex = 8;
3025*23b7c7b8SHermès Bélusca-Maïto             continue;
3026*23b7c7b8SHermès Bélusca-Maïto         }
3027*23b7c7b8SHermès Bélusca-Maïto 
3028*23b7c7b8SHermès Bélusca-Maïto         //
3029*23b7c7b8SHermès Bélusca-Maïto         //  The character must be legal in order to be 8.3
3030*23b7c7b8SHermès Bélusca-Maïto         //
3031*23b7c7b8SHermès Bélusca-Maïto 
3032*23b7c7b8SHermès Bélusca-Maïto         if ((Lfn[i] < 0x80) &&
3033*23b7c7b8SHermès Bélusca-Maïto             !FsRtlIsAnsiCharacterLegalFat((UCHAR)Lfn[i], FALSE)) {
3034*23b7c7b8SHermès Bélusca-Maïto             return FALSE;
3035*23b7c7b8SHermès Bélusca-Maïto         }
3036*23b7c7b8SHermès Bélusca-Maïto 
3037*23b7c7b8SHermès Bélusca-Maïto         //
3038*23b7c7b8SHermès Bélusca-Maïto         //  If the name contains no extended chars, continue building DIRENT
3039*23b7c7b8SHermès Bélusca-Maïto         //
3040*23b7c7b8SHermès Bélusca-Maïto 
3041*23b7c7b8SHermès Bélusca-Maïto         if (!ExtendedChars) {
3042*23b7c7b8SHermès Bélusca-Maïto             if (Lfn[i] > 0x7f) {
3043*23b7c7b8SHermès Bélusca-Maïto                 ExtendedChars = TRUE;
3044*23b7c7b8SHermès Bélusca-Maïto             } else {
3045*23b7c7b8SHermès Bélusca-Maïto                 DirentName[DirentIndex++] = (UCHAR) (
3046*23b7c7b8SHermès Bélusca-Maïto                 Lfn[i] < 'a' ? Lfn[i] : Lfn[i] <= 'z' ? Lfn[i] - ('a' - 'A') : Lfn[i]);
3047*23b7c7b8SHermès Bélusca-Maïto             }
3048*23b7c7b8SHermès Bélusca-Maïto         }
3049*23b7c7b8SHermès Bélusca-Maïto     }
3050*23b7c7b8SHermès Bélusca-Maïto 
3051*23b7c7b8SHermès Bélusca-Maïto     //
3052*23b7c7b8SHermès Bélusca-Maïto     //  If the LFN ended in a space, or there was no dot and the name
3053*23b7c7b8SHermès Bélusca-Maïto     //  has more than 8 characters, then it is not 8.3 compliant.
3054*23b7c7b8SHermès Bélusca-Maïto     //
3055*23b7c7b8SHermès Bélusca-Maïto 
3056*23b7c7b8SHermès Bélusca-Maïto     if ((Lfn[LfnSize - 1] == L' ') ||
3057*23b7c7b8SHermès Bélusca-Maïto         (!DotEncountered && (LfnSize > 8))) {
3058*23b7c7b8SHermès Bélusca-Maïto         return FALSE;
3059*23b7c7b8SHermès Bélusca-Maïto     }
3060*23b7c7b8SHermès Bélusca-Maïto 
3061*23b7c7b8SHermès Bélusca-Maïto     //
3062*23b7c7b8SHermès Bélusca-Maïto     //  OK, now if we got this far then the LFN is 8dot3.  If there are
3063*23b7c7b8SHermès Bélusca-Maïto     //  no extended characters, then we can also check to make sure that
3064*23b7c7b8SHermès Bélusca-Maïto     //  the LFN is only a case varient of the DIRENT.
3065*23b7c7b8SHermès Bélusca-Maïto     //
3066*23b7c7b8SHermès Bélusca-Maïto 
3067*23b7c7b8SHermès Bélusca-Maïto     if (!ExtendedChars &&
3068*23b7c7b8SHermès Bélusca-Maïto         !RtlEqualMemory(Dirent->FileName, DirentName, 11)) {
3069*23b7c7b8SHermès Bélusca-Maïto 
3070*23b7c7b8SHermès Bélusca-Maïto         return FALSE;
3071*23b7c7b8SHermès Bélusca-Maïto     }
3072*23b7c7b8SHermès Bélusca-Maïto 
3073*23b7c7b8SHermès Bélusca-Maïto     //
3074*23b7c7b8SHermès Bélusca-Maïto     //  We have now verified this pairing the very best we can without
3075*23b7c7b8SHermès Bélusca-Maïto     //  knowledge of the code page that the file was created under.
3076*23b7c7b8SHermès Bélusca-Maïto     //
3077*23b7c7b8SHermès Bélusca-Maïto 
3078*23b7c7b8SHermès Bélusca-Maïto     return TRUE;
3079*23b7c7b8SHermès Bélusca-Maïto }
3080*23b7c7b8SHermès Bélusca-Maïto #endif //0
3081*23b7c7b8SHermès Bélusca-Maïto 
3082*23b7c7b8SHermès Bélusca-Maïto //
3083*23b7c7b8SHermès Bélusca-Maïto //  Internal support routine
3084*23b7c7b8SHermès Bélusca-Maïto //
3085*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)3086*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
3087*23b7c7b8SHermès Bélusca-Maïto VOID
3088*23b7c7b8SHermès Bélusca-Maïto FatRescanDirectory (
3089*23b7c7b8SHermès Bélusca-Maïto     PIRP_CONTEXT IrpContext,
3090*23b7c7b8SHermès Bélusca-Maïto     PDCB Dcb
3091*23b7c7b8SHermès Bélusca-Maïto     )
3092*23b7c7b8SHermès Bélusca-Maïto 
3093*23b7c7b8SHermès Bélusca-Maïto /*++
3094*23b7c7b8SHermès Bélusca-Maïto 
3095*23b7c7b8SHermès Bélusca-Maïto Routine Description:
3096*23b7c7b8SHermès Bélusca-Maïto 
3097*23b7c7b8SHermès Bélusca-Maïto     This routine rescans the given directory, finding the first unused
3098*23b7c7b8SHermès Bélusca-Maïto     dirent, first deleted dirent, and setting the free dirent bitmap
3099*23b7c7b8SHermès Bélusca-Maïto     appropriately.
3100*23b7c7b8SHermès Bélusca-Maïto 
3101*23b7c7b8SHermès Bélusca-Maïto Arguments:
3102*23b7c7b8SHermès Bélusca-Maïto 
3103*23b7c7b8SHermès Bélusca-Maïto     Dcb - Supplies the directory to rescan.
3104*23b7c7b8SHermès Bélusca-Maïto 
3105*23b7c7b8SHermès Bélusca-Maïto Return Value:
3106*23b7c7b8SHermès Bélusca-Maïto 
3107*23b7c7b8SHermès Bélusca-Maïto     None.
3108*23b7c7b8SHermès Bélusca-Maïto 
3109*23b7c7b8SHermès Bélusca-Maïto --*/
3110*23b7c7b8SHermès Bélusca-Maïto 
3111*23b7c7b8SHermès Bélusca-Maïto {
3112*23b7c7b8SHermès Bélusca-Maïto     PBCB Bcb = NULL;
3113*23b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent = NULL;
3114*23b7c7b8SHermès Bélusca-Maïto     NTSTATUS Status = STATUS_SUCCESS;
3115*23b7c7b8SHermès Bélusca-Maïto 
3116*23b7c7b8SHermès Bélusca-Maïto     ULONG UnusedVbo;
3117*23b7c7b8SHermès Bélusca-Maïto     ULONG DeletedHint;
3118*23b7c7b8SHermès Bélusca-Maïto     ULONG DirentIndex;
3119*23b7c7b8SHermès Bélusca-Maïto     ULONG DirentsThisRun;
3120*23b7c7b8SHermès Bélusca-Maïto     ULONG StartIndexOfThisRun;
3121*23b7c7b8SHermès Bélusca-Maïto 
3122*23b7c7b8SHermès Bélusca-Maïto     enum RunType {
3123*23b7c7b8SHermès Bélusca-Maïto         InitialRun,
3124*23b7c7b8SHermès Bélusca-Maïto         FreeDirents,
3125*23b7c7b8SHermès Bélusca-Maïto         AllocatedDirents,
3126*23b7c7b8SHermès Bélusca-Maïto     } CurrentRun;
3127*23b7c7b8SHermès Bélusca-Maïto 
3128*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
3129*23b7c7b8SHermès Bélusca-Maïto 
3130*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "We must scan the whole directory.\n", 0);
3131*23b7c7b8SHermès Bélusca-Maïto 
3132*23b7c7b8SHermès Bélusca-Maïto     UnusedVbo = 0;
3133*23b7c7b8SHermès Bélusca-Maïto     DeletedHint = 0xffffffff;
3134*23b7c7b8SHermès Bélusca-Maïto 
3135*23b7c7b8SHermès Bélusca-Maïto     //
3136*23b7c7b8SHermès Bélusca-Maïto     //  To start with, we have to find out if the first dirent is free.
3137*23b7c7b8SHermès Bélusca-Maïto     //
3138*23b7c7b8SHermès Bélusca-Maïto 
3139*23b7c7b8SHermès Bélusca-Maïto     CurrentRun = InitialRun;
3140*23b7c7b8SHermès Bélusca-Maïto     DirentIndex =
3141*23b7c7b8SHermès Bélusca-Maïto     StartIndexOfThisRun = 0;
3142*23b7c7b8SHermès Bélusca-Maïto 
3143*23b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
3144*23b7c7b8SHermès Bélusca-Maïto 
3145*23b7c7b8SHermès Bélusca-Maïto         while ( TRUE ) {
3146*23b7c7b8SHermès Bélusca-Maïto 
3147*23b7c7b8SHermès Bélusca-Maïto             BOOLEAN DirentDeleted;
3148*23b7c7b8SHermès Bélusca-Maïto 
3149*23b7c7b8SHermès Bélusca-Maïto             //
3150*23b7c7b8SHermès Bélusca-Maïto             //  Read a dirent
3151*23b7c7b8SHermès Bélusca-Maïto             //
3152*23b7c7b8SHermès Bélusca-Maïto 
3153*23b7c7b8SHermès Bélusca-Maïto             FatReadDirent( IrpContext,
3154*23b7c7b8SHermès Bélusca-Maïto                            Dcb,
3155*23b7c7b8SHermès Bélusca-Maïto                            UnusedVbo,
3156*23b7c7b8SHermès Bélusca-Maïto                            &Bcb,
3157*23b7c7b8SHermès Bélusca-Maïto                            &Dirent,
3158*23b7c7b8SHermès Bélusca-Maïto                            &Status );
3159*23b7c7b8SHermès Bélusca-Maïto 
3160*23b7c7b8SHermès Bélusca-Maïto             //
3161*23b7c7b8SHermès Bélusca-Maïto             //  If EOF, or we found a NEVER_USED entry, we exit the loop
3162*23b7c7b8SHermès Bélusca-Maïto             //
3163*23b7c7b8SHermès Bélusca-Maïto 
3164*23b7c7b8SHermès Bélusca-Maïto             if ( (Status == STATUS_END_OF_FILE ) ||
3165*23b7c7b8SHermès Bélusca-Maïto                  (Dirent->FileName[0] == FAT_DIRENT_NEVER_USED)) {
3166*23b7c7b8SHermès Bélusca-Maïto 
3167*23b7c7b8SHermès Bélusca-Maïto                 break;
3168*23b7c7b8SHermès Bélusca-Maïto             }
3169*23b7c7b8SHermès Bélusca-Maïto 
3170*23b7c7b8SHermès Bélusca-Maïto             //
3171*23b7c7b8SHermès Bélusca-Maïto             //  If the dirent is DELETED, and it is the first one we found, set
3172*23b7c7b8SHermès Bélusca-Maïto             //  it in the deleted hint.
3173*23b7c7b8SHermès Bélusca-Maïto             //
3174*23b7c7b8SHermès Bélusca-Maïto 
3175*23b7c7b8SHermès Bélusca-Maïto             if (Dirent->FileName[0] == FAT_DIRENT_DELETED) {
3176*23b7c7b8SHermès Bélusca-Maïto 
3177*23b7c7b8SHermès Bélusca-Maïto                 DirentDeleted = TRUE;
3178*23b7c7b8SHermès Bélusca-Maïto 
3179*23b7c7b8SHermès Bélusca-Maïto                 if (DeletedHint == 0xffffffff) {
3180*23b7c7b8SHermès Bélusca-Maïto 
3181*23b7c7b8SHermès Bélusca-Maïto                     DeletedHint = UnusedVbo;
3182*23b7c7b8SHermès Bélusca-Maïto                 }
3183*23b7c7b8SHermès Bélusca-Maïto 
3184*23b7c7b8SHermès Bélusca-Maïto             } else {
3185*23b7c7b8SHermès Bélusca-Maïto 
3186*23b7c7b8SHermès Bélusca-Maïto                 DirentDeleted = FALSE;
3187*23b7c7b8SHermès Bélusca-Maïto             }
3188*23b7c7b8SHermès Bélusca-Maïto 
3189*23b7c7b8SHermès Bélusca-Maïto             //
3190*23b7c7b8SHermès Bélusca-Maïto             //  Check for the first time through the loop, and determine
3191*23b7c7b8SHermès Bélusca-Maïto             //  the current run type.
3192*23b7c7b8SHermès Bélusca-Maïto             //
3193*23b7c7b8SHermès Bélusca-Maïto 
3194*23b7c7b8SHermès Bélusca-Maïto             if (CurrentRun == InitialRun) {
3195*23b7c7b8SHermès Bélusca-Maïto 
3196*23b7c7b8SHermès Bélusca-Maïto                 CurrentRun = DirentDeleted ?
3197*23b7c7b8SHermès Bélusca-Maïto                              FreeDirents : AllocatedDirents;
3198*23b7c7b8SHermès Bélusca-Maïto 
3199*23b7c7b8SHermès Bélusca-Maïto             } else {
3200*23b7c7b8SHermès Bélusca-Maïto 
3201*23b7c7b8SHermès Bélusca-Maïto                 //
3202*23b7c7b8SHermès Bélusca-Maïto                 //  Are we switching from a free run to an allocated run?
3203*23b7c7b8SHermès Bélusca-Maïto                 //
3204*23b7c7b8SHermès Bélusca-Maïto 
3205*23b7c7b8SHermès Bélusca-Maïto                 if ((CurrentRun == FreeDirents) && !DirentDeleted) {
3206*23b7c7b8SHermès Bélusca-Maïto 
3207*23b7c7b8SHermès Bélusca-Maïto                     DirentsThisRun = DirentIndex - StartIndexOfThisRun;
3208*23b7c7b8SHermès Bélusca-Maïto 
3209*23b7c7b8SHermès Bélusca-Maïto                     RtlClearBits( &Dcb->Specific.Dcb.FreeDirentBitmap,
3210*23b7c7b8SHermès Bélusca-Maïto                                   StartIndexOfThisRun,
3211*23b7c7b8SHermès Bélusca-Maïto                                   DirentsThisRun );
3212*23b7c7b8SHermès Bélusca-Maïto 
3213*23b7c7b8SHermès Bélusca-Maïto                     CurrentRun = AllocatedDirents;
3214*23b7c7b8SHermès Bélusca-Maïto                     StartIndexOfThisRun = DirentIndex;
3215*23b7c7b8SHermès Bélusca-Maïto                 }
3216*23b7c7b8SHermès Bélusca-Maïto 
3217*23b7c7b8SHermès Bélusca-Maïto                 //
3218*23b7c7b8SHermès Bélusca-Maïto                 //  Are we switching from an allocated run to a free run?
3219*23b7c7b8SHermès Bélusca-Maïto                 //
3220*23b7c7b8SHermès Bélusca-Maïto 
3221*23b7c7b8SHermès Bélusca-Maïto                 if ((CurrentRun == AllocatedDirents) && DirentDeleted) {
3222*23b7c7b8SHermès Bélusca-Maïto 
3223*23b7c7b8SHermès Bélusca-Maïto                     DirentsThisRun = DirentIndex - StartIndexOfThisRun;
3224*23b7c7b8SHermès Bélusca-Maïto 
3225*23b7c7b8SHermès Bélusca-Maïto                     RtlSetBits( &Dcb->Specific.Dcb.FreeDirentBitmap,
3226*23b7c7b8SHermès Bélusca-Maïto                                 StartIndexOfThisRun,
3227*23b7c7b8SHermès Bélusca-Maïto                                 DirentsThisRun );
3228*23b7c7b8SHermès Bélusca-Maïto 
3229*23b7c7b8SHermès Bélusca-Maïto                     CurrentRun = FreeDirents;
3230*23b7c7b8SHermès Bélusca-Maïto                     StartIndexOfThisRun = DirentIndex;
3231*23b7c7b8SHermès Bélusca-Maïto                 }
3232*23b7c7b8SHermès Bélusca-Maïto             }
3233*23b7c7b8SHermès Bélusca-Maïto 
3234*23b7c7b8SHermès Bélusca-Maïto             //
3235*23b7c7b8SHermès Bélusca-Maïto             //  Move on to the next dirent.
3236*23b7c7b8SHermès Bélusca-Maïto             //
3237*23b7c7b8SHermès Bélusca-Maïto 
3238*23b7c7b8SHermès Bélusca-Maïto             UnusedVbo += sizeof(DIRENT);
3239*23b7c7b8SHermès Bélusca-Maïto             Dirent += 1;
3240*23b7c7b8SHermès Bélusca-Maïto             DirentIndex += 1;
3241*23b7c7b8SHermès Bélusca-Maïto         }
3242*23b7c7b8SHermès Bélusca-Maïto 
3243*23b7c7b8SHermès Bélusca-Maïto         //
3244*23b7c7b8SHermès Bélusca-Maïto         //  Now we have to record the final run we encoutered
3245*23b7c7b8SHermès Bélusca-Maïto         //
3246*23b7c7b8SHermès Bélusca-Maïto 
3247*23b7c7b8SHermès Bélusca-Maïto         DirentsThisRun = DirentIndex - StartIndexOfThisRun;
3248*23b7c7b8SHermès Bélusca-Maïto 
3249*23b7c7b8SHermès Bélusca-Maïto         if ((CurrentRun == FreeDirents) || (CurrentRun == InitialRun)) {
3250*23b7c7b8SHermès Bélusca-Maïto 
3251*23b7c7b8SHermès Bélusca-Maïto             RtlClearBits( &Dcb->Specific.Dcb.FreeDirentBitmap,
3252*23b7c7b8SHermès Bélusca-Maïto                           StartIndexOfThisRun,
3253*23b7c7b8SHermès Bélusca-Maïto                           DirentsThisRun );
3254*23b7c7b8SHermès Bélusca-Maïto 
3255*23b7c7b8SHermès Bélusca-Maïto         } else {
3256*23b7c7b8SHermès Bélusca-Maïto 
3257*23b7c7b8SHermès Bélusca-Maïto             RtlSetBits( &Dcb->Specific.Dcb.FreeDirentBitmap,
3258*23b7c7b8SHermès Bélusca-Maïto                         StartIndexOfThisRun,
3259*23b7c7b8SHermès Bélusca-Maïto                         DirentsThisRun );
3260*23b7c7b8SHermès Bélusca-Maïto         }
3261*23b7c7b8SHermès Bélusca-Maïto 
3262*23b7c7b8SHermès Bélusca-Maïto         //
3263*23b7c7b8SHermès Bélusca-Maïto         //  Now if there we bailed prematurely out of the loop because
3264*23b7c7b8SHermès Bélusca-Maïto         //  we hit an unused entry, set all the rest as free.
3265*23b7c7b8SHermès Bélusca-Maïto         //
3266*23b7c7b8SHermès Bélusca-Maïto 
3267*23b7c7b8SHermès Bélusca-Maïto         if (UnusedVbo < Dcb->Header.AllocationSize.LowPart) {
3268*23b7c7b8SHermès Bélusca-Maïto 
3269*23b7c7b8SHermès Bélusca-Maïto             StartIndexOfThisRun = UnusedVbo / sizeof(DIRENT);
3270*23b7c7b8SHermès Bélusca-Maïto 
3271*23b7c7b8SHermès Bélusca-Maïto             DirentsThisRun = (Dcb->Header.AllocationSize.LowPart -
3272*23b7c7b8SHermès Bélusca-Maïto                               UnusedVbo) / sizeof(DIRENT);
3273*23b7c7b8SHermès Bélusca-Maïto 
3274*23b7c7b8SHermès Bélusca-Maïto             RtlClearBits( &Dcb->Specific.Dcb.FreeDirentBitmap,
3275*23b7c7b8SHermès Bélusca-Maïto                           StartIndexOfThisRun,
3276*23b7c7b8SHermès Bélusca-Maïto                           DirentsThisRun);
3277*23b7c7b8SHermès Bélusca-Maïto         }
3278*23b7c7b8SHermès Bélusca-Maïto 
3279*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
3280*23b7c7b8SHermès Bélusca-Maïto 
3281*23b7c7b8SHermès Bélusca-Maïto         FatUnpinBcb( IrpContext, Bcb );
3282*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
3283*23b7c7b8SHermès Bélusca-Maïto 
3284*23b7c7b8SHermès Bélusca-Maïto     //
3285*23b7c7b8SHermès Bélusca-Maïto     //  If there weren't any DELETED entries, set the index to our current
3286*23b7c7b8SHermès Bélusca-Maïto     //  position.
3287*23b7c7b8SHermès Bélusca-Maïto     //
3288*23b7c7b8SHermès Bélusca-Maïto 
3289*23b7c7b8SHermès Bélusca-Maïto     if (DeletedHint == 0xffffffff) { DeletedHint = UnusedVbo; }
3290*23b7c7b8SHermès Bélusca-Maïto 
3291*23b7c7b8SHermès Bélusca-Maïto     Dcb->Specific.Dcb.UnusedDirentVbo = UnusedVbo;
3292*23b7c7b8SHermès Bélusca-Maïto     Dcb->Specific.Dcb.DeletedDirentHint = DeletedHint;
3293*23b7c7b8SHermès Bélusca-Maïto 
3294*23b7c7b8SHermès Bélusca-Maïto     return;
3295*23b7c7b8SHermès Bélusca-Maïto }
3296*23b7c7b8SHermès Bélusca-Maïto 
3297*23b7c7b8SHermès Bélusca-Maïto 
3298*23b7c7b8SHermès Bélusca-Maïto //
3299*23b7c7b8SHermès Bélusca-Maïto //  Internal support routine
3300*23b7c7b8SHermès Bélusca-Maïto //
3301*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)3302*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
3303*23b7c7b8SHermès Bélusca-Maïto ULONG
3304*23b7c7b8SHermès Bélusca-Maïto FatDefragDirectory (
3305*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
3306*23b7c7b8SHermès Bélusca-Maïto     IN PDCB Dcb,
3307*23b7c7b8SHermès Bélusca-Maïto     IN ULONG DirentsNeeded
3308*23b7c7b8SHermès Bélusca-Maïto     )
3309*23b7c7b8SHermès Bélusca-Maïto 
3310*23b7c7b8SHermès Bélusca-Maïto /*++
3311*23b7c7b8SHermès Bélusca-Maïto 
3312*23b7c7b8SHermès Bélusca-Maïto Routine Description:
3313*23b7c7b8SHermès Bélusca-Maïto 
3314*23b7c7b8SHermès Bélusca-Maïto     This routine determines if the requested number of dirents can be found
3315*23b7c7b8SHermès Bélusca-Maïto     in the directory, looking for deleted dirents and orphaned LFNs.  If the
3316*23b7c7b8SHermès Bélusca-Maïto     request can be satisifed, orphaned LFNs are marked as deleted, and deleted
3317*23b7c7b8SHermès Bélusca-Maïto     dirents are all grouped together at the end of the directory.
3318*23b7c7b8SHermès Bélusca-Maïto 
3319*23b7c7b8SHermès Bélusca-Maïto     Note that this routine is currently used only on the root directory, but
3320*23b7c7b8SHermès Bélusca-Maïto     it is completely general and could be used on any directory.
3321*23b7c7b8SHermès Bélusca-Maïto 
3322*23b7c7b8SHermès Bélusca-Maïto Arguments:
3323*23b7c7b8SHermès Bélusca-Maïto 
3324*23b7c7b8SHermès Bélusca-Maïto     Dcb - Supplies the directory to defrag.
3325*23b7c7b8SHermès Bélusca-Maïto 
3326*23b7c7b8SHermès Bélusca-Maïto Return Value:
3327*23b7c7b8SHermès Bélusca-Maïto 
3328*23b7c7b8SHermès Bélusca-Maïto     The Index of the first dirent available for use, or -1 if the
3329*23b7c7b8SHermès Bélusca-Maïto     request cannot be satisfied.
3330*23b7c7b8SHermès Bélusca-Maïto 
3331*23b7c7b8SHermès Bélusca-Maïto --*/
3332*23b7c7b8SHermès Bélusca-Maïto 
3333*23b7c7b8SHermès Bélusca-Maïto {
3334*23b7c7b8SHermès Bélusca-Maïto     ULONG SavedIrpContextFlag;
3335*23b7c7b8SHermès Bélusca-Maïto     PLIST_ENTRY Links;
3336*23b7c7b8SHermès Bélusca-Maïto     ULONG ReturnValue = 0;
3337*23b7c7b8SHermès Bélusca-Maïto     PFCB Fcb;
3338*23b7c7b8SHermès Bélusca-Maïto 
3339*23b7c7b8SHermès Bélusca-Maïto     PBCB Bcb = NULL;
3340*23b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent = NULL;
3341*23b7c7b8SHermès Bélusca-Maïto     UNICODE_STRING Lfn = {0,0,NULL};
3342*23b7c7b8SHermès Bélusca-Maïto 
3343*23b7c7b8SHermès Bélusca-Maïto     LARGE_MCB Mcb;
3344*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN McbInitialized = FALSE;
3345*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN InvalidateFcbs = FALSE;
3346*23b7c7b8SHermès Bélusca-Maïto 
3347*23b7c7b8SHermès Bélusca-Maïto     PUCHAR Directory = NULL;
3348*23b7c7b8SHermès Bélusca-Maïto     PUCHAR UnusedDirents;
3349*23b7c7b8SHermès Bélusca-Maïto     PUCHAR UnusedDirentBuffer = NULL;
3350*23b7c7b8SHermès Bélusca-Maïto     PUCHAR UsedDirents;
3351*23b7c7b8SHermès Bélusca-Maïto     PUCHAR UsedDirentBuffer = NULL;
3352*23b7c7b8SHermès Bélusca-Maïto 
3353*23b7c7b8SHermès Bélusca-Maïto     PBCB *Bcbs = NULL;
3354*23b7c7b8SHermès Bélusca-Maïto     ULONG Page;
3355*23b7c7b8SHermès Bélusca-Maïto     ULONG PagesPinned = 0;
3356*23b7c7b8SHermès Bélusca-Maïto 
3357*23b7c7b8SHermès Bélusca-Maïto     ULONG DcbSize;
3358*23b7c7b8SHermès Bélusca-Maïto     ULONG TotalBytesAllocated = 0;
3359*23b7c7b8SHermès Bélusca-Maïto 
3360*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
3361*23b7c7b8SHermès Bélusca-Maïto 
3362*23b7c7b8SHermès Bélusca-Maïto     //
3363*23b7c7b8SHermès Bélusca-Maïto     //  We assume we own the Vcb.
3364*23b7c7b8SHermès Bélusca-Maïto     //
3365*23b7c7b8SHermès Bélusca-Maïto 
3366*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( FatVcbAcquiredExclusive(IrpContext, Dcb->Vcb) );
3367*23b7c7b8SHermès Bélusca-Maïto 
3368*23b7c7b8SHermès Bélusca-Maïto     //
3369*23b7c7b8SHermès Bélusca-Maïto     //  We will only attempt this on directories less than 0x40000 bytes
3370*23b7c7b8SHermès Bélusca-Maïto     //  long (by default on DOS the root directory is only 0x2000 long).
3371*23b7c7b8SHermès Bélusca-Maïto     //  This is to avoid a cache manager complication.
3372*23b7c7b8SHermès Bélusca-Maïto     //
3373*23b7c7b8SHermès Bélusca-Maïto 
3374*23b7c7b8SHermès Bélusca-Maïto     DcbSize = Dcb->Header.AllocationSize.LowPart;
3375*23b7c7b8SHermès Bélusca-Maïto 
3376*23b7c7b8SHermès Bélusca-Maïto     if (DcbSize > 0x40000) {
3377*23b7c7b8SHermès Bélusca-Maïto 
3378*23b7c7b8SHermès Bélusca-Maïto         return (ULONG)-1;
3379*23b7c7b8SHermès Bélusca-Maïto     }
3380*23b7c7b8SHermès Bélusca-Maïto 
3381*23b7c7b8SHermès Bélusca-Maïto     //
3382*23b7c7b8SHermès Bélusca-Maïto     //  Force wait to TRUE
3383*23b7c7b8SHermès Bélusca-Maïto     //
3384*23b7c7b8SHermès Bélusca-Maïto 
3385*23b7c7b8SHermès Bélusca-Maïto     SavedIrpContextFlag = IrpContext->Flags;
3386*23b7c7b8SHermès Bélusca-Maïto 
3387*23b7c7b8SHermès Bélusca-Maïto     SetFlag( IrpContext->Flags,
3388*23b7c7b8SHermès Bélusca-Maïto              IRP_CONTEXT_FLAG_WAIT | IRP_CONTEXT_FLAG_WRITE_THROUGH );
3389*23b7c7b8SHermès Bélusca-Maïto 
3390*23b7c7b8SHermès Bélusca-Maïto     //
3391*23b7c7b8SHermès Bélusca-Maïto     //  Now acquire all open Fcbs in the Dcb exclusive.
3392*23b7c7b8SHermès Bélusca-Maïto     //
3393*23b7c7b8SHermès Bélusca-Maïto 
3394*23b7c7b8SHermès Bélusca-Maïto     for (Links = Dcb->Specific.Dcb.ParentDcbQueue.Flink;
3395*23b7c7b8SHermès Bélusca-Maïto          Links != &Dcb->Specific.Dcb.ParentDcbQueue;
3396*23b7c7b8SHermès Bélusca-Maïto          Links = Links->Flink) {
3397*23b7c7b8SHermès Bélusca-Maïto 
3398*23b7c7b8SHermès Bélusca-Maïto         Fcb = CONTAINING_RECORD( Links, FCB, ParentDcbLinks );
3399*23b7c7b8SHermès Bélusca-Maïto 
3400*23b7c7b8SHermès Bélusca-Maïto         (VOID)ExAcquireResourceExclusiveLite( Fcb->Header.Resource, TRUE );
3401*23b7c7b8SHermès Bélusca-Maïto     }
3402*23b7c7b8SHermès Bélusca-Maïto 
3403*23b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
3404*23b7c7b8SHermès Bélusca-Maïto 
3405*23b7c7b8SHermès Bélusca-Maïto         CCB Ccb;
3406*23b7c7b8SHermès Bélusca-Maïto         ULONG QueryOffset = 0;
3407*23b7c7b8SHermès Bélusca-Maïto         ULONG FoundOffset = 0;
3408*23b7c7b8SHermès Bélusca-Maïto         ULONGLONG BytesUsed = 0;
3409*23b7c7b8SHermès Bélusca-Maïto 
3410*23b7c7b8SHermès Bélusca-Maïto         NTSTATUS DontCare;
3411*23b7c7b8SHermès Bélusca-Maïto         ULONG Run;
3412*23b7c7b8SHermès Bélusca-Maïto         ULONG TotalRuns;
3413*23b7c7b8SHermès Bélusca-Maïto         BOOLEAN Result;
3414*23b7c7b8SHermès Bélusca-Maïto         PUCHAR Char;
3415*23b7c7b8SHermès Bélusca-Maïto 
3416*23b7c7b8SHermès Bélusca-Maïto         //
3417*23b7c7b8SHermès Bélusca-Maïto         //  We are going to build a new bitmap that will show all orphaned
3418*23b7c7b8SHermès Bélusca-Maïto         //  LFNs as well as deleted dirents as available.
3419*23b7c7b8SHermès Bélusca-Maïto         //
3420*23b7c7b8SHermès Bélusca-Maïto         //  Initialize our local CCB that will match all files and even
3421*23b7c7b8SHermès Bélusca-Maïto         //  a label if it is here.
3422*23b7c7b8SHermès Bélusca-Maïto         //
3423*23b7c7b8SHermès Bélusca-Maïto 
3424*23b7c7b8SHermès Bélusca-Maïto         RtlZeroMemory( &Ccb, sizeof(CCB) );
3425*23b7c7b8SHermès Bélusca-Maïto         Ccb.Flags = CCB_FLAG_MATCH_ALL | CCB_FLAG_MATCH_VOLUME_ID;
3426*23b7c7b8SHermès Bélusca-Maïto 
3427*23b7c7b8SHermès Bélusca-Maïto         //
3428*23b7c7b8SHermès Bélusca-Maïto         //  Init the Long File Name string.
3429*23b7c7b8SHermès Bélusca-Maïto         //
3430*23b7c7b8SHermès Bélusca-Maïto 
3431*23b7c7b8SHermès Bélusca-Maïto         Lfn.MaximumLength = 260 * sizeof(WCHAR);
3432*23b7c7b8SHermès Bélusca-Maïto         Lfn.Buffer = FsRtlAllocatePoolWithTag( PagedPool,
3433*23b7c7b8SHermès Bélusca-Maïto                                                260*sizeof(WCHAR),
3434*23b7c7b8SHermès Bélusca-Maïto                                                TAG_FILENAME_BUFFER );
3435*23b7c7b8SHermès Bélusca-Maïto 
3436*23b7c7b8SHermès Bélusca-Maïto         //
3437*23b7c7b8SHermès Bélusca-Maïto         //  Initalize the Mcb.  We use this structure to keep track of runs
3438*23b7c7b8SHermès Bélusca-Maïto         //  of free and allocated dirents.  Runs are identity allocations, and
3439*23b7c7b8SHermès Bélusca-Maïto         //  holes are free dirents.
3440*23b7c7b8SHermès Bélusca-Maïto         //
3441*23b7c7b8SHermès Bélusca-Maïto 
3442*23b7c7b8SHermès Bélusca-Maïto         FsRtlInitializeLargeMcb( &Mcb, PagedPool );
3443*23b7c7b8SHermès Bélusca-Maïto 
3444*23b7c7b8SHermès Bélusca-Maïto         McbInitialized = TRUE;
3445*23b7c7b8SHermès Bélusca-Maïto 
3446*23b7c7b8SHermès Bélusca-Maïto         do {
3447*23b7c7b8SHermès Bélusca-Maïto 
3448*23b7c7b8SHermès Bélusca-Maïto             FatLocateDirent( IrpContext,
3449*23b7c7b8SHermès Bélusca-Maïto                              Dcb,
3450*23b7c7b8SHermès Bélusca-Maïto                              &Ccb,
3451*23b7c7b8SHermès Bélusca-Maïto                              QueryOffset,
3452*23b7c7b8SHermès Bélusca-Maïto                              NULL,
3453*23b7c7b8SHermès Bélusca-Maïto                              &Dirent,
3454*23b7c7b8SHermès Bélusca-Maïto                              &Bcb,
3455*23b7c7b8SHermès Bélusca-Maïto                              (PVBO)&FoundOffset,
3456*23b7c7b8SHermès Bélusca-Maïto                              NULL,
3457*23b7c7b8SHermès Bélusca-Maïto                              &Lfn,
3458*23b7c7b8SHermès Bélusca-Maïto                              NULL );
3459*23b7c7b8SHermès Bélusca-Maïto 
3460*23b7c7b8SHermès Bélusca-Maïto             if (Dirent != NULL) {
3461*23b7c7b8SHermès Bélusca-Maïto 
3462*23b7c7b8SHermès Bélusca-Maïto                 ULONG LfnByteOffset;
3463*23b7c7b8SHermès Bélusca-Maïto 
3464*23b7c7b8SHermès Bélusca-Maïto                 //
3465*23b7c7b8SHermès Bélusca-Maïto                 //  Compute the LfnByteOffset.
3466*23b7c7b8SHermès Bélusca-Maïto                 //
3467*23b7c7b8SHermès Bélusca-Maïto 
3468*23b7c7b8SHermès Bélusca-Maïto                 LfnByteOffset = FoundOffset -
3469*23b7c7b8SHermès Bélusca-Maïto                                 FAT_LFN_DIRENTS_NEEDED(&Lfn) * sizeof(LFN_DIRENT);
3470*23b7c7b8SHermès Bélusca-Maïto 
3471*23b7c7b8SHermès Bélusca-Maïto                 BytesUsed = FoundOffset - LfnByteOffset + sizeof(DIRENT);
3472*23b7c7b8SHermès Bélusca-Maïto 
3473*23b7c7b8SHermès Bélusca-Maïto                 //
3474*23b7c7b8SHermès Bélusca-Maïto                 //  Set a run to represent all the dirents used for this
3475*23b7c7b8SHermès Bélusca-Maïto                 //  file in the Dcb dir.
3476*23b7c7b8SHermès Bélusca-Maïto                 //
3477*23b7c7b8SHermès Bélusca-Maïto 
3478*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
3479*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress:28931, "needed for debug build" )
3480*23b7c7b8SHermès Bélusca-Maïto #endif
3481*23b7c7b8SHermès Bélusca-Maïto                 Result = FsRtlAddLargeMcbEntry( &Mcb,
3482*23b7c7b8SHermès Bélusca-Maïto                                                 LfnByteOffset,
3483*23b7c7b8SHermès Bélusca-Maïto                                                 LfnByteOffset,
3484*23b7c7b8SHermès Bélusca-Maïto                                                 BytesUsed );
3485*23b7c7b8SHermès Bélusca-Maïto 
3486*23b7c7b8SHermès Bélusca-Maïto                 NT_ASSERT( Result );
3487*23b7c7b8SHermès Bélusca-Maïto 
3488*23b7c7b8SHermès Bélusca-Maïto                 //
3489*23b7c7b8SHermès Bélusca-Maïto                 //  Move on to the next dirent.
3490*23b7c7b8SHermès Bélusca-Maïto                 //
3491*23b7c7b8SHermès Bélusca-Maïto 
3492*23b7c7b8SHermès Bélusca-Maïto                 TotalBytesAllocated += (ULONG) BytesUsed;
3493*23b7c7b8SHermès Bélusca-Maïto                 QueryOffset = FoundOffset + sizeof(DIRENT);
3494*23b7c7b8SHermès Bélusca-Maïto             }
3495*23b7c7b8SHermès Bélusca-Maïto 
3496*23b7c7b8SHermès Bélusca-Maïto         } while ((Dirent != NULL) && (QueryOffset < DcbSize));
3497*23b7c7b8SHermès Bélusca-Maïto 
3498*23b7c7b8SHermès Bélusca-Maïto         if (Bcb != NULL) {
3499*23b7c7b8SHermès Bélusca-Maïto 
3500*23b7c7b8SHermès Bélusca-Maïto             FatUnpinBcb( IrpContext, Bcb );
3501*23b7c7b8SHermès Bélusca-Maïto         }
3502*23b7c7b8SHermès Bélusca-Maïto 
3503*23b7c7b8SHermès Bélusca-Maïto         //
3504*23b7c7b8SHermès Bélusca-Maïto         //  If we need more dirents than are available, bail.
3505*23b7c7b8SHermès Bélusca-Maïto         //
3506*23b7c7b8SHermès Bélusca-Maïto 
3507*23b7c7b8SHermès Bélusca-Maïto         if (DirentsNeeded > (DcbSize - TotalBytesAllocated)/sizeof(DIRENT)) {
3508*23b7c7b8SHermès Bélusca-Maïto 
3509*23b7c7b8SHermès Bélusca-Maïto             try_return(ReturnValue = (ULONG)-1);
3510*23b7c7b8SHermès Bélusca-Maïto         }
3511*23b7c7b8SHermès Bélusca-Maïto 
3512*23b7c7b8SHermès Bélusca-Maïto         //
3513*23b7c7b8SHermès Bélusca-Maïto         //  Now we are going to copy all the used and un-used parts of the
3514*23b7c7b8SHermès Bélusca-Maïto         //  directory to separate pool.
3515*23b7c7b8SHermès Bélusca-Maïto         //
3516*23b7c7b8SHermès Bélusca-Maïto         //  Allocate these buffers and pin the entire directory.
3517*23b7c7b8SHermès Bélusca-Maïto         //
3518*23b7c7b8SHermès Bélusca-Maïto 
3519*23b7c7b8SHermès Bélusca-Maïto         UnusedDirents =
3520*23b7c7b8SHermès Bélusca-Maïto         UnusedDirentBuffer = FsRtlAllocatePoolWithTag( PagedPool,
3521*23b7c7b8SHermès Bélusca-Maïto                                                        DcbSize - TotalBytesAllocated,
3522*23b7c7b8SHermès Bélusca-Maïto                                                        TAG_DIRENT );
3523*23b7c7b8SHermès Bélusca-Maïto 
3524*23b7c7b8SHermès Bélusca-Maïto         UsedDirents =
3525*23b7c7b8SHermès Bélusca-Maïto         UsedDirentBuffer = FsRtlAllocatePoolWithTag( PagedPool,
3526*23b7c7b8SHermès Bélusca-Maïto                                                      TotalBytesAllocated,
3527*23b7c7b8SHermès Bélusca-Maïto                                                      TAG_DIRENT );
3528*23b7c7b8SHermès Bélusca-Maïto 
3529*23b7c7b8SHermès Bélusca-Maïto         PagesPinned = (DcbSize + (PAGE_SIZE - 1 )) / PAGE_SIZE;
3530*23b7c7b8SHermès Bélusca-Maïto 
3531*23b7c7b8SHermès Bélusca-Maïto         Bcbs = FsRtlAllocatePoolWithTag( PagedPool,
3532*23b7c7b8SHermès Bélusca-Maïto                                          PagesPinned * sizeof(PBCB),
3533*23b7c7b8SHermès Bélusca-Maïto                                          TAG_BCB );
3534*23b7c7b8SHermès Bélusca-Maïto 
3535*23b7c7b8SHermès Bélusca-Maïto         RtlZeroMemory( Bcbs, PagesPinned * sizeof(PBCB) );
3536*23b7c7b8SHermès Bélusca-Maïto 
3537*23b7c7b8SHermès Bélusca-Maïto         for (Page = 0; Page < PagesPinned; Page += 1) {
3538*23b7c7b8SHermès Bélusca-Maïto 
3539*23b7c7b8SHermès Bélusca-Maïto             ULONG PinSize;
3540*23b7c7b8SHermès Bélusca-Maïto 
3541*23b7c7b8SHermès Bélusca-Maïto             //
3542*23b7c7b8SHermès Bélusca-Maïto             //  Don't try to pin beyond the Dcb size.
3543*23b7c7b8SHermès Bélusca-Maïto             //
3544*23b7c7b8SHermès Bélusca-Maïto 
3545*23b7c7b8SHermès Bélusca-Maïto             if ((Page + 1) * PAGE_SIZE > DcbSize) {
3546*23b7c7b8SHermès Bélusca-Maïto 
3547*23b7c7b8SHermès Bélusca-Maïto                 PinSize = DcbSize - (Page * PAGE_SIZE);
3548*23b7c7b8SHermès Bélusca-Maïto 
3549*23b7c7b8SHermès Bélusca-Maïto             } else {
3550*23b7c7b8SHermès Bélusca-Maïto 
3551*23b7c7b8SHermès Bélusca-Maïto                 PinSize = PAGE_SIZE;
3552*23b7c7b8SHermès Bélusca-Maïto             }
3553*23b7c7b8SHermès Bélusca-Maïto 
3554*23b7c7b8SHermès Bélusca-Maïto             FatPrepareWriteDirectoryFile( IrpContext,
3555*23b7c7b8SHermès Bélusca-Maïto                                           Dcb,
3556*23b7c7b8SHermès Bélusca-Maïto                                           Page * PAGE_SIZE,
3557*23b7c7b8SHermès Bélusca-Maïto                                           PinSize,
3558*23b7c7b8SHermès Bélusca-Maïto                                           &Bcbs[Page],
3559*23b7c7b8SHermès Bélusca-Maïto #ifndef __REACTOS__
3560*23b7c7b8SHermès Bélusca-Maïto                                           &Dirent,
3561*23b7c7b8SHermès Bélusca-Maïto #else
3562*23b7c7b8SHermès Bélusca-Maïto                                           (PVOID *)&Dirent,
3563*23b7c7b8SHermès Bélusca-Maïto #endif
3564*23b7c7b8SHermès Bélusca-Maïto                                           FALSE,
3565*23b7c7b8SHermès Bélusca-Maïto                                           TRUE,
3566*23b7c7b8SHermès Bélusca-Maïto                                           &DontCare );
3567*23b7c7b8SHermès Bélusca-Maïto 
3568*23b7c7b8SHermès Bélusca-Maïto             if (Page == 0) {
3569*23b7c7b8SHermès Bélusca-Maïto                 Directory = (PUCHAR)Dirent;
3570*23b7c7b8SHermès Bélusca-Maïto             }
3571*23b7c7b8SHermès Bélusca-Maïto         }
3572*23b7c7b8SHermès Bélusca-Maïto 
3573*23b7c7b8SHermès Bélusca-Maïto         TotalRuns = FsRtlNumberOfRunsInLargeMcb( &Mcb );
3574*23b7c7b8SHermès Bélusca-Maïto 
3575*23b7c7b8SHermès Bélusca-Maïto         for (Run = 0; Run < TotalRuns; Run++) {
3576*23b7c7b8SHermès Bélusca-Maïto 
3577*23b7c7b8SHermès Bélusca-Maïto             LBO Vbo;
3578*23b7c7b8SHermès Bélusca-Maïto             LBO Lbo;
3579*23b7c7b8SHermès Bélusca-Maïto 
3580*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
3581*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress:28931, "needed for debug build" )
3582*23b7c7b8SHermès Bélusca-Maïto #endif
3583*23b7c7b8SHermès Bélusca-Maïto             Result = FsRtlGetNextLargeMcbEntry( &Mcb,
3584*23b7c7b8SHermès Bélusca-Maïto                                                 Run,
3585*23b7c7b8SHermès Bélusca-Maïto                                                 &Vbo,
3586*23b7c7b8SHermès Bélusca-Maïto                                                 &Lbo,
3587*23b7c7b8SHermès Bélusca-Maïto                                                 (PLONGLONG)&BytesUsed );
3588*23b7c7b8SHermès Bélusca-Maïto 
3589*23b7c7b8SHermès Bélusca-Maïto             NT_ASSERT(Result);
3590*23b7c7b8SHermès Bélusca-Maïto 
3591*23b7c7b8SHermès Bélusca-Maïto             //
3592*23b7c7b8SHermès Bélusca-Maïto             //  Copy each run to their specific pool.
3593*23b7c7b8SHermès Bélusca-Maïto             //
3594*23b7c7b8SHermès Bélusca-Maïto 
3595*23b7c7b8SHermès Bélusca-Maïto             if (Lbo != -1) {
3596*23b7c7b8SHermès Bélusca-Maïto 
3597*23b7c7b8SHermès Bélusca-Maïto                 RtlCopyMemory( UsedDirents,
3598*23b7c7b8SHermès Bélusca-Maïto                                Directory + Vbo,
3599*23b7c7b8SHermès Bélusca-Maïto                                (ULONG) BytesUsed );
3600*23b7c7b8SHermès Bélusca-Maïto 
3601*23b7c7b8SHermès Bélusca-Maïto                 UsedDirents += BytesUsed;
3602*23b7c7b8SHermès Bélusca-Maïto 
3603*23b7c7b8SHermès Bélusca-Maïto             } else {
3604*23b7c7b8SHermès Bélusca-Maïto 
3605*23b7c7b8SHermès Bélusca-Maïto                 RtlCopyMemory( UnusedDirents,
3606*23b7c7b8SHermès Bélusca-Maïto                                Directory + Vbo,
3607*23b7c7b8SHermès Bélusca-Maïto                                (ULONG) BytesUsed );
3608*23b7c7b8SHermès Bélusca-Maïto 
3609*23b7c7b8SHermès Bélusca-Maïto                 UnusedDirents += BytesUsed;
3610*23b7c7b8SHermès Bélusca-Maïto             }
3611*23b7c7b8SHermès Bélusca-Maïto         }
3612*23b7c7b8SHermès Bélusca-Maïto 
3613*23b7c7b8SHermès Bélusca-Maïto         //
3614*23b7c7b8SHermès Bélusca-Maïto         //  Marking all the un-used dirents as "deleted".  This will reclaim
3615*23b7c7b8SHermès Bélusca-Maïto         //  storage used by orphaned LFNs.
3616*23b7c7b8SHermès Bélusca-Maïto         //
3617*23b7c7b8SHermès Bélusca-Maïto 
3618*23b7c7b8SHermès Bélusca-Maïto         for (Char = UnusedDirentBuffer; Char < UnusedDirents; Char += sizeof(DIRENT)) {
3619*23b7c7b8SHermès Bélusca-Maïto 
3620*23b7c7b8SHermès Bélusca-Maïto             *Char = FAT_DIRENT_DELETED;
3621*23b7c7b8SHermès Bélusca-Maïto         }
3622*23b7c7b8SHermès Bélusca-Maïto 
3623*23b7c7b8SHermès Bélusca-Maïto         //
3624*23b7c7b8SHermès Bélusca-Maïto         //  Now, for the permanent step.  Copy the two pool buffer back to the
3625*23b7c7b8SHermès Bélusca-Maïto         //  real Dcb directory, and flush the Dcb directory
3626*23b7c7b8SHermès Bélusca-Maïto         //
3627*23b7c7b8SHermès Bélusca-Maïto 
3628*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( TotalBytesAllocated == (ULONG)(UsedDirents - UsedDirentBuffer) );
3629*23b7c7b8SHermès Bélusca-Maïto 
3630*23b7c7b8SHermès Bélusca-Maïto         RtlCopyMemory( Directory, UsedDirentBuffer, TotalBytesAllocated );
3631*23b7c7b8SHermès Bélusca-Maïto 
3632*23b7c7b8SHermès Bélusca-Maïto         RtlCopyMemory( Directory + TotalBytesAllocated,
3633*23b7c7b8SHermès Bélusca-Maïto                        UnusedDirentBuffer,
3634*23b7c7b8SHermès Bélusca-Maïto                        UnusedDirents - UnusedDirentBuffer );
3635*23b7c7b8SHermès Bélusca-Maïto 
3636*23b7c7b8SHermès Bélusca-Maïto         //
3637*23b7c7b8SHermès Bélusca-Maïto         //  We need to unpin here so that the UnpinRepinned won't deadlock.
3638*23b7c7b8SHermès Bélusca-Maïto         //
3639*23b7c7b8SHermès Bélusca-Maïto 
3640*23b7c7b8SHermès Bélusca-Maïto         if (Bcbs) {
3641*23b7c7b8SHermès Bélusca-Maïto             for (Page = 0; Page < PagesPinned; Page += 1) {
3642*23b7c7b8SHermès Bélusca-Maïto                 FatUnpinBcb( IrpContext, Bcbs[Page] );
3643*23b7c7b8SHermès Bélusca-Maïto             }
3644*23b7c7b8SHermès Bélusca-Maïto             ExFreePool(Bcbs);
3645*23b7c7b8SHermès Bélusca-Maïto             Bcbs = NULL;
3646*23b7c7b8SHermès Bélusca-Maïto         }
3647*23b7c7b8SHermès Bélusca-Maïto 
3648*23b7c7b8SHermès Bélusca-Maïto         //
3649*23b7c7b8SHermès Bélusca-Maïto         //  Now make the free dirent bitmap reflect the new state of the Dcb
3650*23b7c7b8SHermès Bélusca-Maïto         //  directory.
3651*23b7c7b8SHermès Bélusca-Maïto         //
3652*23b7c7b8SHermès Bélusca-Maïto 
3653*23b7c7b8SHermès Bélusca-Maïto         RtlSetBits( &Dcb->Specific.Dcb.FreeDirentBitmap,
3654*23b7c7b8SHermès Bélusca-Maïto                     0,
3655*23b7c7b8SHermès Bélusca-Maïto                     TotalBytesAllocated / sizeof(DIRENT) );
3656*23b7c7b8SHermès Bélusca-Maïto 
3657*23b7c7b8SHermès Bélusca-Maïto         RtlClearBits( &Dcb->Specific.Dcb.FreeDirentBitmap,
3658*23b7c7b8SHermès Bélusca-Maïto                       TotalBytesAllocated / sizeof(DIRENT),
3659*23b7c7b8SHermès Bélusca-Maïto                       (DcbSize - TotalBytesAllocated) / sizeof(DIRENT) );
3660*23b7c7b8SHermès Bélusca-Maïto 
3661*23b7c7b8SHermès Bélusca-Maïto         ReturnValue = TotalBytesAllocated / sizeof(DIRENT);
3662*23b7c7b8SHermès Bélusca-Maïto 
3663*23b7c7b8SHermès Bélusca-Maïto         //
3664*23b7c7b8SHermès Bélusca-Maïto         //  Flush the directory to disk.  If we raise, we will need to invalidate
3665*23b7c7b8SHermès Bélusca-Maïto         //  all of the children.  Sorry, guys, but I can't figure out where you are
3666*23b7c7b8SHermès Bélusca-Maïto         //  now - if this failed I probably can't read the media either.  And we
3667*23b7c7b8SHermès Bélusca-Maïto         //  probably purged the cache to boot.
3668*23b7c7b8SHermès Bélusca-Maïto         //
3669*23b7c7b8SHermès Bélusca-Maïto 
3670*23b7c7b8SHermès Bélusca-Maïto         _SEH2_TRY {
3671*23b7c7b8SHermès Bélusca-Maïto 
3672*23b7c7b8SHermès Bélusca-Maïto             FatUnpinRepinnedBcbs( IrpContext );
3673*23b7c7b8SHermès Bélusca-Maïto 
3674*23b7c7b8SHermès Bélusca-Maïto         } _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
3675*23b7c7b8SHermès Bélusca-Maïto                  EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
3676*23b7c7b8SHermès Bélusca-Maïto 
3677*23b7c7b8SHermès Bélusca-Maïto               InvalidateFcbs = TRUE;
3678*23b7c7b8SHermès Bélusca-Maïto         } _SEH2_END;
3679*23b7c7b8SHermès Bélusca-Maïto 
3680*23b7c7b8SHermès Bélusca-Maïto         //
3681*23b7c7b8SHermès Bélusca-Maïto         //  OK, now nothing can go wrong.  We have two more things to do.
3682*23b7c7b8SHermès Bélusca-Maïto         //  First, we have to fix up all the dirent offsets in any open Fcbs.
3683*23b7c7b8SHermès Bélusca-Maïto         //  If we cannot now find the Fcb, the file is marked invalid.  Also,
3684*23b7c7b8SHermès Bélusca-Maïto         //  we skip deleted files.
3685*23b7c7b8SHermès Bélusca-Maïto         //
3686*23b7c7b8SHermès Bélusca-Maïto 
3687*23b7c7b8SHermès Bélusca-Maïto         for (Links = Dcb->Specific.Dcb.ParentDcbQueue.Flink;
3688*23b7c7b8SHermès Bélusca-Maïto              Links != &Dcb->Specific.Dcb.ParentDcbQueue;
3689*23b7c7b8SHermès Bélusca-Maïto              Links = Links->Flink) {
3690*23b7c7b8SHermès Bélusca-Maïto 
3691*23b7c7b8SHermès Bélusca-Maïto             PBCB TmpBcb = NULL;
3692*23b7c7b8SHermès Bélusca-Maïto             ULONG TmpOffset = 0;
3693*23b7c7b8SHermès Bélusca-Maïto             PDIRENT TmpDirent = NULL;
3694*23b7c7b8SHermès Bélusca-Maïto             ULONG PreviousLfnSpread;
3695*23b7c7b8SHermès Bélusca-Maïto 
3696*23b7c7b8SHermès Bélusca-Maïto             Fcb = CONTAINING_RECORD( Links, FCB, ParentDcbLinks );
3697*23b7c7b8SHermès Bélusca-Maïto 
3698*23b7c7b8SHermès Bélusca-Maïto             if (IsFileDeleted( IrpContext, Fcb )) {
3699*23b7c7b8SHermès Bélusca-Maïto 
3700*23b7c7b8SHermès Bélusca-Maïto                 continue;
3701*23b7c7b8SHermès Bélusca-Maïto             }
3702*23b7c7b8SHermès Bélusca-Maïto 
3703*23b7c7b8SHermès Bélusca-Maïto             //
3704*23b7c7b8SHermès Bélusca-Maïto             //  If we aren't already giving up, safely try to pick up the dirent
3705*23b7c7b8SHermès Bélusca-Maïto             //  to update the Fcb.  If this raises, we have to give up and blow
3706*23b7c7b8SHermès Bélusca-Maïto             //  evenyone else away too.
3707*23b7c7b8SHermès Bélusca-Maïto             //
3708*23b7c7b8SHermès Bélusca-Maïto 
3709*23b7c7b8SHermès Bélusca-Maïto             if (!InvalidateFcbs) {
3710*23b7c7b8SHermès Bélusca-Maïto 
3711*23b7c7b8SHermès Bélusca-Maïto                 _SEH2_TRY {
3712*23b7c7b8SHermès Bélusca-Maïto 
3713*23b7c7b8SHermès Bélusca-Maïto                     FatLocateSimpleOemDirent( IrpContext,
3714*23b7c7b8SHermès Bélusca-Maïto                                               Dcb,
3715*23b7c7b8SHermès Bélusca-Maïto                                               &Fcb->ShortName.Name.Oem,
3716*23b7c7b8SHermès Bélusca-Maïto                                               &TmpDirent,
3717*23b7c7b8SHermès Bélusca-Maïto                                               &TmpBcb,
3718*23b7c7b8SHermès Bélusca-Maïto                                               (PVBO)&TmpOffset );
3719*23b7c7b8SHermès Bélusca-Maïto 
3720*23b7c7b8SHermès Bélusca-Maïto                 } _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
3721*23b7c7b8SHermès Bélusca-Maïto                          EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
3722*23b7c7b8SHermès Bélusca-Maïto 
3723*23b7c7b8SHermès Bélusca-Maïto                       InvalidateFcbs = TRUE;
3724*23b7c7b8SHermès Bélusca-Maïto                 } _SEH2_END;
3725*23b7c7b8SHermès Bélusca-Maïto             }
3726*23b7c7b8SHermès Bélusca-Maïto 
3727*23b7c7b8SHermès Bélusca-Maïto             if (TmpBcb == NULL || InvalidateFcbs) {
3728*23b7c7b8SHermès Bélusca-Maïto 
3729*23b7c7b8SHermès Bélusca-Maïto                 FatUnpinBcb( IrpContext, TmpBcb );
3730*23b7c7b8SHermès Bélusca-Maïto                 FatMarkFcbCondition( IrpContext, Fcb, FcbBad, TRUE );
3731*23b7c7b8SHermès Bélusca-Maïto 
3732*23b7c7b8SHermès Bélusca-Maïto             } else {
3733*23b7c7b8SHermès Bélusca-Maïto 
3734*23b7c7b8SHermès Bélusca-Maïto                 FatUnpinBcb( IrpContext, TmpBcb );
3735*23b7c7b8SHermès Bélusca-Maïto 
3736*23b7c7b8SHermès Bélusca-Maïto                 PreviousLfnSpread = Fcb->DirentOffsetWithinDirectory -
3737*23b7c7b8SHermès Bélusca-Maïto                                     Fcb->LfnOffsetWithinDirectory;
3738*23b7c7b8SHermès Bélusca-Maïto 
3739*23b7c7b8SHermès Bélusca-Maïto                 Fcb->DirentOffsetWithinDirectory = TmpOffset;
3740*23b7c7b8SHermès Bélusca-Maïto                 Fcb->LfnOffsetWithinDirectory = TmpOffset - PreviousLfnSpread;
3741*23b7c7b8SHermès Bélusca-Maïto             }
3742*23b7c7b8SHermès Bélusca-Maïto         }
3743*23b7c7b8SHermès Bélusca-Maïto 
3744*23b7c7b8SHermès Bélusca-Maïto     try_exit: NOTHING;
3745*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
3746*23b7c7b8SHermès Bélusca-Maïto 
3747*23b7c7b8SHermès Bélusca-Maïto         //
3748*23b7c7b8SHermès Bélusca-Maïto         //  Free all our resources and stuff.
3749*23b7c7b8SHermès Bélusca-Maïto         //
3750*23b7c7b8SHermès Bélusca-Maïto 
3751*23b7c7b8SHermès Bélusca-Maïto         if (McbInitialized) {
3752*23b7c7b8SHermès Bélusca-Maïto             FsRtlUninitializeLargeMcb( &Mcb );
3753*23b7c7b8SHermès Bélusca-Maïto         }
3754*23b7c7b8SHermès Bélusca-Maïto 
3755*23b7c7b8SHermès Bélusca-Maïto         if (Lfn.Buffer) {
3756*23b7c7b8SHermès Bélusca-Maïto             ExFreePool( Lfn.Buffer );
3757*23b7c7b8SHermès Bélusca-Maïto         }
3758*23b7c7b8SHermès Bélusca-Maïto 
3759*23b7c7b8SHermès Bélusca-Maïto         if (UnusedDirentBuffer) {
3760*23b7c7b8SHermès Bélusca-Maïto             ExFreePool( UnusedDirentBuffer );
3761*23b7c7b8SHermès Bélusca-Maïto         }
3762*23b7c7b8SHermès Bélusca-Maïto 
3763*23b7c7b8SHermès Bélusca-Maïto         if (UsedDirentBuffer) {
3764*23b7c7b8SHermès Bélusca-Maïto             ExFreePool( UsedDirentBuffer );
3765*23b7c7b8SHermès Bélusca-Maïto         }
3766*23b7c7b8SHermès Bélusca-Maïto 
3767*23b7c7b8SHermès Bélusca-Maïto         if (Bcbs) {
3768*23b7c7b8SHermès Bélusca-Maïto             for (Page = 0; Page < PagesPinned; Page += 1) {
3769*23b7c7b8SHermès Bélusca-Maïto                 FatUnpinBcb( IrpContext, Bcbs[Page] );
3770*23b7c7b8SHermès Bélusca-Maïto             }
3771*23b7c7b8SHermès Bélusca-Maïto             ExFreePool(Bcbs);
3772*23b7c7b8SHermès Bélusca-Maïto         }
3773*23b7c7b8SHermès Bélusca-Maïto 
3774*23b7c7b8SHermès Bélusca-Maïto         FatUnpinBcb( IrpContext, Bcb );
3775*23b7c7b8SHermès Bélusca-Maïto 
3776*23b7c7b8SHermès Bélusca-Maïto         for (Links = Dcb->Specific.Dcb.ParentDcbQueue.Flink;
3777*23b7c7b8SHermès Bélusca-Maïto              Links != &Dcb->Specific.Dcb.ParentDcbQueue;
3778*23b7c7b8SHermès Bélusca-Maïto              Links = Links->Flink) {
3779*23b7c7b8SHermès Bélusca-Maïto 
3780*23b7c7b8SHermès Bélusca-Maïto             Fcb = CONTAINING_RECORD( Links, FCB, ParentDcbLinks );
3781*23b7c7b8SHermès Bélusca-Maïto 
3782*23b7c7b8SHermès Bélusca-Maïto             ExReleaseResourceLite( Fcb->Header.Resource );
3783*23b7c7b8SHermès Bélusca-Maïto         }
3784*23b7c7b8SHermès Bélusca-Maïto 
3785*23b7c7b8SHermès Bélusca-Maïto         IrpContext->Flags = SavedIrpContextFlag;
3786*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
3787*23b7c7b8SHermès Bélusca-Maïto 
3788*23b7c7b8SHermès Bélusca-Maïto     //
3789*23b7c7b8SHermès Bélusca-Maïto     //  Now return the offset of the first free dirent to the caller.
3790*23b7c7b8SHermès Bélusca-Maïto     //
3791*23b7c7b8SHermès Bélusca-Maïto 
3792*23b7c7b8SHermès Bélusca-Maïto     return ReturnValue;
3793*23b7c7b8SHermès Bélusca-Maïto }
3794*23b7c7b8SHermès Bélusca-Maïto 
3795*23b7c7b8SHermès Bélusca-Maïto 
3796*23b7c7b8SHermès Bélusca-Maïto 
3797