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.
19 /* $Id: create.c,v 1.47 2002/10/01 19:27:17 chorns Exp $
21 * PROJECT: ReactOS kernel
22 * FILE: services/fs/vfat/create.c
23 * PURPOSE: VFAT Filesystem
24 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
28 /* INCLUDES *****************************************************************/
30 #include <ddk/ntddk.h>
39 /* GLOBALS *******************************************************************/
41 #define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FATDirEntry))
43 /* FUNCTIONS *****************************************************************/
46 IsLastEntry (PVOID Block
, ULONG Offset
)
48 * FUNCTION: Determine if the given directory entry is the last
51 return (((FATDirEntry
*) Block
)[Offset
].Filename
[0] == 0);
55 IsVolEntry (PVOID Block
, ULONG Offset
)
57 * FUNCTION: Determine if the given directory entry is a vol entry
60 if ((((FATDirEntry
*) Block
)[Offset
].Attrib
) == 0x28)
67 IsDeletedEntry (PVOID Block
, ULONG Offset
)
69 * FUNCTION: Determines if the given entry is a deleted one
72 /* Checks special character */
74 return ((((FATDirEntry
*) Block
)[Offset
].Filename
[0] == 0xe5) ||
75 (((FATDirEntry
*) Block
)[Offset
].Filename
[0] == 0));
78 void vfat8Dot3ToString (PCHAR pBasename
, PCHAR pExtension
, PWSTR pName
)
80 int fromIndex
, toIndex
;
82 fromIndex
= toIndex
= 0;
83 while (fromIndex
< 8 && pBasename
[fromIndex
] != ' ')
85 pName
[toIndex
++] = pBasename
[fromIndex
++];
87 if (pExtension
[0] != ' ')
89 pName
[toIndex
++] = L
'.';
91 while (fromIndex
< 3 && pExtension
[fromIndex
] != ' ')
93 pName
[toIndex
++] = pExtension
[fromIndex
++];
96 pName
[toIndex
] = L
'\0';
99 static void vfat8Dot3ToVolumeLabel (PCHAR pBasename
, PCHAR pExtension
, PWSTR pName
)
101 int fromIndex
, toIndex
;
103 fromIndex
= toIndex
= 0;
104 while (fromIndex
< 8 && pBasename
[fromIndex
] != ' ')
106 pName
[toIndex
++] = pBasename
[fromIndex
++];
108 if (pExtension
[0] != ' ')
111 while (fromIndex
< 3 && pBasename
[fromIndex
] != ' ')
113 pName
[toIndex
++] = pExtension
[fromIndex
++];
116 pName
[toIndex
] = L
'\0';
120 GetEntryName(PVOID
*pContext
,
122 PFILE_OBJECT FileObject
,
127 * FUNCTION: Retrieves the file name, be it in short or long file name format
134 ULONG Offset
= *pIndex
% ENTRIES_PER_PAGE
;
136 LARGE_INTEGER FileOffset
;
141 test
= (FATDirEntry
*) *Block
;
142 test2
= (slot
*) *Block
;
143 if (vfatIsDirEntryEndMarker(&test
[Offset
]))
145 return STATUS_NO_MORE_ENTRIES
;
147 if (test2
[Offset
].attr
== 0x0f && !vfatIsDirEntryDeleted(&test
[Offset
]))
151 *pIndex2
= *pIndex
; // start of dir entry
153 DPRINT (" long name entry found at %d\n", *pIndex
);
155 DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
156 5, test2
[Offset
].name0_4
,
157 6, test2
[Offset
].name5_10
,
158 2, test2
[Offset
].name11_12
);
160 vfat_initstr (Name
, 255);
161 vfat_wcsncpy (Name
, test2
[Offset
].name0_4
, 5);
162 vfat_wcsncat (Name
, test2
[Offset
].name5_10
, 5, 6);
163 vfat_wcsncat (Name
, test2
[Offset
].name11_12
, 11, 2);
165 DPRINT (" longName: [%S]\n", Name
);
167 while ((test2
[Offset
].id
!= 0x41) && (test2
[Offset
].id
!= 0x01) &&
168 (test2
[Offset
].attr
> 0))
173 if (Offset
== ENTRIES_PER_PAGE
)
176 CcUnpinData(*pContext
);
177 FileOffset
.QuadPart
= *pIndex
* sizeof(FATDirEntry
);
178 if(!CcMapData(FileObject
, &FileOffset
, PAGE_SIZE
, TRUE
, pContext
, Block
))
181 return STATUS_NO_MORE_ENTRIES
;
183 test2
= (slot
*) *Block
;
185 DPRINT (" long name entry found at %d\n", *pIndex
);
187 DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
188 5, test2
[Offset
].name0_4
,
189 6, test2
[Offset
].name5_10
,
190 2, test2
[Offset
].name11_12
);
193 vfat_movstr (Name
, 13, 0, cpos
* 13);
194 vfat_wcsncpy (Name
, test2
[Offset
].name0_4
, 5);
195 vfat_wcsncat (Name
, test2
[Offset
].name5_10
, 5, 6);
196 vfat_wcsncat (Name
, test2
[Offset
].name11_12
, 11, 2);
198 DPRINT (" longName: [%S]\n", Name
);
202 if (Offset
== ENTRIES_PER_PAGE
)
205 CcUnpinData(*pContext
);
206 FileOffset
.QuadPart
= *pIndex
* sizeof(FATDirEntry
);
207 if(!CcMapData(FileObject
, &FileOffset
, PAGE_SIZE
, TRUE
, pContext
, Block
))
210 return STATUS_NO_MORE_ENTRIES
;
212 test2
= (slot
*) *Block
;
213 test
= (FATDirEntry
*) *Block
;
218 if (vfatIsDirEntryEndMarker(&test
[Offset
]))
219 return STATUS_NO_MORE_ENTRIES
;
220 if (vfatIsDirEntryDeleted(&test
[Offset
]))
221 return STATUS_UNSUCCESSFUL
;
224 vfat8Dot3ToString (test
[Offset
].Filename
, test
[Offset
].Ext
, Name
);
231 return STATUS_SUCCESS
;
235 ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt
, PVPB Vpb
)
237 * FUNCTION: Read the volume label
240 PVOID Context
= NULL
;
245 LARGE_INTEGER FileOffset
;
247 *(Vpb
->VolumeLabel
) = 0;
248 Vpb
->VolumeLabelLength
= 0;
250 pFcb
= vfatOpenRootFCB (DeviceExt
);
254 if (Context
== NULL
|| Offset
== ENTRIES_PER_PAGE
)
256 if (Offset
== ENTRIES_PER_PAGE
)
262 CcUnpinData(Context
);
264 FileOffset
.u
.HighPart
= 0;
265 FileOffset
.u
.LowPart
= (DirIndex
- Offset
) * sizeof(FATDirEntry
);
266 if (!CcMapData(pFcb
->FileObject
, &FileOffset
, PAGE_SIZE
, TRUE
, &Context
, (PVOID
*)&Entry
))
272 if (IsVolEntry(Entry
, Offset
))
274 /* copy volume label */
275 vfat8Dot3ToVolumeLabel (Entry
[Offset
].Filename
, Entry
[Offset
].Ext
, Vpb
->VolumeLabel
);
276 Vpb
->VolumeLabelLength
= wcslen (Vpb
->VolumeLabel
) * sizeof(WCHAR
);
279 if (IsLastEntry(Entry
, Offset
))
289 CcUnpinData(Context
);
291 vfatReleaseFCB (DeviceExt
, pFcb
);
293 return STATUS_SUCCESS
;
297 FindFile (PDEVICE_EXTENSION DeviceExt
,
304 * FUNCTION: Find a file
318 LARGE_INTEGER FileOffset
;
319 PVOID Context
= NULL
;
321 DPRINT ("FindFile(Parent %x, FileToFind '%S', DirIndex: %d)\n", Parent
, FileToFind
, pDirIndex
? *pDirIndex
: 0);
322 DPRINT ("FindFile: old Pathname %x, old Objectname %x)\n",Fcb
->PathName
, Fcb
->ObjectName
);
326 if (wcslen (FileToFind
) == 0)
329 TempStr
[0] = (WCHAR
) '.';
331 FileToFind
= (PWSTR
)&TempStr
;
335 FirstCluster
= vfatDirEntryGetFirstCluster(DeviceExt
, &Parent
->entry
);
336 if (DeviceExt
->FatInfo
.FatType
== FAT32
)
338 if (FirstCluster
== DeviceExt
->FatInfo
.RootCluster
)
343 if (FirstCluster
== 1)
351 if (DeviceExt
->FatInfo
.FatType
== FAT32
)
352 FirstCluster
= DeviceExt
->FatInfo
.RootCluster
;
356 if (FileToFind
[0] == 0 || (FileToFind
[0] == '\\' && FileToFind
[1] == 0)
357 || (FileToFind
[0] == '.' && FileToFind
[1] == 0))
359 /* it's root : complete essentials fields then return ok */
361 memset (Fcb
, 0, sizeof (VFATFCB
));
362 memset (Fcb
->entry
.Filename
, ' ', 11);
364 Fcb
->PathName
[0]='\\';
365 Fcb
->ObjectName
= &Fcb
->PathName
[1];
366 Fcb
->entry
.FileSize
= DeviceExt
->FatInfo
.rootDirectorySectors
* DeviceExt
->FatInfo
.BytesPerSector
;
367 Fcb
->entry
.Attrib
= FILE_ATTRIBUTE_DIRECTORY
;
368 if (DeviceExt
->FatInfo
.FatType
== FAT32
)
370 Fcb
->entry
.FirstCluster
= ((PUSHORT
)FirstCluster
)[0];
371 Fcb
->entry
.FirstClusterHigh
= ((PUSHORT
)FirstCluster
)[1];
374 Fcb
->entry
.FirstCluster
= 1;
379 DPRINT("FindFile: new Pathname %S, new Objectname %S)\n",Fcb
->PathName
, Fcb
->ObjectName
);
380 return (STATUS_SUCCESS
);
385 DPRINT ("Parent->entry.FileSize %x\n", Parent
->entry
.FileSize
);
386 FirstCluster
= vfatDirEntryGetFirstCluster (DeviceExt
, &Parent
->entry
);
388 if (pDirIndex
&& (*pDirIndex
))
389 DirIndex
= *pDirIndex
;
391 Offset
= DirIndex
% ENTRIES_PER_PAGE
;
394 if (Context
== NULL
|| Offset
== ENTRIES_PER_PAGE
)
396 if (Offset
== ENTRIES_PER_PAGE
)
400 CcUnpinData(Context
);
402 FileOffset
.QuadPart
= (DirIndex
- Offset
) * sizeof(FATDirEntry
);
403 if (!CcMapData(Parent
->FileObject
, &FileOffset
, PAGE_SIZE
, TRUE
,
404 &Context
, (PVOID
*)&block
))
410 if (vfatIsDirEntryVolume(&((FATDirEntry
*)block
)[Offset
]))
416 Status
= GetEntryName (&Context
, (PVOID
*)&block
, Parent
->FileObject
, name
,
417 &DirIndex
, pDirIndex2
);
418 if (Status
== STATUS_NO_MORE_ENTRIES
)
420 Offset
= DirIndex
% ENTRIES_PER_PAGE
;
421 if (NT_SUCCESS(Status
))
423 vfat8Dot3ToString(((FATDirEntry
*) block
)[Offset
].Filename
,((FATDirEntry
*) block
)[Offset
].Ext
, name2
);
424 if (wstrcmpjoki (name
, FileToFind
) || wstrcmpjoki (name2
, FileToFind
))
426 if (Parent
&& Parent
->PathName
)
428 len
= wcslen(Parent
->PathName
);
430 memcpy(Fcb
->PathName
, Parent
->PathName
, len
*sizeof(WCHAR
));
431 Fcb
->ObjectName
=&Fcb
->PathName
[len
];
432 if (len
!= 1 || Fcb
->PathName
[0] != '\\')
434 Fcb
->ObjectName
[0] = '\\';
435 Fcb
->ObjectName
= &Fcb
->ObjectName
[1];
440 Fcb
->ObjectName
=Fcb
->PathName
;
441 Fcb
->ObjectName
[0]='\\';
442 Fcb
->ObjectName
=&Fcb
->ObjectName
[1];
445 memcpy (&Fcb
->entry
, &((FATDirEntry
*) block
)[Offset
],
446 sizeof (FATDirEntry
));
447 vfat_wcsncpy (Fcb
->ObjectName
, name
, MAX_PATH
);
449 *pDirIndex
= DirIndex
;
450 DPRINT("FindFile: new Pathname %S, new Objectname %S, DirIndex %d\n",Fcb
->PathName
, Fcb
->ObjectName
, DirIndex
);
452 CcUnpinData(Context
);
453 return STATUS_SUCCESS
;
460 *pDirIndex
= DirIndex
;
462 CcUnpinData(Context
);
463 return (STATUS_UNSUCCESSFUL
);
467 vfatMakeAbsoluteFilename (PFILE_OBJECT pFileObject
,
468 PWSTR pRelativeFileName
,
469 PWSTR
*pAbsoluteFilename
)
475 DPRINT ("try related for %S\n", pRelativeFileName
);
476 ccb
= pFileObject
->FsContext2
;
481 /* verify related object is a directory and target name
482 don't start with \. */
483 if (!(fcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
484 || (pRelativeFileName
[0] == L
'\\'))
486 return STATUS_INVALID_PARAMETER
;
489 /* construct absolute path name */
490 assert (wcslen (fcb
->PathName
) + 1 + wcslen (pRelativeFileName
) + 1
492 rcName
= ExAllocatePool (NonPagedPool
, MAX_PATH
* sizeof(WCHAR
));
495 return STATUS_INSUFFICIENT_RESOURCES
;
497 wcscpy (rcName
, fcb
->PathName
);
498 if (!vfatFCBIsRoot(fcb
))
499 wcscat (rcName
, L
"\\");
500 wcscat (rcName
, pRelativeFileName
);
501 *pAbsoluteFilename
= rcName
;
503 return STATUS_SUCCESS
;
507 VfatOpenFile (PDEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
,
510 * FUNCTION: Opens a file
516 PWSTR AbsFileName
= NULL
;
518 DPRINT ("VfatOpenFile(%08lx, %08lx, %S)\n", DeviceExt
, FileObject
, FileName
);
520 if (FileObject
->RelatedFileObject
)
522 DPRINT ("Converting relative filename to absolute filename\n");
523 Status
= vfatMakeAbsoluteFilename (FileObject
->RelatedFileObject
,
526 FileName
= AbsFileName
;
527 if (!NT_SUCCESS(Status
))
533 //FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
535 DPRINT ("PathName to open: %S\n", FileName
);
537 /* try first to find an existing FCB in memory */
538 DPRINT ("Checking for existing FCB in memory\n");
539 Fcb
= vfatGrabFCBFromTable (DeviceExt
, FileName
);
542 DPRINT ("No existing FCB found, making a new one if file exists.\n");
543 Status
= vfatGetFCBForFile (DeviceExt
, &ParentFcb
, &Fcb
, FileName
);
544 if (ParentFcb
!= NULL
)
546 vfatReleaseFCB (DeviceExt
, ParentFcb
);
548 if (!NT_SUCCESS (Status
))
550 DPRINT ("Could not make a new FCB, status: %x\n", Status
);
553 ExFreePool (AbsFileName
);
558 if (Fcb
->Flags
& FCB_DELETE_PENDING
)
560 vfatReleaseFCB (DeviceExt
, Fcb
);
562 ExFreePool (AbsFileName
);
563 return STATUS_DELETE_PENDING
;
565 DPRINT ("Attaching FCB to fileObject\n");
566 Status
= vfatAttachFCBToFileObject (DeviceExt
, Fcb
, FileObject
);
569 ExFreePool (AbsFileName
);
575 VfatPagingFileCreate(PDEVICE_EXTENSION DeviceExt
, PVFATFCB Fcb
)
577 ULONG CurrentCluster
, NextCluster
, i
;
580 Fcb
->Flags
|= FCB_IS_PAGE_FILE
;
582 ((Fcb
->entry
.FileSize
+ DeviceExt
->FatInfo
.BytesPerCluster
- 1) /
583 DeviceExt
->FatInfo
.BytesPerCluster
);
584 if (Fcb
->FatChainSize
)
587 ExAllocatePool(NonPagedPool
, Fcb
->FatChainSize
* sizeof(ULONG
));
590 if (DeviceExt
->FatInfo
.FatType
== FAT32
)
592 CurrentCluster
= Fcb
->entry
.FirstCluster
+
593 Fcb
->entry
.FirstClusterHigh
* 65536;
597 CurrentCluster
= Fcb
->entry
.FirstCluster
;
601 if (Fcb
->FatChainSize
)
603 while (CurrentCluster
!= 0xffffffff)
605 Fcb
->FatChain
[i
] = CurrentCluster
;
606 Status
= GetNextCluster (DeviceExt
, CurrentCluster
,
607 &NextCluster
, FALSE
);
609 CurrentCluster
= NextCluster
;
615 VfatSupersedeFile(PDEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
,
618 ULONG Cluster
, NextCluster
;
621 Fcb
->entry
.FileSize
= 0;
622 if (DeviceExt
->FatInfo
.FatType
== FAT32
)
624 Cluster
= Fcb
->entry
.FirstCluster
+ Fcb
->entry
.FirstClusterHigh
* 65536;
628 Cluster
= Fcb
->entry
.FirstCluster
;
630 Fcb
->entry
.FirstCluster
= 0;
631 Fcb
->entry
.FirstClusterHigh
= 0;
632 VfatUpdateEntry (DeviceExt
, FileObject
);
633 if (Fcb
->RFCB
.FileSize
.QuadPart
> 0)
635 Fcb
->RFCB
.AllocationSize
.QuadPart
= 0;
636 Fcb
->RFCB
.FileSize
.QuadPart
= 0;
637 Fcb
->RFCB
.ValidDataLength
.QuadPart
= 0;
638 CcSetFileSizes(FileObject
, (PCC_FILE_SIZES
)&Fcb
->RFCB
.AllocationSize
);
640 while (Cluster
!= 0xffffffff && Cluster
> 1)
642 Status
= GetNextCluster (DeviceExt
, Cluster
, &NextCluster
, FALSE
);
643 WriteCluster (DeviceExt
, Cluster
, 0);
644 Cluster
= NextCluster
;
649 VfatCreateFile (PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
651 * FUNCTION: Create or open a file
654 PIO_STACK_LOCATION Stack
;
655 PFILE_OBJECT FileObject
;
656 NTSTATUS Status
= STATUS_SUCCESS
;
657 PDEVICE_EXTENSION DeviceExt
;
658 ULONG RequestedDisposition
, RequestedOptions
;
662 BOOLEAN PagingFileCreate
= FALSE
;
664 /* Unpack the various parameters. */
665 Stack
= IoGetCurrentIrpStackLocation (Irp
);
666 RequestedDisposition
= ((Stack
->Parameters
.Create
.Options
>> 24) & 0xff);
668 Stack
->Parameters
.Create
.Options
& FILE_VALID_OPTION_FLAGS
;
669 PagingFileCreate
= (Stack
->Flags
& SL_OPEN_PAGING_FILE
) ? TRUE
: FALSE
;
670 FileObject
= Stack
->FileObject
;
671 DeviceExt
= DeviceObject
->DeviceExtension
;
673 /* Check their validity. */
674 if (RequestedOptions
& FILE_DIRECTORY_FILE
&&
675 RequestedDisposition
== FILE_SUPERSEDE
)
677 return(STATUS_INVALID_PARAMETER
);
680 /* This a open operation for the volume itself */
681 if (FileObject
->FileName
.Length
== 0 &&
682 FileObject
->RelatedFileObject
== NULL
)
684 if (RequestedDisposition
== FILE_CREATE
||
685 RequestedDisposition
== FILE_OVERWRITE_IF
||
686 RequestedDisposition
== FILE_SUPERSEDE
)
688 return(STATUS_ACCESS_DENIED
);
690 if (RequestedOptions
& FILE_DIRECTORY_FILE
)
692 return(STATUS_NOT_A_DIRECTORY
);
694 pFcb
= DeviceExt
->VolumeFcb
;
695 pCcb
= ExAllocatePoolWithTag (NonPagedPool
, sizeof (VFATCCB
), TAG_CCB
);
698 return (STATUS_INSUFFICIENT_RESOURCES
);
700 memset(pCcb
, 0, sizeof(VFATCCB
));
701 FileObject
->Flags
|= FO_FCB_IS_VALID
;
702 FileObject
->SectionObjectPointers
= &pFcb
->SectionObjectPointers
;
703 FileObject
->FsContext
= (PVOID
) &pFcb
->RFCB
;
704 FileObject
->FsContext2
= pCcb
;
706 pCcb
->PtrFileObject
= FileObject
;
707 pFcb
->pDevExt
= DeviceExt
;
710 Irp
->IoStatus
.Information
= FILE_OPENED
;
711 return(STATUS_SUCCESS
);
715 * Check for illegal characters in the file name
717 c
= FileObject
->FileName
.Buffer
;
720 if (*c
== L
'*' || *c
== L
'?' || (*c
== L
'\\' && c
[1] == L
'\\'))
722 return(STATUS_OBJECT_NAME_INVALID
);
727 /* Try opening the file. */
728 Status
= VfatOpenFile (DeviceExt
, FileObject
, FileObject
->FileName
.Buffer
);
731 * If the directory containing the file to open doesn't exist then
734 if (Status
== STATUS_OBJECT_PATH_NOT_FOUND
||
735 Status
== STATUS_INVALID_PARAMETER
||
736 Status
== STATUS_DELETE_PENDING
)
742 * If the file open failed then create the required file
744 if (!NT_SUCCESS (Status
))
746 if (RequestedDisposition
== FILE_CREATE
||
747 RequestedDisposition
== FILE_OPEN_IF
||
748 RequestedDisposition
== FILE_OVERWRITE_IF
||
749 RequestedDisposition
== FILE_SUPERSEDE
)
752 Attributes
= Stack
->Parameters
.Create
.FileAttributes
;
753 Status
= VfatAddEntry (DeviceExt
, FileObject
, RequestedOptions
,
754 Attributes
& FILE_ATTRIBUTE_VALID_FLAGS
);
755 if (NT_SUCCESS (Status
))
757 pCcb
= FileObject
->FsContext2
;
759 Irp
->IoStatus
.Information
= FILE_CREATED
;
760 VfatSetAllocationSizeInformation(FileObject
,
763 &Irp
->Overlay
.AllocationSize
);
764 VfatSetExtendedAttributes(FileObject
,
765 Irp
->AssociatedIrp
.SystemBuffer
,
766 Stack
->Parameters
.Create
.EaLength
);
767 IoSetShareAccess(0 /*DesiredAccess*/,
768 Stack
->Parameters
.Create
.ShareAccess
,
770 &pFcb
->FCBShareAccess
);
784 /* Otherwise fail if the caller wanted to create a new file */
785 if (RequestedDisposition
== FILE_CREATE
)
787 Irp
->IoStatus
.Information
= FILE_EXISTS
;
788 return(STATUS_OBJECT_NAME_COLLISION
);
791 pCcb
= FileObject
->FsContext2
;
795 * Check the file has the requested attributes
797 if (RequestedOptions
& FILE_NON_DIRECTORY_FILE
&&
798 pFcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
800 VfatCloseFile (DeviceExt
, FileObject
);
801 return(STATUS_FILE_IS_A_DIRECTORY
);
803 if (RequestedOptions
& FILE_DIRECTORY_FILE
&&
804 !(pFcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
))
806 VfatCloseFile (DeviceExt
, FileObject
);
807 return(STATUS_NOT_A_DIRECTORY
);
810 /* Supersede the file */
811 if (RequestedDisposition
== FILE_SUPERSEDE
)
813 VfatSupersedeFile(DeviceExt
, FileObject
, pFcb
);
814 Irp
->IoStatus
.Information
= FILE_SUPERSEDED
;
818 Irp
->IoStatus
.Information
= FILE_OPENED
;
823 * If this create was for a paging file then make sure all the
824 * information needed to manipulate it is locked in memory.
826 if (PagingFileCreate
)
828 VfatPagingFileCreate(DeviceExt
, pFcb
);
831 /* FIXME : test share access */
832 /* FIXME : test write access if requested */
838 NTSTATUS
VfatCreate (PVFAT_IRP_CONTEXT IrpContext
)
840 * FUNCTION: Create or open a file
847 if (IrpContext
->DeviceObject
== VfatGlobalData
->DeviceObject
)
849 /* DeviceObject represents FileSystem instead of logical volume */
850 DPRINT ("FsdCreate called with file system\n");
851 IrpContext
->Irp
->IoStatus
.Information
= FILE_OPENED
;
852 IrpContext
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
853 IoCompleteRequest (IrpContext
->Irp
, IO_DISK_INCREMENT
);
854 VfatFreeIrpContext(IrpContext
);
855 return(STATUS_SUCCESS
);
858 if (!(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
))
860 return(VfatQueueRequest (IrpContext
));
863 IrpContext
->Irp
->IoStatus
.Information
= 0;
864 ExAcquireResourceExclusiveLite (&IrpContext
->DeviceExt
->DirResource
, TRUE
);
865 Status
= VfatCreateFile (IrpContext
->DeviceObject
, IrpContext
->Irp
);
866 ExReleaseResourceLite (&IrpContext
->DeviceExt
->DirResource
);
868 IrpContext
->Irp
->IoStatus
.Status
= Status
;
869 IoCompleteRequest (IrpContext
->Irp
,
870 NT_SUCCESS(Status
) ? IO_DISK_INCREMENT
: IO_NO_INCREMENT
);
871 VfatFreeIrpContext(IrpContext
);