merge ROS Shell without integrated explorer part into trunk
[reactos.git] / reactos / drivers / fs / vfat / dir.c
1 /*
2 * $Id$
3 *
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
8 * UPDATE HISTORY:
9 19-12-1998 : created
10
11 */
12
13 #define NDEBUG
14 #include "vfat.h"
15
16
17 // function like DosDateTimeToFileTime
18 BOOLEAN
19 FsdDosDateTimeToSystemTime (PDEVICE_EXTENSION DeviceExt, USHORT DosDate, USHORT DosTime, PLARGE_INTEGER SystemTime)
20 {
21 PDOSTIME pdtime = (PDOSTIME) &DosTime;
22 PDOSDATE pddate = (PDOSDATE) &DosDate;
23 TIME_FIELDS TimeFields;
24 LARGE_INTEGER LocalTime;
25
26 if (SystemTime == NULL)
27 return FALSE;
28
29 TimeFields.Milliseconds = 0;
30 TimeFields.Second = pdtime->Second * 2;
31 TimeFields.Minute = pdtime->Minute;
32 TimeFields.Hour = pdtime->Hour;
33
34 TimeFields.Day = pddate->Day;
35 TimeFields.Month = pddate->Month;
36 TimeFields.Year = (CSHORT)(DeviceExt->BaseDateYear + pddate->Year);
37
38 RtlTimeFieldsToTime (&TimeFields, &LocalTime);
39 ExLocalTimeToSystemTime(&LocalTime, SystemTime);
40
41 return TRUE;
42 }
43
44 // function like FileTimeToDosDateTime
45 BOOLEAN
46 FsdSystemTimeToDosDateTime (PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER SystemTime, USHORT *pDosDate, USHORT *pDosTime)
47 {
48 PDOSTIME pdtime = (PDOSTIME) pDosTime;
49 PDOSDATE pddate = (PDOSDATE) pDosDate;
50 TIME_FIELDS TimeFields;
51 LARGE_INTEGER LocalTime;
52
53 if (SystemTime == NULL)
54 return FALSE;
55
56 ExSystemTimeToLocalTime (SystemTime, &LocalTime);
57 RtlTimeToTimeFields (&LocalTime, &TimeFields);
58
59 if (pdtime)
60 {
61 pdtime->Second = TimeFields.Second / 2;
62 pdtime->Minute = TimeFields.Minute;
63 pdtime->Hour = TimeFields.Hour;
64 }
65
66 if (pddate)
67 {
68 pddate->Day = TimeFields.Day;
69 pddate->Month = TimeFields.Month;
70 pddate->Year = (USHORT) (TimeFields.Year - DeviceExt->BaseDateYear);
71 }
72
73 return TRUE;
74 }
75
76 #define ULONG_ROUND_UP(x) ROUND_UP((x), (sizeof(ULONG)))
77
78 NTSTATUS
79 VfatGetFileNameInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
80 PFILE_NAMES_INFORMATION pInfo, ULONG BufferLength)
81 {
82 if ((sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
83 return STATUS_BUFFER_OVERFLOW;
84 pInfo->FileNameLength = DirContext->LongNameU.Length;
85 pInfo->NextEntryOffset =
86 ULONG_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
87 RtlCopyMemory (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
88 return STATUS_SUCCESS;
89 }
90
91 NTSTATUS
92 VfatGetFileDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
93 PDEVICE_EXTENSION DeviceExt,
94 PFILE_DIRECTORY_INFORMATION pInfo,
95 ULONG BufferLength)
96 {
97 if ((sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
98 return STATUS_BUFFER_OVERFLOW;
99 pInfo->FileNameLength = DirContext->LongNameU.Length;
100 pInfo->NextEntryOffset =
101 ULONG_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
102 RtlCopyMemory (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
103 // pInfo->FileIndex=;
104 if (DeviceExt->Flags & VCB_IS_FATX)
105 {
106 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.CreationDate,
107 DirContext->DirEntry.FatX.CreationTime,
108 &pInfo->CreationTime);
109 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.AccessDate,
110 DirContext->DirEntry.FatX.AccessTime,
111 &pInfo->LastAccessTime);
112 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.UpdateDate,
113 DirContext->DirEntry.FatX.UpdateTime,
114 &pInfo->LastWriteTime);
115 pInfo->ChangeTime = pInfo->LastWriteTime;
116 if (DirContext->DirEntry.FatX.Attrib & FILE_ATTRIBUTE_DIRECTORY)
117 {
118 pInfo->EndOfFile.QuadPart = 0LL;
119 pInfo->AllocationSize.QuadPart = 0LL;
120 }
121 else
122 {
123 pInfo->EndOfFile.u.HighPart = 0;
124 pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.FatX.FileSize;
125 /* Make allocsize a rounded up multiple of BytesPerCluster */
126 pInfo->AllocationSize.u.HighPart = 0;
127 pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.FatX.FileSize, DeviceExt->FatInfo.BytesPerCluster);
128 }
129 pInfo->FileAttributes = DirContext->DirEntry.FatX.Attrib & 0x3f;
130 }
131 else
132 {
133 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.CreationDate,
134 DirContext->DirEntry.Fat.CreationTime,
135 &pInfo->CreationTime);
136 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.AccessDate, 0,
137 &pInfo->LastAccessTime);
138 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.UpdateDate,
139 DirContext->DirEntry.Fat.UpdateTime,
140 &pInfo->LastWriteTime);
141 pInfo->ChangeTime = pInfo->LastWriteTime;
142 if (DirContext->DirEntry.Fat.Attrib & FILE_ATTRIBUTE_DIRECTORY)
143 {
144 pInfo->EndOfFile.QuadPart = 0LL;
145 pInfo->AllocationSize.QuadPart = 0LL;
146 }
147 else
148 {
149 pInfo->EndOfFile.u.HighPart = 0;
150 pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.Fat.FileSize;
151 /* Make allocsize a rounded up multiple of BytesPerCluster */
152 pInfo->AllocationSize.u.HighPart = 0;
153 pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.Fat.FileSize, DeviceExt->FatInfo.BytesPerCluster);
154 }
155 pInfo->FileAttributes = DirContext->DirEntry.Fat.Attrib & 0x3f;
156 }
157
158 return STATUS_SUCCESS;
159 }
160
161 NTSTATUS
162 VfatGetFileFullDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
163 PDEVICE_EXTENSION DeviceExt,
164 PFILE_FULL_DIR_INFORMATION pInfo,
165 ULONG BufferLength)
166 {
167 if ((sizeof (FILE_FULL_DIR_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
168 return STATUS_BUFFER_OVERFLOW;
169 pInfo->FileNameLength = DirContext->LongNameU.Length;
170 pInfo->NextEntryOffset =
171 ULONG_ROUND_UP (sizeof (FILE_FULL_DIR_INFORMATION) + DirContext->LongNameU.Length);
172 RtlCopyMemory (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
173 // pInfo->FileIndex=;
174 if (DeviceExt->Flags & VCB_IS_FATX)
175 {
176 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.CreationDate,
177 DirContext->DirEntry.FatX.CreationTime,
178 &pInfo->CreationTime);
179 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.AccessDate,
180 DirContext->DirEntry.FatX.AccessTime,
181 &pInfo->LastAccessTime);
182 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.UpdateDate,
183 DirContext->DirEntry.FatX.UpdateTime,
184 &pInfo->LastWriteTime);
185 pInfo->ChangeTime = pInfo->LastWriteTime;
186 pInfo->EndOfFile.u.HighPart = 0;
187 pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.FatX.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.FatX.FileSize, DeviceExt->FatInfo.BytesPerCluster);
191 pInfo->FileAttributes = DirContext->DirEntry.FatX.Attrib & 0x3f;
192 }
193 else
194 {
195 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.CreationDate,
196 DirContext->DirEntry.Fat.CreationTime,
197 &pInfo->CreationTime);
198 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.AccessDate,
199 0, &pInfo->LastAccessTime);
200 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.UpdateDate,
201 DirContext->DirEntry.Fat.UpdateTime,
202 &pInfo->LastWriteTime);
203 pInfo->ChangeTime = pInfo->LastWriteTime;
204 pInfo->EndOfFile.u.HighPart = 0;
205 pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.Fat.FileSize;
206 /* Make allocsize a rounded up multiple of BytesPerCluster */
207 pInfo->AllocationSize.u.HighPart = 0;
208 pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.Fat.FileSize, DeviceExt->FatInfo.BytesPerCluster);
209 pInfo->FileAttributes = DirContext->DirEntry.Fat.Attrib & 0x3f;
210 }
211 // pInfo->EaSize=;
212 return STATUS_SUCCESS;
213 }
214
215 NTSTATUS
216 VfatGetFileBothInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
217 PDEVICE_EXTENSION DeviceExt,
218 PFILE_BOTH_DIR_INFORMATION pInfo,
219 ULONG BufferLength)
220 {
221 if ((sizeof (FILE_BOTH_DIR_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
222 return STATUS_BUFFER_OVERFLOW;
223
224 if (DeviceExt->Flags & VCB_IS_FATX)
225 {
226 pInfo->FileNameLength = DirContext->LongNameU.Length;
227 RtlCopyMemory(pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
228 pInfo->NextEntryOffset =
229 ULONG_ROUND_UP (sizeof (FILE_BOTH_DIR_INFORMATION) + DirContext->LongNameU.Length);
230 pInfo->ShortName[0] = 0;
231 pInfo->ShortNameLength = 0;
232 // pInfo->FileIndex=;
233 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.CreationDate,
234 DirContext->DirEntry.FatX.CreationTime,
235 &pInfo->CreationTime);
236 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.AccessDate,
237 DirContext->DirEntry.FatX.AccessTime,
238 &pInfo->LastAccessTime);
239 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.UpdateDate,
240 DirContext->DirEntry.FatX.UpdateTime,
241 &pInfo->LastWriteTime);
242 pInfo->ChangeTime = pInfo->LastWriteTime;
243 if (DirContext->DirEntry.FatX.Attrib & FILE_ATTRIBUTE_DIRECTORY)
244 {
245 pInfo->EndOfFile.QuadPart = 0LL;
246 pInfo->AllocationSize.QuadPart = 0LL;
247 }
248 else
249 {
250 pInfo->EndOfFile.u.HighPart = 0;
251 pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.FatX.FileSize;
252 /* Make allocsize a rounded up multiple of BytesPerCluster */
253 pInfo->AllocationSize.u.HighPart = 0;
254 pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.FatX.FileSize, DeviceExt->FatInfo.BytesPerCluster);
255 }
256 pInfo->FileAttributes = DirContext->DirEntry.FatX.Attrib & 0x3f;
257 }
258 else
259 {
260 pInfo->FileNameLength = DirContext->LongNameU.Length;
261 pInfo->NextEntryOffset =
262 ULONG_ROUND_UP (sizeof (FILE_BOTH_DIR_INFORMATION) + DirContext->LongNameU.Length);
263 RtlCopyMemory(pInfo->ShortName, DirContext->ShortNameU.Buffer, DirContext->ShortNameU.Length);
264 pInfo->ShortNameLength = (CCHAR)DirContext->ShortNameU.Length;
265 RtlCopyMemory (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
266 // pInfo->FileIndex=;
267 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.CreationDate,
268 DirContext->DirEntry.Fat.CreationTime,
269 &pInfo->CreationTime);
270 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.AccessDate, 0,
271 &pInfo->LastAccessTime);
272 FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.UpdateDate,
273 DirContext->DirEntry.Fat.UpdateTime,
274 &pInfo->LastWriteTime);
275 pInfo->ChangeTime = pInfo->LastWriteTime;
276 if (DirContext->DirEntry.Fat.Attrib & FILE_ATTRIBUTE_DIRECTORY)
277 {
278 pInfo->EndOfFile.QuadPart = 0LL;
279 pInfo->AllocationSize.QuadPart = 0LL;
280 }
281 else
282 {
283 pInfo->EndOfFile.u.HighPart = 0;
284 pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.Fat.FileSize;
285 /* Make allocsize a rounded up multiple of BytesPerCluster */
286 pInfo->AllocationSize.u.HighPart = 0;
287 pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.Fat.FileSize, DeviceExt->FatInfo.BytesPerCluster);
288 }
289 pInfo->FileAttributes = DirContext->DirEntry.Fat.Attrib & 0x3f;
290 }
291 pInfo->EaSize=0;
292 return STATUS_SUCCESS;
293 }
294
295 NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext)
296 {
297 NTSTATUS RC = STATUS_SUCCESS;
298 long BufferLength = 0;
299 PUNICODE_STRING pSearchPattern = NULL;
300 FILE_INFORMATION_CLASS FileInformationClass;
301 unsigned long FileIndex = 0;
302 unsigned char *Buffer = NULL;
303 PFILE_NAMES_INFORMATION Buffer0 = NULL;
304 PVFATFCB pFcb;
305 PVFATCCB pCcb;
306 BOOLEAN First = FALSE;
307 BOOLEAN FirstCall;
308 VFAT_DIRENTRY_CONTEXT DirContext;
309 WCHAR LongNameBuffer[LONGNAME_MAX_LENGTH + 1];
310 WCHAR ShortNameBuffer[13];
311
312 PIO_STACK_LOCATION Stack = IrpContext->Stack;
313
314 pCcb = (PVFATCCB) IrpContext->FileObject->FsContext2;
315 pFcb = (PVFATFCB) IrpContext->FileObject->FsContext;
316
317 // determine Buffer for result :
318 BufferLength = Stack->Parameters.QueryDirectory.Length;
319 #if 0
320 /* Do not probe the user buffer until SEH is available */
321 if (IrpContext->Irp->RequestorMode != KernelMode &&
322 IrpContext->Irp->MdlAddress == NULL &&
323 IrpContext->Irp->UserBuffer != NULL)
324 {
325 ProbeForWrite(IrpContext->Irp->UserBuffer, BufferLength, 1);
326 }
327 #endif
328 Buffer = VfatGetUserBuffer(IrpContext->Irp);
329
330 if (!ExAcquireResourceSharedLite(&pFcb->MainResource,
331 (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
332 {
333 RC = VfatLockUserBuffer(IrpContext->Irp, BufferLength, IoWriteAccess);
334 if (NT_SUCCESS(RC))
335 {
336 RC = STATUS_PENDING;
337 }
338 return RC;
339 }
340
341 /* Obtain the callers parameters */
342 #ifdef _MSC_VER
343 /* HACKHACK: Bug in the MS ntifs.h header:
344 * FileName is really a PUNICODE_STRING, not a PSTRING */
345 pSearchPattern = (PUNICODE_STRING)Stack->Parameters.QueryDirectory.FileName;
346 #else
347 pSearchPattern = Stack->Parameters.QueryDirectory.FileName;
348 #endif
349 FileInformationClass =
350 Stack->Parameters.QueryDirectory.FileInformationClass;
351 FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
352 if (pSearchPattern)
353 {
354 if (!pCcb->SearchPattern.Buffer)
355 {
356 First = TRUE;
357 pCcb->SearchPattern.MaximumLength = pSearchPattern->Length + sizeof(WCHAR);
358 pCcb->SearchPattern.Buffer = ExAllocatePool(NonPagedPool, pCcb->SearchPattern.MaximumLength);
359 if (!pCcb->SearchPattern.Buffer)
360 {
361 ExReleaseResourceLite(&pFcb->MainResource);
362 return STATUS_INSUFFICIENT_RESOURCES;
363 }
364 RtlCopyUnicodeString(&pCcb->SearchPattern, pSearchPattern);
365 pCcb->SearchPattern.Buffer[pCcb->SearchPattern.Length / sizeof(WCHAR)] = 0;
366 }
367 }
368 else if (!pCcb->SearchPattern.Buffer)
369 {
370 First = TRUE;
371 pCcb->SearchPattern.MaximumLength = 2 * sizeof(WCHAR);
372 pCcb->SearchPattern.Buffer = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
373 if (!pCcb->SearchPattern.Buffer)
374 {
375 ExReleaseResourceLite(&pFcb->MainResource);
376 return STATUS_INSUFFICIENT_RESOURCES;
377 }
378 pCcb->SearchPattern.Buffer[0] = L'*';
379 pCcb->SearchPattern.Buffer[1] = 0;
380 pCcb->SearchPattern.Length = sizeof(WCHAR);
381 }
382
383 if (IrpContext->Stack->Flags & SL_INDEX_SPECIFIED)
384 {
385 DirContext.DirIndex = pCcb->Entry = pCcb->CurrentByteOffset.u.LowPart;
386 FirstCall = TRUE;
387 }
388 else if (First || (IrpContext->Stack->Flags & SL_RESTART_SCAN))
389 {
390 DirContext.DirIndex = pCcb->Entry = 0;
391 FirstCall = TRUE;
392 }
393 else
394 {
395 DirContext.DirIndex = pCcb->Entry;
396 FirstCall = FALSE;
397 }
398
399 DPRINT ("Buffer=%x tofind=%wZ\n", Buffer, &pCcb->SearchPattern);
400
401 DirContext.LongNameU.Buffer = LongNameBuffer;
402 DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
403 DirContext.ShortNameU.Buffer = ShortNameBuffer;
404 DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
405
406 while (RC == STATUS_SUCCESS && BufferLength > 0)
407 {
408 RC = FindFile (IrpContext->DeviceExt, pFcb,
409 &pCcb->SearchPattern, &DirContext, FirstCall);
410 pCcb->Entry = DirContext.DirIndex;
411 DPRINT ("Found %wZ, RC=%x, entry %x\n", &DirContext.LongNameU, RC, pCcb->Entry);
412 FirstCall = FALSE;
413 if (NT_SUCCESS (RC))
414 {
415 switch (FileInformationClass)
416 {
417 case FileNameInformation:
418 RC = VfatGetFileNameInformation (&DirContext,
419 (PFILE_NAMES_INFORMATION) Buffer,
420 BufferLength);
421 break;
422 case FileDirectoryInformation:
423 RC = VfatGetFileDirectoryInformation (&DirContext,
424 IrpContext->DeviceExt,
425 (PFILE_DIRECTORY_INFORMATION) Buffer,
426 BufferLength);
427 break;
428 case FileFullDirectoryInformation:
429 RC = VfatGetFileFullDirectoryInformation (&DirContext,
430 IrpContext->DeviceExt,
431 (PFILE_FULL_DIR_INFORMATION) Buffer,
432 BufferLength);
433 break;
434 case FileBothDirectoryInformation:
435 RC = VfatGetFileBothInformation (&DirContext,
436 IrpContext->DeviceExt,
437 (PFILE_BOTH_DIR_INFORMATION) Buffer,
438 BufferLength);
439 break;
440 default:
441 RC = STATUS_INVALID_INFO_CLASS;
442 }
443 if (RC == STATUS_BUFFER_OVERFLOW)
444 {
445 if (Buffer0)
446 {
447 Buffer0->NextEntryOffset = 0;
448 }
449 break;
450 }
451 }
452 else
453 {
454 if (Buffer0)
455 {
456 Buffer0->NextEntryOffset = 0;
457 }
458 if (First)
459 {
460 RC = STATUS_NO_SUCH_FILE;
461 }
462 else
463 {
464 RC = STATUS_NO_MORE_FILES;
465 }
466 break;
467 }
468 Buffer0 = (PFILE_NAMES_INFORMATION) Buffer;
469 Buffer0->FileIndex = FileIndex++;
470 pCcb->Entry = ++DirContext.DirIndex;
471 if (IrpContext->Stack->Flags & SL_RETURN_SINGLE_ENTRY)
472 {
473 break;
474 }
475 BufferLength -= Buffer0->NextEntryOffset;
476 Buffer += Buffer0->NextEntryOffset;
477 }
478 if (Buffer0)
479 {
480 Buffer0->NextEntryOffset = 0;
481 }
482 if (FileIndex > 0)
483 {
484 RC = STATUS_SUCCESS;
485 }
486 ExReleaseResourceLite(&pFcb->MainResource);
487 return RC;
488 }
489
490
491 NTSTATUS VfatDirectoryControl (PVFAT_IRP_CONTEXT IrpContext)
492 /*
493 * FUNCTION: directory control : read/write directory informations
494 */
495 {
496 NTSTATUS RC = STATUS_SUCCESS;
497 CHECKPOINT;
498 switch (IrpContext->MinorFunction)
499 {
500 case IRP_MN_QUERY_DIRECTORY:
501 RC = DoQuery (IrpContext);
502 break;
503 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
504 DPRINT (" vfat, dir : change\n");
505 RC = STATUS_NOT_IMPLEMENTED;
506 break;
507 default:
508 // error
509 DbgPrint ("unexpected minor function %x in VFAT driver\n",
510 IrpContext->MinorFunction);
511 RC = STATUS_INVALID_DEVICE_REQUEST;
512 break;
513 }
514 if (RC == STATUS_PENDING)
515 {
516 RC = VfatQueueRequest(IrpContext);
517 }
518 else
519 {
520 IrpContext->Irp->IoStatus.Status = RC;
521 IrpContext->Irp->IoStatus.Information = 0;
522 IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
523 VfatFreeIrpContext(IrpContext);
524 }
525 return RC;
526 }
527
528