2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/fs/vfat/dir.c
5 * PURPOSE: VFAT Filesystem : directory control
11 /* INCLUDES *****************************************************************/
18 /* FUNCTIONS ****************************************************************/
20 /* Function like DosDateTimeToFileTime */
22 FsdDosDateTimeToSystemTime(
23 PDEVICE_EXTENSION DeviceExt
,
26 PLARGE_INTEGER SystemTime
)
28 PDOSTIME pdtime
= (PDOSTIME
)&DosTime
;
29 PDOSDATE pddate
= (PDOSDATE
)&DosDate
;
30 TIME_FIELDS TimeFields
;
31 LARGE_INTEGER LocalTime
;
33 if (SystemTime
== NULL
)
36 TimeFields
.Milliseconds
= 0;
37 TimeFields
.Second
= pdtime
->Second
* 2;
38 TimeFields
.Minute
= pdtime
->Minute
;
39 TimeFields
.Hour
= pdtime
->Hour
;
41 TimeFields
.Day
= pddate
->Day
;
42 TimeFields
.Month
= pddate
->Month
;
43 TimeFields
.Year
= (CSHORT
)(DeviceExt
->BaseDateYear
+ pddate
->Year
);
45 RtlTimeFieldsToTime(&TimeFields
, &LocalTime
);
46 ExLocalTimeToSystemTime(&LocalTime
, SystemTime
);
51 /* Function like FileTimeToDosDateTime */
53 FsdSystemTimeToDosDateTime(
54 PDEVICE_EXTENSION DeviceExt
,
55 PLARGE_INTEGER SystemTime
,
59 PDOSTIME pdtime
= (PDOSTIME
)pDosTime
;
60 PDOSDATE pddate
= (PDOSDATE
)pDosDate
;
61 TIME_FIELDS TimeFields
;
62 LARGE_INTEGER LocalTime
;
64 if (SystemTime
== NULL
)
67 ExSystemTimeToLocalTime(SystemTime
, &LocalTime
);
68 RtlTimeToTimeFields(&LocalTime
, &TimeFields
);
72 pdtime
->Second
= TimeFields
.Second
/ 2;
73 pdtime
->Minute
= TimeFields
.Minute
;
74 pdtime
->Hour
= TimeFields
.Hour
;
79 pddate
->Day
= TimeFields
.Day
;
80 pddate
->Month
= TimeFields
.Month
;
81 pddate
->Year
= (USHORT
) (TimeFields
.Year
- DeviceExt
->BaseDateYear
);
87 #define ULONG_ROUND_UP(x) ROUND_UP((x), (sizeof(ULONG)))
91 VfatGetFileNameInformation(
92 PVFAT_DIRENTRY_CONTEXT DirContext
,
93 PFILE_NAMES_INFORMATION pInfo
,
96 if ((sizeof(FILE_DIRECTORY_INFORMATION
) + DirContext
->LongNameU
.Length
) > BufferLength
)
97 return STATUS_BUFFER_OVERFLOW
;
99 pInfo
->FileNameLength
= DirContext
->LongNameU
.Length
;
100 pInfo
->NextEntryOffset
= ULONG_ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION
) +
101 DirContext
->LongNameU
.Length
);
103 RtlCopyMemory(pInfo
->FileName
,
104 DirContext
->LongNameU
.Buffer
,
105 DirContext
->LongNameU
.Length
);
107 return STATUS_SUCCESS
;
112 VfatGetFileDirectoryInformation(
113 PVFAT_DIRENTRY_CONTEXT DirContext
,
114 PDEVICE_EXTENSION DeviceExt
,
115 PFILE_DIRECTORY_INFORMATION pInfo
,
118 if ((sizeof(FILE_DIRECTORY_INFORMATION
) + DirContext
->LongNameU
.Length
) > BufferLength
)
119 return STATUS_BUFFER_OVERFLOW
;
121 pInfo
->FileNameLength
= DirContext
->LongNameU
.Length
;
122 pInfo
->NextEntryOffset
= ULONG_ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION
) +
123 DirContext
->LongNameU
.Length
);
124 /* pInfo->FileIndex = ; */
126 RtlCopyMemory(pInfo
->FileName
,
127 DirContext
->LongNameU
.Buffer
,
128 DirContext
->LongNameU
.Length
);
130 if (DeviceExt
->Flags
& VCB_IS_FATX
)
132 FsdDosDateTimeToSystemTime(DeviceExt
,
133 DirContext
->DirEntry
.FatX
.CreationDate
,
134 DirContext
->DirEntry
.FatX
.CreationTime
,
135 &pInfo
->CreationTime
);
136 FsdDosDateTimeToSystemTime(DeviceExt
,
137 DirContext
->DirEntry
.FatX
.AccessDate
,
138 DirContext
->DirEntry
.FatX
.AccessTime
,
139 &pInfo
->LastAccessTime
);
140 FsdDosDateTimeToSystemTime(DeviceExt
,
141 DirContext
->DirEntry
.FatX
.UpdateDate
,
142 DirContext
->DirEntry
.FatX
.UpdateTime
,
143 &pInfo
->LastWriteTime
);
145 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
147 if (DirContext
->DirEntry
.FatX
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
149 pInfo
->EndOfFile
.QuadPart
= 0;
150 pInfo
->AllocationSize
.QuadPart
= 0;
154 pInfo
->EndOfFile
.u
.HighPart
= 0;
155 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.FatX
.FileSize
;
156 /* Make allocsize a rounded up multiple of BytesPerCluster */
157 pInfo
->AllocationSize
.u
.HighPart
= 0;
158 pInfo
->AllocationSize
.u
.LowPart
= ROUND_UP(DirContext
->DirEntry
.FatX
.FileSize
,
159 DeviceExt
->FatInfo
.BytesPerCluster
);
162 pInfo
->FileAttributes
= DirContext
->DirEntry
.FatX
.Attrib
& 0x3f;
166 FsdDosDateTimeToSystemTime(DeviceExt
,
167 DirContext
->DirEntry
.Fat
.CreationDate
,
168 DirContext
->DirEntry
.Fat
.CreationTime
,
169 &pInfo
->CreationTime
);
170 FsdDosDateTimeToSystemTime(DeviceExt
,
171 DirContext
->DirEntry
.Fat
.AccessDate
,
173 &pInfo
->LastAccessTime
);
174 FsdDosDateTimeToSystemTime(DeviceExt
,
175 DirContext
->DirEntry
.Fat
.UpdateDate
,
176 DirContext
->DirEntry
.Fat
.UpdateTime
,
177 &pInfo
->LastWriteTime
);
179 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
181 if (DirContext
->DirEntry
.Fat
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
183 pInfo
->EndOfFile
.QuadPart
= 0;
184 pInfo
->AllocationSize
.QuadPart
= 0;
188 pInfo
->EndOfFile
.u
.HighPart
= 0;
189 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.Fat
.FileSize
;
190 /* Make allocsize a rounded up multiple of BytesPerCluster */
191 pInfo
->AllocationSize
.u
.HighPart
= 0;
192 pInfo
->AllocationSize
.u
.LowPart
= ROUND_UP(DirContext
->DirEntry
.Fat
.FileSize
,
193 DeviceExt
->FatInfo
.BytesPerCluster
);
196 pInfo
->FileAttributes
= DirContext
->DirEntry
.Fat
.Attrib
& 0x3f;
199 return STATUS_SUCCESS
;
204 VfatGetFileFullDirectoryInformation(
205 PVFAT_DIRENTRY_CONTEXT DirContext
,
206 PDEVICE_EXTENSION DeviceExt
,
207 PFILE_FULL_DIR_INFORMATION pInfo
,
210 if ((sizeof(FILE_FULL_DIR_INFORMATION
) + DirContext
->LongNameU
.Length
) > BufferLength
)
211 return STATUS_BUFFER_OVERFLOW
;
213 pInfo
->FileNameLength
= DirContext
->LongNameU
.Length
;
214 pInfo
->NextEntryOffset
= ULONG_ROUND_UP(sizeof(FILE_FULL_DIR_INFORMATION
) +
215 DirContext
->LongNameU
.Length
);
216 /* pInfo->FileIndex = ; */
217 /* pInfo->EaSize = ; */
219 RtlCopyMemory(pInfo
->FileName
,
220 DirContext
->LongNameU
.Buffer
,
221 DirContext
->LongNameU
.Length
);
223 if (DeviceExt
->Flags
& VCB_IS_FATX
)
225 FsdDosDateTimeToSystemTime(DeviceExt
,
226 DirContext
->DirEntry
.FatX
.CreationDate
,
227 DirContext
->DirEntry
.FatX
.CreationTime
,
228 &pInfo
->CreationTime
);
229 FsdDosDateTimeToSystemTime(DeviceExt
,
230 DirContext
->DirEntry
.FatX
.AccessDate
,
231 DirContext
->DirEntry
.FatX
.AccessTime
,
232 &pInfo
->LastAccessTime
);
233 FsdDosDateTimeToSystemTime(DeviceExt
,
234 DirContext
->DirEntry
.FatX
.UpdateDate
,
235 DirContext
->DirEntry
.FatX
.UpdateTime
,
236 &pInfo
->LastWriteTime
);
238 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
239 pInfo
->EndOfFile
.u
.HighPart
= 0;
240 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.FatX
.FileSize
;
241 /* Make allocsize a rounded up multiple of BytesPerCluster */
242 pInfo
->AllocationSize
.u
.HighPart
= 0;
243 pInfo
->AllocationSize
.u
.LowPart
= ROUND_UP(DirContext
->DirEntry
.FatX
.FileSize
,
244 DeviceExt
->FatInfo
.BytesPerCluster
);
245 pInfo
->FileAttributes
= DirContext
->DirEntry
.FatX
.Attrib
& 0x3f;
249 FsdDosDateTimeToSystemTime(DeviceExt
,
250 DirContext
->DirEntry
.Fat
.CreationDate
,
251 DirContext
->DirEntry
.Fat
.CreationTime
,
252 &pInfo
->CreationTime
);
253 FsdDosDateTimeToSystemTime(DeviceExt
,
254 DirContext
->DirEntry
.Fat
.AccessDate
,
256 &pInfo
->LastAccessTime
);
257 FsdDosDateTimeToSystemTime(DeviceExt
,
258 DirContext
->DirEntry
.Fat
.UpdateDate
,
259 DirContext
->DirEntry
.Fat
.UpdateTime
,
260 &pInfo
->LastWriteTime
);
262 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
263 pInfo
->EndOfFile
.u
.HighPart
= 0;
264 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.Fat
.FileSize
;
265 /* Make allocsize a rounded up multiple of BytesPerCluster */
266 pInfo
->AllocationSize
.u
.HighPart
= 0;
267 pInfo
->AllocationSize
.u
.LowPart
= ROUND_UP(DirContext
->DirEntry
.Fat
.FileSize
,
268 DeviceExt
->FatInfo
.BytesPerCluster
);
269 pInfo
->FileAttributes
= DirContext
->DirEntry
.Fat
.Attrib
& 0x3f;
272 return STATUS_SUCCESS
;
277 VfatGetFileBothInformation(
278 PVFAT_DIRENTRY_CONTEXT DirContext
,
279 PDEVICE_EXTENSION DeviceExt
,
280 PFILE_BOTH_DIR_INFORMATION pInfo
,
283 if ((sizeof(FILE_BOTH_DIR_INFORMATION
) + DirContext
->LongNameU
.Length
) > BufferLength
)
284 return STATUS_BUFFER_OVERFLOW
;
288 if (DeviceExt
->Flags
& VCB_IS_FATX
)
290 pInfo
->FileNameLength
= DirContext
->LongNameU
.Length
;
292 RtlCopyMemory(pInfo
->FileName
,
293 DirContext
->LongNameU
.Buffer
,
294 DirContext
->LongNameU
.Length
);
296 pInfo
->NextEntryOffset
= ULONG_ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION
) +
297 DirContext
->LongNameU
.Length
);
298 pInfo
->ShortName
[0] = 0;
299 pInfo
->ShortNameLength
= 0;
300 /* pInfo->FileIndex = ; */
302 FsdDosDateTimeToSystemTime(DeviceExt
,
303 DirContext
->DirEntry
.FatX
.CreationDate
,
304 DirContext
->DirEntry
.FatX
.CreationTime
,
305 &pInfo
->CreationTime
);
306 FsdDosDateTimeToSystemTime(DeviceExt
,
307 DirContext
->DirEntry
.FatX
.AccessDate
,
308 DirContext
->DirEntry
.FatX
.AccessTime
,
309 &pInfo
->LastAccessTime
);
310 FsdDosDateTimeToSystemTime(DeviceExt
,
311 DirContext
->DirEntry
.FatX
.UpdateDate
,
312 DirContext
->DirEntry
.FatX
.UpdateTime
,
313 &pInfo
->LastWriteTime
);
315 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
317 if (DirContext
->DirEntry
.FatX
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
319 pInfo
->EndOfFile
.QuadPart
= 0;
320 pInfo
->AllocationSize
.QuadPart
= 0;
324 pInfo
->EndOfFile
.u
.HighPart
= 0;
325 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.FatX
.FileSize
;
326 /* Make allocsize a rounded up multiple of BytesPerCluster */
327 pInfo
->AllocationSize
.u
.HighPart
= 0;
328 pInfo
->AllocationSize
.u
.LowPart
= ROUND_UP(DirContext
->DirEntry
.FatX
.FileSize
,
329 DeviceExt
->FatInfo
.BytesPerCluster
);
332 pInfo
->FileAttributes
= DirContext
->DirEntry
.FatX
.Attrib
& 0x3f;
336 pInfo
->FileNameLength
= DirContext
->LongNameU
.Length
;
337 pInfo
->NextEntryOffset
= ULONG_ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION
) +
338 DirContext
->LongNameU
.Length
);
340 RtlCopyMemory(pInfo
->ShortName
,
341 DirContext
->ShortNameU
.Buffer
,
342 DirContext
->ShortNameU
.Length
);
344 pInfo
->ShortNameLength
= (CCHAR
)DirContext
->ShortNameU
.Length
;
346 RtlCopyMemory(pInfo
->FileName
,
347 DirContext
->LongNameU
.Buffer
,
348 DirContext
->LongNameU
.Length
);
350 /* pInfo->FileIndex = ; */
352 FsdDosDateTimeToSystemTime(DeviceExt
,
353 DirContext
->DirEntry
.Fat
.CreationDate
,
354 DirContext
->DirEntry
.Fat
.CreationTime
,
355 &pInfo
->CreationTime
);
356 FsdDosDateTimeToSystemTime(DeviceExt
,
357 DirContext
->DirEntry
.Fat
.AccessDate
,
359 &pInfo
->LastAccessTime
);
360 FsdDosDateTimeToSystemTime(DeviceExt
,
361 DirContext
->DirEntry
.Fat
.UpdateDate
,
362 DirContext
->DirEntry
.Fat
.UpdateTime
,
363 &pInfo
->LastWriteTime
);
365 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
367 if (DirContext
->DirEntry
.Fat
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
369 pInfo
->EndOfFile
.QuadPart
= 0;
370 pInfo
->AllocationSize
.QuadPart
= 0;
374 pInfo
->EndOfFile
.u
.HighPart
= 0;
375 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.Fat
.FileSize
;
376 /* Make allocsize a rounded up multiple of BytesPerCluster */
377 pInfo
->AllocationSize
.u
.HighPart
= 0;
378 pInfo
->AllocationSize
.u
.LowPart
= ROUND_UP(DirContext
->DirEntry
.Fat
.FileSize
, DeviceExt
->FatInfo
.BytesPerCluster
);
381 pInfo
->FileAttributes
= DirContext
->DirEntry
.Fat
.Attrib
& 0x3f;
384 return STATUS_SUCCESS
;
390 PVFAT_IRP_CONTEXT IrpContext
)
392 NTSTATUS Status
= STATUS_SUCCESS
;
393 LONG BufferLength
= 0;
394 PUNICODE_STRING pSearchPattern
= NULL
;
395 FILE_INFORMATION_CLASS FileInformationClass
;
396 PUCHAR Buffer
= NULL
;
397 PFILE_NAMES_INFORMATION Buffer0
= NULL
;
400 BOOLEAN FirstQuery
= FALSE
;
401 BOOLEAN FirstCall
= TRUE
;
402 VFAT_DIRENTRY_CONTEXT DirContext
;
403 WCHAR LongNameBuffer
[LONGNAME_MAX_LENGTH
+ 1];
404 WCHAR ShortNameBuffer
[13];
406 PIO_STACK_LOCATION Stack
= IrpContext
->Stack
;
408 pCcb
= (PVFATCCB
)IrpContext
->FileObject
->FsContext2
;
409 pFcb
= (PVFATFCB
)IrpContext
->FileObject
->FsContext
;
411 /* Determine Buffer for result : */
412 BufferLength
= Stack
->Parameters
.QueryDirectory
.Length
;
414 /* Do not probe the user buffer until SEH is available */
415 if (IrpContext
->Irp
->RequestorMode
!= KernelMode
&&
416 IrpContext
->Irp
->MdlAddress
== NULL
&&
417 IrpContext
->Irp
->UserBuffer
!= NULL
)
419 ProbeForWrite(IrpContext
->Irp
->UserBuffer
, BufferLength
, 1);
422 Buffer
= VfatGetUserBuffer(IrpContext
->Irp
);
424 if (!ExAcquireResourceSharedLite(&pFcb
->MainResource
,
425 (BOOLEAN
)(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
)))
427 Status
= VfatLockUserBuffer(IrpContext
->Irp
, BufferLength
, IoWriteAccess
);
428 if (NT_SUCCESS(Status
))
429 Status
= STATUS_PENDING
;
434 /* Obtain the callers parameters */
436 /* HACKHACK: Bug in the MS ntifs.h header:
437 * FileName is really a PUNICODE_STRING, not a PSTRING */
438 pSearchPattern
= (PUNICODE_STRING
)Stack
->Parameters
.QueryDirectory
.FileName
;
440 pSearchPattern
= Stack
->Parameters
.QueryDirectory
.FileName
;
442 FileInformationClass
= Stack
->Parameters
.QueryDirectory
.FileInformationClass
;
444 /* Allocate search pattern in case:
445 * -> We don't have one already in context
446 * -> We have been given an input pattern
447 * -> The pattern length is not null
448 * -> The pattern buffer is not null
449 * Otherwise, we'll fall later and allocate a match all (*) pattern
451 if (pSearchPattern
&&
452 pSearchPattern
->Length
!= 0 && pSearchPattern
->Buffer
!= NULL
)
454 if (!pCcb
->SearchPattern
.Buffer
)
457 pCcb
->SearchPattern
.MaximumLength
= pSearchPattern
->Length
+ sizeof(WCHAR
);
458 pCcb
->SearchPattern
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
459 pCcb
->SearchPattern
.MaximumLength
,
461 if (!pCcb
->SearchPattern
.Buffer
)
463 ExReleaseResourceLite(&pFcb
->MainResource
);
464 return STATUS_INSUFFICIENT_RESOURCES
;
466 RtlCopyUnicodeString(&pCcb
->SearchPattern
, pSearchPattern
);
467 pCcb
->SearchPattern
.Buffer
[pCcb
->SearchPattern
.Length
/ sizeof(WCHAR
)] = 0;
470 else if (!pCcb
->SearchPattern
.Buffer
)
473 pCcb
->SearchPattern
.MaximumLength
= 2 * sizeof(WCHAR
);
474 pCcb
->SearchPattern
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
477 if (!pCcb
->SearchPattern
.Buffer
)
479 ExReleaseResourceLite(&pFcb
->MainResource
);
480 return STATUS_INSUFFICIENT_RESOURCES
;
482 pCcb
->SearchPattern
.Buffer
[0] = L
'*';
483 pCcb
->SearchPattern
.Buffer
[1] = 0;
484 pCcb
->SearchPattern
.Length
= sizeof(WCHAR
);
487 if (IrpContext
->Stack
->Flags
& SL_INDEX_SPECIFIED
)
489 DirContext
.DirIndex
= pCcb
->Entry
= Stack
->Parameters
.QueryDirectory
.FileIndex
;
491 else if (FirstQuery
|| (IrpContext
->Stack
->Flags
& SL_RESTART_SCAN
))
493 DirContext
.DirIndex
= pCcb
->Entry
= 0;
497 DirContext
.DirIndex
= pCcb
->Entry
;
500 DPRINT("Buffer=%p tofind=%wZ\n", Buffer
, &pCcb
->SearchPattern
);
502 DirContext
.LongNameU
.Buffer
= LongNameBuffer
;
503 DirContext
.LongNameU
.MaximumLength
= sizeof(LongNameBuffer
);
504 DirContext
.ShortNameU
.Buffer
= ShortNameBuffer
;
505 DirContext
.ShortNameU
.MaximumLength
= sizeof(ShortNameBuffer
);
507 while ((Status
== STATUS_SUCCESS
) && (BufferLength
> 0))
509 Status
= FindFile(IrpContext
->DeviceExt
,
511 &pCcb
->SearchPattern
,
514 pCcb
->Entry
= DirContext
.DirIndex
;
516 DPRINT("Found %wZ, Status=%x, entry %x\n", &DirContext
.LongNameU
, Status
, pCcb
->Entry
);
519 if (NT_SUCCESS(Status
))
521 switch (FileInformationClass
)
523 case FileNameInformation
:
524 Status
= VfatGetFileNameInformation(&DirContext
,
525 (PFILE_NAMES_INFORMATION
)Buffer
,
529 case FileDirectoryInformation
:
530 Status
= VfatGetFileDirectoryInformation(&DirContext
,
531 IrpContext
->DeviceExt
,
532 (PFILE_DIRECTORY_INFORMATION
)Buffer
,
536 case FileFullDirectoryInformation
:
537 Status
= VfatGetFileFullDirectoryInformation(&DirContext
,
538 IrpContext
->DeviceExt
,
539 (PFILE_FULL_DIR_INFORMATION
)Buffer
,
543 case FileBothDirectoryInformation
:
544 Status
= VfatGetFileBothInformation(&DirContext
,
545 IrpContext
->DeviceExt
,
546 (PFILE_BOTH_DIR_INFORMATION
)Buffer
,
551 Status
= STATUS_INVALID_INFO_CLASS
;
555 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_INVALID_INFO_CLASS
)
560 Status
= (FirstQuery
? STATUS_NO_SUCH_FILE
: STATUS_NO_MORE_FILES
);
564 Buffer0
= (PFILE_NAMES_INFORMATION
) Buffer
;
565 Buffer0
->FileIndex
= DirContext
.DirIndex
;
566 pCcb
->Entry
= ++DirContext
.DirIndex
;
567 BufferLength
-= Buffer0
->NextEntryOffset
;
569 if (IrpContext
->Stack
->Flags
& SL_RETURN_SINGLE_ENTRY
)
572 Buffer
+= Buffer0
->NextEntryOffset
;
577 Buffer0
->NextEntryOffset
= 0;
578 Status
= STATUS_SUCCESS
;
579 IrpContext
->Irp
->IoStatus
.Information
= Stack
->Parameters
.QueryDirectory
.Length
- BufferLength
;
582 ExReleaseResourceLite(&pFcb
->MainResource
);
587 NTSTATUS
VfatNotifyChangeDirectory(PVFAT_IRP_CONTEXT
* IrpContext
)
591 PIO_STACK_LOCATION Stack
;
592 Stack
= (*IrpContext
)->Stack
;
593 pVcb
= (*IrpContext
)->DeviceExt
;
594 pFcb
= (PVFATFCB
) (*IrpContext
)->FileObject
->FsContext
;
596 FsRtlNotifyFullChangeDirectory(pVcb
->NotifySync
,
598 (*IrpContext
)->FileObject
->FsContext2
,
599 (PSTRING
)&(pFcb
->PathNameU
),
600 BooleanFlagOn(Stack
->Flags
, SL_WATCH_TREE
),
602 Stack
->Parameters
.NotifyDirectory
.CompletionFilter
,
607 /* We don't need the IRP context as we won't handle IRP completion */
608 VfatFreeIrpContext(*IrpContext
);
611 return STATUS_PENDING
;
615 * FUNCTION: directory control : read/write directory informations
618 VfatDirectoryControl(
619 PVFAT_IRP_CONTEXT IrpContext
)
621 NTSTATUS Status
= STATUS_SUCCESS
;
623 IrpContext
->Irp
->IoStatus
.Information
= 0;
625 switch (IrpContext
->MinorFunction
)
627 case IRP_MN_QUERY_DIRECTORY
:
628 Status
= DoQuery (IrpContext
);
631 case IRP_MN_NOTIFY_CHANGE_DIRECTORY
:
632 Status
= VfatNotifyChangeDirectory(&IrpContext
);
637 DPRINT("Unexpected minor function %x in VFAT driver\n",
638 IrpContext
->MinorFunction
);
639 Status
= STATUS_INVALID_DEVICE_REQUEST
;
643 if (Status
== STATUS_PENDING
)
645 /* Only queue if there's IRP context */
648 Status
= VfatQueueRequest(IrpContext
);
653 IrpContext
->Irp
->IoStatus
.Status
= Status
;
654 IoCompleteRequest (IrpContext
->Irp
, IO_NO_INCREMENT
);
655 VfatFreeIrpContext(IrpContext
);