4 * COPYRIGHT: See COPYING in the top level directory
5 * PROJECT: ReactOS kernel
6 * FILE: drivers/fs/vfat/dir.c
7 * PURPOSE: VFAT Filesystem : directory control
13 #include <ddk/ntddk.h>
22 // function like DosDateTimeToFileTime
24 FsdDosDateTimeToSystemTime (PDEVICE_EXTENSION DeviceExt
, USHORT wDosDate
, WORD wDosTime
, PLARGE_INTEGER SystemTime
)
26 PDOSTIME pdtime
= (PDOSTIME
) & wDosTime
;
27 PDOSDATE pddate
= (PDOSDATE
) & wDosDate
;
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
= DeviceExt
->BaseDateYear
+ pddate
->Year
;
43 RtlTimeFieldsToTime (&TimeFields
, &LocalTime
);
44 ExLocalTimeToSystemTime(&LocalTime
, SystemTime
);
49 // function like FileTimeToDosDateTime
51 FsdSystemTimeToDosDateTime (PDEVICE_EXTENSION DeviceExt
, PLARGE_INTEGER SystemTime
, USHORT
*pDosDate
, USHORT
*pDosTime
)
53 PDOSTIME pdtime
= (PDOSTIME
) pDosTime
;
54 PDOSDATE pddate
= (PDOSDATE
) pDosDate
;
55 TIME_FIELDS TimeFields
;
56 LARGE_INTEGER LocalTime
;
58 if (SystemTime
== NULL
)
61 ExSystemTimeToLocalTime (SystemTime
, &LocalTime
);
62 RtlTimeToTimeFields (&LocalTime
, &TimeFields
);
66 pdtime
->Second
= TimeFields
.Second
/ 2;
67 pdtime
->Minute
= TimeFields
.Minute
;
68 pdtime
->Hour
= TimeFields
.Hour
;
73 pddate
->Day
= TimeFields
.Day
;
74 pddate
->Month
= TimeFields
.Month
;
75 pddate
->Year
= (USHORT
) (TimeFields
.Year
- DeviceExt
->BaseDateYear
);
81 #define ULONG_ROUND_UP(x) ROUND_UP((x), (sizeof(ULONG)))
84 VfatGetFileNameInformation (PVFAT_DIRENTRY_CONTEXT DirContext
,
85 PFILE_NAMES_INFORMATION pInfo
, ULONG BufferLength
)
87 if ((sizeof (FILE_DIRECTORY_INFORMATION
) + DirContext
->LongNameU
.Length
) > BufferLength
)
88 return STATUS_BUFFER_OVERFLOW
;
89 pInfo
->FileNameLength
= DirContext
->LongNameU
.Length
;
90 pInfo
->NextEntryOffset
=
91 ULONG_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION
) + DirContext
->LongNameU
.Length
);
92 RtlCopyMemory (pInfo
->FileName
, DirContext
->LongNameU
.Buffer
, DirContext
->LongNameU
.Length
);
93 return STATUS_SUCCESS
;
97 VfatGetFileDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext
,
98 PDEVICE_EXTENSION DeviceExt
,
99 PFILE_DIRECTORY_INFORMATION pInfo
,
102 if ((sizeof (FILE_DIRECTORY_INFORMATION
) + DirContext
->LongNameU
.Length
) > BufferLength
)
103 return STATUS_BUFFER_OVERFLOW
;
104 pInfo
->FileNameLength
= DirContext
->LongNameU
.Length
;
105 pInfo
->NextEntryOffset
=
106 ULONG_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION
) + DirContext
->LongNameU
.Length
);
107 RtlCopyMemory (pInfo
->FileName
, DirContext
->LongNameU
.Buffer
, DirContext
->LongNameU
.Length
);
108 // pInfo->FileIndex=;
109 if (DeviceExt
->Flags
& VCB_IS_FATX
)
111 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.FatX
.CreationDate
,
112 DirContext
->DirEntry
.FatX
.CreationTime
,
113 &pInfo
->CreationTime
);
114 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.FatX
.AccessDate
,
115 DirContext
->DirEntry
.FatX
.AccessTime
,
116 &pInfo
->LastAccessTime
);
117 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.FatX
.UpdateDate
,
118 DirContext
->DirEntry
.FatX
.UpdateTime
,
119 &pInfo
->LastWriteTime
);
120 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
121 if (DirContext
->DirEntry
.FatX
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
123 pInfo
->EndOfFile
.QuadPart
= 0LL;
124 pInfo
->AllocationSize
.QuadPart
= 0LL;
128 pInfo
->EndOfFile
.u
.HighPart
= 0;
129 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.FatX
.FileSize
;
130 /* Make allocsize a rounded up multiple of BytesPerCluster */
131 pInfo
->AllocationSize
.u
.HighPart
= 0;
132 pInfo
->AllocationSize
.u
.LowPart
= ROUND_UP(DirContext
->DirEntry
.FatX
.FileSize
, DeviceExt
->FatInfo
.BytesPerCluster
);
134 pInfo
->FileAttributes
= DirContext
->DirEntry
.FatX
.Attrib
& 0x3f;
138 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.Fat
.CreationDate
,
139 DirContext
->DirEntry
.Fat
.CreationTime
,
140 &pInfo
->CreationTime
);
141 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.Fat
.AccessDate
, 0,
142 &pInfo
->LastAccessTime
);
143 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.Fat
.UpdateDate
,
144 DirContext
->DirEntry
.Fat
.UpdateTime
,
145 &pInfo
->LastWriteTime
);
146 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
147 if (DirContext
->DirEntry
.Fat
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
149 pInfo
->EndOfFile
.QuadPart
= 0LL;
150 pInfo
->AllocationSize
.QuadPart
= 0LL;
154 pInfo
->EndOfFile
.u
.HighPart
= 0;
155 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.Fat
.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
.Fat
.FileSize
, DeviceExt
->FatInfo
.BytesPerCluster
);
160 pInfo
->FileAttributes
= DirContext
->DirEntry
.Fat
.Attrib
& 0x3f;
163 return STATUS_SUCCESS
;
167 VfatGetFileFullDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext
,
168 PDEVICE_EXTENSION DeviceExt
,
169 PFILE_FULL_DIRECTORY_INFORMATION pInfo
,
172 if ((sizeof (FILE_FULL_DIRECTORY_INFORMATION
) + DirContext
->LongNameU
.Length
) > BufferLength
)
173 return STATUS_BUFFER_OVERFLOW
;
174 pInfo
->FileNameLength
= DirContext
->LongNameU
.Length
;
175 pInfo
->NextEntryOffset
=
176 ULONG_ROUND_UP (sizeof (FILE_FULL_DIRECTORY_INFORMATION
) + DirContext
->LongNameU
.Length
);
177 RtlCopyMemory (pInfo
->FileName
, DirContext
->LongNameU
.Buffer
, DirContext
->LongNameU
.Length
);
178 // pInfo->FileIndex=;
179 if (DeviceExt
->Flags
& VCB_IS_FATX
)
181 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.FatX
.CreationDate
,
182 DirContext
->DirEntry
.FatX
.CreationTime
,
183 &pInfo
->CreationTime
);
184 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.FatX
.AccessDate
,
185 DirContext
->DirEntry
.FatX
.AccessTime
,
186 &pInfo
->LastAccessTime
);
187 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.FatX
.UpdateDate
,
188 DirContext
->DirEntry
.FatX
.UpdateTime
,
189 &pInfo
->LastWriteTime
);
190 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
191 pInfo
->EndOfFile
.u
.HighPart
= 0;
192 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.FatX
.FileSize
;
193 /* Make allocsize a rounded up multiple of BytesPerCluster */
194 pInfo
->AllocationSize
.u
.HighPart
= 0;
195 pInfo
->AllocationSize
.u
.LowPart
= ROUND_UP(DirContext
->DirEntry
.FatX
.FileSize
, DeviceExt
->FatInfo
.BytesPerCluster
);
196 pInfo
->FileAttributes
= DirContext
->DirEntry
.FatX
.Attrib
& 0x3f;
200 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.Fat
.CreationDate
,
201 DirContext
->DirEntry
.Fat
.CreationTime
,
202 &pInfo
->CreationTime
);
203 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.Fat
.AccessDate
,
204 0, &pInfo
->LastAccessTime
);
205 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.Fat
.UpdateDate
,
206 DirContext
->DirEntry
.Fat
.UpdateTime
,
207 &pInfo
->LastWriteTime
);
208 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
209 pInfo
->EndOfFile
.u
.HighPart
= 0;
210 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.Fat
.FileSize
;
211 /* Make allocsize a rounded up multiple of BytesPerCluster */
212 pInfo
->AllocationSize
.u
.HighPart
= 0;
213 pInfo
->AllocationSize
.u
.LowPart
= ROUND_UP(DirContext
->DirEntry
.Fat
.FileSize
, DeviceExt
->FatInfo
.BytesPerCluster
);
214 pInfo
->FileAttributes
= DirContext
->DirEntry
.Fat
.Attrib
& 0x3f;
217 return STATUS_SUCCESS
;
221 VfatGetFileBothInformation (PVFAT_DIRENTRY_CONTEXT DirContext
,
222 PDEVICE_EXTENSION DeviceExt
,
223 PFILE_BOTH_DIRECTORY_INFORMATION pInfo
,
226 if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION
) + DirContext
->LongNameU
.Length
) > BufferLength
)
227 return STATUS_BUFFER_OVERFLOW
;
229 if (DeviceExt
->Flags
& VCB_IS_FATX
)
231 pInfo
->FileNameLength
= DirContext
->LongNameU
.Length
;
232 RtlCopyMemory(pInfo
->FileName
, DirContext
->LongNameU
.Buffer
, DirContext
->LongNameU
.Length
);
233 pInfo
->NextEntryOffset
=
234 ULONG_ROUND_UP (sizeof (FILE_BOTH_DIRECTORY_INFORMATION
) + DirContext
->LongNameU
.Length
);
235 pInfo
->ShortName
[0] = 0;
236 pInfo
->ShortNameLength
= 0;
237 // pInfo->FileIndex=;
238 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.FatX
.CreationDate
,
239 DirContext
->DirEntry
.FatX
.CreationTime
,
240 &pInfo
->CreationTime
);
241 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.FatX
.AccessDate
,
242 DirContext
->DirEntry
.FatX
.AccessTime
,
243 &pInfo
->LastAccessTime
);
244 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.FatX
.UpdateDate
,
245 DirContext
->DirEntry
.FatX
.UpdateTime
,
246 &pInfo
->LastWriteTime
);
247 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
248 if (DirContext
->DirEntry
.FatX
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
250 pInfo
->EndOfFile
.QuadPart
= 0LL;
251 pInfo
->AllocationSize
.QuadPart
= 0LL;
255 pInfo
->EndOfFile
.u
.HighPart
= 0;
256 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.FatX
.FileSize
;
257 /* Make allocsize a rounded up multiple of BytesPerCluster */
258 pInfo
->AllocationSize
.u
.HighPart
= 0;
259 pInfo
->AllocationSize
.u
.LowPart
= ROUND_UP(DirContext
->DirEntry
.FatX
.FileSize
, DeviceExt
->FatInfo
.BytesPerCluster
);
261 pInfo
->FileAttributes
= DirContext
->DirEntry
.FatX
.Attrib
& 0x3f;
265 pInfo
->FileNameLength
= DirContext
->LongNameU
.Length
;
266 pInfo
->NextEntryOffset
=
267 ULONG_ROUND_UP (sizeof (FILE_BOTH_DIRECTORY_INFORMATION
) + DirContext
->LongNameU
.Length
);
268 RtlCopyMemory(pInfo
->ShortName
, DirContext
->ShortNameU
.Buffer
, DirContext
->ShortNameU
.Length
);
269 pInfo
->ShortNameLength
= DirContext
->ShortNameU
.Length
;
270 RtlCopyMemory (pInfo
->FileName
, DirContext
->LongNameU
.Buffer
, DirContext
->LongNameU
.Length
);
271 // pInfo->FileIndex=;
272 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.Fat
.CreationDate
,
273 DirContext
->DirEntry
.Fat
.CreationTime
,
274 &pInfo
->CreationTime
);
275 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.Fat
.AccessDate
, 0,
276 &pInfo
->LastAccessTime
);
277 FsdDosDateTimeToSystemTime (DeviceExt
, DirContext
->DirEntry
.Fat
.UpdateDate
,
278 DirContext
->DirEntry
.Fat
.UpdateTime
,
279 &pInfo
->LastWriteTime
);
280 pInfo
->ChangeTime
= pInfo
->LastWriteTime
;
281 if (DirContext
->DirEntry
.Fat
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
283 pInfo
->EndOfFile
.QuadPart
= 0LL;
284 pInfo
->AllocationSize
.QuadPart
= 0LL;
288 pInfo
->EndOfFile
.u
.HighPart
= 0;
289 pInfo
->EndOfFile
.u
.LowPart
= DirContext
->DirEntry
.Fat
.FileSize
;
290 /* Make allocsize a rounded up multiple of BytesPerCluster */
291 pInfo
->AllocationSize
.u
.HighPart
= 0;
292 pInfo
->AllocationSize
.u
.LowPart
= ROUND_UP(DirContext
->DirEntry
.Fat
.FileSize
, DeviceExt
->FatInfo
.BytesPerCluster
);
294 pInfo
->FileAttributes
= DirContext
->DirEntry
.Fat
.Attrib
& 0x3f;
297 return STATUS_SUCCESS
;
300 NTSTATUS
DoQuery (PVFAT_IRP_CONTEXT IrpContext
)
302 NTSTATUS RC
= STATUS_SUCCESS
;
303 long BufferLength
= 0;
304 PUNICODE_STRING pSearchPattern
= NULL
;
305 FILE_INFORMATION_CLASS FileInformationClass
;
306 unsigned long FileIndex
= 0;
307 unsigned char *Buffer
= NULL
;
308 PFILE_NAMES_INFORMATION Buffer0
= NULL
;
311 BOOLEAN First
= FALSE
;
313 VFAT_DIRENTRY_CONTEXT DirContext
;
314 WCHAR LongNameBuffer
[MAX_PATH
];
315 WCHAR ShortNameBuffer
[13];
317 PIO_STACK_LOCATION Stack
= IrpContext
->Stack
;
319 pCcb
= (PVFATCCB
) IrpContext
->FileObject
->FsContext2
;
320 pFcb
= (PVFATFCB
) IrpContext
->FileObject
->FsContext
;
322 // determine Buffer for result :
323 BufferLength
= Stack
->Parameters
.QueryDirectory
.Length
;
325 /* Do not probe the user buffer until SEH is available */
326 if (IrpContext
->Irp
->RequestorMode
!= KernelMode
&&
327 IrpContext
->Irp
->MdlAddress
== NULL
&&
328 IrpContext
->Irp
->UserBuffer
!= NULL
)
330 ProbeForWrite(IrpContext
->Irp
->UserBuffer
, BufferLength
, 1);
333 Buffer
= VfatGetUserBuffer(IrpContext
->Irp
);
335 if (!ExAcquireResourceSharedLite(&pFcb
->MainResource
,
336 (BOOLEAN
)(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
)))
338 RC
= VfatLockUserBuffer(IrpContext
->Irp
, BufferLength
, IoWriteAccess
);
346 /* Obtain the callers parameters */
347 pSearchPattern
= Stack
->Parameters
.QueryDirectory
.FileName
;
348 FileInformationClass
=
349 Stack
->Parameters
.QueryDirectory
.FileInformationClass
;
350 FileIndex
= Stack
->Parameters
.QueryDirectory
.FileIndex
;
353 if (!pCcb
->SearchPattern
.Buffer
)
356 pCcb
->SearchPattern
.MaximumLength
= pSearchPattern
->Length
+ sizeof(WCHAR
);
357 pCcb
->SearchPattern
.Buffer
= ExAllocatePool(NonPagedPool
, pCcb
->SearchPattern
.MaximumLength
);
358 if (!pCcb
->SearchPattern
.Buffer
)
360 ExReleaseResourceLite(&pFcb
->MainResource
);
361 return STATUS_INSUFFICIENT_RESOURCES
;
363 RtlCopyUnicodeString(&pCcb
->SearchPattern
, pSearchPattern
);
364 pCcb
->SearchPattern
.Buffer
[pCcb
->SearchPattern
.Length
/ sizeof(WCHAR
)] = 0;
367 else if (!pCcb
->SearchPattern
.Buffer
)
370 pCcb
->SearchPattern
.MaximumLength
= 2 * sizeof(WCHAR
);
371 pCcb
->SearchPattern
.Buffer
= ExAllocatePool(NonPagedPool
, 2 * sizeof(WCHAR
));
372 if (!pCcb
->SearchPattern
.Buffer
)
374 ExReleaseResourceLite(&pFcb
->MainResource
);
375 return STATUS_INSUFFICIENT_RESOURCES
;
377 pCcb
->SearchPattern
.Buffer
[0] = L
'*';
378 pCcb
->SearchPattern
.Buffer
[1] = 0;
379 pCcb
->SearchPattern
.Length
= sizeof(WCHAR
);
382 if (IrpContext
->Stack
->Flags
& SL_INDEX_SPECIFIED
)
384 DirContext
.DirIndex
= pCcb
->Entry
= pCcb
->CurrentByteOffset
.u
.LowPart
;
387 else if (First
|| (IrpContext
->Stack
->Flags
& SL_RESTART_SCAN
))
389 DirContext
.DirIndex
= pCcb
->Entry
= 0;
394 DirContext
.DirIndex
= pCcb
->Entry
;
398 DPRINT ("Buffer=%x tofind=%wZ\n", Buffer
, &pCcb
->SearchPattern
);
400 DirContext
.LongNameU
.Buffer
= LongNameBuffer
;
401 DirContext
.LongNameU
.MaximumLength
= sizeof(LongNameBuffer
);
402 DirContext
.ShortNameU
.Buffer
= ShortNameBuffer
;
403 DirContext
.ShortNameU
.MaximumLength
= sizeof(ShortNameBuffer
);
405 while (RC
== STATUS_SUCCESS
&& BufferLength
> 0)
407 RC
= FindFile (IrpContext
->DeviceExt
, pFcb
,
408 &pCcb
->SearchPattern
, &DirContext
, FirstCall
);
409 pCcb
->Entry
= DirContext
.DirIndex
;
410 DPRINT ("Found %wZ, RC=%x, entry %x\n", &DirContext
.LongNameU
, RC
, pCcb
->Entry
);
414 switch (FileInformationClass
)
416 case FileNameInformation
:
417 RC
= VfatGetFileNameInformation (&DirContext
,
418 (PFILE_NAMES_INFORMATION
) Buffer
,
421 case FileDirectoryInformation
:
422 RC
= VfatGetFileDirectoryInformation (&DirContext
,
423 IrpContext
->DeviceExt
,
424 (PFILE_DIRECTORY_INFORMATION
) Buffer
,
427 case FileFullDirectoryInformation
:
428 RC
= VfatGetFileFullDirectoryInformation (&DirContext
,
429 IrpContext
->DeviceExt
,
430 (PFILE_FULL_DIRECTORY_INFORMATION
) Buffer
,
433 case FileBothDirectoryInformation
:
434 RC
= VfatGetFileBothInformation (&DirContext
,
435 IrpContext
->DeviceExt
,
436 (PFILE_BOTH_DIRECTORY_INFORMATION
) Buffer
,
440 RC
= STATUS_INVALID_INFO_CLASS
;
442 if (RC
== STATUS_BUFFER_OVERFLOW
)
446 Buffer0
->NextEntryOffset
= 0;
455 Buffer0
->NextEntryOffset
= 0;
459 RC
= STATUS_NO_SUCH_FILE
;
463 RC
= STATUS_NO_MORE_FILES
;
467 Buffer0
= (PFILE_NAMES_INFORMATION
) Buffer
;
468 Buffer0
->FileIndex
= FileIndex
++;
469 pCcb
->Entry
= ++DirContext
.DirIndex
;
470 if (IrpContext
->Stack
->Flags
& SL_RETURN_SINGLE_ENTRY
)
474 BufferLength
-= Buffer0
->NextEntryOffset
;
475 Buffer
+= Buffer0
->NextEntryOffset
;
479 Buffer0
->NextEntryOffset
= 0;
485 ExReleaseResourceLite(&pFcb
->MainResource
);
490 NTSTATUS
VfatDirectoryControl (PVFAT_IRP_CONTEXT IrpContext
)
492 * FUNCTION: directory control : read/write directory informations
495 NTSTATUS RC
= STATUS_SUCCESS
;
497 switch (IrpContext
->MinorFunction
)
499 case IRP_MN_QUERY_DIRECTORY
:
500 RC
= DoQuery (IrpContext
);
502 case IRP_MN_NOTIFY_CHANGE_DIRECTORY
:
503 DPRINT (" vfat, dir : change\n");
504 RC
= STATUS_NOT_IMPLEMENTED
;
508 DbgPrint ("unexpected minor function %x in VFAT driver\n",
509 IrpContext
->MinorFunction
);
510 RC
= STATUS_INVALID_DEVICE_REQUEST
;
513 if (RC
== STATUS_PENDING
)
515 RC
= VfatQueueRequest(IrpContext
);
519 IrpContext
->Irp
->IoStatus
.Status
= RC
;
520 IrpContext
->Irp
->IoStatus
.Information
= 0;
521 IoCompleteRequest (IrpContext
->Irp
, IO_NO_INCREMENT
);
522 VfatFreeIrpContext(IrpContext
);