3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: create.c,v 1.71 2004/08/01 21:57:17 navaraf Exp $
21 * PROJECT: ReactOS kernel
22 * FILE: drivers/fs/vfat/create.c
23 * PURPOSE: VFAT Filesystem
24 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
28 /* INCLUDES *****************************************************************/
30 #include <ddk/ntddk.h>
39 /* GLOBALS *******************************************************************/
41 #define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FATDirEntry))
43 /* FUNCTIONS *****************************************************************/
45 void vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry
, PUNICODE_STRING NameU
)
51 memcpy(cString
, pEntry
->Filename
, 11);
53 if (cString
[0] == 0x05)
58 StringA
.Buffer
= cString
;
59 for (StringA
.Length
= 0;
60 StringA
.Length
< 8 && StringA
.Buffer
[StringA
.Length
] != ' ';
62 StringA
.MaximumLength
= StringA
.Length
;
64 RtlOemStringToUnicodeString(NameU
, &StringA
, FALSE
);
66 if (pEntry
->lCase
& VFAT_CASE_LOWER_BASE
)
68 RtlDowncaseUnicodeString(NameU
, NameU
, FALSE
);
70 if (cString
[8] != ' ')
72 Length
= NameU
->Length
;
73 NameU
->Buffer
+= Length
/ sizeof(WCHAR
);
74 if (!ENTRY_VOLUME(pEntry
))
76 Length
+= sizeof(WCHAR
);
77 NameU
->Buffer
[0] = L
'.';
81 NameU
->MaximumLength
-= Length
;
83 StringA
.Buffer
= &cString
[8];
84 for (StringA
.Length
= 0;
85 StringA
.Length
< 3 && StringA
.Buffer
[StringA
.Length
] != ' ';
87 StringA
.MaximumLength
= StringA
.Length
;
88 RtlOemStringToUnicodeString(NameU
, &StringA
, FALSE
);
89 if (pEntry
->lCase
& VFAT_CASE_LOWER_EXT
)
91 RtlDowncaseUnicodeString(NameU
, NameU
, FALSE
);
93 NameU
->Buffer
-= Length
/ sizeof(WCHAR
);
94 NameU
->Length
+= Length
;
95 NameU
->MaximumLength
+= Length
;
97 NameU
->Buffer
[NameU
->Length
/ sizeof(WCHAR
)] = 0;
98 DPRINT("'%wZ'\n", NameU
);
102 ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt
, PVPB Vpb
)
104 * FUNCTION: Read the volume label
107 PVOID Context
= NULL
;
111 LARGE_INTEGER FileOffset
;
112 UNICODE_STRING NameU
;
114 NameU
.Buffer
= Vpb
->VolumeLabel
;
116 NameU
.MaximumLength
= sizeof(Vpb
->VolumeLabel
);
117 *(Vpb
->VolumeLabel
) = 0;
118 Vpb
->VolumeLabelLength
= 0;
120 ExAcquireResourceExclusiveLite (&DeviceExt
->DirResource
, TRUE
);
121 pFcb
= vfatOpenRootFCB (DeviceExt
);
122 ExReleaseResourceLite (&DeviceExt
->DirResource
);
124 FileOffset
.QuadPart
= 0;
125 if (CcMapData(pFcb
->FileObject
, &FileOffset
, PAGE_SIZE
, TRUE
, &Context
, (PVOID
*)&Entry
))
129 if (ENTRY_VOLUME(Entry
))
131 /* copy volume label */
132 vfat8Dot3ToString (Entry
, &NameU
);
133 Vpb
->VolumeLabelLength
= NameU
.Length
;
136 if (ENTRY_END(Entry
))
142 if ((DirIndex
% ENTRIES_PER_PAGE
) == 0)
144 CcUnpinData(Context
);
145 FileOffset
.u
.LowPart
+= PAGE_SIZE
;
146 if (!CcMapData(pFcb
->FileObject
, &FileOffset
, PAGE_SIZE
, TRUE
, &Context
, (PVOID
*)&Entry
))
155 CcUnpinData(Context
);
158 ExAcquireResourceExclusiveLite (&DeviceExt
->DirResource
, TRUE
);
159 vfatReleaseFCB (DeviceExt
, pFcb
);
160 ExReleaseResourceLite (&DeviceExt
->DirResource
);
162 return STATUS_SUCCESS
;
166 FindFile (PDEVICE_EXTENSION DeviceExt
,
168 PUNICODE_STRING FileToFindU
,
169 PVFAT_DIRENTRY_CONTEXT DirContext
,
172 * FUNCTION: Find a file
175 WCHAR PathNameBuffer
[MAX_PATH
];
177 PVOID Context
= NULL
;
181 BOOLEAN FoundShort
= FALSE
;
182 UNICODE_STRING PathNameU
;
186 DPRINT ("FindFile(Parent %x, FileToFind '%wZ', DirIndex: %d)\n",
187 Parent
, FileToFindU
, DirContext
->DirIndex
);
188 DPRINT ("FindFile: Path %wZ)\n",&Parent
->PathNameU
);
190 PathNameU
.Buffer
= PathNameBuffer
;
191 PathNameU
.Length
= 0;
192 PathNameU
.MaximumLength
= sizeof(PathNameBuffer
);
194 DirContext
->LongNameU
.Length
= 0;
195 DirContext
->ShortNameU
.Length
= 0;
197 /* FIXME: Use FsRtlDoesNameContainWildCards */
199 curr
= FileToFindU
->Buffer
;
200 last
= FileToFindU
->Buffer
+ FileToFindU
->Length
/ sizeof(WCHAR
);
203 if (*curr
== L
'?' || *curr
== L
'*')
211 if (WildCard
== FALSE
)
213 /* if there is no '*?' in the search name, than look first for an existing fcb */
214 RtlCopyUnicodeString(&PathNameU
, &Parent
->PathNameU
);
215 if (!vfatFCBIsRoot(Parent
))
217 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = L
'\\';
218 PathNameU
.Length
+= sizeof(WCHAR
);
220 RtlAppendUnicodeStringToString(&PathNameU
, FileToFindU
);
221 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = 0;
222 rcFcb
= vfatGrabFCBFromTable(DeviceExt
, &PathNameU
);
225 if(rcFcb
->startIndex
>= DirContext
->DirIndex
)
227 RtlCopyUnicodeString(&DirContext
->LongNameU
, &rcFcb
->LongNameU
);
228 RtlCopyUnicodeString(&DirContext
->ShortNameU
, &rcFcb
->ShortNameU
);
229 memcpy(&DirContext
->FatDirEntry
, &rcFcb
->entry
, sizeof(FATDirEntry
));
230 DirContext
->StartIndex
= rcFcb
->startIndex
;
231 DirContext
->DirIndex
= rcFcb
->dirIndex
;
232 DPRINT("FindFile: new Name %wZ, DirIndex %d (%d)\n",
233 &DirContext
->LongNameU
, DirContext
->DirIndex
, DirContext
->StartIndex
);
234 Status
= STATUS_SUCCESS
;
239 Status
= STATUS_UNSUCCESSFUL
;
241 vfatReleaseFCB(DeviceExt
, rcFcb
);
248 Status
= vfatGetNextDirEntry(&Context
, &Page
, Parent
, DirContext
, First
);
250 if (Status
== STATUS_NO_MORE_ENTRIES
)
254 if (ENTRY_VOLUME(&DirContext
->FatDirEntry
))
256 DirContext
->DirIndex
++;
259 DirContext
->LongNameU
.Buffer
[DirContext
->LongNameU
.Length
/ sizeof(WCHAR
)] = 0;
260 DirContext
->ShortNameU
.Buffer
[DirContext
->ShortNameU
.Length
/ sizeof(WCHAR
)] = 0;
263 /* FIXME: Use FsRtlIsNameInExpression */
264 if (DirContext
->LongNameU
.Length
> 0 &&
265 wstrcmpjoki (DirContext
->LongNameU
.Buffer
, FileToFindU
->Buffer
))
273 if (FoundLong
== FALSE
)
275 /* FIXME: Use FsRtlIsNameInExpression */
276 FoundShort
= wstrcmpjoki (DirContext
->ShortNameU
.Buffer
, FileToFindU
->Buffer
);
285 FoundLong
= RtlEqualUnicodeString(&DirContext
->LongNameU
, FileToFindU
, TRUE
);
286 if (FoundLong
== FALSE
)
288 FoundShort
= RtlEqualUnicodeString(&DirContext
->ShortNameU
, FileToFindU
, TRUE
);
292 if (FoundLong
|| FoundShort
)
296 RtlCopyUnicodeString(&PathNameU
, &Parent
->PathNameU
);
297 if (!vfatFCBIsRoot(Parent
))
299 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = L
'\\';
300 PathNameU
.Length
+= sizeof(WCHAR
);
302 RtlAppendUnicodeStringToString(&PathNameU
, &DirContext
->LongNameU
);
303 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = 0;
304 rcFcb
= vfatGrabFCBFromTable(DeviceExt
, &PathNameU
);
307 memcpy(&DirContext
->FatDirEntry
, &rcFcb
->entry
, sizeof(FATDirEntry
));
308 vfatReleaseFCB(DeviceExt
, rcFcb
);
311 DPRINT("%d\n", DirContext
->LongNameU
.Length
);
312 DPRINT("FindFile: new Name %wZ, DirIndex %d\n",
313 &DirContext
->LongNameU
, DirContext
->DirIndex
);
317 CcUnpinData(Context
);
319 return STATUS_SUCCESS
;
321 DirContext
->DirIndex
++;
326 CcUnpinData(Context
);
333 VfatOpenFile (PDEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
,
334 PUNICODE_STRING FileNameU
)
336 * FUNCTION: Opens a file
344 // PDEVICE_OBJECT DeviceObject = DeviceExt->StorageDevice->Vpb->DeviceObject;
346 DPRINT ("VfatOpenFile(%08lx, %08lx, '%wZ')\n", DeviceExt
, FileObject
, &FileObject
->FileName
);
348 if (FileObject
->RelatedFileObject
)
350 DPRINT ("Converting relative filename to absolute filename\n");
352 Fcb
= FileObject
->RelatedFileObject
->FsContext
;
353 RtlCopyUnicodeString(FileNameU
, &Fcb
->PathNameU
);
354 if (!vfatFCBIsRoot(Fcb
))
356 RtlAppendUnicodeToString(FileNameU
, L
"\\");
358 RtlAppendUnicodeStringToString(FileNameU
, &FileObject
->FileName
);
362 RtlCopyUnicodeString(FileNameU
, &FileObject
->FileName
);
364 if (FileNameU
->Length
> sizeof(WCHAR
) &&
365 FileNameU
->Buffer
[FileNameU
->Length
/ sizeof(WCHAR
) - 1] == L
'\\')
367 FileNameU
->Length
-= sizeof(WCHAR
);
369 FileNameU
->Buffer
[FileNameU
->Length
/ sizeof(WCHAR
)] = 0;
371 DPRINT ("PathName to open: '%wZ'\n", FileNameU
);
373 if (!DeviceExt
->FatInfo
.FixedMedia
)
375 Status
= VfatBlockDeviceIoControl (DeviceExt
->StorageDevice
,
376 IOCTL_DISK_CHECK_VERIFY
,
383 if (Status
== STATUS_VERIFY_REQUIRED
)
386 PDEVICE_OBJECT DeviceToVerify
;
388 DPRINT ("Media change detected!\n");
389 DPRINT ("Device %p\n", DeviceExt
->StorageDevice
);
391 DeviceToVerify
= IoGetDeviceToVerify (PsGetCurrentThread ());
393 IoSetDeviceToVerify (PsGetCurrentThread (),
395 Status
= IoVerifyVolume (DeviceExt
->StorageDevice
,
398 if (!NT_SUCCESS(Status
))
400 DPRINT ("Status %lx\n", Status
);
406 /* try first to find an existing FCB in memory */
407 DPRINT ("Checking for existing FCB in memory\n");
408 Fcb
= vfatGrabFCBFromTable (DeviceExt
, FileNameU
);
411 DPRINT ("No existing FCB found, making a new one if file exists.\n");
412 Status
= vfatGetFCBForFile (DeviceExt
, &ParentFcb
, &Fcb
, FileNameU
);
413 if (ParentFcb
!= NULL
)
415 vfatReleaseFCB (DeviceExt
, ParentFcb
);
417 if (!NT_SUCCESS (Status
))
419 DPRINT ("Could not make a new FCB, status: %x\n", Status
);
425 RtlCopyUnicodeString(FileNameU
, &Fcb
->PathNameU
);
427 if (Fcb
->Flags
& FCB_DELETE_PENDING
)
429 vfatReleaseFCB (DeviceExt
, Fcb
);
430 return STATUS_DELETE_PENDING
;
432 DPRINT ("Attaching FCB to fileObject\n");
433 Status
= vfatAttachFCBToFileObject (DeviceExt
, Fcb
, FileObject
);
439 VfatSupersedeFile(PDEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
,
442 ULONG Cluster
, NextCluster
;
445 Fcb
->entry
.FileSize
= 0;
446 if (DeviceExt
->FatInfo
.FatType
== FAT32
)
448 Cluster
= Fcb
->entry
.FirstCluster
+ Fcb
->entry
.FirstClusterHigh
* 65536;
452 Cluster
= Fcb
->entry
.FirstCluster
;
454 Fcb
->entry
.FirstCluster
= 0;
455 Fcb
->entry
.FirstClusterHigh
= 0;
456 Fcb
->LastOffset
= Fcb
->LastCluster
= 0;
457 VfatUpdateEntry (Fcb
);
458 if (Fcb
->RFCB
.FileSize
.QuadPart
> 0)
460 Fcb
->RFCB
.AllocationSize
.QuadPart
= 0;
461 Fcb
->RFCB
.FileSize
.QuadPart
= 0;
462 Fcb
->RFCB
.ValidDataLength
.QuadPart
= 0;
463 /* Notify cache manager about the change in file size if caching is
464 initialized on the file stream */
465 if (FileObject
->SectionObjectPointer
->SharedCacheMap
!= NULL
)
467 CcSetFileSizes(FileObject
, (PCC_FILE_SIZES
)&Fcb
->RFCB
.AllocationSize
);
470 while (Cluster
!= 0xffffffff && Cluster
> 1)
472 Status
= GetNextCluster (DeviceExt
, Cluster
, &NextCluster
, FALSE
);
473 WriteCluster (DeviceExt
, Cluster
, 0);
474 Cluster
= NextCluster
;
479 VfatCreateFile (PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
481 * FUNCTION: Create or open a file
484 PIO_STACK_LOCATION Stack
;
485 PFILE_OBJECT FileObject
;
486 NTSTATUS Status
= STATUS_SUCCESS
;
487 PDEVICE_EXTENSION DeviceExt
;
488 ULONG RequestedDisposition
, RequestedOptions
;
492 BOOLEAN PagingFileCreate
= FALSE
;
493 LARGE_INTEGER AllocationSize
;
495 UNICODE_STRING NameU
;
496 WCHAR NameW
[MAX_PATH
];
498 /* Unpack the various parameters. */
499 Stack
= IoGetCurrentIrpStackLocation (Irp
);
500 RequestedDisposition
= ((Stack
->Parameters
.Create
.Options
>> 24) & 0xff);
502 Stack
->Parameters
.Create
.Options
& FILE_VALID_OPTION_FLAGS
;
503 PagingFileCreate
= (Stack
->Flags
& SL_OPEN_PAGING_FILE
) ? TRUE
: FALSE
;
504 FileObject
= Stack
->FileObject
;
505 DeviceExt
= DeviceObject
->DeviceExtension
;
507 /* Check their validity. */
508 if (RequestedOptions
& FILE_DIRECTORY_FILE
&&
509 RequestedDisposition
== FILE_SUPERSEDE
)
511 return(STATUS_INVALID_PARAMETER
);
514 /* This a open operation for the volume itself */
515 if (FileObject
->FileName
.Length
== 0 &&
516 FileObject
->RelatedFileObject
== NULL
)
518 if (RequestedDisposition
== FILE_CREATE
||
519 RequestedDisposition
== FILE_OVERWRITE_IF
||
520 RequestedDisposition
== FILE_SUPERSEDE
)
522 return(STATUS_ACCESS_DENIED
);
524 if (RequestedOptions
& FILE_DIRECTORY_FILE
)
526 return(STATUS_NOT_A_DIRECTORY
);
528 pFcb
= DeviceExt
->VolumeFcb
;
529 pCcb
= ExAllocateFromNPagedLookasideList(&VfatGlobalData
->CcbLookasideList
);
532 return (STATUS_INSUFFICIENT_RESOURCES
);
534 memset(pCcb
, 0, sizeof(VFATCCB
));
535 FileObject
->Flags
|= FO_FCB_IS_VALID
;
536 FileObject
->SectionObjectPointer
= &pFcb
->SectionObjectPointers
;
537 FileObject
->FsContext
= pFcb
;
538 FileObject
->FsContext2
= pCcb
;
541 Irp
->IoStatus
.Information
= FILE_OPENED
;
542 return(STATUS_SUCCESS
);
546 * Check for illegal characters and illegale dot sequences in the file name
548 c
= FileObject
->FileName
.Buffer
+ FileObject
->FileName
.Length
/ sizeof(WCHAR
);
551 while (c
-- > FileObject
->FileName
.Buffer
)
553 if (*c
== L
'\\' || c
== FileObject
->FileName
.Buffer
)
555 if (Dots
&& last
> c
)
557 return(STATUS_OBJECT_NAME_INVALID
);
567 if (*c
!= '\\' && vfatIsLongIllegal(*c
))
569 return(STATUS_OBJECT_NAME_INVALID
);
573 NameU
.Buffer
= NameW
;
575 NameU
.MaximumLength
= sizeof(NameW
);
577 /* Try opening the file. */
578 Status
= VfatOpenFile (DeviceExt
, FileObject
, &NameU
);
581 * If the directory containing the file to open doesn't exist then
584 if (Status
== STATUS_OBJECT_PATH_NOT_FOUND
||
585 Status
== STATUS_INVALID_PARAMETER
||
586 Status
== STATUS_DELETE_PENDING
)
592 * If the file open failed then create the required file
594 if (!NT_SUCCESS (Status
))
596 if (RequestedDisposition
== FILE_CREATE
||
597 RequestedDisposition
== FILE_OPEN_IF
||
598 RequestedDisposition
== FILE_OVERWRITE_IF
||
599 RequestedDisposition
== FILE_SUPERSEDE
)
602 Attributes
= Stack
->Parameters
.Create
.FileAttributes
;
603 Status
= VfatAddEntry (DeviceExt
, &NameU
, FileObject
, RequestedOptions
,
604 (UCHAR
)(Attributes
& FILE_ATTRIBUTE_VALID_FLAGS
));
605 if (NT_SUCCESS (Status
))
607 pFcb
= FileObject
->FsContext
;
609 Irp
->IoStatus
.Information
= FILE_CREATED
;
611 VfatSetAllocationSizeInformation(FileObject
,
614 &Irp
->Overlay
.AllocationSize
);
615 VfatSetExtendedAttributes(FileObject
,
616 Irp
->AssociatedIrp
.SystemBuffer
,
617 Stack
->Parameters
.Create
.EaLength
);
618 IoSetShareAccess(0 /*DesiredAccess*/,
619 Stack
->Parameters
.Create
.ShareAccess
,
621 &pFcb
->FCBShareAccess
);
623 if (PagingFileCreate
)
625 pFcb
->Flags
|= FCB_IS_PAGE_FILE
;
640 /* Otherwise fail if the caller wanted to create a new file */
641 if (RequestedDisposition
== FILE_CREATE
)
643 Irp
->IoStatus
.Information
= FILE_EXISTS
;
644 VfatCloseFile (DeviceExt
, FileObject
);
645 return(STATUS_OBJECT_NAME_COLLISION
);
648 pFcb
= FileObject
->FsContext
;
651 * Check the file has the requested attributes
653 if (RequestedOptions
& FILE_NON_DIRECTORY_FILE
&&
654 pFcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
656 VfatCloseFile (DeviceExt
, FileObject
);
657 return(STATUS_FILE_IS_A_DIRECTORY
);
659 if (RequestedOptions
& FILE_DIRECTORY_FILE
&&
660 !(pFcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
))
662 VfatCloseFile (DeviceExt
, FileObject
);
663 return(STATUS_NOT_A_DIRECTORY
);
666 if (PagingFileCreate
)
669 * Do more checking for page files. It is possible,
670 * that the file was opened and closed previously
671 * as a normal cached file. In this case, the cache
672 * manager has referenced the fileobject and the fcb
673 * is held in memory. Try to remove the fileobject
674 * from cache manager and use the fcb.
676 if (pFcb
->RefCount
> 1)
678 if(!(pFcb
->Flags
& FCB_IS_PAGE_FILE
))
680 VfatCloseFile(DeviceExt
, FileObject
);
681 return(STATUS_INVALID_PARAMETER
);
686 pFcb
->Flags
|= FCB_IS_PAGE_FILE
;
691 if (pFcb
->Flags
& FCB_IS_PAGE_FILE
)
693 VfatCloseFile(DeviceExt
, FileObject
);
694 return(STATUS_INVALID_PARAMETER
);
699 if (RequestedDisposition
== FILE_OVERWRITE
||
700 RequestedDisposition
== FILE_OVERWRITE_IF
)
702 AllocationSize
.QuadPart
= 0;
703 Status
= VfatSetAllocationSizeInformation (FileObject
,
707 if (!NT_SUCCESS (Status
))
709 VfatCloseFile (DeviceExt
, FileObject
);
715 /* Supersede the file */
716 if (RequestedDisposition
== FILE_SUPERSEDE
)
718 VfatSupersedeFile(DeviceExt
, FileObject
, pFcb
);
719 Irp
->IoStatus
.Information
= FILE_SUPERSEDED
;
721 else if (RequestedDisposition
== FILE_OVERWRITE
|| RequestedDisposition
== FILE_OVERWRITE_IF
)
723 Irp
->IoStatus
.Information
= FILE_OVERWRITTEN
;
727 Irp
->IoStatus
.Information
= FILE_OPENED
;
731 /* FIXME : test share access */
732 /* FIXME : test write access if requested */
738 NTSTATUS
VfatCreate (PVFAT_IRP_CONTEXT IrpContext
)
740 * FUNCTION: Create or open a file
747 if (IrpContext
->DeviceObject
== VfatGlobalData
->DeviceObject
)
749 /* DeviceObject represents FileSystem instead of logical volume */
750 DPRINT ("FsdCreate called with file system\n");
751 IrpContext
->Irp
->IoStatus
.Information
= FILE_OPENED
;
752 IrpContext
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
753 IoCompleteRequest (IrpContext
->Irp
, IO_DISK_INCREMENT
);
754 VfatFreeIrpContext(IrpContext
);
755 return(STATUS_SUCCESS
);
758 if (!(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
))
760 return(VfatQueueRequest (IrpContext
));
763 IrpContext
->Irp
->IoStatus
.Information
= 0;
764 ExAcquireResourceExclusiveLite (&IrpContext
->DeviceExt
->DirResource
, TRUE
);
765 Status
= VfatCreateFile (IrpContext
->DeviceObject
, IrpContext
->Irp
);
766 ExReleaseResourceLite (&IrpContext
->DeviceExt
->DirResource
);
768 IrpContext
->Irp
->IoStatus
.Status
= Status
;
769 IoCompleteRequest (IrpContext
->Irp
,
770 (CCHAR
)(NT_SUCCESS(Status
) ? IO_DISK_INCREMENT
: IO_NO_INCREMENT
));
771 VfatFreeIrpContext(IrpContext
);