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 *****************************************************************/
35 PFAT_DIR_ENTRY pEntry
,
36 PUNICODE_STRING NameU
)
42 RtlCopyMemory(cString
, pEntry
->ShortName
, 11);
44 if (cString
[0] == 0x05)
49 StringA
.Buffer
= cString
;
50 for (StringA
.Length
= 0;
51 StringA
.Length
< 8 && StringA
.Buffer
[StringA
.Length
] != ' ';
53 StringA
.MaximumLength
= StringA
.Length
;
55 RtlOemStringToUnicodeString(NameU
, &StringA
, FALSE
);
57 if (pEntry
->lCase
& VFAT_CASE_LOWER_BASE
)
59 RtlDowncaseUnicodeString(NameU
, NameU
, FALSE
);
62 if (cString
[8] != ' ')
64 Length
= NameU
->Length
;
65 NameU
->Buffer
+= Length
/ sizeof(WCHAR
);
66 if (!FAT_ENTRY_VOLUME(pEntry
))
68 Length
+= sizeof(WCHAR
);
69 NameU
->Buffer
[0] = L
'.';
73 NameU
->MaximumLength
-= Length
;
75 StringA
.Buffer
= &cString
[8];
76 for (StringA
.Length
= 0;
77 StringA
.Length
< 3 && StringA
.Buffer
[StringA
.Length
] != ' ';
79 StringA
.MaximumLength
= StringA
.Length
;
80 RtlOemStringToUnicodeString(NameU
, &StringA
, FALSE
);
81 if (pEntry
->lCase
& VFAT_CASE_LOWER_EXT
)
83 RtlDowncaseUnicodeString(NameU
, NameU
, FALSE
);
85 NameU
->Buffer
-= Length
/ sizeof(WCHAR
);
86 NameU
->Length
+= Length
;
87 NameU
->MaximumLength
+= Length
;
90 NameU
->Buffer
[NameU
->Length
/ sizeof(WCHAR
)] = 0;
91 DPRINT("'%wZ'\n", NameU
);
95 * FUNCTION: Read the volume label
99 PDEVICE_EXTENSION DeviceExt
,
102 PVOID Context
= NULL
;
106 LARGE_INTEGER FileOffset
;
107 UNICODE_STRING NameU
;
109 ULONG EntriesPerPage
;
112 NameU
.Buffer
= Vpb
->VolumeLabel
;
114 NameU
.MaximumLength
= sizeof(Vpb
->VolumeLabel
);
115 *(Vpb
->VolumeLabel
) = 0;
116 Vpb
->VolumeLabelLength
= 0;
118 if (DeviceExt
->Flags
& VCB_IS_FATX
)
120 SizeDirEntry
= sizeof(FATX_DIR_ENTRY
);
121 EntriesPerPage
= FATX_ENTRIES_PER_PAGE
;
125 SizeDirEntry
= sizeof(FAT_DIR_ENTRY
);
126 EntriesPerPage
= FAT_ENTRIES_PER_PAGE
;
129 ExAcquireResourceExclusiveLite(&DeviceExt
->DirResource
, TRUE
);
130 pFcb
= vfatOpenRootFCB(DeviceExt
);
131 ExReleaseResourceLite(&DeviceExt
->DirResource
);
133 FileOffset
.QuadPart
= 0;
134 if (CcMapData(pFcb
->FileObject
, &FileOffset
, SizeDirEntry
, TRUE
, &Context
, (PVOID
*)&Entry
))
138 if (ENTRY_VOLUME(DeviceExt
, Entry
))
140 /* copy volume label */
141 if (DeviceExt
->Flags
& VCB_IS_FATX
)
143 StringO
.Buffer
= (PCHAR
)Entry
->FatX
.Filename
;
144 StringO
.MaximumLength
= StringO
.Length
= Entry
->FatX
.FilenameLength
;
145 RtlOemStringToUnicodeString(&NameU
, &StringO
, FALSE
);
149 vfat8Dot3ToString(&Entry
->Fat
, &NameU
);
151 Vpb
->VolumeLabelLength
= NameU
.Length
;
154 if (ENTRY_END(DeviceExt
, Entry
))
159 Entry
= (PDIR_ENTRY
)((ULONG_PTR
)Entry
+ SizeDirEntry
);
160 if ((DirIndex
% EntriesPerPage
) == 0)
162 CcUnpinData(Context
);
163 FileOffset
.u
.LowPart
+= PAGE_SIZE
;
164 if (!CcMapData(pFcb
->FileObject
, &FileOffset
, SizeDirEntry
, TRUE
, &Context
, (PVOID
*)&Entry
))
173 CcUnpinData(Context
);
176 ExAcquireResourceExclusiveLite(&DeviceExt
->DirResource
, TRUE
);
177 vfatReleaseFCB(DeviceExt
, pFcb
);
178 ExReleaseResourceLite(&DeviceExt
->DirResource
);
180 return STATUS_SUCCESS
;
184 * FUNCTION: Find a file
188 PDEVICE_EXTENSION DeviceExt
,
190 PUNICODE_STRING FileToFindU
,
191 PVFAT_DIRENTRY_CONTEXT DirContext
,
194 PWCHAR PathNameBuffer
;
195 USHORT PathNameBufferLength
;
197 PVOID Context
= NULL
;
201 UNICODE_STRING PathNameU
;
202 UNICODE_STRING FileToFindUpcase
;
205 DPRINT("FindFile(Parent %p, FileToFind '%wZ', DirIndex: %u)\n",
206 Parent
, FileToFindU
, DirContext
->DirIndex
);
207 DPRINT("FindFile: Path %wZ\n",&Parent
->PathNameU
);
209 PathNameBufferLength
= LONGNAME_MAX_LENGTH
* sizeof(WCHAR
);
210 PathNameBuffer
= ExAllocatePoolWithTag(NonPagedPool
, PathNameBufferLength
+ sizeof(WCHAR
), TAG_VFAT
);
213 return STATUS_INSUFFICIENT_RESOURCES
;
216 PathNameU
.Buffer
= PathNameBuffer
;
217 PathNameU
.Length
= 0;
218 PathNameU
.MaximumLength
= PathNameBufferLength
;
220 DirContext
->LongNameU
.Length
= 0;
221 DirContext
->ShortNameU
.Length
= 0;
223 WildCard
= FsRtlDoesNameContainWildCards(FileToFindU
);
225 if (WildCard
== FALSE
)
227 /* if there is no '*?' in the search name, than look first for an existing fcb */
228 RtlCopyUnicodeString(&PathNameU
, &Parent
->PathNameU
);
229 if (!vfatFCBIsRoot(Parent
))
231 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = L
'\\';
232 PathNameU
.Length
+= sizeof(WCHAR
);
234 RtlAppendUnicodeStringToString(&PathNameU
, FileToFindU
);
235 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = 0;
236 rcFcb
= vfatGrabFCBFromTable(DeviceExt
, &PathNameU
);
239 ULONG startIndex
= rcFcb
->startIndex
;
240 if ((rcFcb
->Flags
& FCB_IS_FATX_ENTRY
) && !vfatFCBIsRoot(Parent
))
244 if(startIndex
>= DirContext
->DirIndex
)
246 RtlCopyUnicodeString(&DirContext
->LongNameU
, &rcFcb
->LongNameU
);
247 RtlCopyUnicodeString(&DirContext
->ShortNameU
, &rcFcb
->ShortNameU
);
248 RtlCopyMemory(&DirContext
->DirEntry
, &rcFcb
->entry
, sizeof(DIR_ENTRY
));
249 DirContext
->StartIndex
= rcFcb
->startIndex
;
250 DirContext
->DirIndex
= rcFcb
->dirIndex
;
251 DPRINT("FindFile: new Name %wZ, DirIndex %u (%u)\n",
252 &DirContext
->LongNameU
, DirContext
->DirIndex
, DirContext
->StartIndex
);
253 Status
= STATUS_SUCCESS
;
257 DPRINT("FCB not found for %wZ\n", &PathNameU
);
258 Status
= STATUS_UNSUCCESSFUL
;
260 vfatReleaseFCB(DeviceExt
, rcFcb
);
261 ExFreePool(PathNameBuffer
);
266 /* FsRtlIsNameInExpression need the searched string to be upcase,
267 * even if IgnoreCase is specified */
268 Status
= RtlUpcaseUnicodeString(&FileToFindUpcase
, FileToFindU
, TRUE
);
269 if (!NT_SUCCESS(Status
))
271 ExFreePool(PathNameBuffer
);
277 Status
= DeviceExt
->GetNextDirEntry(&Context
, &Page
, Parent
, DirContext
, First
);
279 if (Status
== STATUS_NO_MORE_ENTRIES
)
283 if (ENTRY_VOLUME(DeviceExt
, &DirContext
->DirEntry
))
285 DirContext
->DirIndex
++;
290 Found
= FsRtlIsNameInExpression(&FileToFindUpcase
, &DirContext
->LongNameU
, TRUE
, NULL
) ||
291 FsRtlIsNameInExpression(&FileToFindUpcase
, &DirContext
->ShortNameU
, TRUE
, NULL
);
295 Found
= FsRtlAreNamesEqual(&DirContext
->LongNameU
, FileToFindU
, TRUE
, NULL
) ||
296 FsRtlAreNamesEqual(&DirContext
->ShortNameU
, FileToFindU
, TRUE
, NULL
);
303 RtlCopyUnicodeString(&PathNameU
, &Parent
->PathNameU
);
304 if (!vfatFCBIsRoot(Parent
))
306 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = L
'\\';
307 PathNameU
.Length
+= sizeof(WCHAR
);
309 RtlAppendUnicodeStringToString(&PathNameU
, &DirContext
->LongNameU
);
310 PathNameU
.Buffer
[PathNameU
.Length
/ sizeof(WCHAR
)] = 0;
311 rcFcb
= vfatGrabFCBFromTable(DeviceExt
, &PathNameU
);
314 RtlCopyMemory(&DirContext
->DirEntry
, &rcFcb
->entry
, sizeof(DIR_ENTRY
));
315 vfatReleaseFCB(DeviceExt
, rcFcb
);
318 DPRINT("%u\n", DirContext
->LongNameU
.Length
);
319 DPRINT("FindFile: new Name %wZ, DirIndex %u\n",
320 &DirContext
->LongNameU
, DirContext
->DirIndex
);
324 CcUnpinData(Context
);
326 RtlFreeUnicodeString(&FileToFindUpcase
);
327 ExFreePool(PathNameBuffer
);
328 return STATUS_SUCCESS
;
330 DirContext
->DirIndex
++;
335 CcUnpinData(Context
);
338 RtlFreeUnicodeString(&FileToFindUpcase
);
339 ExFreePool(PathNameBuffer
);
344 * FUNCTION: Opens a file
349 PDEVICE_EXTENSION DeviceExt
,
350 PUNICODE_STRING PathNameU
,
351 PFILE_OBJECT FileObject
,
352 ULONG RequestedDisposition
,
358 DPRINT("VfatOpenFile(%p, '%wZ', %p, %p)\n", DeviceExt
, PathNameU
, FileObject
, ParentFcb
);
360 if (FileObject
->RelatedFileObject
)
362 DPRINT("'%wZ'\n", &FileObject
->RelatedFileObject
->FileName
);
364 *ParentFcb
= FileObject
->RelatedFileObject
->FsContext
;
365 (*ParentFcb
)->RefCount
++;
372 if (!DeviceExt
->FatInfo
.FixedMedia
)
374 Status
= VfatBlockDeviceIoControl(DeviceExt
->StorageDevice
,
375 IOCTL_DISK_CHECK_VERIFY
,
381 if (!NT_SUCCESS(Status
))
383 DPRINT("Status %lx\n", Status
);
391 (*ParentFcb
)->RefCount
++;
394 /* try first to find an existing FCB in memory */
395 DPRINT("Checking for existing FCB in memory\n");
397 Status
= vfatGetFCBForFile(DeviceExt
, ParentFcb
, &Fcb
, PathNameU
);
398 if (!NT_SUCCESS(Status
))
400 DPRINT ("Could not make a new FCB, status: %x\n", Status
);
403 if (Fcb
->Flags
& FCB_DELETE_PENDING
)
405 vfatReleaseFCB(DeviceExt
, Fcb
);
406 return STATUS_DELETE_PENDING
;
409 /* Fail, if we try to overwrite a read-only file */
410 if ((*Fcb
->Attributes
& FILE_ATTRIBUTE_READONLY
) &&
411 (RequestedDisposition
== FILE_OVERWRITE
))
413 vfatReleaseFCB(DeviceExt
, Fcb
);
414 return STATUS_ACCESS_DENIED
;
417 DPRINT("Attaching FCB to fileObject\n");
418 Status
= vfatAttachFCBToFileObject(DeviceExt
, Fcb
, FileObject
);
419 if (!NT_SUCCESS(Status
))
421 vfatReleaseFCB(DeviceExt
, Fcb
);
427 * FUNCTION: Create or open a file
431 PDEVICE_OBJECT DeviceObject
,
434 PIO_STACK_LOCATION Stack
;
435 PFILE_OBJECT FileObject
;
436 NTSTATUS Status
= STATUS_SUCCESS
;
437 PDEVICE_EXTENSION DeviceExt
;
438 ULONG RequestedDisposition
, RequestedOptions
;
439 PVFATFCB pFcb
= NULL
;
440 PVFATFCB ParentFcb
= NULL
;
442 BOOLEAN PagingFileCreate
= FALSE
;
444 UNICODE_STRING FileNameU
;
445 UNICODE_STRING PathNameU
;
448 /* Unpack the various parameters. */
449 Stack
= IoGetCurrentIrpStackLocation(Irp
);
450 RequestedDisposition
= ((Stack
->Parameters
.Create
.Options
>> 24) & 0xff);
451 RequestedOptions
= Stack
->Parameters
.Create
.Options
& FILE_VALID_OPTION_FLAGS
;
452 PagingFileCreate
= (Stack
->Flags
& SL_OPEN_PAGING_FILE
) ? TRUE
: FALSE
;
453 FileObject
= Stack
->FileObject
;
454 DeviceExt
= DeviceObject
->DeviceExtension
;
456 /* Check their validity. */
457 if (RequestedOptions
& FILE_DIRECTORY_FILE
&&
458 RequestedDisposition
== FILE_SUPERSEDE
)
460 return STATUS_INVALID_PARAMETER
;
463 if (RequestedOptions
& FILE_DIRECTORY_FILE
&&
464 RequestedOptions
& FILE_NON_DIRECTORY_FILE
)
466 return STATUS_INVALID_PARAMETER
;
469 /* This a open operation for the volume itself */
470 if (FileObject
->FileName
.Length
== 0 &&
471 (FileObject
->RelatedFileObject
== NULL
|| FileObject
->RelatedFileObject
->FsContext2
!= NULL
))
473 if (RequestedDisposition
!= FILE_OPEN
&&
474 RequestedDisposition
!= FILE_OPEN_IF
)
476 return STATUS_ACCESS_DENIED
;
479 /* In spite of what is shown in WDK, it seems that Windows FAT driver doesn't perform that test */
480 if (RequestedOptions
& FILE_DIRECTORY_FILE
)
482 return STATUS_NOT_A_DIRECTORY
;
486 pFcb
= DeviceExt
->VolumeFcb
;
487 vfatAttachFCBToFileObject(DeviceExt
, pFcb
, FileObject
);
490 Irp
->IoStatus
.Information
= FILE_OPENED
;
491 return STATUS_SUCCESS
;
494 /* Check for illegal characters and illegale dot sequences in the file name */
495 PathNameU
= FileObject
->FileName
;
496 c
= PathNameU
.Buffer
+ PathNameU
.Length
/ sizeof(WCHAR
);
499 while (c
-- > PathNameU
.Buffer
)
501 if (*c
== L
'\\' || c
== PathNameU
.Buffer
)
503 if (Dots
&& last
> c
)
505 return STATUS_OBJECT_NAME_INVALID
;
515 if (*c
!= '\\' && vfatIsLongIllegal(*c
))
517 return STATUS_OBJECT_NAME_INVALID
;
521 if (FileObject
->RelatedFileObject
&& PathNameU
.Length
>= sizeof(WCHAR
) && PathNameU
.Buffer
[0] == L
'\\')
523 return STATUS_OBJECT_NAME_INVALID
;
526 if (PathNameU
.Length
> sizeof(WCHAR
) && PathNameU
.Buffer
[PathNameU
.Length
/sizeof(WCHAR
)-1] == L
'\\')
528 PathNameU
.Length
-= sizeof(WCHAR
);
531 /* Try opening the file. */
532 Status
= VfatOpenFile(DeviceExt
, &PathNameU
, FileObject
, RequestedDisposition
, &ParentFcb
);
535 * If the directory containing the file to open doesn't exist then
538 if (Status
== STATUS_OBJECT_PATH_NOT_FOUND
||
539 Status
== STATUS_INVALID_PARAMETER
||
540 Status
== STATUS_DELETE_PENDING
)
544 vfatReleaseFCB(DeviceExt
, ParentFcb
);
549 if (!NT_SUCCESS(Status
) && ParentFcb
== NULL
)
551 DPRINT1("VfatOpenFile faild for '%wZ', status %x\n", &PathNameU
, Status
);
555 /* If the file open failed then create the required file */
556 if (!NT_SUCCESS (Status
))
558 if (RequestedDisposition
== FILE_CREATE
||
559 RequestedDisposition
== FILE_OPEN_IF
||
560 RequestedDisposition
== FILE_OVERWRITE_IF
||
561 RequestedDisposition
== FILE_SUPERSEDE
)
563 Attributes
= Stack
->Parameters
.Create
.FileAttributes
& ~FILE_ATTRIBUTE_NORMAL
;
564 if (!(RequestedOptions
& FILE_DIRECTORY_FILE
))
565 Attributes
|= FILE_ATTRIBUTE_ARCHIVE
;
566 vfatSplitPathName(&PathNameU
, NULL
, &FileNameU
);
567 Status
= VfatAddEntry(DeviceExt
, &FileNameU
, &pFcb
, ParentFcb
, RequestedOptions
,
568 (UCHAR
)(Attributes
& FILE_ATTRIBUTE_VALID_FLAGS
));
569 vfatReleaseFCB(DeviceExt
, ParentFcb
);
570 if (NT_SUCCESS(Status
))
572 Status
= vfatAttachFCBToFileObject(DeviceExt
, pFcb
, FileObject
);
573 if (!NT_SUCCESS(Status
))
575 vfatReleaseFCB(DeviceExt
, pFcb
);
579 Irp
->IoStatus
.Information
= FILE_CREATED
;
580 VfatSetAllocationSizeInformation(FileObject
,
583 &Irp
->Overlay
.AllocationSize
);
584 VfatSetExtendedAttributes(FileObject
,
585 Irp
->AssociatedIrp
.SystemBuffer
,
586 Stack
->Parameters
.Create
.EaLength
);
588 if (PagingFileCreate
)
590 pFcb
->Flags
|= FCB_IS_PAGE_FILE
;
602 vfatReleaseFCB(DeviceExt
, ParentFcb
);
611 vfatReleaseFCB(DeviceExt
, ParentFcb
);
614 /* Otherwise fail if the caller wanted to create a new file */
615 if (RequestedDisposition
== FILE_CREATE
)
617 Irp
->IoStatus
.Information
= FILE_EXISTS
;
618 VfatCloseFile(DeviceExt
, FileObject
);
619 return STATUS_OBJECT_NAME_COLLISION
;
622 pFcb
= FileObject
->FsContext
;
624 if (pFcb
->OpenHandleCount
!= 0)
626 Status
= IoCheckShareAccess(Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
,
627 Stack
->Parameters
.Create
.ShareAccess
,
629 &pFcb
->FCBShareAccess
,
631 if (!NT_SUCCESS(Status
))
633 VfatCloseFile(DeviceExt
, FileObject
);
639 * Check the file has the requested attributes
641 if (RequestedOptions
& FILE_NON_DIRECTORY_FILE
&&
642 *pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
)
644 VfatCloseFile (DeviceExt
, FileObject
);
645 return STATUS_FILE_IS_A_DIRECTORY
;
647 if (RequestedOptions
& FILE_DIRECTORY_FILE
&&
648 !(*pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
))
650 VfatCloseFile (DeviceExt
, FileObject
);
651 return STATUS_NOT_A_DIRECTORY
;
653 #ifndef USE_ROS_CC_AND_FS
654 if (!(*pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
))
656 if (Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
& FILE_WRITE_DATA
||
657 RequestedDisposition
== FILE_OVERWRITE
||
658 RequestedDisposition
== FILE_OVERWRITE_IF
)
660 if (!MmFlushImageSection(&pFcb
->SectionObjectPointers
, MmFlushForWrite
))
662 DPRINT1("%wZ\n", &pFcb
->PathNameU
);
663 DPRINT1("%d %d %d\n", Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
& FILE_WRITE_DATA
,
664 RequestedDisposition
== FILE_OVERWRITE
, RequestedDisposition
== FILE_OVERWRITE_IF
);
665 VfatCloseFile (DeviceExt
, FileObject
);
666 return STATUS_SHARING_VIOLATION
;
671 if (PagingFileCreate
)
674 * Do more checking for page files. It is possible,
675 * that the file was opened and closed previously
676 * as a normal cached file. In this case, the cache
677 * manager has referenced the fileobject and the fcb
678 * is held in memory. Try to remove the fileobject
679 * from cache manager and use the fcb.
681 if (pFcb
->RefCount
> 1)
683 if(!(pFcb
->Flags
& FCB_IS_PAGE_FILE
))
685 VfatCloseFile(DeviceExt
, FileObject
);
686 return STATUS_INVALID_PARAMETER
;
691 pFcb
->Flags
|= FCB_IS_PAGE_FILE
;
696 if (pFcb
->Flags
& FCB_IS_PAGE_FILE
)
698 VfatCloseFile(DeviceExt
, FileObject
);
699 return STATUS_INVALID_PARAMETER
;
703 if (RequestedDisposition
== FILE_OVERWRITE
||
704 RequestedDisposition
== FILE_OVERWRITE_IF
||
705 RequestedDisposition
== FILE_SUPERSEDE
)
707 if (!(*pFcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
))
709 *pFcb
->Attributes
= Stack
->Parameters
.Create
.FileAttributes
& ~FILE_ATTRIBUTE_NORMAL
;
710 *pFcb
->Attributes
|= FILE_ATTRIBUTE_ARCHIVE
;
711 VfatUpdateEntry(pFcb
);
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
);
751 IoUpdateShareAccess(FileObject
,
752 &pFcb
->FCBShareAccess
);
755 pFcb
->OpenHandleCount
++;
757 /* FIXME : test write access if requested */
763 * FUNCTION: Create or open a file
767 PVFAT_IRP_CONTEXT IrpContext
)
773 if (IrpContext
->DeviceObject
== VfatGlobalData
->DeviceObject
)
775 /* DeviceObject represents FileSystem instead of logical volume */
776 DPRINT ("FsdCreate called with file system\n");
777 IrpContext
->Irp
->IoStatus
.Information
= FILE_OPENED
;
778 IrpContext
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
779 IoCompleteRequest(IrpContext
->Irp
, IO_DISK_INCREMENT
);
780 VfatFreeIrpContext(IrpContext
);
781 return STATUS_SUCCESS
;
784 if (!(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
))
786 return(VfatQueueRequest(IrpContext
));
789 IrpContext
->Irp
->IoStatus
.Information
= 0;
790 ExAcquireResourceExclusiveLite(&IrpContext
->DeviceExt
->DirResource
, TRUE
);
791 Status
= VfatCreateFile(IrpContext
->DeviceObject
, IrpContext
->Irp
);
792 ExReleaseResourceLite(&IrpContext
->DeviceExt
->DirResource
);
794 IrpContext
->Irp
->IoStatus
.Status
= Status
;
795 IoCompleteRequest(IrpContext
->Irp
,
796 (CCHAR
)(NT_SUCCESS(Status
) ? IO_DISK_INCREMENT
: IO_NO_INCREMENT
));
797 VfatFreeIrpContext(IrpContext
);