1 /* $Id: create.c,v 1.38 2002/02/08 02:57:09 chorns Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/fs/vfat/create.c
6 * PURPOSE: VFAT Filesystem
7 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
11 /* INCLUDES *****************************************************************/
13 #include <ddk/ntddk.h>
22 /* GLOBALS *******************************************************************/
24 #define ENTRIES_PER_PAGE (PAGESIZE / sizeof (FATDirEntry))
26 /* FUNCTIONS *****************************************************************/
29 IsLastEntry (PVOID Block
, ULONG Offset
)
31 * FUNCTION: Determine if the given directory entry is the last
34 return (((FATDirEntry
*) Block
)[Offset
].Filename
[0] == 0);
38 IsVolEntry (PVOID Block
, ULONG Offset
)
40 * FUNCTION: Determine if the given directory entry is a vol entry
43 if ((((FATDirEntry
*) Block
)[Offset
].Attrib
) == 0x28)
50 IsDeletedEntry (PVOID Block
, ULONG Offset
)
52 * FUNCTION: Determines if the given entry is a deleted one
55 /* Checks special character */
57 return ((((FATDirEntry
*) Block
)[Offset
].Filename
[0] == 0xe5) ||
58 (((FATDirEntry
*) Block
)[Offset
].Filename
[0] == 0));
61 void vfat8Dot3ToString (PCHAR pBasename
, PCHAR pExtension
, PWSTR pName
)
63 int fromIndex
, toIndex
;
65 fromIndex
= toIndex
= 0;
66 while (fromIndex
< 8 && pBasename
[fromIndex
] != ' ')
68 pName
[toIndex
++] = pBasename
[fromIndex
++];
70 if (pExtension
[0] != ' ')
72 pName
[toIndex
++] = L
'.';
74 while (fromIndex
< 3 && pExtension
[fromIndex
] != ' ')
76 pName
[toIndex
++] = pExtension
[fromIndex
++];
79 pName
[toIndex
] = L
'\0';
82 static void vfat8Dot3ToVolumeLabel (PCHAR pBasename
, PCHAR pExtension
, PWSTR pName
)
84 int fromIndex
, toIndex
;
86 fromIndex
= toIndex
= 0;
87 while (fromIndex
< 8 && pBasename
[fromIndex
] != ' ')
89 pName
[toIndex
++] = pBasename
[fromIndex
++];
91 if (pExtension
[0] != ' ')
94 while (fromIndex
< 3 && pBasename
[fromIndex
] != ' ')
96 pName
[toIndex
++] = pExtension
[fromIndex
++];
99 pName
[toIndex
] = L
'\0';
103 GetEntryName(PVOID
*pContext
,
105 PFILE_OBJECT FileObject
,
110 * FUNCTION: Retrieves the file name, be it in short or long file name format
117 ULONG Offset
= *pIndex
% ENTRIES_PER_PAGE
;
119 LARGE_INTEGER FileOffset
;
124 test
= (FATDirEntry
*) *Block
;
125 test2
= (slot
*) *Block
;
126 if (vfatIsDirEntryEndMarker(&test
[Offset
]))
128 return STATUS_NO_MORE_ENTRIES
;
130 if (test2
[Offset
].attr
== 0x0f && !vfatIsDirEntryDeleted(&test
[Offset
]))
134 *pIndex2
= *pIndex
; // start of dir entry
136 DPRINT (" long name entry found at %d\n", *pIndex
);
138 DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
139 5, test2
[Offset
].name0_4
,
140 6, test2
[Offset
].name5_10
,
141 2, test2
[Offset
].name11_12
);
143 vfat_initstr (Name
, 255);
144 vfat_wcsncpy (Name
, test2
[Offset
].name0_4
, 5);
145 vfat_wcsncat (Name
, test2
[Offset
].name5_10
, 5, 6);
146 vfat_wcsncat (Name
, test2
[Offset
].name11_12
, 11, 2);
148 DPRINT (" longName: [%S]\n", Name
);
150 while ((test2
[Offset
].id
!= 0x41) && (test2
[Offset
].id
!= 0x01) &&
151 (test2
[Offset
].attr
> 0))
156 if (Offset
== ENTRIES_PER_PAGE
)
159 CcUnpinData(*pContext
);
160 FileOffset
.QuadPart
= *pIndex
* sizeof(FATDirEntry
);
161 if(!CcMapData(FileObject
, &FileOffset
, PAGESIZE
, TRUE
, pContext
, Block
))
164 return STATUS_NO_MORE_ENTRIES
;
166 test2
= (slot
*) *Block
;
168 DPRINT (" long name entry found at %d\n", *pIndex
);
170 DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
171 5, test2
[Offset
].name0_4
,
172 6, test2
[Offset
].name5_10
,
173 2, test2
[Offset
].name11_12
);
176 vfat_movstr (Name
, 13, 0, cpos
* 13);
177 vfat_wcsncpy (Name
, test2
[Offset
].name0_4
, 5);
178 vfat_wcsncat (Name
, test2
[Offset
].name5_10
, 5, 6);
179 vfat_wcsncat (Name
, test2
[Offset
].name11_12
, 11, 2);
181 DPRINT (" longName: [%S]\n", Name
);
185 if (Offset
== ENTRIES_PER_PAGE
)
188 CcUnpinData(*pContext
);
189 FileOffset
.QuadPart
= *pIndex
* sizeof(FATDirEntry
);
190 if(!CcMapData(FileObject
, &FileOffset
, PAGESIZE
, TRUE
, pContext
, Block
))
193 return STATUS_NO_MORE_ENTRIES
;
195 test2
= (slot
*) *Block
;
196 test
= (FATDirEntry
*) *Block
;
201 if (vfatIsDirEntryEndMarker(&test
[Offset
]))
202 return STATUS_NO_MORE_ENTRIES
;
203 if (vfatIsDirEntryDeleted(&test
[Offset
]))
204 return STATUS_UNSUCCESSFUL
;
207 vfat8Dot3ToString (test
[Offset
].Filename
, test
[Offset
].Ext
, Name
);
214 return STATUS_SUCCESS
;
218 ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt
, PVPB Vpb
)
220 * FUNCTION: Read the volume label
227 ULONG StartingSector
;
231 Size
= DeviceExt
->rootDirectorySectors
; /* FIXME : in fat32, no limit */
232 StartingSector
= DeviceExt
->rootStart
;
235 block
= ExAllocatePool (NonPagedPool
, BLOCKSIZE
);
236 DPRINT ("ReadVolumeLabel : start at sector %lx, entry %ld\n", StartingSector
, i
);
237 for (j
= 0; j
< Size
; j
++)
239 /* FIXME: Check status */
240 Status
= VfatReadSectors (DeviceExt
->StorageDevice
, StartingSector
, 1, block
);
241 if (!NT_SUCCESS(Status
))
243 *(Vpb
->VolumeLabel
) = 0;
244 Vpb
->VolumeLabelLength
= 0;
249 for (i
= 0; i
< ENTRIES_PER_SECTOR
; i
++)
251 if (IsVolEntry ((PVOID
) block
, i
))
253 FATDirEntry
*test
= (FATDirEntry
*) block
;
255 /* copy volume label */
256 vfat8Dot3ToVolumeLabel (test
[i
].Filename
, test
[i
].Ext
, Vpb
->VolumeLabel
);
257 Vpb
->VolumeLabelLength
= wcslen (Vpb
->VolumeLabel
);
260 return (STATUS_SUCCESS
);
262 if (IsLastEntry ((PVOID
) block
, i
))
264 *(Vpb
->VolumeLabel
) = 0;
265 Vpb
->VolumeLabelLength
= 0;
267 return (STATUS_UNSUCCESSFUL
);
270 /* not found in this sector, try next : */
272 /* directory can be fragmented although it is best to keep them
276 if (DeviceExt
->FatType
== FAT32
)
278 if (StartingSector
== ClusterToSector (DeviceExt
, NextCluster
+ 1))
280 Status
= GetNextCluster (DeviceExt
, NextCluster
, &NextCluster
,
282 if (NextCluster
== 0 || NextCluster
== 0xffffffff)
284 *(Vpb
->VolumeLabel
) = 0;
285 Vpb
->VolumeLabelLength
= 0;
287 return (STATUS_UNSUCCESSFUL
);
289 StartingSector
= ClusterToSector (DeviceExt
, NextCluster
);
293 *(Vpb
->VolumeLabel
) = 0;
294 Vpb
->VolumeLabelLength
= 0;
296 return (STATUS_UNSUCCESSFUL
);
300 FindFile (PDEVICE_EXTENSION DeviceExt
,
307 * FUNCTION: Find a file
321 LARGE_INTEGER FileOffset
;
322 PVOID Context
= NULL
;
324 DPRINT ("FindFile(Parent %x, FileToFind '%S', DirIndex: %d)\n", Parent
, FileToFind
, pDirIndex
? *pDirIndex
: 0);
325 DPRINT ("FindFile: old Pathname %x, old Objectname %x)\n",Fcb
->PathName
, Fcb
->ObjectName
);
329 if (wcslen (FileToFind
) == 0)
332 TempStr
[0] = (WCHAR
) '.';
334 FileToFind
= (PWSTR
)&TempStr
;
338 FirstCluster
= vfatDirEntryGetFirstCluster(DeviceExt
, &Parent
->entry
);
339 if (DeviceExt
->FatType
== FAT32
)
341 if (FirstCluster
== ((struct _BootSector32
*)(DeviceExt
->Boot
))->RootCluster
)
346 if (FirstCluster
== 1)
354 if (DeviceExt
->FatType
== FAT32
)
355 FirstCluster
= ((struct _BootSector32
*)(DeviceExt
->Boot
))->RootCluster
;
359 if (FileToFind
[0] == 0 || (FileToFind
[0] == '\\' && FileToFind
[1] == 0)
360 || (FileToFind
[0] == '.' && FileToFind
[1] == 0))
362 /* it's root : complete essentials fields then return ok */
364 memset (Fcb
, 0, sizeof (VFATFCB
));
365 memset (Fcb
->entry
.Filename
, ' ', 11);
367 Fcb
->PathName
[0]='\\';
368 Fcb
->ObjectName
= &Fcb
->PathName
[1];
369 Fcb
->entry
.FileSize
= DeviceExt
->rootDirectorySectors
* BLOCKSIZE
;
370 Fcb
->entry
.Attrib
= FILE_ATTRIBUTE_DIRECTORY
;
371 if (DeviceExt
->FatType
== FAT32
)
373 Fcb
->entry
.FirstCluster
= ((PUSHORT
)FirstCluster
)[0];
374 Fcb
->entry
.FirstClusterHigh
= ((PUSHORT
)FirstCluster
)[1];
377 Fcb
->entry
.FirstCluster
= 1;
382 DPRINT("FindFile: new Pathname %S, new Objectname %S)\n",Fcb
->PathName
, Fcb
->ObjectName
);
383 return (STATUS_SUCCESS
);
388 DPRINT ("Parent->entry.FileSize %x\n", Parent
->entry
.FileSize
);
389 FirstCluster
= vfatDirEntryGetFirstCluster (DeviceExt
, &Parent
->entry
);
391 if (pDirIndex
&& (*pDirIndex
))
392 DirIndex
= *pDirIndex
;
394 Offset
= DirIndex
% ENTRIES_PER_PAGE
;
397 if (Context
== NULL
|| Offset
== ENTRIES_PER_PAGE
)
399 if (Offset
== ENTRIES_PER_PAGE
)
403 CcUnpinData(Context
);
405 FileOffset
.QuadPart
= (DirIndex
- Offset
) * sizeof(FATDirEntry
);
406 if (!CcMapData(Parent
->FileObject
, &FileOffset
, PAGESIZE
, TRUE
,
407 &Context
, (PVOID
*)&block
))
413 if (vfatIsDirEntryVolume(&((FATDirEntry
*)block
)[Offset
]))
419 Status
= GetEntryName (&Context
, (PVOID
*)&block
, Parent
->FileObject
, name
,
420 &DirIndex
, pDirIndex2
);
421 if (Status
== STATUS_NO_MORE_ENTRIES
)
423 Offset
= DirIndex
% ENTRIES_PER_PAGE
;
424 if (NT_SUCCESS(Status
))
426 vfat8Dot3ToString(((FATDirEntry
*) block
)[Offset
].Filename
,((FATDirEntry
*) block
)[Offset
].Ext
, name2
);
427 if (wstrcmpjoki (name
, FileToFind
) || wstrcmpjoki (name2
, FileToFind
))
429 if (Parent
&& Parent
->PathName
)
431 len
= wcslen(Parent
->PathName
);
433 memcpy(Fcb
->PathName
, Parent
->PathName
, len
*sizeof(WCHAR
));
434 Fcb
->ObjectName
=&Fcb
->PathName
[len
];
435 if (len
!= 1 || Fcb
->PathName
[0] != '\\')
437 Fcb
->ObjectName
[0] = '\\';
438 Fcb
->ObjectName
= &Fcb
->ObjectName
[1];
443 Fcb
->ObjectName
=Fcb
->PathName
;
444 Fcb
->ObjectName
[0]='\\';
445 Fcb
->ObjectName
=&Fcb
->ObjectName
[1];
448 memcpy (&Fcb
->entry
, &((FATDirEntry
*) block
)[Offset
],
449 sizeof (FATDirEntry
));
450 vfat_wcsncpy (Fcb
->ObjectName
, name
, MAX_PATH
);
452 *pDirIndex
= DirIndex
;
453 DPRINT("FindFile: new Pathname %S, new Objectname %S, DirIndex %d\n",Fcb
->PathName
, Fcb
->ObjectName
, DirIndex
);
455 CcUnpinData(Context
);
456 return STATUS_SUCCESS
;
463 *pDirIndex
= DirIndex
;
465 CcUnpinData(Context
);
466 return (STATUS_UNSUCCESSFUL
);
470 vfatMakeAbsoluteFilename (PFILE_OBJECT pFileObject
,
471 PWSTR pRelativeFileName
,
472 PWSTR
*pAbsoluteFilename
)
478 DPRINT ("try related for %S\n", pRelativeFileName
);
479 ccb
= pFileObject
->FsContext2
;
484 /* verify related object is a directory and target name
485 don't start with \. */
486 if (!(fcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
487 || (pRelativeFileName
[0] == L
'\\'))
489 return STATUS_INVALID_PARAMETER
;
492 /* construct absolute path name */
493 assert (wcslen (fcb
->PathName
) + 1 + wcslen (pRelativeFileName
) + 1
495 rcName
= ExAllocatePool (NonPagedPool
, MAX_PATH
* sizeof(WCHAR
));
498 return STATUS_INSUFFICIENT_RESOURCES
;
500 wcscpy (rcName
, fcb
->PathName
);
501 if (!vfatFCBIsRoot(fcb
))
502 wcscat (rcName
, L
"\\");
503 wcscat (rcName
, pRelativeFileName
);
504 *pAbsoluteFilename
= rcName
;
506 return STATUS_SUCCESS
;
510 VfatOpenFile (PDEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
,
513 * FUNCTION: Opens a file
519 PWSTR AbsFileName
= NULL
;
521 DPRINT ("VfatOpenFile(%08lx, %08lx, %S)\n", DeviceExt
, FileObject
, FileName
);
523 if (FileObject
->RelatedFileObject
)
525 DPRINT ("Converting relative filename to absolute filename\n");
526 Status
= vfatMakeAbsoluteFilename (FileObject
->RelatedFileObject
,
529 FileName
= AbsFileName
;
530 if (!NT_SUCCESS(Status
))
536 //FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
538 DPRINT ("PathName to open: %S\n", FileName
);
540 /* try first to find an existing FCB in memory */
541 DPRINT ("Checking for existing FCB in memory\n");
542 Fcb
= vfatGrabFCBFromTable (DeviceExt
, FileName
);
545 DPRINT ("No existing FCB found, making a new one if file exists.\n");
546 Status
= vfatGetFCBForFile (DeviceExt
, &ParentFcb
, &Fcb
, FileName
);
547 if (ParentFcb
!= NULL
)
549 vfatReleaseFCB (DeviceExt
, ParentFcb
);
551 if (!NT_SUCCESS (Status
))
553 DPRINT ("Could not make a new FCB, status: %x\n", Status
);
556 ExFreePool (AbsFileName
);
561 if (Fcb
->Flags
& FCB_DELETE_PENDING
)
563 vfatReleaseFCB (DeviceExt
, Fcb
);
565 ExFreePool (AbsFileName
);
566 return STATUS_DELETE_PENDING
;
568 DPRINT ("Attaching FCB to fileObject\n");
569 Status
= vfatAttachFCBToFileObject (DeviceExt
, Fcb
, FileObject
);
572 ExFreePool (AbsFileName
);
578 VfatCreateFile (PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
580 * FUNCTION: Create or open a file
583 PIO_STACK_LOCATION Stack
;
584 PFILE_OBJECT FileObject
;
585 NTSTATUS Status
= STATUS_SUCCESS
;
586 PDEVICE_EXTENSION DeviceExt
;
587 ULONG RequestedDisposition
, RequestedOptions
;
591 BOOLEAN PagingFileCreate
= FALSE
;
593 Stack
= IoGetCurrentIrpStackLocation (Irp
);
595 RequestedDisposition
= ((Stack
->Parameters
.Create
.Options
>> 24) & 0xff);
597 Stack
->Parameters
.Create
.Options
& FILE_VALID_OPTION_FLAGS
;
598 PagingFileCreate
= (Stack
->Flags
& SL_OPEN_PAGING_FILE
) ? TRUE
: FALSE
;
599 if ((RequestedOptions
& FILE_DIRECTORY_FILE
)
600 && RequestedDisposition
== FILE_SUPERSEDE
)
601 return STATUS_INVALID_PARAMETER
;
602 FileObject
= Stack
->FileObject
;
603 DeviceExt
= DeviceObject
->DeviceExtension
;
607 * Check for illegal characters in the file name
609 c
= FileObject
->FileName
.Buffer
;
612 if (*c
== L
'*' || *c
== L
'?' || (*c
== L
'\\' && c
[1] == L
'\\'))
614 Irp
->IoStatus
.Information
= 0;
615 Irp
->IoStatus
.Status
= STATUS_OBJECT_NAME_INVALID
;
616 return(STATUS_OBJECT_NAME_INVALID
);
621 Status
= VfatOpenFile (DeviceExt
, FileObject
, FileObject
->FileName
.Buffer
);
624 * If the directory containing the file to open doesn't exist then
627 Irp
->IoStatus
.Information
= 0;
628 if (Status
== STATUS_OBJECT_PATH_NOT_FOUND
)
630 Irp
->IoStatus
.Status
= Status
;
634 if (Status
== STATUS_DELETE_PENDING
)
636 Irp
->IoStatus
.Status
= Status
;
639 if (!NT_SUCCESS (Status
))
642 * If the file open failed then create the required file
644 if (RequestedDisposition
== FILE_CREATE
||
645 RequestedDisposition
== FILE_OPEN_IF
||
646 RequestedDisposition
== FILE_OVERWRITE_IF
||
647 RequestedDisposition
== FILE_SUPERSEDE
)
651 addEntry (DeviceExt
, FileObject
, RequestedOptions
,
653 Create
.FileAttributes
& FILE_ATTRIBUTE_VALID_FLAGS
));
654 if (NT_SUCCESS (Status
))
656 if (PagingFileCreate
)
658 DPRINT("Creating a new paging file.\n");
659 pCcb
= FileObject
->FsContext2
;
661 pFcb
->Flags
|= FCB_IS_PAGE_FILE
;
662 pFcb
->FatChainSize
= 0;
663 pFcb
->FatChain
= NULL
;
666 Irp
->IoStatus
.Information
= FILE_CREATED
;
668 /* FIXME set size if AllocationSize requested */
669 /* FIXME set extended attributes? */
670 /* FIXME set share access */
671 /* IoSetShareAccess(DesiredAccess,ShareAccess,FileObject,
672 * ((PVfatCCB)(FileObject->FsContext2))->pFcb->FCBShareAccess);
679 * Otherwise fail if the caller wanted to create a new file
681 if (RequestedDisposition
== FILE_CREATE
)
683 Irp
->IoStatus
.Information
= FILE_EXISTS
;
684 Status
= STATUS_OBJECT_NAME_COLLISION
;
686 pCcb
= FileObject
->FsContext2
;
689 * If requested then delete the file and create a new one with the
692 if (RequestedDisposition
== FILE_SUPERSEDE
)
694 ULONG Cluster
, NextCluster
;
695 /* FIXME set size to 0 and free clusters */
696 pFcb
->entry
.FileSize
= 0;
697 if (DeviceExt
->FatType
== FAT32
)
698 Cluster
= pFcb
->entry
.FirstCluster
699 + pFcb
->entry
.FirstClusterHigh
* 65536;
701 Cluster
= pFcb
->entry
.FirstCluster
;
702 pFcb
->entry
.FirstCluster
= 0;
703 pFcb
->entry
.FirstClusterHigh
= 0;
704 updEntry (DeviceExt
, FileObject
);
705 if ((ULONG
)pFcb
->RFCB
.FileSize
.QuadPart
> 0)
707 pFcb
->RFCB
.AllocationSize
.QuadPart
= 0;
708 pFcb
->RFCB
.FileSize
.QuadPart
= 0;
709 pFcb
->RFCB
.ValidDataLength
.QuadPart
= 0;
710 CcSetFileSizes(FileObject
, (PCC_FILE_SIZES
)&pFcb
->RFCB
.AllocationSize
);
712 while (Cluster
!= 0xffffffff && Cluster
> 1)
714 Status
= GetNextCluster (DeviceExt
, Cluster
, &NextCluster
, FALSE
);
715 WriteCluster (DeviceExt
, Cluster
, 0);
716 Cluster
= NextCluster
;
721 * If this create was for a paging file then make sure all the
722 * information needed to manipulate it is locked in memory.
724 if (PagingFileCreate
)
726 ULONG CurrentCluster
, NextCluster
, i
;
727 DPRINT("Open an existing paging file\n");
728 pFcb
->Flags
|= FCB_IS_PAGE_FILE
;
730 ((pFcb
->entry
.FileSize
+ DeviceExt
->BytesPerCluster
- 1) / DeviceExt
->BytesPerCluster
);
731 if (pFcb
->FatChainSize
)
733 pFcb
->FatChain
= ExAllocatePool(NonPagedPool
,
734 pFcb
->FatChainSize
* sizeof(ULONG
));
737 if (DeviceExt
->FatType
== FAT32
)
739 CurrentCluster
= pFcb
->entry
.FirstCluster
+
740 pFcb
->entry
.FirstClusterHigh
* 65536;
744 CurrentCluster
= pFcb
->entry
.FirstCluster
;
748 if (pFcb
->FatChainSize
)
750 while (CurrentCluster
!= 0xffffffff)
752 pFcb
->FatChain
[i
] = CurrentCluster
;
753 Status
= GetNextCluster (DeviceExt
, CurrentCluster
, &NextCluster
,
756 CurrentCluster
= NextCluster
;
762 * Check the file has the requested attributes
764 if ((RequestedOptions
& FILE_NON_DIRECTORY_FILE
)
765 && (pFcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
))
767 Status
= STATUS_FILE_IS_A_DIRECTORY
;
769 if ((RequestedOptions
& FILE_DIRECTORY_FILE
)
770 && !(pFcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
))
772 Status
= STATUS_NOT_A_DIRECTORY
;
774 /* FIXME : test share access */
775 /* FIXME : test write access if requested */
776 if (!NT_SUCCESS (Status
))
777 VfatCloseFile (DeviceExt
, FileObject
);
779 Irp
->IoStatus
.Information
= FILE_OPENED
;
780 /* FIXME : make supersed or overwrite if requested */
783 Irp
->IoStatus
.Status
= Status
;
789 NTSTATUS
VfatCreate (PVFAT_IRP_CONTEXT IrpContext
)
791 * FUNCTION: Create or open a file
798 if (IrpContext
->DeviceObject
->Size
== sizeof (DEVICE_OBJECT
))
800 /* DeviceObject represents FileSystem instead of logical volume */
801 DPRINT ("FsdCreate called with file system\n");
802 IrpContext
->Irp
->IoStatus
.Information
= FILE_OPENED
;
803 Status
= STATUS_SUCCESS
;
807 if (!(IrpContext
->Flags
& IRPCONTEXT_CANWAIT
))
809 return VfatQueueRequest (IrpContext
);
812 ExAcquireResourceExclusiveLite (&IrpContext
->DeviceExt
->DirResource
, TRUE
);
813 Status
= VfatCreateFile (IrpContext
->DeviceObject
, IrpContext
->Irp
);
814 ExReleaseResourceLite (&IrpContext
->DeviceExt
->DirResource
);
817 IrpContext
->Irp
->IoStatus
.Status
= Status
;
818 IoCompleteRequest (IrpContext
->Irp
, NT_SUCCESS(Status
) ? IO_DISK_INCREMENT
: IO_NO_INCREMENT
);
819 VfatFreeIrpContext(IrpContext
);