2 * PROJECT: ReactOS FAT file system driver
3 * LICENSE: GNU GPLv3 as published by the Free Software Foundation
4 * FILE: drivers/filesystems/fastfat/create.c
5 * PURPOSE: Create routines
6 * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
9 /* INCLUDES *****************************************************************/
14 /* FUNCTIONS *****************************************************************/
18 FatiOpenRootDcb(IN PFAT_IRP_CONTEXT IrpContext
,
19 IN PFILE_OBJECT FileObject
,
21 IN PACCESS_MASK DesiredAccess
,
22 IN USHORT ShareAccess
,
23 IN ULONG CreateDisposition
)
27 DPRINT1("Opening root directory\n");
29 Iosb
.Status
= STATUS_NOT_IMPLEMENTED
;
36 FatiTryToOpen(IN PFILE_OBJECT FileObject
,
40 CHAR AnsiNameBuf
[512];
45 /* Convert the name to ANSI */
46 AnsiName
.Buffer
= AnsiNameBuf
;
48 AnsiName
.MaximumLength
= sizeof(AnsiNameBuf
);
49 RtlZeroMemory(AnsiNameBuf
, sizeof(AnsiNameBuf
));
50 Status
= RtlUpcaseUnicodeStringToCountedOemString(&AnsiName
, &FileObject
->FileName
, FALSE
);
51 if (!NT_SUCCESS(Status
))
56 /* Open the file with FullFAT */
57 FileHandle
= FF_Open(Vcb
->Ioman
, AnsiName
.Buffer
, FF_MODE_READ
, &Error
);
59 /* Close the handle */
60 if (FileHandle
) FF_Close(FileHandle
);
68 FatiOpenExistingDir(IN PFAT_IRP_CONTEXT IrpContext
,
69 IN PFILE_OBJECT FileObject
,
72 IN PACCESS_MASK DesiredAccess
,
73 IN USHORT ShareAccess
,
74 IN ULONG AllocationSize
,
75 IN PFILE_FULL_EA_INFORMATION EaBuffer
,
77 IN UCHAR FileAttributes
,
78 IN ULONG CreateDisposition
,
79 IN BOOLEAN DeleteOnClose
)
81 IO_STATUS_BLOCK Iosb
= {{0}};
83 CHAR AnsiNameBuf
[512];
88 /* Only open is permitted */
89 if (CreateDisposition
!= FILE_OPEN
&&
90 CreateDisposition
!= FILE_OPEN_IF
)
92 Iosb
.Status
= STATUS_OBJECT_NAME_COLLISION
;
96 // TODO: Check dir access
98 /* Convert the name to ANSI */
99 AnsiName
.Buffer
= AnsiNameBuf
;
101 AnsiName
.MaximumLength
= sizeof(AnsiNameBuf
);
102 RtlZeroMemory(AnsiNameBuf
, sizeof(AnsiNameBuf
));
103 Status
= RtlUpcaseUnicodeStringToCountedOemString(&AnsiName
, &FileObject
->FileName
, FALSE
);
104 if (!NT_SUCCESS(Status
))
109 /* Open the dir with FullFAT */
110 FileHandle
= FF_Open(Vcb
->Ioman
, AnsiName
.Buffer
, FF_MODE_DIR
, NULL
);
114 Iosb
.Status
= STATUS_OBJECT_NAME_NOT_FOUND
; // FIXME: A shortcut for now
118 /* Create a new DCB for this directory */
119 Fcb
= FatCreateDcb(IrpContext
, Vcb
, ParentDcb
, FileHandle
);
121 /* Set share access */
122 IoSetShareAccess(*DesiredAccess
, ShareAccess
, FileObject
, &Fcb
->ShareAccess
);
124 /* Set context and section object pointers */
125 FatSetFileObject(FileObject
,
130 Iosb
.Status
= STATUS_SUCCESS
;
131 Iosb
.Information
= FILE_OPENED
;
133 DPRINT1("Successfully opened dir %s\n", AnsiNameBuf
);
140 FatiOpenExistingFile(IN PFAT_IRP_CONTEXT IrpContext
,
141 IN PFILE_OBJECT FileObject
,
144 IN PACCESS_MASK DesiredAccess
,
145 IN USHORT ShareAccess
,
146 IN ULONG AllocationSize
,
147 IN PFILE_FULL_EA_INFORMATION EaBuffer
,
149 IN UCHAR FileAttributes
,
150 IN ULONG CreateDisposition
,
151 IN BOOLEAN IsPagingFile
,
152 IN BOOLEAN DeleteOnClose
,
153 IN BOOLEAN IsDosName
)
155 IO_STATUS_BLOCK Iosb
= {{0}};
157 CHAR AnsiNameBuf
[512];
162 /* Check for create file option and fail */
163 if (CreateDisposition
== FILE_CREATE
)
165 Iosb
.Status
= STATUS_OBJECT_NAME_COLLISION
;
169 // TODO: Check more params
171 /* Convert the name to ANSI */
172 AnsiName
.Buffer
= AnsiNameBuf
;
174 AnsiName
.MaximumLength
= sizeof(AnsiNameBuf
);
175 RtlZeroMemory(AnsiNameBuf
, sizeof(AnsiNameBuf
));
176 Status
= RtlUpcaseUnicodeStringToCountedOemString(&AnsiName
, &FileObject
->FileName
, FALSE
);
177 if (!NT_SUCCESS(Status
))
182 /* Open the file with FullFAT */
183 FileHandle
= FF_Open(Vcb
->Ioman
, AnsiName
.Buffer
, FF_MODE_READ
, NULL
);
187 Iosb
.Status
= STATUS_OBJECT_NAME_NOT_FOUND
; // FIXME: A shortcut for now
191 /* Create a new FCB for this file */
192 Fcb
= FatCreateFcb(IrpContext
, Vcb
, ParentDcb
, FileHandle
);
194 // TODO: Check if overwrite is needed
196 // This is usual file open branch, without overwriting!
197 /* Set context and section object pointers */
198 FatSetFileObject(FileObject
,
202 FileObject
->SectionObjectPointer
= &Fcb
->SectionObjectPointers
;
204 Iosb
.Status
= STATUS_SUCCESS
;
205 Iosb
.Information
= FILE_OPENED
;
212 FatiOpenVolume(IN PFAT_IRP_CONTEXT IrpContext
,
213 IN PFILE_OBJECT FileObject
,
215 IN PACCESS_MASK DesiredAccess
,
216 IN USHORT ShareAccess
,
217 IN ULONG CreateDisposition
)
220 IO_STATUS_BLOCK Iosb
= {{0}};
221 BOOLEAN VolumeFlushed
= FALSE
;
223 /* Check parameters */
224 if (CreateDisposition
!= FILE_OPEN
&&
225 CreateDisposition
!= FILE_OPEN_IF
)
228 Iosb
.Status
= STATUS_ACCESS_DENIED
;
231 /* Check if it's exclusive open */
232 if (!FlagOn(ShareAccess
, FILE_SHARE_WRITE
) &&
233 !FlagOn(ShareAccess
, FILE_SHARE_DELETE
))
235 // TODO: Check if exclusive read access requested
236 // and opened handles count is not 0
237 //if (!FlagOn(ShareAccess, FILE_SHARE_READ)
239 DPRINT1("Exclusive voume open\n");
241 // TODO: Flush the volume
242 VolumeFlushed
= TRUE
;
244 else if (FlagOn(*DesiredAccess
, FILE_READ_DATA
| FILE_WRITE_DATA
| FILE_APPEND_DATA
))
246 DPRINT1("Shared open\n");
248 // TODO: Flush the volume
249 VolumeFlushed
= TRUE
;
253 !FlagOn(Vcb
->State
, VCB_STATE_MOUNTED_DIRTY
) &&
254 FlagOn(Vcb
->State
, VCB_STATE_FLAG_DIRTY
) &&
255 CcIsThereDirtyData(Vcb
->Vpb
))
260 /* Set share access */
261 if (Vcb
->DirectOpenCount
> 0)
263 /* This volume has already been opened */
264 Iosb
.Status
= IoCheckShareAccess(*DesiredAccess
,
270 if (!NT_SUCCESS(Iosb
.Status
))
277 /* This is the first time open */
278 IoSetShareAccess(*DesiredAccess
,
284 /* Set file object pointers */
285 Ccb
= FatCreateCcb(IrpContext
);
286 FatSetFileObject(FileObject
, UserVolumeOpen
, Vcb
, Ccb
);
287 FileObject
->SectionObjectPointer
= &Vcb
->SectionObjectPointers
;
289 /* Increase direct open count */
290 Vcb
->DirectOpenCount
++;
291 Vcb
->OpenFileCount
++;
293 /* Set no buffering flag */
294 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
296 // TODO: User's access check
298 Iosb
.Status
= STATUS_SUCCESS
;
299 Iosb
.Information
= FILE_OPENED
;
306 FatiCreate(IN PFAT_IRP_CONTEXT IrpContext
,
309 /* Boolean options */
310 BOOLEAN CreateDirectory
;
311 BOOLEAN SequentialOnly
;
312 BOOLEAN NoIntermediateBuffering
;
313 BOOLEAN OpenDirectory
;
314 BOOLEAN IsPagingFile
;
315 BOOLEAN OpenTargetDirectory
;
316 BOOLEAN DirectoryFile
;
317 BOOLEAN NonDirectoryFile
;
318 BOOLEAN NoEaKnowledge
;
319 BOOLEAN DeleteOnClose
;
320 BOOLEAN TemporaryFile
;
321 ULONG CreateDisposition
;
324 PVCB Vcb
, DecodedVcb
, RelatedVcb
;
325 PFCB Fcb
, NextFcb
, RelatedDcb
;
326 PCCB Ccb
, RelatedCcb
;
330 PFILE_OBJECT FileObject
;
331 PFILE_OBJECT RelatedFO
;
332 UNICODE_STRING FileName
;
333 ULONG AllocationSize
;
334 PFILE_FULL_EA_INFORMATION EaBuffer
;
335 PACCESS_MASK DesiredAccess
;
337 UCHAR FileAttributes
;
343 IO_STATUS_BLOCK Iosb
;
344 PIO_STACK_LOCATION IrpSp
;
345 BOOLEAN EndBackslash
= FALSE
, OpenedAsDos
;
346 UNICODE_STRING RemainingPart
, FirstName
, NextName
, FileNameUpcased
;
347 OEM_STRING AnsiFirstName
;
349 TYPE_OF_OPEN TypeOfOpen
;
350 BOOLEAN OplockPostIrp
= FALSE
;
352 Iosb
.Status
= STATUS_SUCCESS
;
354 /* Get current IRP stack location */
355 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
357 DPRINT("FatCommonCreate\n", 0 );
358 DPRINT("Irp = %08lx\n", Irp
);
359 DPRINT("\t->Flags = %08lx\n", Irp
->Flags
);
360 DPRINT("\t->FileObject = %08lx\n", IrpSp
->FileObject
);
361 DPRINT("\t->RelatedFileObject = %08lx\n", IrpSp
->FileObject
->RelatedFileObject
);
362 DPRINT("\t->FileName = %wZ\n", &IrpSp
->FileObject
->FileName
);
363 DPRINT("\t->AllocationSize.LowPart = %08lx\n", Irp
->Overlay
.AllocationSize
.LowPart
);
364 DPRINT("\t->AllocationSize.HighPart = %08lx\n", Irp
->Overlay
.AllocationSize
.HighPart
);
365 DPRINT("\t->SystemBuffer = %08lx\n", Irp
->AssociatedIrp
.SystemBuffer
);
366 DPRINT("\t->DesiredAccess = %08lx\n", IrpSp
->Parameters
.Create
.SecurityContext
->DesiredAccess
);
367 DPRINT("\t->Options = %08lx\n", IrpSp
->Parameters
.Create
.Options
);
368 DPRINT("\t->FileAttributes = %04x\n", IrpSp
->Parameters
.Create
.FileAttributes
);
369 DPRINT("\t->ShareAccess = %04x\n", IrpSp
->Parameters
.Create
.ShareAccess
);
370 DPRINT("\t->EaLength = %08lx\n", IrpSp
->Parameters
.Create
.EaLength
);
372 /* Apply a special hack for Win32, idea taken from FASTFAT reference driver from WDK */
373 if ((IrpSp
->FileObject
->FileName
.Length
> sizeof(WCHAR
)) &&
374 (IrpSp
->FileObject
->FileName
.Buffer
[1] == L
'\\') &&
375 (IrpSp
->FileObject
->FileName
.Buffer
[0] == L
'\\'))
377 /* Remove a leading slash */
378 IrpSp
->FileObject
->FileName
.Length
-= sizeof(WCHAR
);
379 RtlMoveMemory(&IrpSp
->FileObject
->FileName
.Buffer
[0],
380 &IrpSp
->FileObject
->FileName
.Buffer
[1],
381 IrpSp
->FileObject
->FileName
.Length
);
383 /* Check again: if there are still two leading slashes,
384 exit with an error */
385 if ((IrpSp
->FileObject
->FileName
.Length
> sizeof(WCHAR
)) &&
386 (IrpSp
->FileObject
->FileName
.Buffer
[1] == L
'\\') &&
387 (IrpSp
->FileObject
->FileName
.Buffer
[0] == L
'\\'))
389 FatCompleteRequest( IrpContext
, Irp
, STATUS_OBJECT_NAME_INVALID
);
391 DPRINT1("FatiCreate: STATUS_OBJECT_NAME_INVALID\n");
392 return STATUS_OBJECT_NAME_INVALID
;
396 /* Make sure we have SecurityContext */
397 ASSERT(IrpSp
->Parameters
.Create
.SecurityContext
!= NULL
);
399 /* Get necessary data out of IRP */
400 FileObject
= IrpSp
->FileObject
;
401 FileName
= FileObject
->FileName
;
402 RelatedFO
= FileObject
->RelatedFileObject
;
403 AllocationSize
= Irp
->Overlay
.AllocationSize
.LowPart
;
404 EaBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
405 DesiredAccess
= &IrpSp
->Parameters
.Create
.SecurityContext
->DesiredAccess
;
406 Options
= IrpSp
->Parameters
.Create
.Options
;
407 FileAttributes
= (UCHAR
)(IrpSp
->Parameters
.Create
.FileAttributes
& ~FILE_ATTRIBUTE_NORMAL
);
408 ShareAccess
= IrpSp
->Parameters
.Create
.ShareAccess
;
409 EaLength
= IrpSp
->Parameters
.Create
.EaLength
;
411 /* Set VPB to related object's VPB if it exists */
413 FileObject
->Vpb
= RelatedFO
->Vpb
;
415 /* Prepare file attributes mask */
416 FileAttributes
&= (FILE_ATTRIBUTE_READONLY
|
417 FILE_ATTRIBUTE_HIDDEN
|
418 FILE_ATTRIBUTE_SYSTEM
|
419 FILE_ATTRIBUTE_ARCHIVE
);
421 /* Get the volume control object */
422 Vcb
= &((PVOLUME_DEVICE_OBJECT
)IrpSp
->DeviceObject
)->Vcb
;
425 DirectoryFile
= BooleanFlagOn(Options
, FILE_DIRECTORY_FILE
);
426 NonDirectoryFile
= BooleanFlagOn(Options
, FILE_NON_DIRECTORY_FILE
);
427 SequentialOnly
= BooleanFlagOn(Options
, FILE_SEQUENTIAL_ONLY
);
428 NoIntermediateBuffering
= BooleanFlagOn(Options
, FILE_NO_INTERMEDIATE_BUFFERING
);
429 NoEaKnowledge
= BooleanFlagOn(Options
, FILE_NO_EA_KNOWLEDGE
);
430 DeleteOnClose
= BooleanFlagOn(Options
, FILE_DELETE_ON_CLOSE
);
431 TemporaryFile
= BooleanFlagOn(IrpSp
->Parameters
.Create
.FileAttributes
,
432 FILE_ATTRIBUTE_TEMPORARY
);
433 IsPagingFile
= BooleanFlagOn(IrpSp
->Flags
, SL_OPEN_PAGING_FILE
);
434 OpenTargetDirectory
= BooleanFlagOn(IrpSp
->Flags
, SL_OPEN_TARGET_DIRECTORY
);
436 /* Calculate create disposition */
437 CreateDisposition
= (Options
>> 24) & 0x000000ff;
439 /* Get Create/Open directory flags based on it */
440 CreateDirectory
= (BOOLEAN
)(DirectoryFile
&&
441 ((CreateDisposition
== FILE_CREATE
) ||
442 (CreateDisposition
== FILE_OPEN_IF
)));
444 OpenDirectory
= (BOOLEAN
)(DirectoryFile
&&
445 ((CreateDisposition
== FILE_OPEN
) ||
446 (CreateDisposition
== FILE_OPEN_IF
)));
448 /* Validate parameters: directory/nondirectory mismatch and
449 AllocationSize being more than 4GB */
450 if ((DirectoryFile
&& NonDirectoryFile
) ||
451 Irp
->Overlay
.AllocationSize
.HighPart
!= 0)
453 FatCompleteRequest(IrpContext
, Irp
, STATUS_INVALID_PARAMETER
);
455 DPRINT1("FatiCreate: STATUS_INVALID_PARAMETER\n", 0);
456 return STATUS_INVALID_PARAMETER
;
459 /* Acquire the VCB lock exclusively */
460 if (!FatAcquireExclusiveVcb(IrpContext
, Vcb
))
462 // TODO: Postpone the IRP for later processing
464 return STATUS_NOT_IMPLEMENTED
;
467 // TODO: Verify the VCB
469 /* If VCB is locked, then no file openings are possible */
470 if (Vcb
->State
& VCB_STATE_FLAG_LOCKED
)
472 DPRINT1("This volume is locked\n");
473 Status
= STATUS_ACCESS_DENIED
;
475 /* Cleanup and return */
476 FatReleaseVcb(IrpContext
, Vcb
);
480 // TODO: Check if the volume is write protected and disallow DELETE_ON_CLOSE
482 // TODO: Make sure EAs aren't supported on FAT32
484 /* Check if it's a volume open request */
485 if (FileName
.Length
== 0)
487 /* Test related FO to be sure */
489 FatDecodeFileObject(RelatedFO
, &DecodedVcb
, &Fcb
, &Ccb
) == UserVolumeOpen
)
491 /* Check parameters */
492 if (DirectoryFile
|| OpenTargetDirectory
)
494 Status
= DirectoryFile
? STATUS_NOT_A_DIRECTORY
: STATUS_INVALID_PARAMETER
;
497 FatReleaseVcb(IrpContext
, Vcb
);
499 /* Complete the request and return */
500 FatCompleteRequest(IrpContext
, Irp
, Status
);
504 /* It is indeed a volume open request */
505 Iosb
= FatiOpenVolume(IrpContext
,
512 /* Set resulting information */
513 Irp
->IoStatus
.Information
= Iosb
.Information
;
516 FatReleaseVcb(IrpContext
, Vcb
);
518 /* Complete the request and return */
519 FatCompleteRequest(IrpContext
, Irp
, Iosb
.Status
);
524 /* Check if this is a relative open */
527 /* Decode the file object */
528 TypeOfOpen
= FatDecodeFileObject(RelatedFO
,
533 /* Check open type */
534 if (TypeOfOpen
!= UserFileOpen
&&
535 TypeOfOpen
!= UserDirectoryOpen
)
537 DPRINT1("Invalid file object!\n");
539 /* Cleanup and return */
540 FatReleaseVcb(IrpContext
, Vcb
);
541 return STATUS_OBJECT_PATH_NOT_FOUND
;
544 /* File path must be relative */
545 if (FileName
.Length
!= 0 &&
546 FileName
.Buffer
[0] == L
'\\')
548 /* The name is absolute, fail */
549 FatReleaseVcb(IrpContext
, Vcb
);
550 return STATUS_OBJECT_NAME_INVALID
;
553 /* Make sure volume is the same */
554 ASSERT(RelatedVcb
== Vcb
);
557 FileObject
->Vpb
= RelatedFO
->Vpb
;
560 ParentDcb
= RelatedDcb
;
562 DPRINT1("Opening file '%wZ' relatively to '%wZ'\n", &FileName
, &ParentDcb
->FullFileName
);
567 if ((FileName
.Length
== sizeof(WCHAR
)) &&
568 (FileName
.Buffer
[0] == L
'\\'))
570 /* Check if it's ok to open it */
571 if (NonDirectoryFile
)
573 DPRINT1("Trying to open root dir as a file\n");
575 /* Cleanup and return */
576 FatReleaseVcb(IrpContext
, Vcb
);
577 return STATUS_FILE_IS_A_DIRECTORY
;
580 /* Check delete on close on a root dir */
583 /* Cleanup and return */
584 FatReleaseVcb(IrpContext
, Vcb
);
585 return STATUS_CANNOT_DELETE
;
588 /* Call root directory open routine */
589 Iosb
= FatiOpenRootDcb(IrpContext
,
596 Irp
->IoStatus
.Information
= Iosb
.Information
;
598 /* Cleanup and return */
599 FatReleaseVcb(IrpContext
, Vcb
);
605 ParentDcb
= Vcb
->RootDcb
;
606 DPRINT("ParentDcb %p\n", ParentDcb
);
610 /* Check for backslash at the end */
611 if (FileName
.Length
&&
612 FileName
.Buffer
[FileName
.Length
/ sizeof(WCHAR
) - 1] == L
'\\')
615 FileName
.Length
-= sizeof(WCHAR
);
617 /* Remember we cut it */
621 /* Ensure the name is set */
622 if (!ParentDcb
->FullFileName
.Buffer
)
624 /* Set it if it's missing */
625 FatSetFullFileNameInFcb(IrpContext
, ParentDcb
);
628 /* Check max path length */
629 if (ParentDcb
->FullFileName
.Length
+ FileName
.Length
+ sizeof(WCHAR
) <= FileName
.Length
)
631 DPRINT1("Max length is way off\n");
632 Iosb
.Status
= STATUS_OBJECT_NAME_INVALID
;
636 /* Loop through FCBs to find a good one */
641 /* Dissect the name */
642 RemainingPart
= FileName
;
643 while (RemainingPart
.Length
)
645 FsRtlDissectName(RemainingPart
, &FirstName
, &NextName
);
647 /* Check for validity */
648 if ((NextName
.Length
&& NextName
.Buffer
[0] == L
'\\') ||
649 (NextName
.Length
> 255 * sizeof(WCHAR
)))
651 /* The name is invalid */
652 DPRINT1("Invalid name found\n");
653 Iosb
.Status
= STATUS_OBJECT_NAME_INVALID
;
657 /* Convert the name to ANSI */
658 AnsiFirstName
.Buffer
= ExAllocatePool(PagedPool
, FirstName
.Length
);
659 AnsiFirstName
.Length
= 0;
660 AnsiFirstName
.MaximumLength
= FirstName
.Length
;
661 Status
= RtlUpcaseUnicodeStringToCountedOemString(&AnsiFirstName
, &FirstName
, FALSE
);
663 if (!NT_SUCCESS(Status
))
665 DPRINT1("RtlUpcaseUnicodeStringToCountedOemString() failed with 0x%08x\n", Status
);
668 AnsiFirstName
.Length
= 0;
672 /* Find the coresponding FCB */
673 NextFcb
= FatFindFcb(IrpContext
,
674 &Fcb
->Dcb
.SplayLinksAnsi
,
675 (PSTRING
)&AnsiFirstName
,
679 /* If nothing found - try with unicode */
680 if (!NextFcb
&& Fcb
->Dcb
.SplayLinksUnicode
)
682 FileNameUpcased
.Buffer
= FsRtlAllocatePool(PagedPool
, FirstName
.Length
);
683 FileNameUpcased
.Length
= 0;
684 FileNameUpcased
.MaximumLength
= FirstName
.Length
;
686 /* Downcase and then upcase to normalize it */
687 Status
= RtlDowncaseUnicodeString(&FileNameUpcased
, &FirstName
, FALSE
);
688 Status
= RtlUpcaseUnicodeString(&FileNameUpcased
, &FileNameUpcased
, FALSE
);
690 /* Try to find FCB again using unicode name */
691 NextFcb
= FatFindFcb(IrpContext
,
692 &Fcb
->Dcb
.SplayLinksUnicode
,
693 (PSTRING
)&FileNameUpcased
,
697 /* Move to the next FCB */
701 RemainingPart
= NextName
;
704 /* Break out of this loop if nothing can be found */
706 NextName
.Length
== 0 ||
707 FatNodeType(NextFcb
) == FAT_NTC_FCB
)
713 /* Ensure remaining name doesn't start from a backslash */
714 if (RemainingPart
.Length
&&
715 RemainingPart
.Buffer
[0] == L
'\\')
718 RemainingPart
.Buffer
++;
719 RemainingPart
.Length
-= sizeof(WCHAR
);
722 if (Fcb
->Condition
== FcbGood
)
724 /* Good FCB, break out of the loop */
733 /* We have a valid FCB now */
734 if (!RemainingPart
.Length
)
736 /* Check for target dir open */
737 if (OpenTargetDirectory
)
739 DPRINT1("Opening target dir is missing\n");
743 /* Check this FCB's type */
744 if (FatNodeType(Fcb
) == FAT_NTC_ROOT_DCB
||
745 FatNodeType(Fcb
) == FAT_NTC_DCB
)
747 /* Open a directory */
748 if (NonDirectoryFile
)
751 Iosb
.Status
= STATUS_FILE_IS_A_DIRECTORY
;
756 /* Open existing DCB */
757 Iosb
= FatiOpenExistingDcb(IrpContext
,
767 /* Save information */
768 Irp
->IoStatus
.Information
= Iosb
.Information
;
771 FatReleaseVcb(IrpContext
, Vcb
);
773 /* Complete the request */
774 FatCompleteRequest(IrpContext
, Irp
, Iosb
.Status
);
778 else if (FatNodeType(Fcb
) == FAT_NTC_FCB
)
784 Iosb
.Status
= STATUS_NOT_A_DIRECTORY
;
789 /* Check for trailing backslash */
793 Iosb
.Status
= STATUS_OBJECT_NAME_INVALID
;
798 Iosb
= FatiOpenExistingFcb(IrpContext
,
814 /* Check if it's pending */
815 if (Iosb
.Status
!= STATUS_PENDING
)
817 /* In case of success set cache supported flag */
818 if (NT_SUCCESS(Iosb
.Status
) && !NoIntermediateBuffering
)
820 SetFlag(FileObject
->Flags
, FO_CACHE_SUPPORTED
);
823 /* Save information */
824 Irp
->IoStatus
.Information
= Iosb
.Information
;
827 FatReleaseVcb(IrpContext
, Vcb
);
829 /* Complete the request */
830 FatCompleteRequest(IrpContext
, Irp
, Iosb
.Status
);
843 /* Unexpected FCB type */
844 KeBugCheckEx(/*FAT_FILE_SYSTEM*/0x23, __LINE__
, (ULONG_PTR
)Fcb
, 0, 0);
848 /* During parsing we encountered a part which has no attached FCB/DCB.
849 Check that the parent is really DCB and not FCB */
850 if (FatNodeType(Fcb
) != FAT_NTC_ROOT_DCB
&&
851 FatNodeType(Fcb
) != FAT_NTC_DCB
)
853 DPRINT1("Weird FCB node type %x, expected DCB or root DCB\n", FatNodeType(Fcb
));
857 /* Create additional DCBs for all path items */
861 FsRtlDissectName(RemainingPart
, &FirstName
, &RemainingPart
);
863 /* Check for validity */
864 if ((RemainingPart
.Length
&& RemainingPart
.Buffer
[0] == L
'\\') ||
865 (NextName
.Length
> 255 * sizeof(WCHAR
)))
867 /* The name is invalid */
868 DPRINT1("Invalid name found\n");
869 Iosb
.Status
= STATUS_OBJECT_NAME_INVALID
;
873 /* Convert the name to ANSI */
874 AnsiFirstName
.Buffer
= ExAllocatePool(PagedPool
, FirstName
.Length
);
875 AnsiFirstName
.Length
= 0;
876 AnsiFirstName
.MaximumLength
= FirstName
.Length
;
877 Status
= RtlUpcaseUnicodeStringToCountedOemString(&AnsiFirstName
, &FirstName
, FALSE
);
879 if (!NT_SUCCESS(Status
))
884 DPRINT("FirstName %wZ, RemainingPart %wZ\n", &FirstName
, &RemainingPart
);
886 /* Break if came to the end */
887 if (!RemainingPart
.Length
) break;
889 /* Create a DCB for this entry */
890 ParentDcb
= FatCreateDcb(IrpContext
,
896 FatSetFullNameInFcb(ParentDcb
, &FirstName
);
899 /* Try to open it and get a result, saying if this is a dir or a file */
900 FfError
= FatiTryToOpen(FileObject
, Vcb
);
902 /* Check if we need to open target directory */
903 if (OpenTargetDirectory
)
905 // TODO: Open target directory
909 /* Check, if path is a directory or a file */
910 if (FfError
== FF_ERR_FILE_OBJECT_IS_A_DIR
)
912 if (NonDirectoryFile
)
914 DPRINT1("Can't open dir as a file\n");
917 FatReleaseVcb(IrpContext
, Vcb
);
919 /* Complete the request */
920 Iosb
.Status
= STATUS_FILE_IS_A_DIRECTORY
;
921 FatCompleteRequest(IrpContext
, Irp
, Iosb
.Status
);
925 /* Open this directory */
926 Iosb
= FatiOpenExistingDir(IrpContext
,
939 Irp
->IoStatus
.Information
= Iosb
.Information
;
942 FatReleaseVcb(IrpContext
, Vcb
);
944 /* Complete the request */
945 FatCompleteRequest(IrpContext
, Irp
, Iosb
.Status
);
950 /* If end backslash here, then it's definately not permitted,
951 since we're opening files here */
955 FatReleaseVcb(IrpContext
, Vcb
);
957 /* Complete the request */
958 Iosb
.Status
= STATUS_OBJECT_NAME_INVALID
;
959 FatCompleteRequest(IrpContext
, Irp
, Iosb
.Status
);
963 /* Try to open the file */
964 Iosb
= FatiOpenExistingFile(IrpContext
,
979 Irp
->IoStatus
.Information
= Iosb
.Information
;
982 FatReleaseVcb(IrpContext
, Vcb
);
984 /* Complete the request */
985 FatCompleteRequest(IrpContext
, Irp
, Iosb
.Status
);
992 FatCreate(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
994 PFAT_IRP_CONTEXT IrpContext
;
997 /* If it's called with our Disk FS device object - it's always open */
998 // TODO: Add check for CDROM FS device object
999 if (DeviceObject
== FatGlobalData
.DiskDeviceObject
)
1001 /* Complete the request and return success */
1002 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1003 Irp
->IoStatus
.Information
= FILE_OPENED
;
1005 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
1007 return STATUS_SUCCESS
;
1010 /* Enter FsRtl critical region */
1011 FsRtlEnterFileSystem();
1013 /* Build an irp context */
1014 IrpContext
= FatBuildIrpContext(Irp
, TRUE
);
1016 /* Call internal function */
1017 Status
= FatiCreate(IrpContext
, Irp
);
1019 /* Leave FsRtl critical region */
1020 FsRtlExitFileSystem();