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.
21 * PROJECT: ReactOS kernel
22 * FILE: drivers/fs/vfat/create.c
23 * PURPOSE: VFAT Filesystem
24 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
28 /* INCLUDES *****************************************************************/
33 /* FUNCTIONS *****************************************************************/
35 void vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry
, PUNICODE_STRING NameU
)
41 RtlCopyMemory(cString
, pEntry
->Filename
, 11);
43 if (cString
[0] == 0x05)
48 StringA
.Buffer
= cString
;
49 for (StringA
.Length
= 0;
50 StringA
.Length
< 8 && StringA
.Buffer
[StringA
.Length
] != ' ';
52 StringA
.MaximumLength
= StringA
.Length
;
54 RtlOemStringToUnicodeString(NameU
, &StringA
, FALSE
);
56 if (pEntry
->lCase
& VFAT_CASE_LOWER_BASE
)
58 RtlDowncaseUnicodeString(NameU
, NameU
, FALSE
);
60 if (cString
[8] != ' ')
62 Length
= NameU
->Length
;
63 NameU
->Buffer
+= Length
/ sizeof(WCHAR
);
64 if (!FAT_ENTRY_VOLUME(pEntry
))
66 Length
+= sizeof(WCHAR
);
67 NameU
->Buffer
[0] = L
'.';
71 NameU
->MaximumLength
-= Length
;
73 StringA
.Buffer
= &cString
[8];
74 for (StringA
.Length
= 0;
75 StringA
.Length
< 3 && StringA
.Buffer
[StringA
.Length
] != ' ';
77 StringA
.MaximumLength
= StringA
.Length
;
78 RtlOemStringToUnicodeString(NameU
, &StringA
, FALSE
);
79 if (pEntry
->lCase
& VFAT_CASE_LOWER_EXT
)
81 RtlDowncaseUnicodeString(NameU
, NameU
, FALSE
);
83 NameU
->Buffer
-= Length
/ sizeof(WCHAR
);
84 NameU
->Length
+= Length
;
85 NameU
->MaximumLength
+= Length
;
87 NameU
->Buffer
[NameU
->Length
/ sizeof(WCHAR
)] = 0;
88 DPRINT("'%wZ'\n", NameU
);
92 ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt
, PVPB Vpb
)
94 * FUNCTION: Read the volume label
101 LARGE_INTEGER FileOffset
;
102 UNICODE_STRING NameU
;
104 ULONG EntriesPerPage
;
107 NameU
.Buffer
= Vpb
->VolumeLabel
;
109 NameU
.MaximumLength
= sizeof(Vpb
->VolumeLabel
);
110 *(Vpb
->VolumeLabel
) = 0;
111 Vpb
->VolumeLabelLength
= 0;
113 if (DeviceExt
->Flags
& VCB_IS_FATX
)
115 SizeDirEntry
= sizeof(FATX_DIR_ENTRY
);
116 EntriesPerPage
= FATX_ENTRIES_PER_PAGE
;
120 SizeDirEntry
= sizeof(FAT_DIR_ENTRY
);
121 EntriesPerPage
= FAT_ENTRIES_PER_PAGE
;
124 ExAcquireResourceExclusiveLite (&DeviceExt
->DirResource
, TRUE
);
125 pFcb
= vfatOpenRootFCB (DeviceExt
);
126 ExReleaseResourceLite (&DeviceExt
->DirResource
);
128 FileOffset
.QuadPart
= 0;
129 if (CcMapData(pFcb
->FileObject
, &FileOffset
, PAGE_SIZE
, TRUE
, &Context
, (PVOID
*)&Entry
))
133 if (ENTRY_VOLUME(DeviceExt
, Entry
))
135 /* copy volume label */
136 if (DeviceExt
->Flags
& VCB_IS_FATX
)
138 StringO
.Buffer
= (PCHAR
)Entry
->FatX
.Filename
;
139 StringO
.MaximumLength
= StringO
.Length
= Entry
->FatX
.FilenameLength
;
140 RtlOemStringToUnicodeString(&NameU
, &StringO
, FALSE
);
144 vfat8Dot3ToString (&Entry
->Fat
, &NameU
);
146 Vpb
->VolumeLabelLength
= NameU
.Length
;
149 if (ENTRY_END(DeviceExt
, Entry
))
154 Entry
= (PDIR_ENTRY
)((ULONG_PTR
)Entry
+ SizeDirEntry
);
155 if ((DirIndex
% EntriesPerPage
) == 0)
157 CcUnpinData(Context
);
158 FileOffset
.u
.LowPart
+= PAGE_SIZE
;
159 if (!CcMapData(pFcb
->FileObject
, &FileOffset
, PAGE_SIZE
, TRUE
, &Context
, (PVOID
*)&Entry
))
168 CcUnpinData(Context
);
171 ExAcquireResourceExclusiveLite (&DeviceExt
->DirResource
, TRUE
);
172 vfatReleaseFCB (DeviceExt
, pFcb
);
173 ExReleaseResourceLite (&DeviceExt
->DirResource
);
175 return STATUS_SUCCESS
;
179 FindFile (PDEVICE_EXTENSION DeviceExt
,
181 PUNICODE_STRING FileToFindU
,
182 PVFAT_DIRENTRY_CONTEXT DirContext
,
185 * FUNCTION: Find a file
188 PWCHAR PathNameBuffer
;
189 ULONG PathNameBufferLength
;
191 PVOID Context
= NULL
;
195 UNICODE_STRING PathNameU
;
196 UNICODE_STRING FileToFindUpcase
;
199 DPRINT ("FindFile(Parent %x, FileToFind '%wZ', DirIndex: %d)\n",
200 Parent
, FileToFindU
, DirContext
->DirIndex
);
201 DPRINT ("FindFile: Path %wZ)\n",&Parent
->PathNameU
);
203 PathNameBufferLength
= LONGNAME_MAX_LENGTH
* sizeof(WCHAR
);
204 PathNameBuffer
= ExAllocatePool(NonPagedPool
, PathNameBufferLength
+ sizeof(WCHAR
));
208 return STATUS_INSUFFICIENT_RESOURCES
;
211 PathNameU
.Buffer
= PathNameBuffer
;
212 PathNameU
.Length
= 0;
213 PathNameU
.MaximumLength
= PathNameBufferLength
;
215 DirContext
->LongNameU
.Length
= 0;
216 DirContext
->ShortNameU
.Length
= 0;
218 WildCard
= FsRtlDoesNameContainWildCards(FileToFindU
);
220 if (WildCard
== FALSE
)
222 /* if there is no '*?' in the search name, than look first for an existing fcb */
223 RtlCopyUnicodeString(&PathNameU
, &Parent
->PathNameU
);
224 if (!vfatFCBIsRoot(Parent
))
226 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = L
'\\';
227 PathNameU
.Length
+= sizeof(WCHAR
);
229 RtlAppendUnicodeStringToString(&PathNameU
, FileToFindU
);
230 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = 0;
231 rcFcb
= vfatGrabFCBFromTable(DeviceExt
, &PathNameU
);
234 if(rcFcb
->startIndex
>= DirContext
->DirIndex
)
236 RtlCopyUnicodeString(&DirContext
->LongNameU
, &rcFcb
->LongNameU
);
237 RtlCopyUnicodeString(&DirContext
->ShortNameU
, &rcFcb
->ShortNameU
);
238 RtlCopyMemory(&DirContext
->DirEntry
, &rcFcb
->entry
, sizeof(DIR_ENTRY
));
239 DirContext
->StartIndex
= rcFcb
->startIndex
;
240 DirContext
->DirIndex
= rcFcb
->dirIndex
;
241 DPRINT("FindFile: new Name %wZ, DirIndex %d (%d)\n",
242 &DirContext
->LongNameU
, DirContext
->DirIndex
, DirContext
->StartIndex
);
243 Status
= STATUS_SUCCESS
;
248 Status
= STATUS_UNSUCCESSFUL
;
250 vfatReleaseFCB(DeviceExt
, rcFcb
);
251 ExFreePool(PathNameBuffer
);
256 /* FsRtlIsNameInExpression need the searched string to be upcase,
257 * even if IgnoreCase is specified */
258 Status
= RtlUpcaseUnicodeString(&FileToFindUpcase
, FileToFindU
, TRUE
);
259 if (!NT_SUCCESS(Status
))
262 ExFreePool(PathNameBuffer
);
268 Status
= DeviceExt
->GetNextDirEntry(&Context
, &Page
, Parent
, DirContext
, First
);
270 if (Status
== STATUS_NO_MORE_ENTRIES
)
274 if (ENTRY_VOLUME(DeviceExt
, &DirContext
->DirEntry
))
276 DirContext
->DirIndex
++;
281 Found
= FsRtlIsNameInExpression(&FileToFindUpcase
, &DirContext
->LongNameU
, TRUE
, NULL
) ||
282 FsRtlIsNameInExpression(&FileToFindUpcase
, &DirContext
->ShortNameU
, TRUE
, NULL
);
286 Found
= FsRtlAreNamesEqual(&DirContext
->LongNameU
, FileToFindU
, TRUE
, NULL
) ||
287 FsRtlAreNamesEqual(&DirContext
->ShortNameU
, FileToFindU
, TRUE
, NULL
);
294 RtlCopyUnicodeString(&PathNameU
, &Parent
->PathNameU
);
295 if (!vfatFCBIsRoot(Parent
))
297 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = L
'\\';
298 PathNameU
.Length
+= sizeof(WCHAR
);
300 RtlAppendUnicodeStringToString(&PathNameU
, &DirContext
->LongNameU
);
301 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = 0;
302 rcFcb
= vfatGrabFCBFromTable(DeviceExt
, &PathNameU
);
305 RtlCopyMemory(&DirContext
->DirEntry
, &rcFcb
->entry
, sizeof(DIR_ENTRY
));
306 vfatReleaseFCB(DeviceExt
, rcFcb
);
309 DPRINT("%d\n", DirContext
->LongNameU
.Length
);
310 DPRINT("FindFile: new Name %wZ, DirIndex %d\n",
311 &DirContext
->LongNameU
, DirContext
->DirIndex
);
315 CcUnpinData(Context
);
317 RtlFreeUnicodeString(&FileToFindUpcase
);
318 ExFreePool(PathNameBuffer
);
319 return STATUS_SUCCESS
;
321 DirContext
->DirIndex
++;
326 CcUnpinData(Context
);
329 RtlFreeUnicodeString(&FileToFindUpcase
);
330 ExFreePool(PathNameBuffer
);
335 VfatOpenFile (PDEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
, PVFATFCB
* ParentFcb
)
337 * FUNCTION: Opens a file
342 UNICODE_STRING PathNameU
;
345 DPRINT ("VfatOpenFile(%08lx, %08lx, '%wZ')\n", DeviceExt
, FileObject
, &FileObject
->FileName
);
347 if (FileObject
->RelatedFileObject
)
349 DPRINT ("'%wZ'\n", &FileObject
->RelatedFileObject
->FileName
);
351 *ParentFcb
= FileObject
->RelatedFileObject
->FsContext
;
352 (*ParentFcb
)->RefCount
++;
359 if (!DeviceExt
->FatInfo
.FixedMedia
)
361 Status
= VfatBlockDeviceIoControl (DeviceExt
->StorageDevice
,
362 IOCTL_DISK_CHECK_VERIFY
,
369 if (Status
== STATUS_VERIFY_REQUIRED
)
372 PDEVICE_OBJECT DeviceToVerify
;
374 DPRINT ("Media change detected!\n");
375 DPRINT ("Device %p\n", DeviceExt
->StorageDevice
);
377 DeviceToVerify
= IoGetDeviceToVerify (PsGetCurrentThread ());
379 IoSetDeviceToVerify (PsGetCurrentThread (),
381 Status
= IoVerifyVolume (DeviceExt
->StorageDevice
,
384 if (!NT_SUCCESS(Status
))
386 DPRINT ("Status %lx\n", Status
);
394 (*ParentFcb
)->RefCount
++;
397 PathNameU
.Buffer
= Buffer
;
398 PathNameU
.Length
= 0;
399 PathNameU
.MaximumLength
= sizeof(Buffer
);
400 RtlCopyUnicodeString(&PathNameU
, &FileObject
->FileName
);
401 if (PathNameU
.Length
> sizeof(WCHAR
) &&
402 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
) - 1] == L
'\\')
404 PathNameU
.Length
-= sizeof(WCHAR
);
406 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = 0;
408 /* try first to find an existing FCB in memory */
409 DPRINT ("Checking for existing FCB in memory\n");
411 Status
= vfatGetFCBForFile (DeviceExt
, ParentFcb
, &Fcb
, &PathNameU
);
412 if (!NT_SUCCESS (Status
))
414 DPRINT ("Could not make a new FCB, status: %x\n", Status
);
417 if (Fcb
->Flags
& FCB_DELETE_PENDING
)
419 vfatReleaseFCB (DeviceExt
, Fcb
);
420 return STATUS_DELETE_PENDING
;
422 DPRINT ("Attaching FCB to fileObject\n");
423 Status
= vfatAttachFCBToFileObject (DeviceExt
, Fcb
, FileObject
);
424 if (!NT_SUCCESS(Status
))
426 vfatReleaseFCB (DeviceExt
, Fcb
);
432 VfatSupersedeFile(PDEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
,
435 ULONG Cluster
, NextCluster
;
438 if (Fcb
->Flags
& FCB_IS_FATX_ENTRY
)
440 Fcb
->entry
.FatX
.FileSize
= 0;
441 Cluster
= Fcb
->entry
.FatX
.FirstCluster
;
442 Fcb
->entry
.FatX
.FirstCluster
= 0;
446 Fcb
->entry
.Fat
.FileSize
= 0;
447 if (DeviceExt
->FatInfo
.FatType
== FAT32
)
449 Cluster
= Fcb
->entry
.Fat
.FirstCluster
+ Fcb
->entry
.Fat
.FirstClusterHigh
* 65536;
453 Cluster
= Fcb
->entry
.Fat
.FirstCluster
;
455 Fcb
->entry
.Fat
.FirstCluster
= 0;
456 Fcb
->entry
.Fat
.FirstClusterHigh
= 0;
458 Fcb
->LastOffset
= Fcb
->LastCluster
= 0;
459 VfatUpdateEntry (Fcb
);
460 if (Fcb
->RFCB
.FileSize
.QuadPart
> 0)
462 Fcb
->RFCB
.AllocationSize
.QuadPart
= 0;
463 Fcb
->RFCB
.FileSize
.QuadPart
= 0;
464 Fcb
->RFCB
.ValidDataLength
.QuadPart
= 0;
465 /* Notify cache manager about the change in file size if caching is
466 initialized on the file stream */
467 if (FileObject
->SectionObjectPointer
->SharedCacheMap
!= NULL
)
469 CcSetFileSizes(FileObject
, (PCC_FILE_SIZES
)&Fcb
->RFCB
.AllocationSize
);
472 while (Cluster
!= 0xffffffff && Cluster
> 1)
474 Status
= GetNextCluster (DeviceExt
, Cluster
, &NextCluster
);
475 WriteCluster (DeviceExt
, Cluster
, 0);
476 Cluster
= NextCluster
;
481 VfatCreateFile (PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
483 * FUNCTION: Create or open a file
486 PIO_STACK_LOCATION Stack
;
487 PFILE_OBJECT FileObject
;
488 NTSTATUS Status
= STATUS_SUCCESS
;
489 PDEVICE_EXTENSION DeviceExt
;
490 ULONG RequestedDisposition
, RequestedOptions
;
495 BOOLEAN PagingFileCreate
= FALSE
;
496 LARGE_INTEGER AllocationSize
;
498 UNICODE_STRING FileNameU
;
500 /* Unpack the various parameters. */
501 Stack
= IoGetCurrentIrpStackLocation (Irp
);
502 RequestedDisposition
= ((Stack
->Parameters
.Create
.Options
>> 24) & 0xff);
504 Stack
->Parameters
.Create
.Options
& FILE_VALID_OPTION_FLAGS
;
505 PagingFileCreate
= (Stack
->Flags
& SL_OPEN_PAGING_FILE
) ? TRUE
: FALSE
;
506 FileObject
= Stack
->FileObject
;
507 DeviceExt
= DeviceObject
->DeviceExtension
;
509 /* Check their validity. */
510 if (RequestedOptions
& FILE_DIRECTORY_FILE
&&
511 RequestedDisposition
== FILE_SUPERSEDE
)
513 return(STATUS_INVALID_PARAMETER
);
516 /* This a open operation for the volume itself */
517 if (FileObject
->FileName
.Length
== 0 &&
518 FileObject
->RelatedFileObject
== NULL
)
520 if (RequestedDisposition
== FILE_CREATE
||
521 RequestedDisposition
== FILE_OVERWRITE_IF
||
522 RequestedDisposition
== FILE_SUPERSEDE
)
524 return(STATUS_ACCESS_DENIED
);
526 if (RequestedOptions
& FILE_DIRECTORY_FILE
)
528 return(STATUS_NOT_A_DIRECTORY
);
530 pFcb
= DeviceExt
->VolumeFcb
;
531 pCcb
= ExAllocateFromNPagedLookasideList(&VfatGlobalData
->CcbLookasideList
);
534 return (STATUS_INSUFFICIENT_RESOURCES
);
536 RtlZeroMemory(pCcb
, sizeof(VFATCCB
));
537 FileObject
->SectionObjectPointer
= &pFcb
->SectionObjectPointers
;
538 FileObject
->FsContext
= pFcb
;
539 FileObject
->FsContext2
= pCcb
;
542 Irp
->IoStatus
.Information
= FILE_OPENED
;
543 return(STATUS_SUCCESS
);
547 * Check for illegal characters and illegale dot sequences in the file name
549 c
= FileObject
->FileName
.Buffer
+ FileObject
->FileName
.Length
/ sizeof(WCHAR
);
552 while (c
-- > FileObject
->FileName
.Buffer
)
554 if (*c
== L
'\\' || c
== FileObject
->FileName
.Buffer
)
556 if (Dots
&& last
> c
)
558 return(STATUS_OBJECT_NAME_INVALID
);
568 if (*c
!= '\\' && vfatIsLongIllegal(*c
))
570 return(STATUS_OBJECT_NAME_INVALID
);
574 /* Try opening the file. */
575 Status
= VfatOpenFile (DeviceExt
, FileObject
, &ParentFcb
);
578 * If the directory containing the file to open doesn't exist then
581 if (Status
== STATUS_OBJECT_PATH_NOT_FOUND
||
582 Status
== STATUS_INVALID_PARAMETER
||
583 Status
== STATUS_DELETE_PENDING
)
587 vfatReleaseFCB (DeviceExt
, ParentFcb
);
593 * If the file open failed then create the required file
595 if (!NT_SUCCESS (Status
))
597 if (RequestedDisposition
== FILE_CREATE
||
598 RequestedDisposition
== FILE_OPEN_IF
||
599 RequestedDisposition
== FILE_OVERWRITE_IF
||
600 RequestedDisposition
== FILE_SUPERSEDE
)
603 Attributes
= Stack
->Parameters
.Create
.FileAttributes
;
605 vfatSplitPathName(&FileObject
->FileName
, NULL
, &FileNameU
);
606 Status
= VfatAddEntry (DeviceExt
, &FileNameU
, &pFcb
, ParentFcb
, RequestedOptions
,
607 (UCHAR
)(Attributes
& FILE_ATTRIBUTE_VALID_FLAGS
));
608 vfatReleaseFCB (DeviceExt
, ParentFcb
);
609 if (NT_SUCCESS (Status
))
611 vfatAttachFCBToFileObject (DeviceExt
, pFcb
, FileObject
);
613 Irp
->IoStatus
.Information
= FILE_CREATED
;
615 VfatSetAllocationSizeInformation(FileObject
,
618 &Irp
->Overlay
.AllocationSize
);
619 VfatSetExtendedAttributes(FileObject
,
620 Irp
->AssociatedIrp
.SystemBuffer
,
621 Stack
->Parameters
.Create
.EaLength
);
623 if (PagingFileCreate
)
625 pFcb
->Flags
|= FCB_IS_PAGE_FILE
;
635 vfatReleaseFCB (DeviceExt
, ParentFcb
);
643 vfatReleaseFCB (DeviceExt
, ParentFcb
);
645 /* Otherwise fail if the caller wanted to create a new file */
646 if (RequestedDisposition
== FILE_CREATE
)
648 Irp
->IoStatus
.Information
= FILE_EXISTS
;
649 VfatCloseFile (DeviceExt
, FileObject
);
650 return(STATUS_OBJECT_NAME_COLLISION
);
653 pFcb
= FileObject
->FsContext
;
655 if (pFcb
->OpenHandleCount
!= 0)
657 Status
= IoCheckShareAccess(Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
,
658 Stack
->Parameters
.Create
.ShareAccess
,
660 &pFcb
->FCBShareAccess
,
662 if (!NT_SUCCESS(Status
))
664 VfatCloseFile (DeviceExt
, FileObject
);
670 * Check the file has the requested attributes
672 if (RequestedOptions
& FILE_NON_DIRECTORY_FILE
&&
673 *pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
)
675 VfatCloseFile (DeviceExt
, FileObject
);
676 return(STATUS_FILE_IS_A_DIRECTORY
);
678 if (RequestedOptions
& FILE_DIRECTORY_FILE
&&
679 !(*pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
))
681 VfatCloseFile (DeviceExt
, FileObject
);
682 return(STATUS_NOT_A_DIRECTORY
);
685 if (PagingFileCreate
)
688 * Do more checking for page files. It is possible,
689 * that the file was opened and closed previously
690 * as a normal cached file. In this case, the cache
691 * manager has referenced the fileobject and the fcb
692 * is held in memory. Try to remove the fileobject
693 * from cache manager and use the fcb.
695 if (pFcb
->RefCount
> 1)
697 if(!(pFcb
->Flags
& FCB_IS_PAGE_FILE
))
699 VfatCloseFile(DeviceExt
, FileObject
);
700 return(STATUS_INVALID_PARAMETER
);
705 pFcb
->Flags
|= FCB_IS_PAGE_FILE
;
710 if (pFcb
->Flags
& FCB_IS_PAGE_FILE
)
712 VfatCloseFile(DeviceExt
, FileObject
);
713 return(STATUS_INVALID_PARAMETER
);
718 if (RequestedDisposition
== FILE_OVERWRITE
||
719 RequestedDisposition
== FILE_OVERWRITE_IF
)
721 AllocationSize
.QuadPart
= 0;
722 Status
= VfatSetAllocationSizeInformation (FileObject
,
726 if (!NT_SUCCESS (Status
))
728 VfatCloseFile (DeviceExt
, FileObject
);
734 /* Supersede the file */
735 if (RequestedDisposition
== FILE_SUPERSEDE
)
737 VfatSupersedeFile(DeviceExt
, FileObject
, pFcb
);
738 Irp
->IoStatus
.Information
= FILE_SUPERSEDED
;
740 else if (RequestedDisposition
== FILE_OVERWRITE
|| RequestedDisposition
== FILE_OVERWRITE_IF
)
742 Irp
->IoStatus
.Information
= FILE_OVERWRITTEN
;
746 Irp
->IoStatus
.Information
= FILE_OPENED
;
750 if (pFcb
->OpenHandleCount
== 0)
752 IoSetShareAccess(Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
,
753 Stack
->Parameters
.Create
.ShareAccess
,
755 &pFcb
->FCBShareAccess
);
761 &pFcb
->FCBShareAccess
766 pFcb
->OpenHandleCount
++;
768 /* FIXME : test write access if requested */
774 NTSTATUS
VfatCreate (PVFAT_IRP_CONTEXT IrpContext
)
776 * FUNCTION: Create or open a file
783 if (IrpContext
->DeviceObject
== VfatGlobalData
->DeviceObject
)
785 /* DeviceObject represents FileSystem instead of logical volume */
786 DPRINT ("FsdCreate called with file system\n");
787 IrpContext
->Irp
->IoStatus
.Information
= FILE_OPENED
;
788 IrpContext
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
789 IoCompleteRequest (IrpContext
->Irp
, IO_DISK_INCREMENT
);
790 VfatFreeIrpContext(IrpContext
);
791 return(STATUS_SUCCESS
);
794 if (!(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
))
796 return(VfatQueueRequest (IrpContext
));
799 IrpContext
->Irp
->IoStatus
.Information
= 0;
800 ExAcquireResourceExclusiveLite (&IrpContext
->DeviceExt
->DirResource
, TRUE
);
801 Status
= VfatCreateFile (IrpContext
->DeviceObject
, IrpContext
->Irp
);
802 ExReleaseResourceLite (&IrpContext
->DeviceExt
->DirResource
);
804 IrpContext
->Irp
->IoStatus
.Status
= Status
;
805 IoCompleteRequest (IrpContext
->Irp
,
806 (CCHAR
)(NT_SUCCESS(Status
) ? IO_DISK_INCREMENT
: IO_NO_INCREMENT
));
807 VfatFreeIrpContext(IrpContext
);