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