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.
20 * PROJECT: ReactOS kernel
21 * FILE: drivers/fs/vfat/create.c
22 * PURPOSE: VFAT Filesystem
23 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
27 /* INCLUDES *****************************************************************/
32 /* FUNCTIONS *****************************************************************/
34 void vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry
, PUNICODE_STRING NameU
)
40 RtlCopyMemory(cString
, pEntry
->ShortName
, 11);
42 if (cString
[0] == 0x05)
47 StringA
.Buffer
= cString
;
48 for (StringA
.Length
= 0;
49 StringA
.Length
< 8 && StringA
.Buffer
[StringA
.Length
] != ' ';
51 StringA
.MaximumLength
= StringA
.Length
;
53 RtlOemStringToUnicodeString(NameU
, &StringA
, FALSE
);
55 if (pEntry
->lCase
& VFAT_CASE_LOWER_BASE
)
57 RtlDowncaseUnicodeString(NameU
, NameU
, FALSE
);
59 if (cString
[8] != ' ')
61 Length
= NameU
->Length
;
62 NameU
->Buffer
+= Length
/ sizeof(WCHAR
);
63 if (!FAT_ENTRY_VOLUME(pEntry
))
65 Length
+= sizeof(WCHAR
);
66 NameU
->Buffer
[0] = L
'.';
70 NameU
->MaximumLength
-= Length
;
72 StringA
.Buffer
= &cString
[8];
73 for (StringA
.Length
= 0;
74 StringA
.Length
< 3 && StringA
.Buffer
[StringA
.Length
] != ' ';
76 StringA
.MaximumLength
= StringA
.Length
;
77 RtlOemStringToUnicodeString(NameU
, &StringA
, FALSE
);
78 if (pEntry
->lCase
& VFAT_CASE_LOWER_EXT
)
80 RtlDowncaseUnicodeString(NameU
, NameU
, FALSE
);
82 NameU
->Buffer
-= Length
/ sizeof(WCHAR
);
83 NameU
->Length
+= Length
;
84 NameU
->MaximumLength
+= Length
;
86 NameU
->Buffer
[NameU
->Length
/ sizeof(WCHAR
)] = 0;
87 DPRINT("'%wZ'\n", NameU
);
91 ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt
, PVPB Vpb
)
93 * FUNCTION: Read the volume label
100 LARGE_INTEGER FileOffset
;
101 UNICODE_STRING NameU
;
103 ULONG EntriesPerPage
;
106 NameU
.Buffer
= Vpb
->VolumeLabel
;
108 NameU
.MaximumLength
= sizeof(Vpb
->VolumeLabel
);
109 *(Vpb
->VolumeLabel
) = 0;
110 Vpb
->VolumeLabelLength
= 0;
112 if (DeviceExt
->Flags
& VCB_IS_FATX
)
114 SizeDirEntry
= sizeof(FATX_DIR_ENTRY
);
115 EntriesPerPage
= FATX_ENTRIES_PER_PAGE
;
119 SizeDirEntry
= sizeof(FAT_DIR_ENTRY
);
120 EntriesPerPage
= FAT_ENTRIES_PER_PAGE
;
123 ExAcquireResourceExclusiveLite (&DeviceExt
->DirResource
, TRUE
);
124 pFcb
= vfatOpenRootFCB (DeviceExt
);
125 ExReleaseResourceLite (&DeviceExt
->DirResource
);
127 FileOffset
.QuadPart
= 0;
128 if (CcMapData(pFcb
->FileObject
, &FileOffset
, PAGE_SIZE
, TRUE
, &Context
, (PVOID
*)&Entry
))
132 if (ENTRY_VOLUME(DeviceExt
, Entry
))
134 /* copy volume label */
135 if (DeviceExt
->Flags
& VCB_IS_FATX
)
137 StringO
.Buffer
= (PCHAR
)Entry
->FatX
.Filename
;
138 StringO
.MaximumLength
= StringO
.Length
= Entry
->FatX
.FilenameLength
;
139 RtlOemStringToUnicodeString(&NameU
, &StringO
, FALSE
);
143 vfat8Dot3ToString (&Entry
->Fat
, &NameU
);
145 Vpb
->VolumeLabelLength
= NameU
.Length
;
148 if (ENTRY_END(DeviceExt
, Entry
))
153 Entry
= (PDIR_ENTRY
)((ULONG_PTR
)Entry
+ SizeDirEntry
);
154 if ((DirIndex
% EntriesPerPage
) == 0)
156 CcUnpinData(Context
);
157 FileOffset
.u
.LowPart
+= PAGE_SIZE
;
158 if (!CcMapData(pFcb
->FileObject
, &FileOffset
, PAGE_SIZE
, TRUE
, &Context
, (PVOID
*)&Entry
))
167 CcUnpinData(Context
);
170 ExAcquireResourceExclusiveLite (&DeviceExt
->DirResource
, TRUE
);
171 vfatReleaseFCB (DeviceExt
, pFcb
);
172 ExReleaseResourceLite (&DeviceExt
->DirResource
);
174 return STATUS_SUCCESS
;
178 FindFile (PDEVICE_EXTENSION DeviceExt
,
180 PUNICODE_STRING FileToFindU
,
181 PVFAT_DIRENTRY_CONTEXT DirContext
,
184 * FUNCTION: Find a file
187 PWCHAR PathNameBuffer
;
188 USHORT PathNameBufferLength
;
190 PVOID Context
= NULL
;
194 UNICODE_STRING PathNameU
;
195 UNICODE_STRING FileToFindUpcase
;
198 DPRINT ("FindFile(Parent %x, FileToFind '%wZ', DirIndex: %d)\n",
199 Parent
, FileToFindU
, DirContext
->DirIndex
);
200 DPRINT ("FindFile: Path %wZ)\n",&Parent
->PathNameU
);
202 PathNameBufferLength
= LONGNAME_MAX_LENGTH
* sizeof(WCHAR
);
203 PathNameBuffer
= ExAllocatePool(NonPagedPool
, PathNameBufferLength
+ sizeof(WCHAR
));
207 return STATUS_INSUFFICIENT_RESOURCES
;
210 PathNameU
.Buffer
= PathNameBuffer
;
211 PathNameU
.Length
= 0;
212 PathNameU
.MaximumLength
= PathNameBufferLength
;
214 DirContext
->LongNameU
.Length
= 0;
215 DirContext
->ShortNameU
.Length
= 0;
217 WildCard
= FsRtlDoesNameContainWildCards(FileToFindU
);
219 if (WildCard
== FALSE
)
221 /* if there is no '*?' in the search name, than look first for an existing fcb */
222 RtlCopyUnicodeString(&PathNameU
, &Parent
->PathNameU
);
223 if (!vfatFCBIsRoot(Parent
))
225 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = L
'\\';
226 PathNameU
.Length
+= sizeof(WCHAR
);
228 RtlAppendUnicodeStringToString(&PathNameU
, FileToFindU
);
229 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = 0;
230 rcFcb
= vfatGrabFCBFromTable(DeviceExt
, &PathNameU
);
233 ULONG startIndex
= rcFcb
->startIndex
;
234 if ((rcFcb
->Flags
& FCB_IS_FATX_ENTRY
) && !vfatFCBIsRoot(Parent
))
238 if(startIndex
>= DirContext
->DirIndex
)
240 RtlCopyUnicodeString(&DirContext
->LongNameU
, &rcFcb
->LongNameU
);
241 RtlCopyUnicodeString(&DirContext
->ShortNameU
, &rcFcb
->ShortNameU
);
242 RtlCopyMemory(&DirContext
->DirEntry
, &rcFcb
->entry
, sizeof(DIR_ENTRY
));
243 DirContext
->StartIndex
= rcFcb
->startIndex
;
244 DirContext
->DirIndex
= rcFcb
->dirIndex
;
245 DPRINT("FindFile: new Name %wZ, DirIndex %d (%d)\n",
246 &DirContext
->LongNameU
, DirContext
->DirIndex
, DirContext
->StartIndex
);
247 Status
= STATUS_SUCCESS
;
252 Status
= STATUS_UNSUCCESSFUL
;
254 vfatReleaseFCB(DeviceExt
, rcFcb
);
255 ExFreePool(PathNameBuffer
);
260 /* FsRtlIsNameInExpression need the searched string to be upcase,
261 * even if IgnoreCase is specified */
262 Status
= RtlUpcaseUnicodeString(&FileToFindUpcase
, FileToFindU
, TRUE
);
263 if (!NT_SUCCESS(Status
))
266 ExFreePool(PathNameBuffer
);
272 Status
= DeviceExt
->GetNextDirEntry(&Context
, &Page
, Parent
, DirContext
, First
);
274 if (Status
== STATUS_NO_MORE_ENTRIES
)
278 if (ENTRY_VOLUME(DeviceExt
, &DirContext
->DirEntry
))
280 DirContext
->DirIndex
++;
285 Found
= FsRtlIsNameInExpression(&FileToFindUpcase
, &DirContext
->LongNameU
, TRUE
, NULL
) ||
286 FsRtlIsNameInExpression(&FileToFindUpcase
, &DirContext
->ShortNameU
, TRUE
, NULL
);
290 Found
= FsRtlAreNamesEqual(&DirContext
->LongNameU
, FileToFindU
, TRUE
, NULL
) ||
291 FsRtlAreNamesEqual(&DirContext
->ShortNameU
, FileToFindU
, TRUE
, NULL
);
298 RtlCopyUnicodeString(&PathNameU
, &Parent
->PathNameU
);
299 if (!vfatFCBIsRoot(Parent
))
301 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = L
'\\';
302 PathNameU
.Length
+= sizeof(WCHAR
);
304 RtlAppendUnicodeStringToString(&PathNameU
, &DirContext
->LongNameU
);
305 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = 0;
306 rcFcb
= vfatGrabFCBFromTable(DeviceExt
, &PathNameU
);
309 RtlCopyMemory(&DirContext
->DirEntry
, &rcFcb
->entry
, sizeof(DIR_ENTRY
));
310 vfatReleaseFCB(DeviceExt
, rcFcb
);
313 DPRINT("%d\n", DirContext
->LongNameU
.Length
);
314 DPRINT("FindFile: new Name %wZ, DirIndex %d\n",
315 &DirContext
->LongNameU
, DirContext
->DirIndex
);
319 CcUnpinData(Context
);
321 RtlFreeUnicodeString(&FileToFindUpcase
);
322 ExFreePool(PathNameBuffer
);
323 return STATUS_SUCCESS
;
325 DirContext
->DirIndex
++;
330 CcUnpinData(Context
);
333 RtlFreeUnicodeString(&FileToFindUpcase
);
334 ExFreePool(PathNameBuffer
);
339 VfatOpenFile (PDEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
, PVFATFCB
* ParentFcb
)
341 * FUNCTION: Opens a file
346 UNICODE_STRING PathNameU
;
349 DPRINT ("VfatOpenFile(%08lx, %08lx, '%wZ')\n", DeviceExt
, FileObject
, &FileObject
->FileName
);
351 if (FileObject
->RelatedFileObject
)
353 DPRINT ("'%wZ'\n", &FileObject
->RelatedFileObject
->FileName
);
355 *ParentFcb
= FileObject
->RelatedFileObject
->FsContext
;
356 (*ParentFcb
)->RefCount
++;
363 if (!DeviceExt
->FatInfo
.FixedMedia
)
365 Status
= VfatBlockDeviceIoControl (DeviceExt
->StorageDevice
,
366 IOCTL_DISK_CHECK_VERIFY
,
373 if (Status
== STATUS_VERIFY_REQUIRED
)
376 PDEVICE_OBJECT DeviceToVerify
;
378 DPRINT ("Media change detected!\n");
379 DPRINT ("Device %p\n", DeviceExt
->StorageDevice
);
381 DeviceToVerify
= IoGetDeviceToVerify (PsGetCurrentThread ());
383 IoSetDeviceToVerify (PsGetCurrentThread (),
385 Status
= IoVerifyVolume (DeviceExt
->StorageDevice
,
388 if (!NT_SUCCESS(Status
))
390 DPRINT ("Status %lx\n", Status
);
398 (*ParentFcb
)->RefCount
++;
401 PathNameU
.Buffer
= Buffer
;
402 PathNameU
.Length
= 0;
403 PathNameU
.MaximumLength
= sizeof(Buffer
);
404 RtlCopyUnicodeString(&PathNameU
, &FileObject
->FileName
);
405 if (PathNameU
.Length
> sizeof(WCHAR
) &&
406 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
) - 1] == L
'\\')
408 PathNameU
.Length
-= sizeof(WCHAR
);
410 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = 0;
412 /* try first to find an existing FCB in memory */
413 DPRINT ("Checking for existing FCB in memory\n");
415 Status
= vfatGetFCBForFile (DeviceExt
, ParentFcb
, &Fcb
, &PathNameU
);
416 if (!NT_SUCCESS (Status
))
418 DPRINT ("Could not make a new FCB, status: %x\n", Status
);
421 if (Fcb
->Flags
& FCB_DELETE_PENDING
)
423 vfatReleaseFCB (DeviceExt
, Fcb
);
424 return STATUS_DELETE_PENDING
;
426 DPRINT ("Attaching FCB to fileObject\n");
427 Status
= vfatAttachFCBToFileObject (DeviceExt
, Fcb
, FileObject
);
428 if (!NT_SUCCESS(Status
))
430 vfatReleaseFCB (DeviceExt
, Fcb
);
436 VfatCreateFile (PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
438 * FUNCTION: Create or open a file
441 PIO_STACK_LOCATION Stack
;
442 PFILE_OBJECT FileObject
;
443 NTSTATUS Status
= STATUS_SUCCESS
;
444 PDEVICE_EXTENSION DeviceExt
;
445 ULONG RequestedDisposition
, RequestedOptions
;
450 BOOLEAN PagingFileCreate
= FALSE
;
451 LARGE_INTEGER AllocationSize
;
453 UNICODE_STRING FileNameU
;
455 /* Unpack the various parameters. */
456 Stack
= IoGetCurrentIrpStackLocation (Irp
);
457 RequestedDisposition
= ((Stack
->Parameters
.Create
.Options
>> 24) & 0xff);
459 Stack
->Parameters
.Create
.Options
& FILE_VALID_OPTION_FLAGS
;
460 PagingFileCreate
= (Stack
->Flags
& SL_OPEN_PAGING_FILE
) ? TRUE
: FALSE
;
461 FileObject
= Stack
->FileObject
;
462 DeviceExt
= DeviceObject
->DeviceExtension
;
464 /* Check their validity. */
465 if (RequestedOptions
& FILE_DIRECTORY_FILE
&&
466 RequestedDisposition
== FILE_SUPERSEDE
)
468 return(STATUS_INVALID_PARAMETER
);
471 /* This a open operation for the volume itself */
472 if (FileObject
->FileName
.Length
== 0 &&
473 FileObject
->RelatedFileObject
== NULL
)
475 if (RequestedDisposition
== FILE_CREATE
||
476 RequestedDisposition
== FILE_OVERWRITE_IF
||
477 RequestedDisposition
== FILE_SUPERSEDE
)
479 return(STATUS_ACCESS_DENIED
);
481 if (RequestedOptions
& FILE_DIRECTORY_FILE
)
483 return(STATUS_NOT_A_DIRECTORY
);
485 pFcb
= DeviceExt
->VolumeFcb
;
486 pCcb
= ExAllocateFromNPagedLookasideList(&VfatGlobalData
->CcbLookasideList
);
489 return (STATUS_INSUFFICIENT_RESOURCES
);
491 RtlZeroMemory(pCcb
, sizeof(VFATCCB
));
492 FileObject
->SectionObjectPointer
= &pFcb
->SectionObjectPointers
;
493 FileObject
->FsContext
= pFcb
;
494 FileObject
->FsContext2
= pCcb
;
497 Irp
->IoStatus
.Information
= FILE_OPENED
;
498 return(STATUS_SUCCESS
);
502 * Check for illegal characters and illegale dot sequences in the file name
504 c
= FileObject
->FileName
.Buffer
+ FileObject
->FileName
.Length
/ sizeof(WCHAR
);
507 while (c
-- > FileObject
->FileName
.Buffer
)
509 if (*c
== L
'\\' || c
== FileObject
->FileName
.Buffer
)
511 if (Dots
&& last
> c
)
513 return(STATUS_OBJECT_NAME_INVALID
);
523 if (*c
!= '\\' && vfatIsLongIllegal(*c
))
525 return(STATUS_OBJECT_NAME_INVALID
);
529 /* Try opening the file. */
530 Status
= VfatOpenFile (DeviceExt
, FileObject
, &ParentFcb
);
533 * If the directory containing the file to open doesn't exist then
536 if (Status
== STATUS_OBJECT_PATH_NOT_FOUND
||
537 Status
== STATUS_INVALID_PARAMETER
||
538 Status
== STATUS_DELETE_PENDING
)
542 vfatReleaseFCB (DeviceExt
, ParentFcb
);
548 * If the file open failed then create the required file
550 if (!NT_SUCCESS (Status
))
552 if (RequestedDisposition
== FILE_CREATE
||
553 RequestedDisposition
== FILE_OPEN_IF
||
554 RequestedDisposition
== FILE_OVERWRITE_IF
||
555 RequestedDisposition
== FILE_SUPERSEDE
)
558 Attributes
= Stack
->Parameters
.Create
.FileAttributes
;
560 vfatSplitPathName(&FileObject
->FileName
, NULL
, &FileNameU
);
561 Status
= VfatAddEntry (DeviceExt
, &FileNameU
, &pFcb
, ParentFcb
, RequestedOptions
,
562 (UCHAR
)(Attributes
& FILE_ATTRIBUTE_VALID_FLAGS
));
563 vfatReleaseFCB (DeviceExt
, ParentFcb
);
564 if (NT_SUCCESS (Status
))
566 Status
= vfatAttachFCBToFileObject (DeviceExt
, pFcb
, FileObject
);
567 if ( !NT_SUCCESS(Status
) )
569 vfatReleaseFCB (DeviceExt
, pFcb
);
573 Irp
->IoStatus
.Information
= FILE_CREATED
;
575 VfatSetAllocationSizeInformation(FileObject
,
578 &Irp
->Overlay
.AllocationSize
);
579 VfatSetExtendedAttributes(FileObject
,
580 Irp
->AssociatedIrp
.SystemBuffer
,
581 Stack
->Parameters
.Create
.EaLength
);
583 if (PagingFileCreate
)
585 pFcb
->Flags
|= FCB_IS_PAGE_FILE
;
595 vfatReleaseFCB (DeviceExt
, ParentFcb
);
603 vfatReleaseFCB (DeviceExt
, ParentFcb
);
605 /* Otherwise fail if the caller wanted to create a new file */
606 if (RequestedDisposition
== FILE_CREATE
)
608 Irp
->IoStatus
.Information
= FILE_EXISTS
;
609 VfatCloseFile (DeviceExt
, FileObject
);
610 return(STATUS_OBJECT_NAME_COLLISION
);
613 pFcb
= FileObject
->FsContext
;
615 if (pFcb
->OpenHandleCount
!= 0 &&
616 !(*pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
))
618 Status
= IoCheckShareAccess(Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
,
619 Stack
->Parameters
.Create
.ShareAccess
,
621 &pFcb
->FCBShareAccess
,
623 if (!NT_SUCCESS(Status
))
625 VfatCloseFile (DeviceExt
, FileObject
);
631 * Check the file has the requested attributes
633 if (RequestedOptions
& FILE_NON_DIRECTORY_FILE
&&
634 *pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
)
636 VfatCloseFile (DeviceExt
, FileObject
);
637 return(STATUS_FILE_IS_A_DIRECTORY
);
639 if (RequestedOptions
& FILE_DIRECTORY_FILE
&&
640 !(*pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
))
642 VfatCloseFile (DeviceExt
, FileObject
);
643 return(STATUS_NOT_A_DIRECTORY
);
646 if (PagingFileCreate
)
649 * Do more checking for page files. It is possible,
650 * that the file was opened and closed previously
651 * as a normal cached file. In this case, the cache
652 * manager has referenced the fileobject and the fcb
653 * is held in memory. Try to remove the fileobject
654 * from cache manager and use the fcb.
656 if (pFcb
->RefCount
> 1)
658 if(!(pFcb
->Flags
& FCB_IS_PAGE_FILE
))
660 VfatCloseFile(DeviceExt
, FileObject
);
661 return(STATUS_INVALID_PARAMETER
);
666 pFcb
->Flags
|= FCB_IS_PAGE_FILE
;
671 if (pFcb
->Flags
& FCB_IS_PAGE_FILE
)
673 VfatCloseFile(DeviceExt
, FileObject
);
674 return(STATUS_INVALID_PARAMETER
);
679 if (RequestedDisposition
== FILE_OVERWRITE
||
680 RequestedDisposition
== FILE_OVERWRITE_IF
)
682 AllocationSize
.QuadPart
= 0;
683 Status
= VfatSetAllocationSizeInformation (FileObject
,
687 if (!NT_SUCCESS (Status
))
689 VfatCloseFile (DeviceExt
, FileObject
);
695 /* Supersede the file */
696 if (RequestedDisposition
== FILE_SUPERSEDE
)
698 AllocationSize
.QuadPart
= 0;
699 VfatSetAllocationSizeInformation(FileObject
, pFcb
, DeviceExt
, &AllocationSize
);
700 Irp
->IoStatus
.Information
= FILE_SUPERSEDED
;
702 else if (RequestedDisposition
== FILE_OVERWRITE
|| RequestedDisposition
== FILE_OVERWRITE_IF
)
704 Irp
->IoStatus
.Information
= FILE_OVERWRITTEN
;
708 Irp
->IoStatus
.Information
= FILE_OPENED
;
712 if (pFcb
->OpenHandleCount
== 0 &&
713 !(*pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
))
715 IoSetShareAccess(Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
,
716 Stack
->Parameters
.Create
.ShareAccess
,
718 &pFcb
->FCBShareAccess
);
724 &pFcb
->FCBShareAccess
729 pFcb
->OpenHandleCount
++;
731 /* FIXME : test write access if requested */
737 NTSTATUS
VfatCreate (PVFAT_IRP_CONTEXT IrpContext
)
739 * FUNCTION: Create or open a file
746 if (IrpContext
->DeviceObject
== VfatGlobalData
->DeviceObject
)
748 /* DeviceObject represents FileSystem instead of logical volume */
749 DPRINT ("FsdCreate called with file system\n");
750 IrpContext
->Irp
->IoStatus
.Information
= FILE_OPENED
;
751 IrpContext
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
752 IoCompleteRequest (IrpContext
->Irp
, IO_DISK_INCREMENT
);
753 VfatFreeIrpContext(IrpContext
);
754 return(STATUS_SUCCESS
);
757 if (!(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
))
759 return(VfatQueueRequest (IrpContext
));
762 IrpContext
->Irp
->IoStatus
.Information
= 0;
763 ExAcquireResourceExclusiveLite (&IrpContext
->DeviceExt
->DirResource
, TRUE
);
764 Status
= VfatCreateFile (IrpContext
->DeviceObject
, IrpContext
->Irp
);
765 ExReleaseResourceLite (&IrpContext
->DeviceExt
->DirResource
);
767 IrpContext
->Irp
->IoStatus
.Status
= Status
;
768 IoCompleteRequest (IrpContext
->Irp
,
769 (CCHAR
)(NT_SUCCESS(Status
) ? IO_DISK_INCREMENT
: IO_NO_INCREMENT
));
770 VfatFreeIrpContext(IrpContext
);