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/filesystems/fastfat/create.c
22 * PURPOSE: VFAT Filesystem
23 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
24 * Pierre Schweitzer (pierre@reactos.org)
27 /* INCLUDES *****************************************************************/
34 /* FUNCTIONS *****************************************************************/
38 PFAT_DIR_ENTRY pEntry
,
39 PUNICODE_STRING NameU
)
45 RtlCopyMemory(cString
, pEntry
->ShortName
, 11);
47 if (cString
[0] == 0x05)
52 StringA
.Buffer
= cString
;
53 for (StringA
.Length
= 0;
54 StringA
.Length
< 8 && StringA
.Buffer
[StringA
.Length
] != ' ';
56 StringA
.MaximumLength
= StringA
.Length
;
58 RtlOemStringToUnicodeString(NameU
, &StringA
, FALSE
);
60 if (pEntry
->lCase
& VFAT_CASE_LOWER_BASE
)
62 RtlDowncaseUnicodeString(NameU
, NameU
, FALSE
);
65 if (cString
[8] != ' ')
67 Length
= NameU
->Length
;
68 NameU
->Buffer
+= Length
/ sizeof(WCHAR
);
69 if (!FAT_ENTRY_VOLUME(pEntry
))
71 Length
+= sizeof(WCHAR
);
72 NameU
->Buffer
[0] = L
'.';
76 NameU
->MaximumLength
-= Length
;
78 StringA
.Buffer
= &cString
[8];
79 for (StringA
.Length
= 0;
80 StringA
.Length
< 3 && StringA
.Buffer
[StringA
.Length
] != ' ';
82 StringA
.MaximumLength
= StringA
.Length
;
83 RtlOemStringToUnicodeString(NameU
, &StringA
, FALSE
);
84 if (pEntry
->lCase
& VFAT_CASE_LOWER_EXT
)
86 RtlDowncaseUnicodeString(NameU
, NameU
, FALSE
);
88 NameU
->Buffer
-= Length
/ sizeof(WCHAR
);
89 NameU
->Length
+= Length
;
90 NameU
->MaximumLength
+= Length
;
93 NameU
->Buffer
[NameU
->Length
/ sizeof(WCHAR
)] = 0;
94 DPRINT("'%wZ'\n", NameU
);
98 * FUNCTION: Read the volume label
102 PDEVICE_EXTENSION DeviceExt
,
105 PVOID Context
= NULL
;
109 LARGE_INTEGER FileOffset
;
110 UNICODE_STRING NameU
;
112 ULONG EntriesPerPage
;
115 NameU
.Buffer
= Vpb
->VolumeLabel
;
117 NameU
.MaximumLength
= sizeof(Vpb
->VolumeLabel
);
118 *(Vpb
->VolumeLabel
) = 0;
119 Vpb
->VolumeLabelLength
= 0;
121 if (DeviceExt
->Flags
& VCB_IS_FATX
)
123 SizeDirEntry
= sizeof(FATX_DIR_ENTRY
);
124 EntriesPerPage
= FATX_ENTRIES_PER_PAGE
;
128 SizeDirEntry
= sizeof(FAT_DIR_ENTRY
);
129 EntriesPerPage
= FAT_ENTRIES_PER_PAGE
;
132 ExAcquireResourceExclusiveLite(&DeviceExt
->DirResource
, TRUE
);
133 pFcb
= vfatOpenRootFCB(DeviceExt
);
134 ExReleaseResourceLite(&DeviceExt
->DirResource
);
136 FileOffset
.QuadPart
= 0;
137 if (CcMapData(pFcb
->FileObject
, &FileOffset
, SizeDirEntry
, TRUE
, &Context
, (PVOID
*)&Entry
))
141 if (ENTRY_VOLUME(DeviceExt
, Entry
))
143 /* copy volume label */
144 if (DeviceExt
->Flags
& VCB_IS_FATX
)
146 StringO
.Buffer
= (PCHAR
)Entry
->FatX
.Filename
;
147 StringO
.MaximumLength
= StringO
.Length
= Entry
->FatX
.FilenameLength
;
148 RtlOemStringToUnicodeString(&NameU
, &StringO
, FALSE
);
152 vfat8Dot3ToString(&Entry
->Fat
, &NameU
);
154 Vpb
->VolumeLabelLength
= NameU
.Length
;
157 if (ENTRY_END(DeviceExt
, Entry
))
162 Entry
= (PDIR_ENTRY
)((ULONG_PTR
)Entry
+ SizeDirEntry
);
163 if ((DirIndex
% EntriesPerPage
) == 0)
165 CcUnpinData(Context
);
166 FileOffset
.u
.LowPart
+= PAGE_SIZE
;
167 if (!CcMapData(pFcb
->FileObject
, &FileOffset
, SizeDirEntry
, TRUE
, &Context
, (PVOID
*)&Entry
))
176 CcUnpinData(Context
);
179 ExAcquireResourceExclusiveLite(&DeviceExt
->DirResource
, TRUE
);
180 vfatReleaseFCB(DeviceExt
, pFcb
);
181 ExReleaseResourceLite(&DeviceExt
->DirResource
);
183 return STATUS_SUCCESS
;
187 * FUNCTION: Find a file
191 PDEVICE_EXTENSION DeviceExt
,
193 PUNICODE_STRING FileToFindU
,
194 PVFAT_DIRENTRY_CONTEXT DirContext
,
197 PWCHAR PathNameBuffer
;
198 USHORT PathNameBufferLength
;
200 PVOID Context
= NULL
;
204 UNICODE_STRING PathNameU
;
205 UNICODE_STRING FileToFindUpcase
;
208 DPRINT("FindFile(Parent %p, FileToFind '%wZ', DirIndex: %u)\n",
209 Parent
, FileToFindU
, DirContext
->DirIndex
);
210 DPRINT("FindFile: Path %wZ\n",&Parent
->PathNameU
);
212 PathNameBufferLength
= LONGNAME_MAX_LENGTH
* sizeof(WCHAR
);
213 PathNameBuffer
= ExAllocatePoolWithTag(NonPagedPool
, PathNameBufferLength
+ sizeof(WCHAR
), TAG_VFAT
);
216 return STATUS_INSUFFICIENT_RESOURCES
;
219 PathNameU
.Buffer
= PathNameBuffer
;
220 PathNameU
.Length
= 0;
221 PathNameU
.MaximumLength
= PathNameBufferLength
;
223 DirContext
->LongNameU
.Length
= 0;
224 DirContext
->ShortNameU
.Length
= 0;
226 WildCard
= FsRtlDoesNameContainWildCards(FileToFindU
);
228 if (WildCard
== FALSE
)
230 /* if there is no '*?' in the search name, than look first for an existing fcb */
231 RtlCopyUnicodeString(&PathNameU
, &Parent
->PathNameU
);
232 if (!vfatFCBIsRoot(Parent
))
234 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = L
'\\';
235 PathNameU
.Length
+= sizeof(WCHAR
);
237 RtlAppendUnicodeStringToString(&PathNameU
, FileToFindU
);
238 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = 0;
239 rcFcb
= vfatGrabFCBFromTable(DeviceExt
, &PathNameU
);
242 ULONG startIndex
= rcFcb
->startIndex
;
243 if ((rcFcb
->Flags
& FCB_IS_FATX_ENTRY
) && !vfatFCBIsRoot(Parent
))
247 if(startIndex
>= DirContext
->DirIndex
)
249 RtlCopyUnicodeString(&DirContext
->LongNameU
, &rcFcb
->LongNameU
);
250 RtlCopyUnicodeString(&DirContext
->ShortNameU
, &rcFcb
->ShortNameU
);
251 RtlCopyMemory(&DirContext
->DirEntry
, &rcFcb
->entry
, sizeof(DIR_ENTRY
));
252 DirContext
->StartIndex
= rcFcb
->startIndex
;
253 DirContext
->DirIndex
= rcFcb
->dirIndex
;
254 DPRINT("FindFile: new Name %wZ, DirIndex %u (%u)\n",
255 &DirContext
->LongNameU
, DirContext
->DirIndex
, DirContext
->StartIndex
);
256 Status
= STATUS_SUCCESS
;
260 DPRINT("FCB not found for %wZ\n", &PathNameU
);
261 Status
= STATUS_UNSUCCESSFUL
;
263 vfatReleaseFCB(DeviceExt
, rcFcb
);
264 ExFreePool(PathNameBuffer
);
269 /* FsRtlIsNameInExpression need the searched string to be upcase,
270 * even if IgnoreCase is specified */
271 Status
= RtlUpcaseUnicodeString(&FileToFindUpcase
, FileToFindU
, TRUE
);
272 if (!NT_SUCCESS(Status
))
274 ExFreePool(PathNameBuffer
);
280 Status
= DeviceExt
->GetNextDirEntry(&Context
, &Page
, Parent
, DirContext
, First
);
282 if (Status
== STATUS_NO_MORE_ENTRIES
)
286 if (ENTRY_VOLUME(DeviceExt
, &DirContext
->DirEntry
))
288 DirContext
->DirIndex
++;
293 Found
= FsRtlIsNameInExpression(&FileToFindUpcase
, &DirContext
->LongNameU
, TRUE
, NULL
) ||
294 FsRtlIsNameInExpression(&FileToFindUpcase
, &DirContext
->ShortNameU
, TRUE
, NULL
);
298 Found
= FsRtlAreNamesEqual(&DirContext
->LongNameU
, FileToFindU
, TRUE
, NULL
) ||
299 FsRtlAreNamesEqual(&DirContext
->ShortNameU
, FileToFindU
, TRUE
, NULL
);
306 RtlCopyUnicodeString(&PathNameU
, &Parent
->PathNameU
);
307 if (!vfatFCBIsRoot(Parent
))
309 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = L
'\\';
310 PathNameU
.Length
+= sizeof(WCHAR
);
312 RtlAppendUnicodeStringToString(&PathNameU
, &DirContext
->LongNameU
);
313 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = 0;
314 rcFcb
= vfatGrabFCBFromTable(DeviceExt
, &PathNameU
);
317 RtlCopyMemory(&DirContext
->DirEntry
, &rcFcb
->entry
, sizeof(DIR_ENTRY
));
318 vfatReleaseFCB(DeviceExt
, rcFcb
);
321 DPRINT("%u\n", DirContext
->LongNameU
.Length
);
322 DPRINT("FindFile: new Name %wZ, DirIndex %u\n",
323 &DirContext
->LongNameU
, DirContext
->DirIndex
);
327 CcUnpinData(Context
);
329 RtlFreeUnicodeString(&FileToFindUpcase
);
330 ExFreePool(PathNameBuffer
);
331 return STATUS_SUCCESS
;
333 DirContext
->DirIndex
++;
338 CcUnpinData(Context
);
341 RtlFreeUnicodeString(&FileToFindUpcase
);
342 ExFreePool(PathNameBuffer
);
347 * FUNCTION: Opens a file
352 PDEVICE_EXTENSION DeviceExt
,
353 PUNICODE_STRING PathNameU
,
354 PFILE_OBJECT FileObject
,
355 ULONG RequestedDisposition
,
361 DPRINT("VfatOpenFile(%p, '%wZ', %p, %p)\n", DeviceExt
, PathNameU
, FileObject
, ParentFcb
);
363 if (FileObject
->RelatedFileObject
)
365 DPRINT("'%wZ'\n", &FileObject
->RelatedFileObject
->FileName
);
367 *ParentFcb
= FileObject
->RelatedFileObject
->FsContext
;
368 (*ParentFcb
)->RefCount
++;
375 if (!DeviceExt
->FatInfo
.FixedMedia
)
377 Status
= VfatBlockDeviceIoControl(DeviceExt
->StorageDevice
,
378 IOCTL_DISK_CHECK_VERIFY
,
384 if (!NT_SUCCESS(Status
))
386 DPRINT("Status %lx\n", Status
);
394 (*ParentFcb
)->RefCount
++;
397 /* try first to find an existing FCB in memory */
398 DPRINT("Checking for existing FCB in memory\n");
400 Status
= vfatGetFCBForFile(DeviceExt
, ParentFcb
, &Fcb
, PathNameU
);
401 if (!NT_SUCCESS(Status
))
403 DPRINT ("Could not make a new FCB, status: %x\n", Status
);
407 if (Fcb
->Flags
& FCB_DELETE_PENDING
)
409 vfatReleaseFCB(DeviceExt
, Fcb
);
410 return STATUS_DELETE_PENDING
;
413 /* Fail, if we try to overwrite a read-only file */
414 if ((*Fcb
->Attributes
& FILE_ATTRIBUTE_READONLY
) &&
415 (RequestedDisposition
== FILE_OVERWRITE
))
417 vfatReleaseFCB(DeviceExt
, Fcb
);
418 return STATUS_ACCESS_DENIED
;
421 DPRINT("Attaching FCB to fileObject\n");
422 Status
= vfatAttachFCBToFileObject(DeviceExt
, Fcb
, FileObject
);
423 if (!NT_SUCCESS(Status
))
425 vfatReleaseFCB(DeviceExt
, Fcb
);
431 * FUNCTION: Create or open a file
435 PDEVICE_OBJECT DeviceObject
,
438 PIO_STACK_LOCATION Stack
;
439 PFILE_OBJECT FileObject
;
440 NTSTATUS Status
= STATUS_SUCCESS
;
441 PDEVICE_EXTENSION DeviceExt
;
442 ULONG RequestedDisposition
, RequestedOptions
;
443 PVFATFCB pFcb
= NULL
;
444 PVFATFCB ParentFcb
= NULL
;
446 BOOLEAN PagingFileCreate
= FALSE
;
448 BOOLEAN OpenTargetDir
= FALSE
;
449 UNICODE_STRING FileNameU
;
450 UNICODE_STRING PathNameU
;
453 /* Unpack the various parameters. */
454 Stack
= IoGetCurrentIrpStackLocation(Irp
);
455 RequestedDisposition
= ((Stack
->Parameters
.Create
.Options
>> 24) & 0xff);
456 RequestedOptions
= Stack
->Parameters
.Create
.Options
& FILE_VALID_OPTION_FLAGS
;
457 PagingFileCreate
= (Stack
->Flags
& SL_OPEN_PAGING_FILE
) ? TRUE
: FALSE
;
458 OpenTargetDir
= (Stack
->Flags
& SL_OPEN_TARGET_DIRECTORY
) ? TRUE
: FALSE
;
460 FileObject
= Stack
->FileObject
;
461 DeviceExt
= DeviceObject
->DeviceExtension
;
463 /* Check their validity. */
464 if (RequestedOptions
& FILE_DIRECTORY_FILE
&&
465 RequestedDisposition
== FILE_SUPERSEDE
)
467 return STATUS_INVALID_PARAMETER
;
470 if (RequestedOptions
& FILE_DIRECTORY_FILE
&&
471 RequestedOptions
& FILE_NON_DIRECTORY_FILE
)
473 return STATUS_INVALID_PARAMETER
;
476 /* This a open operation for the volume itself */
477 if (FileObject
->FileName
.Length
== 0 &&
478 (FileObject
->RelatedFileObject
== NULL
|| FileObject
->RelatedFileObject
->FsContext2
!= NULL
))
480 if (RequestedDisposition
!= FILE_OPEN
&&
481 RequestedDisposition
!= FILE_OPEN_IF
)
483 return STATUS_ACCESS_DENIED
;
486 /* In spite of what is shown in WDK, it seems that Windows FAT driver doesn't perform that test */
487 if (RequestedOptions
& FILE_DIRECTORY_FILE
)
489 return STATUS_NOT_A_DIRECTORY
;
495 return STATUS_INVALID_PARAMETER
;
498 pFcb
= DeviceExt
->VolumeFcb
;
499 vfatAttachFCBToFileObject(DeviceExt
, pFcb
, FileObject
);
502 Irp
->IoStatus
.Information
= FILE_OPENED
;
503 return STATUS_SUCCESS
;
506 /* Check for illegal characters and illegale dot sequences in the file name */
507 PathNameU
= FileObject
->FileName
;
508 c
= PathNameU
.Buffer
+ PathNameU
.Length
/ sizeof(WCHAR
);
511 while (c
-- > PathNameU
.Buffer
)
513 if (*c
== L
'\\' || c
== PathNameU
.Buffer
)
515 if (Dots
&& last
> c
)
517 return STATUS_OBJECT_NAME_INVALID
;
527 if (*c
!= '\\' && vfatIsLongIllegal(*c
))
529 return STATUS_OBJECT_NAME_INVALID
;
533 /* Check if we try to open target directory of root dir */
534 if (OpenTargetDir
&& FileObject
->RelatedFileObject
== NULL
&& PathNameU
.Length
== sizeof(WCHAR
) &&
535 PathNameU
.Buffer
[0] == L
'\\')
537 return STATUS_INVALID_PARAMETER
;
540 if (FileObject
->RelatedFileObject
&& PathNameU
.Length
>= sizeof(WCHAR
) && PathNameU
.Buffer
[0] == L
'\\')
542 return STATUS_OBJECT_NAME_INVALID
;
545 if (PathNameU
.Length
> sizeof(WCHAR
) && PathNameU
.Buffer
[PathNameU
.Length
/sizeof(WCHAR
)-1] == L
'\\')
547 PathNameU
.Length
-= sizeof(WCHAR
);
550 /* Try opening the file. */
553 Status
= VfatOpenFile(DeviceExt
, &PathNameU
, FileObject
, RequestedDisposition
, &ParentFcb
);
558 LONG idx
, FileNameLen
;
560 ParentFcb
= (FileObject
->RelatedFileObject
!= NULL
) ? FileObject
->RelatedFileObject
->FsContext
: NULL
;
561 Status
= vfatGetFCBForFile(DeviceExt
, &ParentFcb
, &TargetFcb
, &PathNameU
);
563 if (Status
== STATUS_SUCCESS
)
565 ParentFcb
->RefCount
++;
566 vfatReleaseFCB(DeviceExt
, TargetFcb
);
567 Irp
->IoStatus
.Information
= FILE_EXISTS
;
571 Irp
->IoStatus
.Information
= FILE_DOES_NOT_EXIST
;
574 idx
= FileObject
->FileName
.Length
/ sizeof(WCHAR
) - 1;
576 /* Skip tailing \ - if any */
577 if (PathNameU
.Buffer
[idx
] == L
'\\')
580 PathNameU
.Length
-= sizeof(WCHAR
);
584 while (idx
>= 0 && PathNameU
.Buffer
[idx
] != L
'\\')
589 if (idx
> 0 || PathNameU
.Buffer
[0] == L
'\\')
591 /* We don't want to include / in the name */
592 FileNameLen
= PathNameU
.Length
- ((idx
+ 1) * sizeof(WCHAR
));
594 /* Update FO just to keep file name */
595 /* Skip first slash */
597 FileObject
->FileName
.Length
= FileNameLen
;
598 RtlMoveMemory(&PathNameU
.Buffer
[0], &PathNameU
.Buffer
[idx
], FileObject
->FileName
.Length
);
602 /* This is a relative open and we have only the filename, so open the parent directory
603 * It is in RelatedFileObject
605 ASSERT(FileObject
->RelatedFileObject
!= NULL
);
607 /* No need to modify the FO, it already has the name */
610 /* We're done with opening! */
611 if (ParentFcb
!= NULL
)
613 Status
= vfatAttachFCBToFileObject(DeviceExt
, ParentFcb
, FileObject
);
616 if (NT_SUCCESS(Status
))
618 pFcb
= FileObject
->FsContext
;
620 if (pFcb
->OpenHandleCount
== 0)
622 IoSetShareAccess(Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
,
623 Stack
->Parameters
.Create
.ShareAccess
,
625 &pFcb
->FCBShareAccess
);
629 Status
= IoCheckShareAccess(Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
,
630 Stack
->Parameters
.Create
.ShareAccess
,
632 &pFcb
->FCBShareAccess
,
634 if (!NT_SUCCESS(Status
))
636 VfatCloseFile(DeviceExt
, FileObject
);
641 pFcb
->OpenHandleCount
++;
643 else if (ParentFcb
!= NULL
)
645 vfatReleaseFCB(DeviceExt
, ParentFcb
);
652 * If the directory containing the file to open doesn't exist then
655 if (Status
== STATUS_OBJECT_PATH_NOT_FOUND
||
656 Status
== STATUS_INVALID_PARAMETER
||
657 Status
== STATUS_DELETE_PENDING
)
661 vfatReleaseFCB(DeviceExt
, ParentFcb
);
666 if (!NT_SUCCESS(Status
) && ParentFcb
== NULL
)
668 DPRINT1("VfatOpenFile failed for '%wZ', status %x\n", &PathNameU
, Status
);
672 /* If the file open failed then create the required file */
673 if (!NT_SUCCESS (Status
))
675 if (RequestedDisposition
== FILE_CREATE
||
676 RequestedDisposition
== FILE_OPEN_IF
||
677 RequestedDisposition
== FILE_OVERWRITE_IF
||
678 RequestedDisposition
== FILE_SUPERSEDE
)
680 Attributes
= Stack
->Parameters
.Create
.FileAttributes
& ~FILE_ATTRIBUTE_NORMAL
;
681 if (!(RequestedOptions
& FILE_DIRECTORY_FILE
))
682 Attributes
|= FILE_ATTRIBUTE_ARCHIVE
;
683 vfatSplitPathName(&PathNameU
, NULL
, &FileNameU
);
684 Status
= VfatAddEntry(DeviceExt
, &FileNameU
, &pFcb
, ParentFcb
, RequestedOptions
,
685 (UCHAR
)(Attributes
& FILE_ATTRIBUTE_VALID_FLAGS
), NULL
);
686 vfatReleaseFCB(DeviceExt
, ParentFcb
);
687 if (NT_SUCCESS(Status
))
689 Status
= vfatAttachFCBToFileObject(DeviceExt
, pFcb
, FileObject
);
690 if (!NT_SUCCESS(Status
))
692 vfatReleaseFCB(DeviceExt
, pFcb
);
696 Irp
->IoStatus
.Information
= FILE_CREATED
;
697 VfatSetAllocationSizeInformation(FileObject
,
700 &Irp
->Overlay
.AllocationSize
);
701 VfatSetExtendedAttributes(FileObject
,
702 Irp
->AssociatedIrp
.SystemBuffer
,
703 Stack
->Parameters
.Create
.EaLength
);
705 if (PagingFileCreate
)
707 pFcb
->Flags
|= FCB_IS_PAGE_FILE
;
719 vfatReleaseFCB(DeviceExt
, ParentFcb
);
728 vfatReleaseFCB(DeviceExt
, ParentFcb
);
731 /* Otherwise fail if the caller wanted to create a new file */
732 if (RequestedDisposition
== FILE_CREATE
)
734 Irp
->IoStatus
.Information
= FILE_EXISTS
;
735 VfatCloseFile(DeviceExt
, FileObject
);
736 return STATUS_OBJECT_NAME_COLLISION
;
739 pFcb
= FileObject
->FsContext
;
741 if (pFcb
->OpenHandleCount
!= 0)
743 Status
= IoCheckShareAccess(Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
,
744 Stack
->Parameters
.Create
.ShareAccess
,
746 &pFcb
->FCBShareAccess
,
748 if (!NT_SUCCESS(Status
))
750 VfatCloseFile(DeviceExt
, FileObject
);
756 * Check the file has the requested attributes
758 if (RequestedOptions
& FILE_NON_DIRECTORY_FILE
&&
759 *pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
)
761 VfatCloseFile (DeviceExt
, FileObject
);
762 return STATUS_FILE_IS_A_DIRECTORY
;
764 if (RequestedOptions
& FILE_DIRECTORY_FILE
&&
765 !(*pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
))
767 VfatCloseFile (DeviceExt
, FileObject
);
768 return STATUS_NOT_A_DIRECTORY
;
770 #ifndef USE_ROS_CC_AND_FS
771 if (!(*pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
))
773 if (Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
& FILE_WRITE_DATA
||
774 RequestedDisposition
== FILE_OVERWRITE
||
775 RequestedDisposition
== FILE_OVERWRITE_IF
)
777 if (!MmFlushImageSection(&pFcb
->SectionObjectPointers
, MmFlushForWrite
))
779 DPRINT1("%wZ\n", &pFcb
->PathNameU
);
780 DPRINT1("%d %d %d\n", Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
& FILE_WRITE_DATA
,
781 RequestedDisposition
== FILE_OVERWRITE
, RequestedDisposition
== FILE_OVERWRITE_IF
);
782 VfatCloseFile (DeviceExt
, FileObject
);
783 return STATUS_SHARING_VIOLATION
;
788 if (PagingFileCreate
)
791 * Do more checking for page files. It is possible,
792 * that the file was opened and closed previously
793 * as a normal cached file. In this case, the cache
794 * manager has referenced the fileobject and the fcb
795 * is held in memory. Try to remove the fileobject
796 * from cache manager and use the fcb.
798 if (pFcb
->RefCount
> 1)
800 if(!(pFcb
->Flags
& FCB_IS_PAGE_FILE
))
802 VfatCloseFile(DeviceExt
, FileObject
);
803 return STATUS_INVALID_PARAMETER
;
808 pFcb
->Flags
|= FCB_IS_PAGE_FILE
;
813 if (pFcb
->Flags
& FCB_IS_PAGE_FILE
)
815 VfatCloseFile(DeviceExt
, FileObject
);
816 return STATUS_INVALID_PARAMETER
;
820 if (RequestedDisposition
== FILE_OVERWRITE
||
821 RequestedDisposition
== FILE_OVERWRITE_IF
||
822 RequestedDisposition
== FILE_SUPERSEDE
)
824 if (!(*pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
))
826 *pFcb
->Attributes
= Stack
->Parameters
.Create
.FileAttributes
& ~FILE_ATTRIBUTE_NORMAL
;
827 *pFcb
->Attributes
|= FILE_ATTRIBUTE_ARCHIVE
;
828 VfatUpdateEntry(pFcb
);
831 ExAcquireResourceExclusiveLite(&(pFcb
->MainResource
), TRUE
);
832 Status
= VfatSetAllocationSizeInformation(FileObject
,
835 &Irp
->Overlay
.AllocationSize
);
836 ExReleaseResourceLite(&(pFcb
->MainResource
));
837 if (!NT_SUCCESS (Status
))
839 VfatCloseFile(DeviceExt
, FileObject
);
844 if (RequestedDisposition
== FILE_SUPERSEDE
)
846 Irp
->IoStatus
.Information
= FILE_SUPERSEDED
;
848 else if (RequestedDisposition
== FILE_OVERWRITE
||
849 RequestedDisposition
== FILE_OVERWRITE_IF
)
851 Irp
->IoStatus
.Information
= FILE_OVERWRITTEN
;
855 Irp
->IoStatus
.Information
= FILE_OPENED
;
859 if (pFcb
->OpenHandleCount
== 0)
861 IoSetShareAccess(Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
,
862 Stack
->Parameters
.Create
.ShareAccess
,
864 &pFcb
->FCBShareAccess
);
868 IoUpdateShareAccess(FileObject
,
869 &pFcb
->FCBShareAccess
);
872 if (Irp
->IoStatus
.Information
== FILE_CREATED
)
874 FsRtlNotifyFullReportChange(DeviceExt
->NotifySync
,
875 &(DeviceExt
->NotifyList
),
876 (PSTRING
)&pFcb
->PathNameU
,
877 pFcb
->PathNameU
.Length
- pFcb
->LongNameU
.Length
,
880 ((*pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
) ?
881 FILE_NOTIFY_CHANGE_DIR_NAME
: FILE_NOTIFY_CHANGE_FILE_NAME
),
886 pFcb
->OpenHandleCount
++;
888 /* FIXME : test write access if requested */
894 * FUNCTION: Create or open a file
898 PVFAT_IRP_CONTEXT IrpContext
)
904 if (IrpContext
->DeviceObject
== VfatGlobalData
->DeviceObject
)
906 /* DeviceObject represents FileSystem instead of logical volume */
907 DPRINT ("FsdCreate called with file system\n");
908 IrpContext
->Irp
->IoStatus
.Information
= FILE_OPENED
;
909 IrpContext
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
910 IoCompleteRequest(IrpContext
->Irp
, IO_DISK_INCREMENT
);
911 VfatFreeIrpContext(IrpContext
);
912 return STATUS_SUCCESS
;
915 if (!(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
))
917 return(VfatQueueRequest(IrpContext
));
920 IrpContext
->Irp
->IoStatus
.Information
= 0;
921 ExAcquireResourceExclusiveLite(&IrpContext
->DeviceExt
->DirResource
, TRUE
);
922 Status
= VfatCreateFile(IrpContext
->DeviceObject
, IrpContext
->Irp
);
923 ExReleaseResourceLite(&IrpContext
->DeviceExt
->DirResource
);
925 IrpContext
->Irp
->IoStatus
.Status
= Status
;
926 IoCompleteRequest(IrpContext
->Irp
,
927 (CCHAR
)(NT_SUCCESS(Status
) ? IO_DISK_INCREMENT
: IO_NO_INCREMENT
));
928 VfatFreeIrpContext(IrpContext
);