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 *****************************************************************/
16 /* FUNCTIONS ****************************************************************/
18 /* Function like DosDateTimeToFileTime */
20 FsdDosDateTimeToSystemTime(
21 PDEVICE_EXTENSION DeviceExt
,
24 PLARGE_INTEGER SystemTime
)
26 PDOSTIME pdtime
= (PDOSTIME
)&DosTime
;
27 PDOSDATE pddate
= (PDOSDATE
)&DosDate
;
28 TIME_FIELDS TimeFields
;
29 LARGE_INTEGER LocalTime
;
31 if (SystemTime
== NULL
)
34 TimeFields
.Milliseconds
= 0;
35 TimeFields
.Second
= pdtime
->Second
* 2;
36 TimeFields
.Minute
= pdtime
->Minute
;
37 TimeFields
.Hour
= pdtime
->Hour
;
39 TimeFields
.Day
= pddate
->Day
;
40 TimeFields
.Month
= pddate
->Month
;
41 TimeFields
.Year
= (CSHORT
)(DeviceExt
->BaseDateYear
+ pddate
->Year
);
43 RtlTimeFieldsToTime(&TimeFields
, &LocalTime
);
44 ExLocalTimeToSystemTime(&LocalTime
, SystemTime
);
49 /* Function like FileTimeToDosDateTime */
51 FsdSystemTimeToDosDateTime(
52 PDEVICE_EXTENSION DeviceExt
,
53 PLARGE_INTEGER SystemTime
,
57 PDOSTIME pdtime
= (PDOSTIME
)pDosTime
;
58 PDOSDATE pddate
= (PDOSDATE
)pDosDate
;
59 TIME_FIELDS TimeFields
;
60 LARGE_INTEGER LocalTime
;
62 if (SystemTime
== NULL
)
65 ExSystemTimeToLocalTime(SystemTime
, &LocalTime
);
66 RtlTimeToTimeFields(&LocalTime
, &TimeFields
);
70 pdtime
->Second
= TimeFields
.Second
/ 2;
71 pdtime
->Minute
= TimeFields
.Minute
;
72 pdtime
->Hour
= TimeFields
.Hour
;
77 pddate
->Day
= TimeFields
.Day
;
78 pddate
->Month
= TimeFields
.Month
;
79 pddate
->Year
= (USHORT
) (TimeFields
.Year
- DeviceExt
->BaseDateYear
);
85 #define ULONG_ROUND_UP(x) ROUND_UP((x), (sizeof(ULONG)))
89 VfatGetFileNameInformation(
90 PVFAT_DIRENTRY_CONTEXT DirContext
,
91 PFILE_NAMES_INFORMATION pInfo
,
94 if ((sizeof(FILE_DIRECTORY_INFORMATION
) + DirContext
->LongNameU
.Length
) > BufferLength
)
95 return STATUS_BUFFER_OVERFLOW
;
97 pInfo
->FileNameLength
= DirContext
->LongNameU
.Length
;
98 pInfo
->NextEntryOffset
= ULONG_ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION
) +
99 DirContext
->LongNameU
.Length
);
101 RtlCopyMemory(pInfo
->FileName
,
102 DirContext
->LongNameU
.Buffer
,
103 DirContext
->LongNameU
.Length
);
105 return STATUS_SUCCESS
;
110 VfatGetFileDirectoryInformation(
111 PVFAT_DIRENTRY_CONTEXT DirContext
,
112 PDEVICE_EXTENSION DeviceExt
,
113 PFILE_DIRECTORY_INFORMATION pInfo
,
116 if ((sizeof(FILE_DIRECTORY_INFORMATION
) + DirContext
->LongNameU
.Length
) > BufferLength
)
117 return STATUS_BUFFER_OVERFLOW
;
119 pInfo
->FileNameLength
= DirContext
->LongNameU
.Length
;
120 pInfo
->NextEntryOffset
= ULONG_ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION
) +
121 DirContext
->LongNameU
.Length
);
122 /* pInfo->FileIndex = ; */
124 RtlCopyMemory(pInfo
->FileName
,
125 DirContext
->LongNameU
.Buffer
,
126 DirContext
->LongNameU
.Length
);
128 if (DeviceExt
->Flags
& VCB_IS_FATX
)
130 FsdDosDateTimeToSystemTime(DeviceExt
,
131 DirContext
->DirEntry
.FatX
.CreationDate
,
132 DirContext
->DirEntry
.FatX
.CreationTime
,
133 &pInfo
->CreationTime
);
134 FsdDosDateTimeToSystemTime(DeviceExt
,
135 DirContext
->DirEntry
.FatX
.AccessDate
,
136 DirContext
->DirEntry
.FatX
.AccessTime
,
137 &pInfo
->LastAccessTime
);
138 FsdDosDateTimeToSystemTime(DeviceExt
,
139 DirContext
->DirEntry
.FatX
.UpdateDate
,
140 DirContext
->DirEntry
.FatX
.UpdateTime
,
141 &pInfo
->LastWriteTime
);
143 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
145 if (DirContext
->DirEntry
.FatX
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
147 pInfo
->EndOfFile
.QuadPart
= 0;
148 pInfo
->AllocationSize
.QuadPart
= 0;
152 pInfo
->EndOfFile
.u
.HighPart
= 0;
153 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.FatX
.FileSize
;
154 /* Make allocsize a rounded up multiple of BytesPerCluster */
155 pInfo
->AllocationSize
.u
.HighPart
= 0;
156 pInfo
->AllocationSize
.u
.LowPart
= ROUND_UP(DirContext
->DirEntry
.FatX
.FileSize
,
157 DeviceExt
->FatInfo
.BytesPerCluster
);
160 pInfo
->FileAttributes
= DirContext
->DirEntry
.FatX
.Attrib
& 0x3f;
164 FsdDosDateTimeToSystemTime(DeviceExt
,
165 DirContext
->DirEntry
.Fat
.CreationDate
,
166 DirContext
->DirEntry
.Fat
.CreationTime
,
167 &pInfo
->CreationTime
);
168 FsdDosDateTimeToSystemTime(DeviceExt
,
169 DirContext
->DirEntry
.Fat
.AccessDate
,
171 &pInfo
->LastAccessTime
);
172 FsdDosDateTimeToSystemTime(DeviceExt
,
173 DirContext
->DirEntry
.Fat
.UpdateDate
,
174 DirContext
->DirEntry
.Fat
.UpdateTime
,
175 &pInfo
->LastWriteTime
);
177 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
179 if (DirContext
->DirEntry
.Fat
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
181 pInfo
->EndOfFile
.QuadPart
= 0;
182 pInfo
->AllocationSize
.QuadPart
= 0;
186 pInfo
->EndOfFile
.u
.HighPart
= 0;
187 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.Fat
.FileSize
;
188 /* Make allocsize a rounded up multiple of BytesPerCluster */
189 pInfo
->AllocationSize
.u
.HighPart
= 0;
190 pInfo
->AllocationSize
.u
.LowPart
= ROUND_UP(DirContext
->DirEntry
.Fat
.FileSize
,
191 DeviceExt
->FatInfo
.BytesPerCluster
);
194 pInfo
->FileAttributes
= DirContext
->DirEntry
.Fat
.Attrib
& 0x3f;
197 return STATUS_SUCCESS
;
202 VfatGetFileFullDirectoryInformation(
203 PVFAT_DIRENTRY_CONTEXT DirContext
,
204 PDEVICE_EXTENSION DeviceExt
,
205 PFILE_FULL_DIR_INFORMATION pInfo
,
208 if ((sizeof(FILE_FULL_DIR_INFORMATION
) + DirContext
->LongNameU
.Length
) > BufferLength
)
209 return STATUS_BUFFER_OVERFLOW
;
211 pInfo
->FileNameLength
= DirContext
->LongNameU
.Length
;
212 pInfo
->NextEntryOffset
= ULONG_ROUND_UP(sizeof(FILE_FULL_DIR_INFORMATION
) +
213 DirContext
->LongNameU
.Length
);
214 /* pInfo->FileIndex = ; */
215 /* pInfo->EaSize = ; */
217 RtlCopyMemory(pInfo
->FileName
,
218 DirContext
->LongNameU
.Buffer
,
219 DirContext
->LongNameU
.Length
);
221 if (DeviceExt
->Flags
& VCB_IS_FATX
)
223 FsdDosDateTimeToSystemTime(DeviceExt
,
224 DirContext
->DirEntry
.FatX
.CreationDate
,
225 DirContext
->DirEntry
.FatX
.CreationTime
,
226 &pInfo
->CreationTime
);
227 FsdDosDateTimeToSystemTime(DeviceExt
,
228 DirContext
->DirEntry
.FatX
.AccessDate
,
229 DirContext
->DirEntry
.FatX
.AccessTime
,
230 &pInfo
->LastAccessTime
);
231 FsdDosDateTimeToSystemTime(DeviceExt
,
232 DirContext
->DirEntry
.FatX
.UpdateDate
,
233 DirContext
->DirEntry
.FatX
.UpdateTime
,
234 &pInfo
->LastWriteTime
);
236 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
237 pInfo
->EndOfFile
.u
.HighPart
= 0;
238 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.FatX
.FileSize
;
239 /* Make allocsize a rounded up multiple of BytesPerCluster */
240 pInfo
->AllocationSize
.u
.HighPart
= 0;
241 pInfo
->AllocationSize
.u
.LowPart
= ROUND_UP(DirContext
->DirEntry
.FatX
.FileSize
,
242 DeviceExt
->FatInfo
.BytesPerCluster
);
243 pInfo
->FileAttributes
= DirContext
->DirEntry
.FatX
.Attrib
& 0x3f;
247 FsdDosDateTimeToSystemTime(DeviceExt
,
248 DirContext
->DirEntry
.Fat
.CreationDate
,
249 DirContext
->DirEntry
.Fat
.CreationTime
,
250 &pInfo
->CreationTime
);
251 FsdDosDateTimeToSystemTime(DeviceExt
,
252 DirContext
->DirEntry
.Fat
.AccessDate
,
254 &pInfo
->LastAccessTime
);
255 FsdDosDateTimeToSystemTime(DeviceExt
,
256 DirContext
->DirEntry
.Fat
.UpdateDate
,
257 DirContext
->DirEntry
.Fat
.UpdateTime
,
258 &pInfo
->LastWriteTime
);
260 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
261 pInfo
->EndOfFile
.u
.HighPart
= 0;
262 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.Fat
.FileSize
;
263 /* Make allocsize a rounded up multiple of BytesPerCluster */
264 pInfo
->AllocationSize
.u
.HighPart
= 0;
265 pInfo
->AllocationSize
.u
.LowPart
= ROUND_UP(DirContext
->DirEntry
.Fat
.FileSize
,
266 DeviceExt
->FatInfo
.BytesPerCluster
);
267 pInfo
->FileAttributes
= DirContext
->DirEntry
.Fat
.Attrib
& 0x3f;
270 return STATUS_SUCCESS
;
275 VfatGetFileBothInformation(
276 PVFAT_DIRENTRY_CONTEXT DirContext
,
277 PDEVICE_EXTENSION DeviceExt
,
278 PFILE_BOTH_DIR_INFORMATION pInfo
,
281 if ((sizeof(FILE_BOTH_DIR_INFORMATION
) + DirContext
->LongNameU
.Length
) > BufferLength
)
282 return STATUS_BUFFER_OVERFLOW
;
286 if (DeviceExt
->Flags
& VCB_IS_FATX
)
288 pInfo
->FileNameLength
= DirContext
->LongNameU
.Length
;
290 RtlCopyMemory(pInfo
->FileName
,
291 DirContext
->LongNameU
.Buffer
,
292 DirContext
->LongNameU
.Length
);
294 pInfo
->NextEntryOffset
= ULONG_ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION
) +
295 DirContext
->LongNameU
.Length
);
296 pInfo
->ShortName
[0] = 0;
297 pInfo
->ShortNameLength
= 0;
298 /* pInfo->FileIndex = ; */
300 FsdDosDateTimeToSystemTime(DeviceExt
,
301 DirContext
->DirEntry
.FatX
.CreationDate
,
302 DirContext
->DirEntry
.FatX
.CreationTime
,
303 &pInfo
->CreationTime
);
304 FsdDosDateTimeToSystemTime(DeviceExt
,
305 DirContext
->DirEntry
.FatX
.AccessDate
,
306 DirContext
->DirEntry
.FatX
.AccessTime
,
307 &pInfo
->LastAccessTime
);
308 FsdDosDateTimeToSystemTime(DeviceExt
,
309 DirContext
->DirEntry
.FatX
.UpdateDate
,
310 DirContext
->DirEntry
.FatX
.UpdateTime
,
311 &pInfo
->LastWriteTime
);
313 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
315 if (DirContext
->DirEntry
.FatX
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
317 pInfo
->EndOfFile
.QuadPart
= 0;
318 pInfo
->AllocationSize
.QuadPart
= 0;
322 pInfo
->EndOfFile
.u
.HighPart
= 0;
323 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.FatX
.FileSize
;
324 /* Make allocsize a rounded up multiple of BytesPerCluster */
325 pInfo
->AllocationSize
.u
.HighPart
= 0;
326 pInfo
->AllocationSize
.u
.LowPart
= ROUND_UP(DirContext
->DirEntry
.FatX
.FileSize
,
327 DeviceExt
->FatInfo
.BytesPerCluster
);
330 pInfo
->FileAttributes
= DirContext
->DirEntry
.FatX
.Attrib
& 0x3f;
334 pInfo
->FileNameLength
= DirContext
->LongNameU
.Length
;
335 pInfo
->NextEntryOffset
= ULONG_ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION
) +
336 DirContext
->LongNameU
.Length
);
338 RtlCopyMemory(pInfo
->ShortName
,
339 DirContext
->ShortNameU
.Buffer
,
340 DirContext
->ShortNameU
.Length
);
342 pInfo
->ShortNameLength
= (CCHAR
)DirContext
->ShortNameU
.Length
;
344 RtlCopyMemory(pInfo
->FileName
,
345 DirContext
->LongNameU
.Buffer
,
346 DirContext
->LongNameU
.Length
);
348 /* pInfo->FileIndex = ; */
350 FsdDosDateTimeToSystemTime(DeviceExt
,
351 DirContext
->DirEntry
.Fat
.CreationDate
,
352 DirContext
->DirEntry
.Fat
.CreationTime
,
353 &pInfo
->CreationTime
);
354 FsdDosDateTimeToSystemTime(DeviceExt
,
355 DirContext
->DirEntry
.Fat
.AccessDate
,
357 &pInfo
->LastAccessTime
);
358 FsdDosDateTimeToSystemTime(DeviceExt
,
359 DirContext
->DirEntry
.Fat
.UpdateDate
,
360 DirContext
->DirEntry
.Fat
.UpdateTime
,
361 &pInfo
->LastWriteTime
);
363 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
365 if (DirContext
->DirEntry
.Fat
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
367 pInfo
->EndOfFile
.QuadPart
= 0;
368 pInfo
->AllocationSize
.QuadPart
= 0;
372 pInfo
->EndOfFile
.u
.HighPart
= 0;
373 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.Fat
.FileSize
;
374 /* Make allocsize a rounded up multiple of BytesPerCluster */
375 pInfo
->AllocationSize
.u
.HighPart
= 0;
376 pInfo
->AllocationSize
.u
.LowPart
= ROUND_UP(DirContext
->DirEntry
.Fat
.FileSize
, DeviceExt
->FatInfo
.BytesPerCluster
);
379 pInfo
->FileAttributes
= DirContext
->DirEntry
.Fat
.Attrib
& 0x3f;
382 return STATUS_SUCCESS
;
388 PVFAT_IRP_CONTEXT IrpContext
)
390 NTSTATUS Status
= STATUS_SUCCESS
;
391 LONG BufferLength
= 0;
392 PUNICODE_STRING pSearchPattern
= NULL
;
393 FILE_INFORMATION_CLASS FileInformationClass
;
394 PUCHAR Buffer
= NULL
;
395 PFILE_NAMES_INFORMATION Buffer0
= NULL
;
398 BOOLEAN FirstQuery
= FALSE
;
399 BOOLEAN FirstCall
= TRUE
;
400 VFAT_DIRENTRY_CONTEXT DirContext
;
401 WCHAR LongNameBuffer
[LONGNAME_MAX_LENGTH
+ 1];
402 WCHAR ShortNameBuffer
[13];
404 PIO_STACK_LOCATION Stack
= IrpContext
->Stack
;
406 pCcb
= (PVFATCCB
)IrpContext
->FileObject
->FsContext2
;
407 pFcb
= (PVFATFCB
)IrpContext
->FileObject
->FsContext
;
409 /* Determine Buffer for result : */
410 BufferLength
= Stack
->Parameters
.QueryDirectory
.Length
;
412 /* Do not probe the user buffer until SEH is available */
413 if (IrpContext
->Irp
->RequestorMode
!= KernelMode
&&
414 IrpContext
->Irp
->MdlAddress
== NULL
&&
415 IrpContext
->Irp
->UserBuffer
!= NULL
)
417 ProbeForWrite(IrpContext
->Irp
->UserBuffer
, BufferLength
, 1);
420 Buffer
= VfatGetUserBuffer(IrpContext
->Irp
);
422 if (!ExAcquireResourceSharedLite(&pFcb
->MainResource
,
423 (BOOLEAN
)(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
)))
425 Status
= VfatLockUserBuffer(IrpContext
->Irp
, BufferLength
, IoWriteAccess
);
426 if (NT_SUCCESS(Status
))
427 Status
= STATUS_PENDING
;
432 /* Obtain the callers parameters */
434 /* HACKHACK: Bug in the MS ntifs.h header:
435 * FileName is really a PUNICODE_STRING, not a PSTRING */
436 pSearchPattern
= (PUNICODE_STRING
)Stack
->Parameters
.QueryDirectory
.FileName
;
438 pSearchPattern
= Stack
->Parameters
.QueryDirectory
.FileName
;
440 FileInformationClass
= Stack
->Parameters
.QueryDirectory
.FileInformationClass
;
442 /* Allocate search pattern in case:
443 * -> We don't have one already in context
444 * -> We have been given an input pattern
445 * -> The pattern length is not null
446 * -> The pattern buffer is not null
447 * Otherwise, we'll fall later and allocate a match all (*) pattern
449 if (pSearchPattern
&&
450 pSearchPattern
->Length
!= 0 && pSearchPattern
->Buffer
!= NULL
)
452 if (!pCcb
->SearchPattern
.Buffer
)
455 pCcb
->SearchPattern
.MaximumLength
= pSearchPattern
->Length
+ sizeof(WCHAR
);
456 pCcb
->SearchPattern
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
457 pCcb
->SearchPattern
.MaximumLength
,
459 if (!pCcb
->SearchPattern
.Buffer
)
461 ExReleaseResourceLite(&pFcb
->MainResource
);
462 return STATUS_INSUFFICIENT_RESOURCES
;
464 RtlCopyUnicodeString(&pCcb
->SearchPattern
, pSearchPattern
);
465 pCcb
->SearchPattern
.Buffer
[pCcb
->SearchPattern
.Length
/ sizeof(WCHAR
)] = 0;
468 else if (!pCcb
->SearchPattern
.Buffer
)
471 pCcb
->SearchPattern
.MaximumLength
= 2 * sizeof(WCHAR
);
472 pCcb
->SearchPattern
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
475 if (!pCcb
->SearchPattern
.Buffer
)
477 ExReleaseResourceLite(&pFcb
->MainResource
);
478 return STATUS_INSUFFICIENT_RESOURCES
;
480 pCcb
->SearchPattern
.Buffer
[0] = L
'*';
481 pCcb
->SearchPattern
.Buffer
[1] = 0;
482 pCcb
->SearchPattern
.Length
= sizeof(WCHAR
);
485 if (IrpContext
->Stack
->Flags
& SL_INDEX_SPECIFIED
)
487 DirContext
.DirIndex
= pCcb
->Entry
= Stack
->Parameters
.QueryDirectory
.FileIndex
;
489 else if (FirstQuery
|| (IrpContext
->Stack
->Flags
& SL_RESTART_SCAN
))
491 DirContext
.DirIndex
= pCcb
->Entry
= 0;
495 DirContext
.DirIndex
= pCcb
->Entry
;
498 DPRINT("Buffer=%p tofind=%wZ\n", Buffer
, &pCcb
->SearchPattern
);
500 DirContext
.LongNameU
.Buffer
= LongNameBuffer
;
501 DirContext
.LongNameU
.MaximumLength
= sizeof(LongNameBuffer
);
502 DirContext
.ShortNameU
.Buffer
= ShortNameBuffer
;
503 DirContext
.ShortNameU
.MaximumLength
= sizeof(ShortNameBuffer
);
505 while ((Status
== STATUS_SUCCESS
) && (BufferLength
> 0))
507 Status
= FindFile(IrpContext
->DeviceExt
,
509 &pCcb
->SearchPattern
,
512 pCcb
->Entry
= DirContext
.DirIndex
;
514 DPRINT("Found %wZ, Status=%x, entry %x\n", &DirContext
.LongNameU
, Status
, pCcb
->Entry
);
517 if (NT_SUCCESS(Status
))
519 switch (FileInformationClass
)
521 case FileNameInformation
:
522 Status
= VfatGetFileNameInformation(&DirContext
,
523 (PFILE_NAMES_INFORMATION
)Buffer
,
527 case FileDirectoryInformation
:
528 Status
= VfatGetFileDirectoryInformation(&DirContext
,
529 IrpContext
->DeviceExt
,
530 (PFILE_DIRECTORY_INFORMATION
)Buffer
,
534 case FileFullDirectoryInformation
:
535 Status
= VfatGetFileFullDirectoryInformation(&DirContext
,
536 IrpContext
->DeviceExt
,
537 (PFILE_FULL_DIR_INFORMATION
)Buffer
,
541 case FileBothDirectoryInformation
:
542 Status
= VfatGetFileBothInformation(&DirContext
,
543 IrpContext
->DeviceExt
,
544 (PFILE_BOTH_DIR_INFORMATION
)Buffer
,
549 Status
= STATUS_INVALID_INFO_CLASS
;
553 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_INVALID_INFO_CLASS
)
558 Status
= (FirstQuery
? STATUS_NO_SUCH_FILE
: STATUS_NO_MORE_FILES
);
562 Buffer0
= (PFILE_NAMES_INFORMATION
) Buffer
;
563 Buffer0
->FileIndex
= DirContext
.DirIndex
;
564 pCcb
->Entry
= ++DirContext
.DirIndex
;
565 BufferLength
-= Buffer0
->NextEntryOffset
;
567 if (IrpContext
->Stack
->Flags
& SL_RETURN_SINGLE_ENTRY
)
570 Buffer
+= Buffer0
->NextEntryOffset
;
575 Buffer0
->NextEntryOffset
= 0;
576 Status
= STATUS_SUCCESS
;
577 IrpContext
->Irp
->IoStatus
.Information
= Stack
->Parameters
.QueryDirectory
.Length
- BufferLength
;
580 ExReleaseResourceLite(&pFcb
->MainResource
);
587 * FUNCTION: directory control : read/write directory informations
590 VfatDirectoryControl(
591 PVFAT_IRP_CONTEXT IrpContext
)
593 NTSTATUS Status
= STATUS_SUCCESS
;
595 IrpContext
->Irp
->IoStatus
.Information
= 0;
597 switch (IrpContext
->MinorFunction
)
599 case IRP_MN_QUERY_DIRECTORY
:
600 Status
= DoQuery (IrpContext
);
603 case IRP_MN_NOTIFY_CHANGE_DIRECTORY
:
604 DPRINT("VFAT, dir : change\n");
605 Status
= STATUS_NOT_IMPLEMENTED
;
610 DPRINT("Unexpected minor function %x in VFAT driver\n",
611 IrpContext
->MinorFunction
);
612 Status
= STATUS_INVALID_DEVICE_REQUEST
;
616 if (Status
== STATUS_PENDING
)
618 Status
= VfatQueueRequest(IrpContext
);
622 IrpContext
->Irp
->IoStatus
.Status
= Status
;
623 IoCompleteRequest (IrpContext
->Irp
, IO_NO_INCREMENT
);
624 VfatFreeIrpContext(IrpContext
);