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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * PROJECT: ReactOS kernel
21 * FILE: drivers/fs/vfat/create.c
22 * PURPOSE: VFAT Filesystem
23 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
26 /* INCLUDES *****************************************************************/
31 /* FUNCTIONS *****************************************************************/
34 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
;
179 PDEVICE_EXTENSION DeviceExt
,
181 PUNICODE_STRING FileToFindU
,
182 PVFAT_DIRENTRY_CONTEXT DirContext
,
185 * FUNCTION: Find a file
188 PWCHAR PathNameBuffer
;
189 USHORT PathNameBufferLength
;
191 PVOID Context
= NULL
;
195 UNICODE_STRING PathNameU
;
196 UNICODE_STRING FileToFindUpcase
;
199 DPRINT ("FindFile(Parent %p, 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
= ExAllocatePoolWithTag(NonPagedPool
, PathNameBufferLength
+ sizeof(WCHAR
), TAG_VFAT
);
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
;
251 DPRINT("FCB not found for %wZ\n", &PathNameU
);
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
))
265 ExFreePool(PathNameBuffer
);
271 Status
= DeviceExt
->GetNextDirEntry(&Context
, &Page
, Parent
, DirContext
, First
);
273 if (Status
== STATUS_NO_MORE_ENTRIES
)
277 if (ENTRY_VOLUME(DeviceExt
, &DirContext
->DirEntry
))
279 DirContext
->DirIndex
++;
284 Found
= FsRtlIsNameInExpression(&FileToFindUpcase
, &DirContext
->LongNameU
, TRUE
, NULL
) ||
285 FsRtlIsNameInExpression(&FileToFindUpcase
, &DirContext
->ShortNameU
, TRUE
, NULL
);
289 Found
= FsRtlAreNamesEqual(&DirContext
->LongNameU
, FileToFindU
, TRUE
, NULL
) ||
290 FsRtlAreNamesEqual(&DirContext
->ShortNameU
, FileToFindU
, TRUE
, NULL
);
297 RtlCopyUnicodeString(&PathNameU
, &Parent
->PathNameU
);
298 if (!vfatFCBIsRoot(Parent
))
300 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = L
'\\';
301 PathNameU
.Length
+= sizeof(WCHAR
);
303 RtlAppendUnicodeStringToString(&PathNameU
, &DirContext
->LongNameU
);
304 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = 0;
305 rcFcb
= vfatGrabFCBFromTable(DeviceExt
, &PathNameU
);
308 RtlCopyMemory(&DirContext
->DirEntry
, &rcFcb
->entry
, sizeof(DIR_ENTRY
));
309 vfatReleaseFCB(DeviceExt
, rcFcb
);
312 DPRINT("%d\n", DirContext
->LongNameU
.Length
);
313 DPRINT("FindFile: new Name %wZ, DirIndex %d\n",
314 &DirContext
->LongNameU
, DirContext
->DirIndex
);
318 CcUnpinData(Context
);
320 RtlFreeUnicodeString(&FileToFindUpcase
);
321 ExFreePool(PathNameBuffer
);
322 return STATUS_SUCCESS
;
324 DirContext
->DirIndex
++;
329 CcUnpinData(Context
);
332 RtlFreeUnicodeString(&FileToFindUpcase
);
333 ExFreePool(PathNameBuffer
);
340 PDEVICE_EXTENSION DeviceExt
,
341 PUNICODE_STRING PathNameU
,
342 PFILE_OBJECT FileObject
,
343 PVFATFCB
* ParentFcb
)
345 * FUNCTION: Opens a file
351 DPRINT ("VfatOpenFile(%p, '%wZ', %p, %p)\n", DeviceExt
, PathNameU
, FileObject
, ParentFcb
);
353 if (FileObject
->RelatedFileObject
)
355 DPRINT ("'%wZ'\n", &FileObject
->RelatedFileObject
->FileName
);
357 *ParentFcb
= FileObject
->RelatedFileObject
->FsContext
;
358 (*ParentFcb
)->RefCount
++;
365 if (!DeviceExt
->FatInfo
.FixedMedia
)
367 Status
= VfatBlockDeviceIoControl (DeviceExt
->StorageDevice
,
368 IOCTL_DISK_CHECK_VERIFY
,
375 if (Status
== STATUS_VERIFY_REQUIRED
)
378 PDEVICE_OBJECT DeviceToVerify
;
380 DPRINT ("Media change detected!\n");
381 DPRINT ("Device %p\n", DeviceExt
->StorageDevice
);
383 /* Find the device to verify and reset the thread field to empty value again. */
384 DeviceToVerify
= IoGetDeviceToVerify (PsGetCurrentThread ());
385 IoSetDeviceToVerify (PsGetCurrentThread (), NULL
);
386 Status
= IoVerifyVolume (DeviceToVerify
,
389 if (!NT_SUCCESS(Status
))
391 DPRINT ("Status %lx\n", Status
);
399 (*ParentFcb
)->RefCount
++;
402 /* try first to find an existing FCB in memory */
403 DPRINT ("Checking for existing FCB in memory\n");
405 Status
= vfatGetFCBForFile (DeviceExt
, ParentFcb
, &Fcb
, PathNameU
);
406 if (!NT_SUCCESS (Status
))
408 DPRINT ("Could not make a new FCB, status: %x\n", Status
);
411 if (Fcb
->Flags
& FCB_DELETE_PENDING
)
413 vfatReleaseFCB (DeviceExt
, Fcb
);
414 return STATUS_DELETE_PENDING
;
416 DPRINT ("Attaching FCB to fileObject\n");
417 Status
= vfatAttachFCBToFileObject (DeviceExt
, Fcb
, FileObject
);
418 if (!NT_SUCCESS(Status
))
420 vfatReleaseFCB (DeviceExt
, Fcb
);
426 VfatCreateFile ( PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
428 * FUNCTION: Create or open a file
431 PIO_STACK_LOCATION Stack
;
432 PFILE_OBJECT FileObject
;
433 NTSTATUS Status
= STATUS_SUCCESS
;
434 PDEVICE_EXTENSION DeviceExt
;
435 ULONG RequestedDisposition
, RequestedOptions
;
437 PVFATFCB pFcb
= NULL
;
438 PVFATFCB ParentFcb
= NULL
;
440 BOOLEAN PagingFileCreate
= FALSE
;
442 UNICODE_STRING FileNameU
;
443 UNICODE_STRING PathNameU
;
445 /* Unpack the various parameters. */
446 Stack
= IoGetCurrentIrpStackLocation (Irp
);
447 RequestedDisposition
= ((Stack
->Parameters
.Create
.Options
>> 24) & 0xff);
449 Stack
->Parameters
.Create
.Options
& FILE_VALID_OPTION_FLAGS
;
450 PagingFileCreate
= (Stack
->Flags
& SL_OPEN_PAGING_FILE
) ? TRUE
: FALSE
;
451 FileObject
= Stack
->FileObject
;
452 DeviceExt
= DeviceObject
->DeviceExtension
;
454 /* Check their validity. */
455 if (RequestedOptions
& FILE_DIRECTORY_FILE
&&
456 RequestedDisposition
== FILE_SUPERSEDE
)
458 return(STATUS_INVALID_PARAMETER
);
461 if (RequestedOptions
& FILE_DIRECTORY_FILE
&&
462 RequestedOptions
& FILE_NON_DIRECTORY_FILE
)
464 return(STATUS_INVALID_PARAMETER
);
467 /* This a open operation for the volume itself */
468 if (FileObject
->FileName
.Length
== 0 &&
469 (FileObject
->RelatedFileObject
== NULL
|| FileObject
->RelatedFileObject
->FsContext2
!= NULL
))
471 if (RequestedDisposition
== FILE_CREATE
||
472 RequestedDisposition
== FILE_OVERWRITE_IF
||
473 RequestedDisposition
== FILE_SUPERSEDE
)
475 return(STATUS_ACCESS_DENIED
);
478 /* In spite of what is shown in WDK, it seems that Windows FAT driver doesn't perform that test */
479 if (RequestedOptions
& FILE_DIRECTORY_FILE
)
481 return(STATUS_NOT_A_DIRECTORY
);
484 pFcb
= DeviceExt
->VolumeFcb
;
485 pCcb
= ExAllocateFromNPagedLookasideList(&VfatGlobalData
->CcbLookasideList
);
488 return (STATUS_INSUFFICIENT_RESOURCES
);
490 RtlZeroMemory(pCcb
, sizeof(VFATCCB
));
491 FileObject
->SectionObjectPointer
= &pFcb
->SectionObjectPointers
;
492 FileObject
->FsContext
= pFcb
;
493 FileObject
->FsContext2
= pCcb
;
496 Irp
->IoStatus
.Information
= FILE_OPENED
;
497 return(STATUS_SUCCESS
);
501 * Check for illegal characters and illegale dot sequences in the file name
503 PathNameU
= FileObject
->FileName
;
504 c
= PathNameU
.Buffer
+ PathNameU
.Length
/ sizeof(WCHAR
);
507 while (c
-- > PathNameU
.Buffer
)
509 if (*c
== L
'\\' || c
== PathNameU
.Buffer
)
511 if (Dots
&& last
> c
)
513 return(STATUS_OBJECT_NAME_INVALID
);
523 if (*c
!= '\\' && vfatIsLongIllegal(*c
))
525 return(STATUS_OBJECT_NAME_INVALID
);
528 if (FileObject
->RelatedFileObject
&& PathNameU
.Length
>= sizeof(WCHAR
) && PathNameU
.Buffer
[0] == L
'\\')
530 return(STATUS_OBJECT_NAME_INVALID
);
532 if (PathNameU
.Length
> sizeof(WCHAR
) && PathNameU
.Buffer
[PathNameU
.Length
/sizeof(WCHAR
)-1] == L
'\\')
534 PathNameU
.Length
-= sizeof(WCHAR
);
537 /* Try opening the file. */
538 Status
= VfatOpenFile (DeviceExt
, &PathNameU
, FileObject
, &ParentFcb
);
541 * If the directory containing the file to open doesn't exist then
544 if (Status
== STATUS_OBJECT_PATH_NOT_FOUND
||
545 Status
== STATUS_INVALID_PARAMETER
||
546 Status
== STATUS_DELETE_PENDING
)
550 vfatReleaseFCB (DeviceExt
, ParentFcb
);
554 if (!NT_SUCCESS(Status
) && ParentFcb
== NULL
)
556 DPRINT1("VfatOpenFile faild for '%wZ', status %x\n", &PathNameU
, Status
);
561 * If the file open failed then create the required file
563 if (!NT_SUCCESS (Status
))
565 if (RequestedDisposition
== FILE_CREATE
||
566 RequestedDisposition
== FILE_OPEN_IF
||
567 RequestedDisposition
== FILE_OVERWRITE_IF
||
568 RequestedDisposition
== FILE_SUPERSEDE
)
571 Attributes
= Stack
->Parameters
.Create
.FileAttributes
;
573 vfatSplitPathName(&PathNameU
, NULL
, &FileNameU
);
574 Status
= VfatAddEntry (DeviceExt
, &FileNameU
, &pFcb
, ParentFcb
, RequestedOptions
,
575 (UCHAR
)(Attributes
& FILE_ATTRIBUTE_VALID_FLAGS
));
576 vfatReleaseFCB (DeviceExt
, ParentFcb
);
577 if (NT_SUCCESS (Status
))
579 Status
= vfatAttachFCBToFileObject (DeviceExt
, pFcb
, FileObject
);
580 if ( !NT_SUCCESS(Status
) )
582 vfatReleaseFCB (DeviceExt
, pFcb
);
586 Irp
->IoStatus
.Information
= FILE_CREATED
;
587 VfatSetAllocationSizeInformation(FileObject
,
590 &Irp
->Overlay
.AllocationSize
);
591 VfatSetExtendedAttributes(FileObject
,
592 Irp
->AssociatedIrp
.SystemBuffer
,
593 Stack
->Parameters
.Create
.EaLength
);
595 if (PagingFileCreate
)
597 pFcb
->Flags
|= FCB_IS_PAGE_FILE
;
609 vfatReleaseFCB (DeviceExt
, ParentFcb
);
618 vfatReleaseFCB (DeviceExt
, ParentFcb
);
620 /* Otherwise fail if the caller wanted to create a new file */
621 if (RequestedDisposition
== FILE_CREATE
)
623 Irp
->IoStatus
.Information
= FILE_EXISTS
;
624 VfatCloseFile (DeviceExt
, FileObject
);
625 return(STATUS_OBJECT_NAME_COLLISION
);
628 pFcb
= FileObject
->FsContext
;
630 if (pFcb
->OpenHandleCount
!= 0)
632 Status
= IoCheckShareAccess(Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
,
633 Stack
->Parameters
.Create
.ShareAccess
,
635 &pFcb
->FCBShareAccess
,
637 if (!NT_SUCCESS(Status
))
639 VfatCloseFile (DeviceExt
, FileObject
);
645 * Check the file has the requested attributes
647 if (RequestedOptions
& FILE_NON_DIRECTORY_FILE
&&
648 *pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
)
650 VfatCloseFile (DeviceExt
, FileObject
);
651 return(STATUS_FILE_IS_A_DIRECTORY
);
653 if (RequestedOptions
& FILE_DIRECTORY_FILE
&&
654 !(*pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
))
656 VfatCloseFile (DeviceExt
, FileObject
);
657 return(STATUS_NOT_A_DIRECTORY
);
659 #ifndef USE_ROS_CC_AND_FS
660 if (!(*pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
))
662 if (Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
& FILE_WRITE_DATA
||
663 RequestedDisposition
== FILE_OVERWRITE
||
664 RequestedDisposition
== FILE_OVERWRITE_IF
)
666 if (!MmFlushImageSection(&pFcb
->SectionObjectPointers
, MmFlushForWrite
))
668 DPRINT1("%wZ\n", &pFcb
->PathNameU
);
669 DPRINT1("%d %d %d\n", Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
& FILE_WRITE_DATA
,
670 RequestedDisposition
== FILE_OVERWRITE
, RequestedDisposition
== FILE_OVERWRITE_IF
);
671 VfatCloseFile (DeviceExt
, FileObject
);
672 return STATUS_SHARING_VIOLATION
;
677 if (PagingFileCreate
)
680 * Do more checking for page files. It is possible,
681 * that the file was opened and closed previously
682 * as a normal cached file. In this case, the cache
683 * manager has referenced the fileobject and the fcb
684 * is held in memory. Try to remove the fileobject
685 * from cache manager and use the fcb.
687 if (pFcb
->RefCount
> 1)
689 if(!(pFcb
->Flags
& FCB_IS_PAGE_FILE
))
691 VfatCloseFile(DeviceExt
, FileObject
);
692 return(STATUS_INVALID_PARAMETER
);
697 pFcb
->Flags
|= FCB_IS_PAGE_FILE
;
702 if (pFcb
->Flags
& FCB_IS_PAGE_FILE
)
704 VfatCloseFile(DeviceExt
, FileObject
);
705 return(STATUS_INVALID_PARAMETER
);
710 if (RequestedDisposition
== FILE_OVERWRITE
||
711 RequestedDisposition
== FILE_OVERWRITE_IF
||
712 RequestedDisposition
== FILE_SUPERSEDE
)
714 ExAcquireResourceExclusiveLite(&(pFcb
->MainResource
), TRUE
);
715 Status
= VfatSetAllocationSizeInformation (FileObject
,
718 &Irp
->Overlay
.AllocationSize
);
719 ExReleaseResourceLite(&(pFcb
->MainResource
));
720 if (!NT_SUCCESS (Status
))
722 VfatCloseFile (DeviceExt
, FileObject
);
727 if (RequestedDisposition
== FILE_SUPERSEDE
)
729 Irp
->IoStatus
.Information
= FILE_SUPERSEDED
;
731 else if (RequestedDisposition
== FILE_OVERWRITE
||
732 RequestedDisposition
== FILE_OVERWRITE_IF
)
734 Irp
->IoStatus
.Information
= FILE_OVERWRITTEN
;
738 Irp
->IoStatus
.Information
= FILE_OPENED
;
742 if (pFcb
->OpenHandleCount
== 0)
744 IoSetShareAccess(Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
,
745 Stack
->Parameters
.Create
.ShareAccess
,
747 &pFcb
->FCBShareAccess
);
753 &pFcb
->FCBShareAccess
758 pFcb
->OpenHandleCount
++;
760 /* FIXME : test write access if requested */
767 VfatCreate (PVFAT_IRP_CONTEXT IrpContext
)
769 * FUNCTION: Create or open a file
776 if (IrpContext
->DeviceObject
== VfatGlobalData
->DeviceObject
)
778 /* DeviceObject represents FileSystem instead of logical volume */
779 DPRINT ("FsdCreate called with file system\n");
780 IrpContext
->Irp
->IoStatus
.Information
= FILE_OPENED
;
781 IrpContext
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
782 IoCompleteRequest (IrpContext
->Irp
, IO_DISK_INCREMENT
);
783 VfatFreeIrpContext(IrpContext
);
784 return(STATUS_SUCCESS
);
787 if (!(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
))
789 return(VfatQueueRequest (IrpContext
));
792 IrpContext
->Irp
->IoStatus
.Information
= 0;
793 ExAcquireResourceExclusiveLite (&IrpContext
->DeviceExt
->DirResource
, TRUE
);
794 Status
= VfatCreateFile (IrpContext
->DeviceObject
, IrpContext
->Irp
);
795 ExReleaseResourceLite (&IrpContext
->DeviceExt
->DirResource
);
797 IrpContext
->Irp
->IoStatus
.Status
= Status
;
798 IoCompleteRequest (IrpContext
->Irp
,
799 (CCHAR
)(NT_SUCCESS(Status
) ? IO_DISK_INCREMENT
: IO_NO_INCREMENT
));
800 VfatFreeIrpContext(IrpContext
);