123b7c7b8SHermès Bélusca-Maïto /*++
223b7c7b8SHermès Bélusca-Maïto 
323b7c7b8SHermès Bélusca-Maïto Copyright (c) 1989-2000 Microsoft Corporation
423b7c7b8SHermès Bélusca-Maïto 
523b7c7b8SHermès Bélusca-Maïto Module Name:
623b7c7b8SHermès Bélusca-Maïto 
723b7c7b8SHermès Bélusca-Maïto     Create.c
823b7c7b8SHermès Bélusca-Maïto 
923b7c7b8SHermès Bélusca-Maïto Abstract:
1023b7c7b8SHermès Bélusca-Maïto 
1123b7c7b8SHermès Bélusca-Maïto     This module implements the File Create routine for Fat called by the
1223b7c7b8SHermès Bélusca-Maïto     dispatch driver.
1323b7c7b8SHermès Bélusca-Maïto 
1423b7c7b8SHermès Bélusca-Maïto 
1523b7c7b8SHermès Bélusca-Maïto --*/
1623b7c7b8SHermès Bélusca-Maïto 
1723b7c7b8SHermès Bélusca-Maïto #include "fatprocs.h"
1823b7c7b8SHermès Bélusca-Maïto 
1923b7c7b8SHermès Bélusca-Maïto //
2023b7c7b8SHermès Bélusca-Maïto //  The Bug check file id for this module
2123b7c7b8SHermès Bélusca-Maïto //
2223b7c7b8SHermès Bélusca-Maïto 
2323b7c7b8SHermès Bélusca-Maïto #define BugCheckFileId                   (FAT_BUG_CHECK_CREATE)
2423b7c7b8SHermès Bélusca-Maïto 
2523b7c7b8SHermès Bélusca-Maïto //
2623b7c7b8SHermès Bélusca-Maïto //  The debug trace level
2723b7c7b8SHermès Bélusca-Maïto //
2823b7c7b8SHermès Bélusca-Maïto 
2923b7c7b8SHermès Bélusca-Maïto #define Dbg                              (DEBUG_TRACE_CREATE)
3023b7c7b8SHermès Bélusca-Maïto 
3123b7c7b8SHermès Bélusca-Maïto 
3223b7c7b8SHermès Bélusca-Maïto //
3323b7c7b8SHermès Bélusca-Maïto //  Macros for incrementing performance counters.
3423b7c7b8SHermès Bélusca-Maïto //
3523b7c7b8SHermès Bélusca-Maïto 
3623b7c7b8SHermès Bélusca-Maïto #define CollectCreateHitStatistics(VCB) {                                                \
3723b7c7b8SHermès Bélusca-Maïto     PFILE_SYSTEM_STATISTICS Stats = &(VCB)->Statistics[KeGetCurrentProcessorNumber() % FatData.NumberProcessors];   \
3823b7c7b8SHermès Bélusca-Maïto     Stats->Fat.CreateHits += 1;                                                          \
3923b7c7b8SHermès Bélusca-Maïto }
4023b7c7b8SHermès Bélusca-Maïto 
4123b7c7b8SHermès Bélusca-Maïto #define CollectCreateStatistics(VCB,STATUS) {                                            \
4223b7c7b8SHermès Bélusca-Maïto     PFILE_SYSTEM_STATISTICS Stats = &(VCB)->Statistics[KeGetCurrentProcessorNumber() % FatData.NumberProcessors];   \
4323b7c7b8SHermès Bélusca-Maïto     if ((STATUS) == STATUS_SUCCESS) {                                                    \
4423b7c7b8SHermès Bélusca-Maïto         Stats->Fat.SuccessfulCreates += 1;                                               \
4523b7c7b8SHermès Bélusca-Maïto     } else {                                                                             \
4623b7c7b8SHermès Bélusca-Maïto         Stats->Fat.FailedCreates += 1;                                                   \
4723b7c7b8SHermès Bélusca-Maïto     }                                                                                    \
4823b7c7b8SHermès Bélusca-Maïto }
4923b7c7b8SHermès Bélusca-Maïto 
5023b7c7b8SHermès Bélusca-Maïto LUID FatSecurityPrivilege = { SE_SECURITY_PRIVILEGE, 0 };
5123b7c7b8SHermès Bélusca-Maïto 
5223b7c7b8SHermès Bélusca-Maïto //
5323b7c7b8SHermès Bélusca-Maïto //  local procedure prototypes
5423b7c7b8SHermès Bélusca-Maïto //
5523b7c7b8SHermès Bélusca-Maïto 
5623b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
5723b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
5823b7c7b8SHermès Bélusca-Maïto FatOpenVolume (
5923b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
6023b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
6123b7c7b8SHermès Bélusca-Maïto     _Inout_ PVCB Vcb,
6223b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
6323b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
6423b7c7b8SHermès Bélusca-Maïto     _In_ ULONG CreateDisposition
6523b7c7b8SHermès Bélusca-Maïto     );
6623b7c7b8SHermès Bélusca-Maïto 
6723b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
6823b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
6923b7c7b8SHermès Bélusca-Maïto FatOpenRootDcb (
7023b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
7123b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
7223b7c7b8SHermès Bélusca-Maïto     _Inout_ PVCB Vcb,
7323b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
7423b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
7523b7c7b8SHermès Bélusca-Maïto     _In_ ULONG CreateDisposition
7623b7c7b8SHermès Bélusca-Maïto     );
7723b7c7b8SHermès Bélusca-Maïto 
7823b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
7923b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
8023b7c7b8SHermès Bélusca-Maïto FatOpenExistingDcb (
8123b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
8223b7c7b8SHermès Bélusca-Maïto     _In_ PIO_STACK_LOCATION IrpSp,
8323b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
8423b7c7b8SHermès Bélusca-Maïto     _Inout_ PVCB Vcb,
8523b7c7b8SHermès Bélusca-Maïto     _Inout_ PDCB Dcb,
8623b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
8723b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
8823b7c7b8SHermès Bélusca-Maïto     _In_ ULONG CreateDisposition,
8923b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN NoEaKnowledge,
9023b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN DeleteOnClose,
9123b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN OpenRequiringOplock,
9223b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN FileNameOpenedDos,
9323b7c7b8SHermès Bélusca-Maïto     _Out_ PBOOLEAN OplockPostIrp
9423b7c7b8SHermès Bélusca-Maïto     );
9523b7c7b8SHermès Bélusca-Maïto 
9623b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
9723b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
9823b7c7b8SHermès Bélusca-Maïto FatOpenExistingFcb (
9923b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
10023b7c7b8SHermès Bélusca-Maïto     _In_ PIO_STACK_LOCATION IrpSp,
10123b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
10223b7c7b8SHermès Bélusca-Maïto     _Inout_ PVCB Vcb,
10323b7c7b8SHermès Bélusca-Maïto     _Inout_ PFCB Fcb,
10423b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
10523b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
10623b7c7b8SHermès Bélusca-Maïto     _In_ ULONG AllocationSize,
10723b7c7b8SHermès Bélusca-Maïto     _In_ PFILE_FULL_EA_INFORMATION EaBuffer,
10823b7c7b8SHermès Bélusca-Maïto     _In_ ULONG EaLength,
10923b7c7b8SHermès Bélusca-Maïto     _In_ USHORT FileAttributes,
11023b7c7b8SHermès Bélusca-Maïto     _In_ ULONG CreateDisposition,
11123b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN NoEaKnowledge,
11223b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN DeleteOnClose,
11323b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN OpenRequiringOplock,
11423b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN FileNameOpenedDos,
11523b7c7b8SHermès Bélusca-Maïto     _Out_ PBOOLEAN OplockPostIrp
11623b7c7b8SHermès Bélusca-Maïto     );
11723b7c7b8SHermès Bélusca-Maïto 
11823b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
11923b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
12023b7c7b8SHermès Bélusca-Maïto FatOpenTargetDirectory (
12123b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
12223b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
12323b7c7b8SHermès Bélusca-Maïto     _Inout_ PDCB Dcb,
12423b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
12523b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
12623b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN DoesNameExist,
12723b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN FileNameOpenedDos
12823b7c7b8SHermès Bélusca-Maïto     );
12923b7c7b8SHermès Bélusca-Maïto 
13023b7c7b8SHermès Bélusca-Maïto _Success_(return.Status == STATUS_SUCCESS)
13123b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
13223b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
13323b7c7b8SHermès Bélusca-Maïto FatOpenExistingDirectory (
13423b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
13523b7c7b8SHermès Bélusca-Maïto     _In_ PIO_STACK_LOCATION IrpSp,
13623b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
13723b7c7b8SHermès Bélusca-Maïto     _Inout_ PVCB Vcb,
13823b7c7b8SHermès Bélusca-Maïto     _Outptr_result_maybenull_ PDCB *Dcb,
13923b7c7b8SHermès Bélusca-Maïto     _In_ PDCB ParentDcb,
14023b7c7b8SHermès Bélusca-Maïto     _In_ PDIRENT Dirent,
14123b7c7b8SHermès Bélusca-Maïto     _In_ ULONG LfnByteOffset,
14223b7c7b8SHermès Bélusca-Maïto     _In_ ULONG DirentByteOffset,
14323b7c7b8SHermès Bélusca-Maïto     _In_ PUNICODE_STRING Lfn,
14423b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
14523b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
14623b7c7b8SHermès Bélusca-Maïto     _In_ ULONG CreateDisposition,
14723b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN NoEaKnowledge,
14823b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN DeleteOnClose,
14923b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN FileNameOpenedDos,
15023b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN OpenRequiringOplock
15123b7c7b8SHermès Bélusca-Maïto     );
15223b7c7b8SHermès Bélusca-Maïto 
15323b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
15423b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
15523b7c7b8SHermès Bélusca-Maïto FatOpenExistingFile (
15623b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
15723b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
15823b7c7b8SHermès Bélusca-Maïto     _Inout_ PVCB Vcb,
15923b7c7b8SHermès Bélusca-Maïto     _Outptr_result_maybenull_ PFCB *Fcb,
16023b7c7b8SHermès Bélusca-Maïto     _In_ PDCB ParentDcb,
16123b7c7b8SHermès Bélusca-Maïto     _In_ PDIRENT Dirent,
16223b7c7b8SHermès Bélusca-Maïto     _In_ ULONG LfnByteOffset,
16323b7c7b8SHermès Bélusca-Maïto     _In_ ULONG DirentByteOffset,
16423b7c7b8SHermès Bélusca-Maïto     _In_ PUNICODE_STRING Lfn,
16523b7c7b8SHermès Bélusca-Maïto     _In_ PUNICODE_STRING OrigLfn,
16623b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
16723b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
16823b7c7b8SHermès Bélusca-Maïto     _In_ ULONG AllocationSize,
16923b7c7b8SHermès Bélusca-Maïto     _In_ PFILE_FULL_EA_INFORMATION EaBuffer,
17023b7c7b8SHermès Bélusca-Maïto     _In_ ULONG EaLength,
17123b7c7b8SHermès Bélusca-Maïto     _In_ USHORT FileAttributes,
17223b7c7b8SHermès Bélusca-Maïto     _In_ ULONG CreateDisposition,
17323b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN IsPagingFile,
17423b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN NoEaKnowledge,
17523b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN DeleteOnClose,
17623b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN OpenRequiringOplock,
17723b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN FileNameOpenedDos
17823b7c7b8SHermès Bélusca-Maïto     );
17923b7c7b8SHermès Bélusca-Maïto 
18023b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
18123b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
18223b7c7b8SHermès Bélusca-Maïto FatCreateNewDirectory (
18323b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
18423b7c7b8SHermès Bélusca-Maïto     _In_ PIO_STACK_LOCATION IrpSp,
18523b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
18623b7c7b8SHermès Bélusca-Maïto     _Inout_ PVCB Vcb,
18723b7c7b8SHermès Bélusca-Maïto     _Inout_ PDCB ParentDcb,
18823b7c7b8SHermès Bélusca-Maïto     _In_ POEM_STRING OemName,
18923b7c7b8SHermès Bélusca-Maïto     _In_ PUNICODE_STRING UnicodeName,
19023b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
19123b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
19223b7c7b8SHermès Bélusca-Maïto     _In_ PFILE_FULL_EA_INFORMATION EaBuffer,
19323b7c7b8SHermès Bélusca-Maïto     _In_ ULONG EaLength,
19423b7c7b8SHermès Bélusca-Maïto     _In_ USHORT FileAttributes,
19523b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN NoEaKnowledge,
19623b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN DeleteOnClose,
19723b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN OpenRequiringOplock
19823b7c7b8SHermès Bélusca-Maïto     );
19923b7c7b8SHermès Bélusca-Maïto 
20023b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
20123b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
20223b7c7b8SHermès Bélusca-Maïto FatCreateNewFile (
20323b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
20423b7c7b8SHermès Bélusca-Maïto     _In_ PIO_STACK_LOCATION IrpSp,
20523b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
20623b7c7b8SHermès Bélusca-Maïto     _Inout_ PVCB Vcb,
20723b7c7b8SHermès Bélusca-Maïto     _Inout_ PDCB ParentDcb,
20823b7c7b8SHermès Bélusca-Maïto     _In_ POEM_STRING OemName,
20923b7c7b8SHermès Bélusca-Maïto     _In_ PUNICODE_STRING UnicodeName,
21023b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
21123b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
21223b7c7b8SHermès Bélusca-Maïto     _In_ ULONG AllocationSize,
21323b7c7b8SHermès Bélusca-Maïto     _In_ PFILE_FULL_EA_INFORMATION EaBuffer,
21423b7c7b8SHermès Bélusca-Maïto     _In_ ULONG EaLength,
21523b7c7b8SHermès Bélusca-Maïto     _In_ USHORT FileAttributes,
21623b7c7b8SHermès Bélusca-Maïto     _In_ PUNICODE_STRING LfnBuffer,
21723b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN IsPagingFile,
21823b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN NoEaKnowledge,
21923b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN DeleteOnClose,
22023b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN OpenRequiringOplock,
22123b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN TemporaryFile
22223b7c7b8SHermès Bélusca-Maïto     );
22323b7c7b8SHermès Bélusca-Maïto 
22423b7c7b8SHermès Bélusca-Maïto 
22523b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
22623b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
22723b7c7b8SHermès Bélusca-Maïto FatSupersedeOrOverwriteFile (
22823b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
22923b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
23023b7c7b8SHermès Bélusca-Maïto     _Inout_ PFCB Fcb,
23123b7c7b8SHermès Bélusca-Maïto     _In_ ULONG AllocationSize,
23223b7c7b8SHermès Bélusca-Maïto     _In_ PFILE_FULL_EA_INFORMATION EaBuffer,
23323b7c7b8SHermès Bélusca-Maïto     _In_ ULONG EaLength,
23423b7c7b8SHermès Bélusca-Maïto     _In_ USHORT FileAttributes,
23523b7c7b8SHermès Bélusca-Maïto     _In_ ULONG CreateDisposition,
23623b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN NoEaKnowledge
23723b7c7b8SHermès Bélusca-Maïto     );
23823b7c7b8SHermès Bélusca-Maïto 
23923b7c7b8SHermès Bélusca-Maïto NTSTATUS
24023b7c7b8SHermès Bélusca-Maïto FatCheckSystemSecurityAccess (
24123b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext
24223b7c7b8SHermès Bélusca-Maïto     );
24323b7c7b8SHermès Bélusca-Maïto 
24423b7c7b8SHermès Bélusca-Maïto NTSTATUS
24523b7c7b8SHermès Bélusca-Maïto FatCheckShareAccess (
24623b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
24723b7c7b8SHermès Bélusca-Maïto     _In_ PFILE_OBJECT FileObject,
24823b7c7b8SHermès Bélusca-Maïto     _In_ PFCB Fcb,
24923b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
25023b7c7b8SHermès Bélusca-Maïto     _In_ ULONG ShareAccess
25123b7c7b8SHermès Bélusca-Maïto     );
25223b7c7b8SHermès Bélusca-Maïto 
25323b7c7b8SHermès Bélusca-Maïto #ifdef ALLOC_PRAGMA
25423b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatCheckShareAccess)
25523b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatCheckSystemSecurityAccess)
25623b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatCommonCreate)
25723b7c7b8SHermès Bélusca-Maïto 
25823b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
25923b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatCommonCreateOnNewStack)
26023b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatCommonCreateCallout)
26123b7c7b8SHermès Bélusca-Maïto #endif
26223b7c7b8SHermès Bélusca-Maïto 
26323b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatCreateNewDirectory)
26423b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatCreateNewFile)
26523b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatFsdCreate)
26623b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatOpenExistingDcb)
26723b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatOpenExistingDirectory)
26823b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatOpenExistingFcb)
26923b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatOpenExistingFile)
27023b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatOpenRootDcb)
27123b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatOpenTargetDirectory)
27223b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatOpenVolume)
27323b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatSupersedeOrOverwriteFile)
27423b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatSetFullNameInFcb)
27523b7c7b8SHermès Bélusca-Maïto #endif
27623b7c7b8SHermès Bélusca-Maïto 
27723b7c7b8SHermès Bélusca-Maïto 
27823b7c7b8SHermès Bélusca-Maïto _Function_class_(IRP_MJ_CREATE)
_Function_class_(DRIVER_DISPATCH)27923b7c7b8SHermès Bélusca-Maïto _Function_class_(DRIVER_DISPATCH)
28023b7c7b8SHermès Bélusca-Maïto NTSTATUS
28123b7c7b8SHermès Bélusca-Maïto NTAPI
28223b7c7b8SHermès Bélusca-Maïto FatFsdCreate (
28323b7c7b8SHermès Bélusca-Maïto     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
28423b7c7b8SHermès Bélusca-Maïto     _Inout_ PIRP Irp
28523b7c7b8SHermès Bélusca-Maïto     )
28623b7c7b8SHermès Bélusca-Maïto 
28723b7c7b8SHermès Bélusca-Maïto /*++
28823b7c7b8SHermès Bélusca-Maïto 
28923b7c7b8SHermès Bélusca-Maïto Routine Description:
29023b7c7b8SHermès Bélusca-Maïto 
29123b7c7b8SHermès Bélusca-Maïto     This routine implements the FSD part of the NtCreateFile and NtOpenFile
29223b7c7b8SHermès Bélusca-Maïto     API calls.
29323b7c7b8SHermès Bélusca-Maïto 
29423b7c7b8SHermès Bélusca-Maïto Arguments:
29523b7c7b8SHermès Bélusca-Maïto 
29623b7c7b8SHermès Bélusca-Maïto     VolumeDeviceObject - Supplies the volume device object where the
29723b7c7b8SHermès Bélusca-Maïto         file/directory exists that we are trying to open/create
29823b7c7b8SHermès Bélusca-Maïto 
29923b7c7b8SHermès Bélusca-Maïto     Irp - Supplies the Irp being processed
30023b7c7b8SHermès Bélusca-Maïto 
30123b7c7b8SHermès Bélusca-Maïto Return Value:
30223b7c7b8SHermès Bélusca-Maïto 
30323b7c7b8SHermès Bélusca-Maïto     NTSTATUS - The Fsd status for the Irp
30423b7c7b8SHermès Bélusca-Maïto 
30523b7c7b8SHermès Bélusca-Maïto --*/
30623b7c7b8SHermès Bélusca-Maïto 
30723b7c7b8SHermès Bélusca-Maïto {
30823b7c7b8SHermès Bélusca-Maïto     NTSTATUS Status;
30923b7c7b8SHermès Bélusca-Maïto     PIRP_CONTEXT IrpContext = NULL;
31023b7c7b8SHermès Bélusca-Maïto 
31123b7c7b8SHermès Bélusca-Maïto     BOOLEAN TopLevel;
31223b7c7b8SHermès Bélusca-Maïto     BOOLEAN ExceptionCompletedIrp = FALSE;
31323b7c7b8SHermès Bélusca-Maïto 
31423b7c7b8SHermès Bélusca-Maïto 
31523b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
31623b7c7b8SHermès Bélusca-Maïto 
31723b7c7b8SHermès Bélusca-Maïto     //
31823b7c7b8SHermès Bélusca-Maïto     //  If we were called with our file system device object instead of a
31923b7c7b8SHermès Bélusca-Maïto     //  volume device object, just complete this request with STATUS_SUCCESS
32023b7c7b8SHermès Bélusca-Maïto     //
32123b7c7b8SHermès Bélusca-Maïto 
32223b7c7b8SHermès Bélusca-Maïto     if ( FatDeviceIsFatFsdo( VolumeDeviceObject))  {
32323b7c7b8SHermès Bélusca-Maïto 
32423b7c7b8SHermès Bélusca-Maïto         Irp->IoStatus.Status = STATUS_SUCCESS;
32523b7c7b8SHermès Bélusca-Maïto         Irp->IoStatus.Information = FILE_OPENED;
32623b7c7b8SHermès Bélusca-Maïto 
32723b7c7b8SHermès Bélusca-Maïto         IoCompleteRequest( Irp, IO_DISK_INCREMENT );
32823b7c7b8SHermès Bélusca-Maïto 
32923b7c7b8SHermès Bélusca-Maïto         return STATUS_SUCCESS;
33023b7c7b8SHermès Bélusca-Maïto     }
33123b7c7b8SHermès Bélusca-Maïto 
33223b7c7b8SHermès Bélusca-Maïto     TimerStart(Dbg);
33323b7c7b8SHermès Bélusca-Maïto 
33423b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatFsdCreate\n", 0);
33523b7c7b8SHermès Bélusca-Maïto 
33623b7c7b8SHermès Bélusca-Maïto     //
33723b7c7b8SHermès Bélusca-Maïto     //  Call the common create routine, with block allowed if the operation
33823b7c7b8SHermès Bélusca-Maïto     //  is synchronous.
33923b7c7b8SHermès Bélusca-Maïto     //
34023b7c7b8SHermès Bélusca-Maïto 
34123b7c7b8SHermès Bélusca-Maïto     FsRtlEnterFileSystem();
34223b7c7b8SHermès Bélusca-Maïto 
34323b7c7b8SHermès Bélusca-Maïto     TopLevel = FatIsIrpTopLevel( Irp );
34423b7c7b8SHermès Bélusca-Maïto 
34523b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
34623b7c7b8SHermès Bélusca-Maïto 
34723b7c7b8SHermès Bélusca-Maïto         IrpContext = FatCreateIrpContext( Irp, TRUE );
34823b7c7b8SHermès Bélusca-Maïto 
34923b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
35023b7c7b8SHermès Bélusca-Maïto         Status = FatCommonCreateOnNewStack( IrpContext, Irp );
35123b7c7b8SHermès Bélusca-Maïto #else
35223b7c7b8SHermès Bélusca-Maïto         Status = FatCommonCreate( IrpContext, Irp );
35323b7c7b8SHermès Bélusca-Maïto #endif
35423b7c7b8SHermès Bélusca-Maïto 
35523b7c7b8SHermès Bélusca-Maïto     } _SEH2_EXCEPT(FatExceptionFilter( IrpContext, _SEH2_GetExceptionInformation() )) {
35623b7c7b8SHermès Bélusca-Maïto 
35723b7c7b8SHermès Bélusca-Maïto         //
35823b7c7b8SHermès Bélusca-Maïto         //  We had some trouble trying to perform the requested
35923b7c7b8SHermès Bélusca-Maïto         //  operation, so we'll abort the I/O request with
36023b7c7b8SHermès Bélusca-Maïto         //  the error status that we get back from the
36123b7c7b8SHermès Bélusca-Maïto         //  execption code
36223b7c7b8SHermès Bélusca-Maïto         //
36323b7c7b8SHermès Bélusca-Maïto 
36423b7c7b8SHermès Bélusca-Maïto         Status = FatProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
36523b7c7b8SHermès Bélusca-Maïto         ExceptionCompletedIrp = TRUE;
36623b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
36723b7c7b8SHermès Bélusca-Maïto 
36823b7c7b8SHermès Bélusca-Maïto     if (TopLevel) { IoSetTopLevelIrp( NULL ); }
36923b7c7b8SHermès Bélusca-Maïto 
37023b7c7b8SHermès Bélusca-Maïto     FsRtlExitFileSystem();
37123b7c7b8SHermès Bélusca-Maïto 
37223b7c7b8SHermès Bélusca-Maïto 
37323b7c7b8SHermès Bélusca-Maïto     //
37423b7c7b8SHermès Bélusca-Maïto     //  Complete the request, unless we had an exception, in which case it
37523b7c7b8SHermès Bélusca-Maïto     //  was completed in FatProcessException (and the IrpContext freed).
37623b7c7b8SHermès Bélusca-Maïto     //
37723b7c7b8SHermès Bélusca-Maïto     //  IrpContext is freed inside FatCompleteRequest.
37823b7c7b8SHermès Bélusca-Maïto     //
37923b7c7b8SHermès Bélusca-Maïto 
38023b7c7b8SHermès Bélusca-Maïto     if (!ExceptionCompletedIrp && Status != STATUS_PENDING) {
38123b7c7b8SHermès Bélusca-Maïto         FatCompleteRequest( IrpContext, Irp, Status );
38223b7c7b8SHermès Bélusca-Maïto     }
38323b7c7b8SHermès Bélusca-Maïto 
38423b7c7b8SHermès Bélusca-Maïto     //
38523b7c7b8SHermès Bélusca-Maïto     //  And return to our caller
38623b7c7b8SHermès Bélusca-Maïto     //
38723b7c7b8SHermès Bélusca-Maïto 
38823b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatFsdCreate -> %08lx\n", Status );
38923b7c7b8SHermès Bélusca-Maïto 
39023b7c7b8SHermès Bélusca-Maïto     TimerStop(Dbg,"FatFsdCreate");
39123b7c7b8SHermès Bélusca-Maïto 
39223b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( VolumeDeviceObject );
39323b7c7b8SHermès Bélusca-Maïto 
39423b7c7b8SHermès Bélusca-Maïto     return Status;
39523b7c7b8SHermès Bélusca-Maïto }
39623b7c7b8SHermès Bélusca-Maïto 
39723b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
_Requires_lock_held_(_Global_critical_region_)39823b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
39923b7c7b8SHermès Bélusca-Maïto VOID
40023b7c7b8SHermès Bélusca-Maïto FatCommonCreateCallout (
40123b7c7b8SHermès Bélusca-Maïto     _In_ PFAT_CALLOUT_PARAMETERS CalloutParameters
40223b7c7b8SHermès Bélusca-Maïto     )
40323b7c7b8SHermès Bélusca-Maïto 
40423b7c7b8SHermès Bélusca-Maïto /*++
40523b7c7b8SHermès Bélusca-Maïto 
40623b7c7b8SHermès Bélusca-Maïto Routine Description:
40723b7c7b8SHermès Bélusca-Maïto 
40823b7c7b8SHermès Bélusca-Maïto     This function is the callout routine that will execute on a new stack when
40923b7c7b8SHermès Bélusca-Maïto     processing a create.  It simply calls FatCommonCreate() with the parameters
41023b7c7b8SHermès Bélusca-Maïto     in the context and stores the return value in the context.
41123b7c7b8SHermès Bélusca-Maïto 
41223b7c7b8SHermès Bélusca-Maïto Arguments:
41323b7c7b8SHermès Bélusca-Maïto 
41423b7c7b8SHermès Bélusca-Maïto     Context - Supplies an opaque pointer to this function's context.  It is actually
41523b7c7b8SHermès Bélusca-Maïto               an FAT_CALLOUT_PARAMETERS structure.
41623b7c7b8SHermès Bélusca-Maïto 
41723b7c7b8SHermès Bélusca-Maïto Return Value:
41823b7c7b8SHermès Bélusca-Maïto 
41923b7c7b8SHermès Bélusca-Maïto     None.
42023b7c7b8SHermès Bélusca-Maïto 
42123b7c7b8SHermès Bélusca-Maïto --*/
42223b7c7b8SHermès Bélusca-Maïto 
42323b7c7b8SHermès Bélusca-Maïto {
42423b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
42523b7c7b8SHermès Bélusca-Maïto 
42623b7c7b8SHermès Bélusca-Maïto     //
42723b7c7b8SHermès Bélusca-Maïto     //  Call FatCommonCreate() with the passed parameters and store the result.
42823b7c7b8SHermès Bélusca-Maïto     //  Exceptions cannot be raised across stack boundaries, so we need to catch
42923b7c7b8SHermès Bélusca-Maïto     //  exceptions here and deal with them.
43023b7c7b8SHermès Bélusca-Maïto     //
43123b7c7b8SHermès Bélusca-Maïto 
43223b7c7b8SHermès Bélusca-Maïto     try {
43323b7c7b8SHermès Bélusca-Maïto 
43423b7c7b8SHermès Bélusca-Maïto         CalloutParameters->IrpStatus = FatCommonCreate( CalloutParameters->Create.IrpContext,
43523b7c7b8SHermès Bélusca-Maïto                                                         CalloutParameters->Create.Irp );
43623b7c7b8SHermès Bélusca-Maïto 
43723b7c7b8SHermès Bélusca-Maïto     } except (FatExceptionFilter( CalloutParameters->Create.IrpContext, GetExceptionInformation() )) {
43823b7c7b8SHermès Bélusca-Maïto 
43923b7c7b8SHermès Bélusca-Maïto         //
44023b7c7b8SHermès Bélusca-Maïto         //  Return the resulting status.
44123b7c7b8SHermès Bélusca-Maïto         //
44223b7c7b8SHermès Bélusca-Maïto 
44323b7c7b8SHermès Bélusca-Maïto         CalloutParameters->ExceptionStatus = GetExceptionCode();
44423b7c7b8SHermès Bélusca-Maïto     }
44523b7c7b8SHermès Bélusca-Maïto 
44623b7c7b8SHermès Bélusca-Maïto }
44723b7c7b8SHermès Bélusca-Maïto 
44823b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)44923b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
45023b7c7b8SHermès Bélusca-Maïto NTSTATUS
45123b7c7b8SHermès Bélusca-Maïto FatCommonCreateOnNewStack (
45223b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
45323b7c7b8SHermès Bélusca-Maïto     _In_ PIRP Irp
45423b7c7b8SHermès Bélusca-Maïto     )
45523b7c7b8SHermès Bélusca-Maïto 
45623b7c7b8SHermès Bélusca-Maïto /*++
45723b7c7b8SHermès Bélusca-Maïto 
45823b7c7b8SHermès Bélusca-Maïto Routine Description:
45923b7c7b8SHermès Bélusca-Maïto 
46023b7c7b8SHermès Bélusca-Maïto     This routine sets up a switch to a new stack and call to FatCommonCreate().
46123b7c7b8SHermès Bélusca-Maïto 
46223b7c7b8SHermès Bélusca-Maïto Arguments:
46323b7c7b8SHermès Bélusca-Maïto 
46423b7c7b8SHermès Bélusca-Maïto     IrpContext - Supplies the context structure for the overall request.
46523b7c7b8SHermès Bélusca-Maïto 
46623b7c7b8SHermès Bélusca-Maïto     Irp - Supplies the IRP being processed.
46723b7c7b8SHermès Bélusca-Maïto 
46823b7c7b8SHermès Bélusca-Maïto     CreateContext - Supplies a pointer on the old stack that is used to
46923b7c7b8SHermès Bélusca-Maïto                     store context information for the create itself.
47023b7c7b8SHermès Bélusca-Maïto 
47123b7c7b8SHermès Bélusca-Maïto Return Value:
47223b7c7b8SHermès Bélusca-Maïto 
47323b7c7b8SHermès Bélusca-Maïto     NTSTATUS - The status from FatCommonCreate().
47423b7c7b8SHermès Bélusca-Maïto 
47523b7c7b8SHermès Bélusca-Maïto --*/
47623b7c7b8SHermès Bélusca-Maïto {
47723b7c7b8SHermès Bélusca-Maïto     FAT_CALLOUT_PARAMETERS CalloutParameters;
47823b7c7b8SHermès Bélusca-Maïto     NTSTATUS status;
47923b7c7b8SHermès Bélusca-Maïto 
48023b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
48123b7c7b8SHermès Bélusca-Maïto 
48223b7c7b8SHermès Bélusca-Maïto     //
48323b7c7b8SHermès Bélusca-Maïto     //  Create requests consume a lot of stack space.  As such, we always switch to a
48423b7c7b8SHermès Bélusca-Maïto     //  new stack when processing a create.  Setup the callout parameters and make the
48523b7c7b8SHermès Bélusca-Maïto     //  call.  Note that this cannot fail, since we pass a stack context for a reserve stack.
48623b7c7b8SHermès Bélusca-Maïto     //
48723b7c7b8SHermès Bélusca-Maïto 
48823b7c7b8SHermès Bélusca-Maïto     CalloutParameters.Create.IrpContext = IrpContext;
48923b7c7b8SHermès Bélusca-Maïto     CalloutParameters.Create.Irp = Irp;
49023b7c7b8SHermès Bélusca-Maïto     CalloutParameters.ExceptionStatus = CalloutParameters.IrpStatus = STATUS_SUCCESS;
49123b7c7b8SHermès Bélusca-Maïto 
49223b7c7b8SHermès Bélusca-Maïto     //
49323b7c7b8SHermès Bélusca-Maïto     //  Mark that we are swapping the stack
49423b7c7b8SHermès Bélusca-Maïto     //
49523b7c7b8SHermès Bélusca-Maïto 
49623b7c7b8SHermès Bélusca-Maïto     SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_SWAPPED_STACK );
49723b7c7b8SHermès Bélusca-Maïto 
49823b7c7b8SHermès Bélusca-Maïto     status = KeExpandKernelStackAndCalloutEx( FatCommonCreateCallout,
49923b7c7b8SHermès Bélusca-Maïto                                               &CalloutParameters,
50023b7c7b8SHermès Bélusca-Maïto                                               KERNEL_STACK_SIZE,
50123b7c7b8SHermès Bélusca-Maïto                                               FALSE,
50223b7c7b8SHermès Bélusca-Maïto                                               NULL );
50323b7c7b8SHermès Bélusca-Maïto 
50423b7c7b8SHermès Bélusca-Maïto     //
50523b7c7b8SHermès Bélusca-Maïto     //  Mark that the stack is no longer swapped.  Note that there are paths
50623b7c7b8SHermès Bélusca-Maïto     //  that may clear this flag before returning.
50723b7c7b8SHermès Bélusca-Maïto     //
50823b7c7b8SHermès Bélusca-Maïto 
50923b7c7b8SHermès Bélusca-Maïto     if (status != STATUS_PENDING) {
51023b7c7b8SHermès Bélusca-Maïto 
51123b7c7b8SHermès Bélusca-Maïto         ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_SWAPPED_STACK );
51223b7c7b8SHermès Bélusca-Maïto     }
51323b7c7b8SHermès Bélusca-Maïto 
51423b7c7b8SHermès Bélusca-Maïto     //
51523b7c7b8SHermès Bélusca-Maïto     // If we had an exception occur, re-raise the exception.
51623b7c7b8SHermès Bélusca-Maïto     //
51723b7c7b8SHermès Bélusca-Maïto 
51823b7c7b8SHermès Bélusca-Maïto     if (!NT_SUCCESS( CalloutParameters.ExceptionStatus )) {
51923b7c7b8SHermès Bélusca-Maïto         FatRaiseStatus( IrpContext, CalloutParameters.ExceptionStatus );
52023b7c7b8SHermès Bélusca-Maïto     }
52123b7c7b8SHermès Bélusca-Maïto 
52223b7c7b8SHermès Bélusca-Maïto     //
52323b7c7b8SHermès Bélusca-Maïto     //  If the call to KeExpandKernelStackAndCalloutEx returns an error this
52423b7c7b8SHermès Bélusca-Maïto     //  means that the callout routine (FatCommonCreateCallout) was never
52523b7c7b8SHermès Bélusca-Maïto     //  called. Translate that error, and return it.
52623b7c7b8SHermès Bélusca-Maïto     //
52723b7c7b8SHermès Bélusca-Maïto 
52823b7c7b8SHermès Bélusca-Maïto     if (!NT_SUCCESS( status )) {
52923b7c7b8SHermès Bélusca-Maïto 
53023b7c7b8SHermès Bélusca-Maïto         //
53123b7c7b8SHermès Bélusca-Maïto         //  Translate to an expected error value
53223b7c7b8SHermès Bélusca-Maïto         //
53323b7c7b8SHermès Bélusca-Maïto 
53423b7c7b8SHermès Bélusca-Maïto         if (status == STATUS_NO_MEMORY) {
53523b7c7b8SHermès Bélusca-Maïto 
53623b7c7b8SHermès Bélusca-Maïto             status = STATUS_INSUFFICIENT_RESOURCES;
53723b7c7b8SHermès Bélusca-Maïto         }
53823b7c7b8SHermès Bélusca-Maïto 
53923b7c7b8SHermès Bélusca-Maïto         return status;
54023b7c7b8SHermès Bélusca-Maïto     }
54123b7c7b8SHermès Bélusca-Maïto 
54223b7c7b8SHermès Bélusca-Maïto     //
54323b7c7b8SHermès Bélusca-Maïto     // Return the status given to us by the callout.
54423b7c7b8SHermès Bélusca-Maïto     //
54523b7c7b8SHermès Bélusca-Maïto 
54623b7c7b8SHermès Bélusca-Maïto     return CalloutParameters.IrpStatus;
54723b7c7b8SHermès Bélusca-Maïto }
54823b7c7b8SHermès Bélusca-Maïto #endif
54923b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)55023b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
55123b7c7b8SHermès Bélusca-Maïto NTSTATUS
55223b7c7b8SHermès Bélusca-Maïto FatCommonCreate (
55323b7c7b8SHermès Bélusca-Maïto     _Inout_ PIRP_CONTEXT IrpContext,
55423b7c7b8SHermès Bélusca-Maïto     _Inout_ PIRP Irp
55523b7c7b8SHermès Bélusca-Maïto     )
55623b7c7b8SHermès Bélusca-Maïto 
55723b7c7b8SHermès Bélusca-Maïto /*++
55823b7c7b8SHermès Bélusca-Maïto 
55923b7c7b8SHermès Bélusca-Maïto Routine Description:
56023b7c7b8SHermès Bélusca-Maïto 
56123b7c7b8SHermès Bélusca-Maïto     This is the common routine for creating/opening a file called by
56223b7c7b8SHermès Bélusca-Maïto     both the fsd and fsp threads.
56323b7c7b8SHermès Bélusca-Maïto 
56423b7c7b8SHermès Bélusca-Maïto Arguments:
56523b7c7b8SHermès Bélusca-Maïto 
56623b7c7b8SHermès Bélusca-Maïto     Irp - Supplies the Irp to process
56723b7c7b8SHermès Bélusca-Maïto 
56823b7c7b8SHermès Bélusca-Maïto Return Value:
56923b7c7b8SHermès Bélusca-Maïto 
57023b7c7b8SHermès Bélusca-Maïto     NTSTATUS - the return status for the operation
57123b7c7b8SHermès Bélusca-Maïto 
57223b7c7b8SHermès Bélusca-Maïto --*/
57323b7c7b8SHermès Bélusca-Maïto 
57423b7c7b8SHermès Bélusca-Maïto {
57523b7c7b8SHermès Bélusca-Maïto     NTSTATUS Status;
57623b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK Iosb = {0};
57723b7c7b8SHermès Bélusca-Maïto     PIO_STACK_LOCATION IrpSp;
57823b7c7b8SHermès Bélusca-Maïto 
57923b7c7b8SHermès Bélusca-Maïto     PFILE_OBJECT FileObject;
58023b7c7b8SHermès Bélusca-Maïto     PFILE_OBJECT RelatedFileObject;
58123b7c7b8SHermès Bélusca-Maïto     UNICODE_STRING FileName;
58223b7c7b8SHermès Bélusca-Maïto     ULONG AllocationSize;
58323b7c7b8SHermès Bélusca-Maïto     PFILE_FULL_EA_INFORMATION EaBuffer;
58423b7c7b8SHermès Bélusca-Maïto     PACCESS_MASK DesiredAccess;
58523b7c7b8SHermès Bélusca-Maïto     ULONG Options;
58623b7c7b8SHermès Bélusca-Maïto     USHORT FileAttributes;
58723b7c7b8SHermès Bélusca-Maïto     USHORT ShareAccess;
58823b7c7b8SHermès Bélusca-Maïto     ULONG EaLength;
58923b7c7b8SHermès Bélusca-Maïto 
59023b7c7b8SHermès Bélusca-Maïto     BOOLEAN CreateDirectory;
59123b7c7b8SHermès Bélusca-Maïto     BOOLEAN NoIntermediateBuffering;
59223b7c7b8SHermès Bélusca-Maïto     BOOLEAN OpenDirectory;
59323b7c7b8SHermès Bélusca-Maïto     BOOLEAN IsPagingFile;
59423b7c7b8SHermès Bélusca-Maïto     BOOLEAN OpenTargetDirectory;
59523b7c7b8SHermès Bélusca-Maïto     BOOLEAN DirectoryFile;
59623b7c7b8SHermès Bélusca-Maïto     BOOLEAN NonDirectoryFile;
59723b7c7b8SHermès Bélusca-Maïto     BOOLEAN NoEaKnowledge;
59823b7c7b8SHermès Bélusca-Maïto     BOOLEAN DeleteOnClose;
59923b7c7b8SHermès Bélusca-Maïto     BOOLEAN OpenRequiringOplock;
60023b7c7b8SHermès Bélusca-Maïto     BOOLEAN TemporaryFile;
60123b7c7b8SHermès Bélusca-Maïto     BOOLEAN FileNameOpenedDos = FALSE;
60223b7c7b8SHermès Bélusca-Maïto 
60323b7c7b8SHermès Bélusca-Maïto     ULONG CreateDisposition;
60423b7c7b8SHermès Bélusca-Maïto 
60523b7c7b8SHermès Bélusca-Maïto     PVCB Vcb;
60623b7c7b8SHermès Bélusca-Maïto     PFCB Fcb = NULL;
60723b7c7b8SHermès Bélusca-Maïto     PCCB Ccb;
60823b7c7b8SHermès Bélusca-Maïto     PDCB ParentDcb;
60923b7c7b8SHermès Bélusca-Maïto     PDCB FinalDcb = NULL;
61023b7c7b8SHermès Bélusca-Maïto 
61123b7c7b8SHermès Bélusca-Maïto     UNICODE_STRING FinalName = {0};
61223b7c7b8SHermès Bélusca-Maïto     UNICODE_STRING RemainingPart;
61323b7c7b8SHermès Bélusca-Maïto     UNICODE_STRING NextRemainingPart = {0};
61423b7c7b8SHermès Bélusca-Maïto     UNICODE_STRING UpcasedFinalName;
61523b7c7b8SHermès Bélusca-Maïto     WCHAR UpcasedBuffer[ FAT_CREATE_INITIAL_NAME_BUF_SIZE];
61623b7c7b8SHermès Bélusca-Maïto 
61723b7c7b8SHermès Bélusca-Maïto     OEM_STRING OemFinalName;
61823b7c7b8SHermès Bélusca-Maïto     UCHAR OemBuffer[ FAT_CREATE_INITIAL_NAME_BUF_SIZE*2];
61923b7c7b8SHermès Bélusca-Maïto 
62023b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent;
62123b7c7b8SHermès Bélusca-Maïto     PBCB DirentBcb = NULL;
62223b7c7b8SHermès Bélusca-Maïto     ULONG LfnByteOffset;
62323b7c7b8SHermès Bélusca-Maïto     ULONG DirentByteOffset;
62423b7c7b8SHermès Bélusca-Maïto 
62523b7c7b8SHermès Bélusca-Maïto     BOOLEAN PostIrp = FALSE;
62623b7c7b8SHermès Bélusca-Maïto     BOOLEAN OplockPostIrp = FALSE;
62723b7c7b8SHermès Bélusca-Maïto     BOOLEAN TrailingBackslash;
62823b7c7b8SHermès Bélusca-Maïto     BOOLEAN FirstLoop = TRUE;
62923b7c7b8SHermès Bélusca-Maïto 
63023b7c7b8SHermès Bélusca-Maïto     ULONG MatchFlags = 0;
63123b7c7b8SHermès Bélusca-Maïto 
63223b7c7b8SHermès Bélusca-Maïto     CCB LocalCcb;
63323b7c7b8SHermès Bélusca-Maïto     UNICODE_STRING Lfn;
63423b7c7b8SHermès Bélusca-Maïto     UNICODE_STRING OrigLfn = {0};
63523b7c7b8SHermès Bélusca-Maïto 
63623b7c7b8SHermès Bélusca-Maïto     WCHAR LfnBuffer[ FAT_CREATE_INITIAL_NAME_BUF_SIZE];
63723b7c7b8SHermès Bélusca-Maïto 
63823b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
63923b7c7b8SHermès Bélusca-Maïto 
64023b7c7b8SHermès Bélusca-Maïto     //
64123b7c7b8SHermès Bélusca-Maïto     //  Get the current IRP stack location
64223b7c7b8SHermès Bélusca-Maïto     //
64323b7c7b8SHermès Bélusca-Maïto 
64423b7c7b8SHermès Bélusca-Maïto     IrpSp = IoGetCurrentIrpStackLocation( Irp );
64523b7c7b8SHermès Bélusca-Maïto 
64623b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatCommonCreate\n", 0 );
64723b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "Irp                       = %p\n", Irp );
64823b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "->Flags                   = %08lx\n", Irp->Flags );
64923b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "->FileObject              = %p\n", IrpSp->FileObject );
65023b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, " ->RelatedFileObject      = %p\n", IrpSp->FileObject->RelatedFileObject );
65123b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, " ->FileName               = %wZ\n",    &IrpSp->FileObject->FileName );
65223b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, " ->FileName.Length        = 0n%d\n",    IrpSp->FileObject->FileName.Length );
65323b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "->AllocationSize.LowPart  = %08lx\n", Irp->Overlay.AllocationSize.LowPart );
65423b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "->AllocationSize.HighPart = %08lx\n", Irp->Overlay.AllocationSize.HighPart );
65523b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "->SystemBuffer            = %p\n", Irp->AssociatedIrp.SystemBuffer );
65623b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "->DesiredAccess           = %08lx\n", IrpSp->Parameters.Create.SecurityContext->DesiredAccess );
65723b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "->Options                 = %08lx\n", IrpSp->Parameters.Create.Options );
65823b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "->FileAttributes          = %04x\n",  IrpSp->Parameters.Create.FileAttributes );
65923b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "->ShareAccess             = %04x\n",  IrpSp->Parameters.Create.ShareAccess );
66023b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "->EaLength                = %08lx\n", IrpSp->Parameters.Create.EaLength );
66123b7c7b8SHermès Bélusca-Maïto 
66223b7c7b8SHermès Bélusca-Maïto     //
66323b7c7b8SHermès Bélusca-Maïto     //  This is here because the Win32 layer can't avoid sending me double
66423b7c7b8SHermès Bélusca-Maïto     //  beginning backslashes.
66523b7c7b8SHermès Bélusca-Maïto     //
66623b7c7b8SHermès Bélusca-Maïto 
66723b7c7b8SHermès Bélusca-Maïto     if ((IrpSp->FileObject->FileName.Length > sizeof(WCHAR)) &&
66823b7c7b8SHermès Bélusca-Maïto         (IrpSp->FileObject->FileName.Buffer[1] == L'\\') &&
66923b7c7b8SHermès Bélusca-Maïto         (IrpSp->FileObject->FileName.Buffer[0] == L'\\')) {
67023b7c7b8SHermès Bélusca-Maïto 
67123b7c7b8SHermès Bélusca-Maïto         IrpSp->FileObject->FileName.Length -= sizeof(WCHAR);
67223b7c7b8SHermès Bélusca-Maïto 
67323b7c7b8SHermès Bélusca-Maïto         RtlMoveMemory( &IrpSp->FileObject->FileName.Buffer[0],
67423b7c7b8SHermès Bélusca-Maïto                        &IrpSp->FileObject->FileName.Buffer[1],
67523b7c7b8SHermès Bélusca-Maïto                        IrpSp->FileObject->FileName.Length );
67623b7c7b8SHermès Bélusca-Maïto 
67723b7c7b8SHermès Bélusca-Maïto         //
67823b7c7b8SHermès Bélusca-Maïto         //  If there are still two beginning backslashes, the name is bogus.
67923b7c7b8SHermès Bélusca-Maïto         //
68023b7c7b8SHermès Bélusca-Maïto 
68123b7c7b8SHermès Bélusca-Maïto         if ((IrpSp->FileObject->FileName.Length > sizeof(WCHAR)) &&
68223b7c7b8SHermès Bélusca-Maïto             (IrpSp->FileObject->FileName.Buffer[1] == L'\\') &&
68323b7c7b8SHermès Bélusca-Maïto             (IrpSp->FileObject->FileName.Buffer[0] == L'\\')) {
68423b7c7b8SHermès Bélusca-Maïto 
68523b7c7b8SHermès Bélusca-Maïto             DebugTrace(-1, Dbg, "FatCommonCreate -> STATUS_OBJECT_NAME_INVALID\n", 0);
68623b7c7b8SHermès Bélusca-Maïto             return STATUS_OBJECT_NAME_INVALID;
68723b7c7b8SHermès Bélusca-Maïto         }
68823b7c7b8SHermès Bélusca-Maïto     }
68923b7c7b8SHermès Bélusca-Maïto 
69023b7c7b8SHermès Bélusca-Maïto     //
69123b7c7b8SHermès Bélusca-Maïto     //  Reference our input parameters to make things easier
69223b7c7b8SHermès Bélusca-Maïto     //
69323b7c7b8SHermès Bélusca-Maïto 
69423b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( IrpSp->Parameters.Create.SecurityContext != NULL );
69523b7c7b8SHermès Bélusca-Maïto 
69623b7c7b8SHermès Bélusca-Maïto     FileObject        = IrpSp->FileObject;
69723b7c7b8SHermès Bélusca-Maïto     FileName          = FileObject->FileName;
69823b7c7b8SHermès Bélusca-Maïto     RelatedFileObject = FileObject->RelatedFileObject;
69923b7c7b8SHermès Bélusca-Maïto     AllocationSize    = Irp->Overlay.AllocationSize.LowPart;
70023b7c7b8SHermès Bélusca-Maïto     EaBuffer          = Irp->AssociatedIrp.SystemBuffer;
70123b7c7b8SHermès Bélusca-Maïto     DesiredAccess     = &IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
70223b7c7b8SHermès Bélusca-Maïto     Options           = IrpSp->Parameters.Create.Options;
70323b7c7b8SHermès Bélusca-Maïto     FileAttributes    = IrpSp->Parameters.Create.FileAttributes & ~FILE_ATTRIBUTE_NORMAL;
70423b7c7b8SHermès Bélusca-Maïto     ShareAccess       = IrpSp->Parameters.Create.ShareAccess;
70523b7c7b8SHermès Bélusca-Maïto     EaLength          = IrpSp->Parameters.Create.EaLength;
70623b7c7b8SHermès Bélusca-Maïto 
70723b7c7b8SHermès Bélusca-Maïto     //
70823b7c7b8SHermès Bélusca-Maïto     //  Set up the file object's Vpb pointer in case anything happens.
70923b7c7b8SHermès Bélusca-Maïto     //  This will allow us to get a reasonable pop-up.
71023b7c7b8SHermès Bélusca-Maïto     //
71123b7c7b8SHermès Bélusca-Maïto 
71223b7c7b8SHermès Bélusca-Maïto     if ( RelatedFileObject != NULL ) {
71323b7c7b8SHermès Bélusca-Maïto         FileObject->Vpb = RelatedFileObject->Vpb;
71423b7c7b8SHermès Bélusca-Maïto     }
71523b7c7b8SHermès Bélusca-Maïto 
71623b7c7b8SHermès Bélusca-Maïto     //
71723b7c7b8SHermès Bélusca-Maïto     //  Force setting the archive bit in the attributes byte to follow OS/2,
71823b7c7b8SHermès Bélusca-Maïto     //  & DOS semantics.  Also mask out any extraneous bits, note that
71923b7c7b8SHermès Bélusca-Maïto     //  we can't use the ATTRIBUTE_VALID_FLAGS constant because that has
72023b7c7b8SHermès Bélusca-Maïto     //  the control and normal flags set.
72123b7c7b8SHermès Bélusca-Maïto     //
72223b7c7b8SHermès Bélusca-Maïto     //  Delay setting ARCHIVE in case this is a directory: 2/16/95
72323b7c7b8SHermès Bélusca-Maïto     //
72423b7c7b8SHermès Bélusca-Maïto 
72523b7c7b8SHermès Bélusca-Maïto     FileAttributes   &= (FILE_ATTRIBUTE_READONLY |
72623b7c7b8SHermès Bélusca-Maïto                          FILE_ATTRIBUTE_HIDDEN   |
72723b7c7b8SHermès Bélusca-Maïto                          FILE_ATTRIBUTE_SYSTEM   |
72823b7c7b8SHermès Bélusca-Maïto                          FILE_ATTRIBUTE_ARCHIVE  |
72923b7c7b8SHermès Bélusca-Maïto                          FILE_ATTRIBUTE_ENCRYPTED);
73023b7c7b8SHermès Bélusca-Maïto 
73123b7c7b8SHermès Bélusca-Maïto     //
73223b7c7b8SHermès Bélusca-Maïto     //  Locate the volume device object and Vcb that we are trying to access
73323b7c7b8SHermès Bélusca-Maïto     //
73423b7c7b8SHermès Bélusca-Maïto 
73523b7c7b8SHermès Bélusca-Maïto     Vcb = &((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->Vcb;
73623b7c7b8SHermès Bélusca-Maïto 
73723b7c7b8SHermès Bélusca-Maïto     //
73823b7c7b8SHermès Bélusca-Maïto     //  Decipher Option flags and values
73923b7c7b8SHermès Bélusca-Maïto     //
74023b7c7b8SHermès Bélusca-Maïto 
74123b7c7b8SHermès Bélusca-Maïto     //
74223b7c7b8SHermès Bélusca-Maïto     //  If this is an open by fileid operation, just fail it explicitly.  FAT's
74323b7c7b8SHermès Bélusca-Maïto     //  source of fileids is not reversible for open operations.
74423b7c7b8SHermès Bélusca-Maïto     //
74523b7c7b8SHermès Bélusca-Maïto 
74623b7c7b8SHermès Bélusca-Maïto     if (BooleanFlagOn( Options, FILE_OPEN_BY_FILE_ID )) {
74723b7c7b8SHermès Bélusca-Maïto 
74823b7c7b8SHermès Bélusca-Maïto         return STATUS_NOT_IMPLEMENTED;
74923b7c7b8SHermès Bélusca-Maïto     }
75023b7c7b8SHermès Bélusca-Maïto 
75123b7c7b8SHermès Bélusca-Maïto     DirectoryFile           = BooleanFlagOn( Options, FILE_DIRECTORY_FILE );
75223b7c7b8SHermès Bélusca-Maïto     NonDirectoryFile        = BooleanFlagOn( Options, FILE_NON_DIRECTORY_FILE );
75323b7c7b8SHermès Bélusca-Maïto     NoIntermediateBuffering = BooleanFlagOn( Options, FILE_NO_INTERMEDIATE_BUFFERING );
75423b7c7b8SHermès Bélusca-Maïto     NoEaKnowledge           = BooleanFlagOn( Options, FILE_NO_EA_KNOWLEDGE );
75523b7c7b8SHermès Bélusca-Maïto     DeleteOnClose           = BooleanFlagOn( Options, FILE_DELETE_ON_CLOSE );
75623b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN7)
75723b7c7b8SHermès Bélusca-Maïto     OpenRequiringOplock     = BooleanFlagOn( Options, FILE_OPEN_REQUIRING_OPLOCK );
75823b7c7b8SHermès Bélusca-Maïto #else
75923b7c7b8SHermès Bélusca-Maïto     OpenRequiringOplock     = FALSE;
76023b7c7b8SHermès Bélusca-Maïto #endif
76123b7c7b8SHermès Bélusca-Maïto 
76223b7c7b8SHermès Bélusca-Maïto     TemporaryFile = BooleanFlagOn( IrpSp->Parameters.Create.FileAttributes,
76323b7c7b8SHermès Bélusca-Maïto                                    FILE_ATTRIBUTE_TEMPORARY );
76423b7c7b8SHermès Bélusca-Maïto 
76523b7c7b8SHermès Bélusca-Maïto     CreateDisposition = (Options >> 24) & 0x000000ff;
76623b7c7b8SHermès Bélusca-Maïto 
76723b7c7b8SHermès Bélusca-Maïto     IsPagingFile = BooleanFlagOn( IrpSp->Flags, SL_OPEN_PAGING_FILE );
76823b7c7b8SHermès Bélusca-Maïto     OpenTargetDirectory = BooleanFlagOn( IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY );
76923b7c7b8SHermès Bélusca-Maïto 
77023b7c7b8SHermès Bélusca-Maïto     CreateDirectory = (BOOLEAN)(DirectoryFile &&
77123b7c7b8SHermès Bélusca-Maïto                                 ((CreateDisposition == FILE_CREATE) ||
77223b7c7b8SHermès Bélusca-Maïto                                  (CreateDisposition == FILE_OPEN_IF)));
77323b7c7b8SHermès Bélusca-Maïto 
77423b7c7b8SHermès Bélusca-Maïto     OpenDirectory   = (BOOLEAN)(DirectoryFile &&
77523b7c7b8SHermès Bélusca-Maïto                                 ((CreateDisposition == FILE_OPEN) ||
77623b7c7b8SHermès Bélusca-Maïto                                  (CreateDisposition == FILE_OPEN_IF)));
77723b7c7b8SHermès Bélusca-Maïto 
77823b7c7b8SHermès Bélusca-Maïto 
77923b7c7b8SHermès Bélusca-Maïto     //
78023b7c7b8SHermès Bélusca-Maïto     //  Make sure the input large integer is valid and that the dir/nondir
78123b7c7b8SHermès Bélusca-Maïto     //  indicates a storage type we understand.
78223b7c7b8SHermès Bélusca-Maïto     //
78323b7c7b8SHermès Bélusca-Maïto 
78423b7c7b8SHermès Bélusca-Maïto     if (Irp->Overlay.AllocationSize.HighPart != 0 ||
78523b7c7b8SHermès Bélusca-Maïto         (DirectoryFile && NonDirectoryFile)) {
78623b7c7b8SHermès Bélusca-Maïto 
78723b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatCommonCreate -> STATUS_INVALID_PARAMETER\n", 0);
78823b7c7b8SHermès Bélusca-Maïto         return STATUS_INVALID_PARAMETER;
78923b7c7b8SHermès Bélusca-Maïto     }
79023b7c7b8SHermès Bélusca-Maïto 
79123b7c7b8SHermès Bélusca-Maïto     //
79223b7c7b8SHermès Bélusca-Maïto     //  Acquire exclusive access to the vcb, and enqueue the Irp if
79323b7c7b8SHermès Bélusca-Maïto     //  we didn't get it.
79423b7c7b8SHermès Bélusca-Maïto     //
79523b7c7b8SHermès Bélusca-Maïto 
79623b7c7b8SHermès Bélusca-Maïto     if (!FatAcquireExclusiveVcb( IrpContext, Vcb )) {
79723b7c7b8SHermès Bélusca-Maïto 
79823b7c7b8SHermès Bélusca-Maïto         DebugTrace(0, Dbg, "Cannot acquire Vcb\n", 0);
79923b7c7b8SHermès Bélusca-Maïto 
80023b7c7b8SHermès Bélusca-Maïto         Iosb.Status = FatFsdPostRequest( IrpContext, Irp );
80123b7c7b8SHermès Bélusca-Maïto 
80223b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatCommonCreate -> %08lx\n", Iosb.Status );
80323b7c7b8SHermès Bélusca-Maïto         return Iosb.Status;
80423b7c7b8SHermès Bélusca-Maïto     }
80523b7c7b8SHermès Bélusca-Maïto 
80623b7c7b8SHermès Bélusca-Maïto     //
80723b7c7b8SHermès Bélusca-Maïto     //  Make sure we haven't been called recursively by a filter inside an existing
80823b7c7b8SHermès Bélusca-Maïto     //  create request.
80923b7c7b8SHermès Bélusca-Maïto     //
81023b7c7b8SHermès Bélusca-Maïto 
81123b7c7b8SHermès Bélusca-Maïto     if (FlagOn( Vcb->VcbState, VCB_STATE_FLAG_CREATE_IN_PROGRESS)) {
81223b7c7b8SHermès Bélusca-Maïto 
81323b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
81423b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress:28159, "this is a serious programming error if it happens" )
81523b7c7b8SHermès Bélusca-Maïto #endif
81623b7c7b8SHermès Bélusca-Maïto         FatBugCheck( 0, 0, 0);
81723b7c7b8SHermès Bélusca-Maïto     }
81823b7c7b8SHermès Bélusca-Maïto 
81923b7c7b8SHermès Bélusca-Maïto     //
82023b7c7b8SHermès Bélusca-Maïto     //  Initialize the DirentBcb to null
82123b7c7b8SHermès Bélusca-Maïto     //
82223b7c7b8SHermès Bélusca-Maïto 
82323b7c7b8SHermès Bélusca-Maïto     DirentBcb = NULL;
82423b7c7b8SHermès Bélusca-Maïto 
82523b7c7b8SHermès Bélusca-Maïto     //
82623b7c7b8SHermès Bélusca-Maïto     //  Initialize our temp strings with their stack buffers.
82723b7c7b8SHermès Bélusca-Maïto     //
82823b7c7b8SHermès Bélusca-Maïto 
82923b7c7b8SHermès Bélusca-Maïto     OemFinalName.Length = 0;
83023b7c7b8SHermès Bélusca-Maïto     OemFinalName.MaximumLength = sizeof( OemBuffer);
83123b7c7b8SHermès Bélusca-Maïto     OemFinalName.Buffer = (PCHAR)OemBuffer;
83223b7c7b8SHermès Bélusca-Maïto 
83323b7c7b8SHermès Bélusca-Maïto     UpcasedFinalName.Length = 0;
83423b7c7b8SHermès Bélusca-Maïto     UpcasedFinalName.MaximumLength = sizeof( UpcasedBuffer);
83523b7c7b8SHermès Bélusca-Maïto     UpcasedFinalName.Buffer = UpcasedBuffer;
83623b7c7b8SHermès Bélusca-Maïto 
83723b7c7b8SHermès Bélusca-Maïto     Lfn.Length = 0;
83823b7c7b8SHermès Bélusca-Maïto     Lfn.MaximumLength = sizeof( LfnBuffer);
83923b7c7b8SHermès Bélusca-Maïto     Lfn.Buffer = LfnBuffer;
84023b7c7b8SHermès Bélusca-Maïto 
84123b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
84223b7c7b8SHermès Bélusca-Maïto 
84323b7c7b8SHermès Bélusca-Maïto         //
84423b7c7b8SHermès Bélusca-Maïto         //  Make sure the vcb is in a usable condition.  This will raise
84523b7c7b8SHermès Bélusca-Maïto         //  and error condition if the volume is unusable
84623b7c7b8SHermès Bélusca-Maïto         //
84723b7c7b8SHermès Bélusca-Maïto 
84823b7c7b8SHermès Bélusca-Maïto         FatVerifyVcb( IrpContext, Vcb );
84923b7c7b8SHermès Bélusca-Maïto 
85023b7c7b8SHermès Bélusca-Maïto         //
85123b7c7b8SHermès Bélusca-Maïto         //  If the Vcb is locked then we cannot open another file
85223b7c7b8SHermès Bélusca-Maïto         //
85323b7c7b8SHermès Bélusca-Maïto 
85423b7c7b8SHermès Bélusca-Maïto         if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_LOCKED)) {
85523b7c7b8SHermès Bélusca-Maïto 
85623b7c7b8SHermès Bélusca-Maïto             DebugTrace(0, Dbg, "Volume is locked\n", 0);
85723b7c7b8SHermès Bélusca-Maïto 
85823b7c7b8SHermès Bélusca-Maïto             Status = STATUS_ACCESS_DENIED;
85923b7c7b8SHermès Bélusca-Maïto             if (Vcb->VcbCondition != VcbGood) {
86023b7c7b8SHermès Bélusca-Maïto 
86123b7c7b8SHermès Bélusca-Maïto                 Status = STATUS_VOLUME_DISMOUNTED;
86223b7c7b8SHermès Bélusca-Maïto             }
86323b7c7b8SHermès Bélusca-Maïto             try_return( Iosb.Status = Status );
86423b7c7b8SHermès Bélusca-Maïto         }
86523b7c7b8SHermès Bélusca-Maïto 
86623b7c7b8SHermès Bélusca-Maïto         //
86723b7c7b8SHermès Bélusca-Maïto         //  Don't allow the DELETE_ON_CLOSE option if the volume is
86823b7c7b8SHermès Bélusca-Maïto         //  write-protected.
86923b7c7b8SHermès Bélusca-Maïto         //
87023b7c7b8SHermès Bélusca-Maïto 
87123b7c7b8SHermès Bélusca-Maïto         if (DeleteOnClose && FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
87223b7c7b8SHermès Bélusca-Maïto 
87323b7c7b8SHermès Bélusca-Maïto             //
87423b7c7b8SHermès Bélusca-Maïto             //  Set the real device for the pop-up info, and set the verify
87523b7c7b8SHermès Bélusca-Maïto             //  bit in the device object, so that we will force a verify
87623b7c7b8SHermès Bélusca-Maïto             //  in case the user put the correct media back in.
87723b7c7b8SHermès Bélusca-Maïto             //
87823b7c7b8SHermès Bélusca-Maïto 
87923b7c7b8SHermès Bélusca-Maïto             IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
88023b7c7b8SHermès Bélusca-Maïto                                           Vcb->Vpb->RealDevice );
88123b7c7b8SHermès Bélusca-Maïto 
88223b7c7b8SHermès Bélusca-Maïto             SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
88323b7c7b8SHermès Bélusca-Maïto 
88423b7c7b8SHermès Bélusca-Maïto             FatRaiseStatus( IrpContext, STATUS_MEDIA_WRITE_PROTECTED );
88523b7c7b8SHermès Bélusca-Maïto         }
88623b7c7b8SHermès Bélusca-Maïto 
88723b7c7b8SHermès Bélusca-Maïto         //
88823b7c7b8SHermès Bélusca-Maïto         //  If this is a fat32 volume, EA's are not supported.
88923b7c7b8SHermès Bélusca-Maïto         //
89023b7c7b8SHermès Bélusca-Maïto 
89123b7c7b8SHermès Bélusca-Maïto         if (EaBuffer != NULL) {
89223b7c7b8SHermès Bélusca-Maïto 
89323b7c7b8SHermès Bélusca-Maïto             try_return( Iosb.Status = STATUS_EAS_NOT_SUPPORTED );
89423b7c7b8SHermès Bélusca-Maïto         }
89523b7c7b8SHermès Bélusca-Maïto 
89623b7c7b8SHermès Bélusca-Maïto         //
89723b7c7b8SHermès Bélusca-Maïto         //  Check if we are opening the volume and not a file/directory.
89823b7c7b8SHermès Bélusca-Maïto         //  We are opening the volume if the name is empty and there
89923b7c7b8SHermès Bélusca-Maïto         //  isn't a related file object.  If there is a related file object
90023b7c7b8SHermès Bélusca-Maïto         //  then it is the Vcb itself.
90123b7c7b8SHermès Bélusca-Maïto         //
90223b7c7b8SHermès Bélusca-Maïto 
90323b7c7b8SHermès Bélusca-Maïto         if (FileName.Length == 0) {
90423b7c7b8SHermès Bélusca-Maïto 
90523b7c7b8SHermès Bélusca-Maïto             PVCB DecodeVcb = NULL;
90623b7c7b8SHermès Bélusca-Maïto 
90723b7c7b8SHermès Bélusca-Maïto             if (RelatedFileObject == NULL ||
90823b7c7b8SHermès Bélusca-Maïto                 FatDecodeFileObject( RelatedFileObject,
90923b7c7b8SHermès Bélusca-Maïto                                      &DecodeVcb,
91023b7c7b8SHermès Bélusca-Maïto                                      &Fcb,
91123b7c7b8SHermès Bélusca-Maïto                                      &Ccb ) == UserVolumeOpen) {
91223b7c7b8SHermès Bélusca-Maïto 
91323b7c7b8SHermès Bélusca-Maïto                 NT_ASSERT( RelatedFileObject == NULL || Vcb == DecodeVcb );
91423b7c7b8SHermès Bélusca-Maïto 
91523b7c7b8SHermès Bélusca-Maïto                 //
91623b7c7b8SHermès Bélusca-Maïto                 //  Check if we were to open a directory
91723b7c7b8SHermès Bélusca-Maïto                 //
91823b7c7b8SHermès Bélusca-Maïto 
91923b7c7b8SHermès Bélusca-Maïto                 if (DirectoryFile) {
92023b7c7b8SHermès Bélusca-Maïto 
92123b7c7b8SHermès Bélusca-Maïto                     DebugTrace(0, Dbg, "Cannot open volume as a directory\n", 0);
92223b7c7b8SHermès Bélusca-Maïto 
92323b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb.Status = STATUS_NOT_A_DIRECTORY );
92423b7c7b8SHermès Bélusca-Maïto                 }
92523b7c7b8SHermès Bélusca-Maïto 
92623b7c7b8SHermès Bélusca-Maïto                 //
92723b7c7b8SHermès Bélusca-Maïto                 //  Can't open the TargetDirectory of the DASD volume.
92823b7c7b8SHermès Bélusca-Maïto                 //
92923b7c7b8SHermès Bélusca-Maïto 
93023b7c7b8SHermès Bélusca-Maïto                 if (OpenTargetDirectory) {
93123b7c7b8SHermès Bélusca-Maïto 
93223b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb.Status = STATUS_INVALID_PARAMETER );
93323b7c7b8SHermès Bélusca-Maïto                 }
93423b7c7b8SHermès Bélusca-Maïto 
93523b7c7b8SHermès Bélusca-Maïto                 DebugTrace(0, Dbg, "Opening the volume, Vcb = %p\n", Vcb);
93623b7c7b8SHermès Bélusca-Maïto 
93723b7c7b8SHermès Bélusca-Maïto                 CollectCreateHitStatistics(Vcb);
93823b7c7b8SHermès Bélusca-Maïto 
93923b7c7b8SHermès Bélusca-Maïto                 Iosb = FatOpenVolume( IrpContext,
94023b7c7b8SHermès Bélusca-Maïto                                       FileObject,
94123b7c7b8SHermès Bélusca-Maïto                                       Vcb,
94223b7c7b8SHermès Bélusca-Maïto                                       DesiredAccess,
94323b7c7b8SHermès Bélusca-Maïto                                       ShareAccess,
94423b7c7b8SHermès Bélusca-Maïto                                       CreateDisposition );
94523b7c7b8SHermès Bélusca-Maïto 
94623b7c7b8SHermès Bélusca-Maïto                 Irp->IoStatus.Information = Iosb.Information;
94723b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb.Status );
94823b7c7b8SHermès Bélusca-Maïto             }
94923b7c7b8SHermès Bélusca-Maïto         }
95023b7c7b8SHermès Bélusca-Maïto 
95123b7c7b8SHermès Bélusca-Maïto         //
95223b7c7b8SHermès Bélusca-Maïto         //  If there is a related file object then this is a relative open.
95323b7c7b8SHermès Bélusca-Maïto         //  The related file object is the directory to start our search at.
95423b7c7b8SHermès Bélusca-Maïto         //  Return an error if it is not a directory.
95523b7c7b8SHermès Bélusca-Maïto         //
95623b7c7b8SHermès Bélusca-Maïto 
95723b7c7b8SHermès Bélusca-Maïto         if (RelatedFileObject != NULL) {
95823b7c7b8SHermès Bélusca-Maïto 
95923b7c7b8SHermès Bélusca-Maïto             PVCB RelatedVcb;
96023b7c7b8SHermès Bélusca-Maïto             PDCB RelatedDcb;
96123b7c7b8SHermès Bélusca-Maïto             PCCB RelatedCcb;
96223b7c7b8SHermès Bélusca-Maïto             TYPE_OF_OPEN TypeOfOpen;
96323b7c7b8SHermès Bélusca-Maïto 
96423b7c7b8SHermès Bélusca-Maïto             TypeOfOpen = FatDecodeFileObject( RelatedFileObject,
96523b7c7b8SHermès Bélusca-Maïto                                               &RelatedVcb,
96623b7c7b8SHermès Bélusca-Maïto                                               &RelatedDcb,
96723b7c7b8SHermès Bélusca-Maïto                                               &RelatedCcb );
96823b7c7b8SHermès Bélusca-Maïto 
96923b7c7b8SHermès Bélusca-Maïto             if (TypeOfOpen != UserFileOpen &&
97023b7c7b8SHermès Bélusca-Maïto                 TypeOfOpen != UserDirectoryOpen) {
97123b7c7b8SHermès Bélusca-Maïto 
97223b7c7b8SHermès Bélusca-Maïto                 DebugTrace(0, Dbg, "Invalid related file object\n", 0);
97323b7c7b8SHermès Bélusca-Maïto 
97423b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb.Status = STATUS_OBJECT_PATH_NOT_FOUND );
97523b7c7b8SHermès Bélusca-Maïto             }
97623b7c7b8SHermès Bélusca-Maïto 
97723b7c7b8SHermès Bélusca-Maïto             //
97823b7c7b8SHermès Bélusca-Maïto             //  A relative open must be via a relative path.
97923b7c7b8SHermès Bélusca-Maïto             //
98023b7c7b8SHermès Bélusca-Maïto 
98123b7c7b8SHermès Bélusca-Maïto             if (FileName.Length != 0 &&
98223b7c7b8SHermès Bélusca-Maïto                 FileName.Buffer[0] == L'\\') {
98323b7c7b8SHermès Bélusca-Maïto 
98423b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
98523b7c7b8SHermès Bélusca-Maïto             }
98623b7c7b8SHermès Bélusca-Maïto 
98723b7c7b8SHermès Bélusca-Maïto             //
98823b7c7b8SHermès Bélusca-Maïto             //  Set up the file object's Vpb pointer in case anything happens.
98923b7c7b8SHermès Bélusca-Maïto             //
99023b7c7b8SHermès Bélusca-Maïto 
99123b7c7b8SHermès Bélusca-Maïto             NT_ASSERT( Vcb == RelatedVcb );
99223b7c7b8SHermès Bélusca-Maïto 
99323b7c7b8SHermès Bélusca-Maïto             FileObject->Vpb = RelatedFileObject->Vpb;
99423b7c7b8SHermès Bélusca-Maïto 
99523b7c7b8SHermès Bélusca-Maïto             //
99623b7c7b8SHermès Bélusca-Maïto             //  Now verify the related Fcb so we don't get in trouble later
99723b7c7b8SHermès Bélusca-Maïto             //  by assuming its in good shape.
99823b7c7b8SHermès Bélusca-Maïto             //
99923b7c7b8SHermès Bélusca-Maïto 
100023b7c7b8SHermès Bélusca-Maïto             FatVerifyFcb( IrpContext, RelatedDcb );
100123b7c7b8SHermès Bélusca-Maïto 
100223b7c7b8SHermès Bélusca-Maïto             ParentDcb = RelatedDcb;
100323b7c7b8SHermès Bélusca-Maïto 
100423b7c7b8SHermès Bélusca-Maïto         } else {
100523b7c7b8SHermès Bélusca-Maïto 
100623b7c7b8SHermès Bélusca-Maïto             //
100723b7c7b8SHermès Bélusca-Maïto             //  This is not a relative open, so check if we're
100823b7c7b8SHermès Bélusca-Maïto             //  opening the root dcb
100923b7c7b8SHermès Bélusca-Maïto             //
101023b7c7b8SHermès Bélusca-Maïto 
101123b7c7b8SHermès Bélusca-Maïto             if ((FileName.Length == sizeof(WCHAR)) &&
101223b7c7b8SHermès Bélusca-Maïto                 (FileName.Buffer[0] == L'\\')) {
101323b7c7b8SHermès Bélusca-Maïto 
101423b7c7b8SHermès Bélusca-Maïto                 //
101523b7c7b8SHermès Bélusca-Maïto                 //  Check if we were not supposed to open a directory
101623b7c7b8SHermès Bélusca-Maïto                 //
101723b7c7b8SHermès Bélusca-Maïto 
101823b7c7b8SHermès Bélusca-Maïto                 if (NonDirectoryFile) {
101923b7c7b8SHermès Bélusca-Maïto 
102023b7c7b8SHermès Bélusca-Maïto                     DebugTrace(0, Dbg, "Cannot open root directory as a file\n", 0);
102123b7c7b8SHermès Bélusca-Maïto 
102223b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb.Status = STATUS_FILE_IS_A_DIRECTORY );
102323b7c7b8SHermès Bélusca-Maïto                 }
102423b7c7b8SHermès Bélusca-Maïto 
102523b7c7b8SHermès Bélusca-Maïto                 //
102623b7c7b8SHermès Bélusca-Maïto                 //  Can't open the TargetDirectory of the root directory.
102723b7c7b8SHermès Bélusca-Maïto                 //
102823b7c7b8SHermès Bélusca-Maïto 
102923b7c7b8SHermès Bélusca-Maïto                 if (OpenTargetDirectory) {
103023b7c7b8SHermès Bélusca-Maïto 
103123b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb.Status = STATUS_INVALID_PARAMETER );
103223b7c7b8SHermès Bélusca-Maïto                 }
103323b7c7b8SHermès Bélusca-Maïto 
103423b7c7b8SHermès Bélusca-Maïto                 //
103523b7c7b8SHermès Bélusca-Maïto                 //  Not allowed to delete root directory.
103623b7c7b8SHermès Bélusca-Maïto                 //
103723b7c7b8SHermès Bélusca-Maïto 
103823b7c7b8SHermès Bélusca-Maïto                 if (DeleteOnClose) {
103923b7c7b8SHermès Bélusca-Maïto 
104023b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb.Status = STATUS_CANNOT_DELETE );
104123b7c7b8SHermès Bélusca-Maïto                 }
104223b7c7b8SHermès Bélusca-Maïto 
104323b7c7b8SHermès Bélusca-Maïto                 DebugTrace(0, Dbg, "Opening root dcb\n", 0);
104423b7c7b8SHermès Bélusca-Maïto 
104523b7c7b8SHermès Bélusca-Maïto                 CollectCreateHitStatistics(Vcb);
104623b7c7b8SHermès Bélusca-Maïto 
104723b7c7b8SHermès Bélusca-Maïto                 Iosb = FatOpenRootDcb( IrpContext,
104823b7c7b8SHermès Bélusca-Maïto                                        FileObject,
104923b7c7b8SHermès Bélusca-Maïto                                        Vcb,
105023b7c7b8SHermès Bélusca-Maïto                                        DesiredAccess,
105123b7c7b8SHermès Bélusca-Maïto                                        ShareAccess,
105223b7c7b8SHermès Bélusca-Maïto                                        CreateDisposition );
105323b7c7b8SHermès Bélusca-Maïto 
105423b7c7b8SHermès Bélusca-Maïto                 Irp->IoStatus.Information = Iosb.Information;
105523b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb.Status );
105623b7c7b8SHermès Bélusca-Maïto             }
105723b7c7b8SHermès Bélusca-Maïto 
105823b7c7b8SHermès Bélusca-Maïto             //
105923b7c7b8SHermès Bélusca-Maïto             //  Nope, we will be opening relative to the root directory.
106023b7c7b8SHermès Bélusca-Maïto             //
106123b7c7b8SHermès Bélusca-Maïto 
106223b7c7b8SHermès Bélusca-Maïto             ParentDcb = Vcb->RootDcb;
106323b7c7b8SHermès Bélusca-Maïto 
106423b7c7b8SHermès Bélusca-Maïto             //
106523b7c7b8SHermès Bélusca-Maïto             //  Now verify the root Dcb so we don't get in trouble later
106623b7c7b8SHermès Bélusca-Maïto             //  by assuming its in good shape.
106723b7c7b8SHermès Bélusca-Maïto             //
106823b7c7b8SHermès Bélusca-Maïto 
106923b7c7b8SHermès Bélusca-Maïto             FatVerifyFcb( IrpContext, ParentDcb );
107023b7c7b8SHermès Bélusca-Maïto         }
107123b7c7b8SHermès Bélusca-Maïto 
107223b7c7b8SHermès Bélusca-Maïto         //
107323b7c7b8SHermès Bélusca-Maïto         //  FatCommonCreate(): trailing backslash check
107423b7c7b8SHermès Bélusca-Maïto         //
107523b7c7b8SHermès Bélusca-Maïto 
107623b7c7b8SHermès Bélusca-Maïto 
107723b7c7b8SHermès Bélusca-Maïto         if ((FileName.Length != 0) &&
107823b7c7b8SHermès Bélusca-Maïto             (FileName.Buffer[FileName.Length/sizeof(WCHAR)-1] == L'\\')) {
107923b7c7b8SHermès Bélusca-Maïto 
108023b7c7b8SHermès Bélusca-Maïto             FileName.Length -= sizeof(WCHAR);
108123b7c7b8SHermès Bélusca-Maïto             TrailingBackslash = TRUE;
108223b7c7b8SHermès Bélusca-Maïto 
108323b7c7b8SHermès Bélusca-Maïto         } else {
108423b7c7b8SHermès Bélusca-Maïto 
108523b7c7b8SHermès Bélusca-Maïto             TrailingBackslash = FALSE;
108623b7c7b8SHermès Bélusca-Maïto         }
108723b7c7b8SHermès Bélusca-Maïto 
108823b7c7b8SHermès Bélusca-Maïto         //
108923b7c7b8SHermès Bélusca-Maïto         //  Check for max path.  We might want to tighten this down to DOS MAX_PATH
109023b7c7b8SHermès Bélusca-Maïto         //  for maximal interchange with non-NT platforms, but for now defer to the
109123b7c7b8SHermès Bélusca-Maïto         //  possibility of something depending on it.
109223b7c7b8SHermès Bélusca-Maïto         //
109323b7c7b8SHermès Bélusca-Maïto 
109423b7c7b8SHermès Bélusca-Maïto         if (ParentDcb->FullFileName.Buffer == NULL) {
109523b7c7b8SHermès Bélusca-Maïto 
109623b7c7b8SHermès Bélusca-Maïto             FatSetFullFileNameInFcb( IrpContext, ParentDcb );
109723b7c7b8SHermès Bélusca-Maïto         }
109823b7c7b8SHermès Bélusca-Maïto 
109923b7c7b8SHermès Bélusca-Maïto         if ((USHORT) (ParentDcb->FullFileName.Length + sizeof(WCHAR) + FileName.Length) <= FileName.Length) {
110023b7c7b8SHermès Bélusca-Maïto 
110123b7c7b8SHermès Bélusca-Maïto             try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
110223b7c7b8SHermès Bélusca-Maïto         }
110323b7c7b8SHermès Bélusca-Maïto 
110423b7c7b8SHermès Bélusca-Maïto         //
110523b7c7b8SHermès Bélusca-Maïto         //  We loop here until we land on an Fcb that is in a good
110623b7c7b8SHermès Bélusca-Maïto         //  condition.  This way we can reopen files that have stale handles
110723b7c7b8SHermès Bélusca-Maïto         //  to files of the same name but are now different.
110823b7c7b8SHermès Bélusca-Maïto         //
110923b7c7b8SHermès Bélusca-Maïto 
111023b7c7b8SHermès Bélusca-Maïto         while ( TRUE ) {
111123b7c7b8SHermès Bélusca-Maïto 
111223b7c7b8SHermès Bélusca-Maïto             Fcb = ParentDcb;
111323b7c7b8SHermès Bélusca-Maïto             RemainingPart = FileName;
111423b7c7b8SHermès Bélusca-Maïto 
111523b7c7b8SHermès Bélusca-Maïto             //
111623b7c7b8SHermès Bélusca-Maïto             //  Now walk down the Dcb tree looking for the longest prefix.
111723b7c7b8SHermès Bélusca-Maïto             //  This one exit condition in the while() is to handle a
111823b7c7b8SHermès Bélusca-Maïto             //  special case condition (relative NULL name open), the main
111923b7c7b8SHermès Bélusca-Maïto             //  exit conditions are at the bottom of the loop.
112023b7c7b8SHermès Bélusca-Maïto             //
112123b7c7b8SHermès Bélusca-Maïto 
112223b7c7b8SHermès Bélusca-Maïto             while (RemainingPart.Length != 0) {
112323b7c7b8SHermès Bélusca-Maïto 
112423b7c7b8SHermès Bélusca-Maïto                 PFCB NextFcb;
112523b7c7b8SHermès Bélusca-Maïto 
112623b7c7b8SHermès Bélusca-Maïto                 FsRtlDissectName( RemainingPart,
112723b7c7b8SHermès Bélusca-Maïto                                   &FinalName,
112823b7c7b8SHermès Bélusca-Maïto                                   &NextRemainingPart );
112923b7c7b8SHermès Bélusca-Maïto 
113023b7c7b8SHermès Bélusca-Maïto                 //
113123b7c7b8SHermès Bélusca-Maïto                 //  If RemainingPart starts with a backslash the name is
113223b7c7b8SHermès Bélusca-Maïto                 //  invalid.
113323b7c7b8SHermès Bélusca-Maïto                 //  Check for no more than 255 characters in FinalName
113423b7c7b8SHermès Bélusca-Maïto                 //
113523b7c7b8SHermès Bélusca-Maïto 
113623b7c7b8SHermès Bélusca-Maïto                 if (((NextRemainingPart.Length != 0) && (NextRemainingPart.Buffer[0] == L'\\')) ||
113723b7c7b8SHermès Bélusca-Maïto                     (FinalName.Length > 255*sizeof(WCHAR))) {
113823b7c7b8SHermès Bélusca-Maïto 
113923b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
114023b7c7b8SHermès Bélusca-Maïto                 }
114123b7c7b8SHermès Bélusca-Maïto 
114223b7c7b8SHermès Bélusca-Maïto                 //
114323b7c7b8SHermès Bélusca-Maïto                 //  Now, try to convert this one component into Oem and search
114423b7c7b8SHermès Bélusca-Maïto                 //  the splay tree.  If it works then that's great, otherwise
114523b7c7b8SHermès Bélusca-Maïto                 //  we have to try with the UNICODE name instead.
114623b7c7b8SHermès Bélusca-Maïto                 //
114723b7c7b8SHermès Bélusca-Maïto 
114823b7c7b8SHermès Bélusca-Maïto                 FatEnsureStringBufferEnough( &OemFinalName,
114923b7c7b8SHermès Bélusca-Maïto                                              FinalName.Length);
115023b7c7b8SHermès Bélusca-Maïto 
115123b7c7b8SHermès Bélusca-Maïto                 Status = RtlUpcaseUnicodeStringToCountedOemString( &OemFinalName, &FinalName, FALSE );
115223b7c7b8SHermès Bélusca-Maïto 
115323b7c7b8SHermès Bélusca-Maïto 
115423b7c7b8SHermès Bélusca-Maïto                 if (NT_SUCCESS(Status)) {
115523b7c7b8SHermès Bélusca-Maïto 
115623b7c7b8SHermès Bélusca-Maïto                     NextFcb = FatFindFcb( IrpContext,
115723b7c7b8SHermès Bélusca-Maïto                                           &Fcb->Specific.Dcb.RootOemNode,
115823b7c7b8SHermès Bélusca-Maïto                                           (PSTRING)&OemFinalName,
115923b7c7b8SHermès Bélusca-Maïto                                           &FileNameOpenedDos );
116023b7c7b8SHermès Bélusca-Maïto 
116123b7c7b8SHermès Bélusca-Maïto                 } else {
116223b7c7b8SHermès Bélusca-Maïto 
116323b7c7b8SHermès Bélusca-Maïto                     NextFcb = NULL;
116423b7c7b8SHermès Bélusca-Maïto                     OemFinalName.Length = 0;
116523b7c7b8SHermès Bélusca-Maïto 
116623b7c7b8SHermès Bélusca-Maïto                     if (Status != STATUS_UNMAPPABLE_CHARACTER) {
116723b7c7b8SHermès Bélusca-Maïto 
116823b7c7b8SHermès Bélusca-Maïto                         try_return( Iosb.Status = Status );
116923b7c7b8SHermès Bélusca-Maïto                     }
117023b7c7b8SHermès Bélusca-Maïto                 }
117123b7c7b8SHermès Bélusca-Maïto 
117223b7c7b8SHermès Bélusca-Maïto                 //
117323b7c7b8SHermès Bélusca-Maïto                 //  If we didn't find anything searching the Oem space, we
117423b7c7b8SHermès Bélusca-Maïto                 //  have to try the Unicode space.  To save cycles in the
117523b7c7b8SHermès Bélusca-Maïto                 //  common case that this tree is empty, we do a quick check
117623b7c7b8SHermès Bélusca-Maïto                 //  here.
117723b7c7b8SHermès Bélusca-Maïto                 //
117823b7c7b8SHermès Bélusca-Maïto 
117923b7c7b8SHermès Bélusca-Maïto                 if ((NextFcb == NULL) && Fcb->Specific.Dcb.RootUnicodeNode) {
118023b7c7b8SHermès Bélusca-Maïto 
118123b7c7b8SHermès Bélusca-Maïto                     //
118223b7c7b8SHermès Bélusca-Maïto                     // First downcase, then upcase the string, because this
118323b7c7b8SHermès Bélusca-Maïto                     // is what happens when putting names into the tree (see
118423b7c7b8SHermès Bélusca-Maïto                     // strucsup.c, FatConstructNamesInFcb()).
118523b7c7b8SHermès Bélusca-Maïto                     //
118623b7c7b8SHermès Bélusca-Maïto 
118723b7c7b8SHermès Bélusca-Maïto                     FatEnsureStringBufferEnough( &UpcasedFinalName,
118823b7c7b8SHermès Bélusca-Maïto                                                  FinalName.Length);
118923b7c7b8SHermès Bélusca-Maïto 
119023b7c7b8SHermès Bélusca-Maïto                     Status = RtlDowncaseUnicodeString(&UpcasedFinalName, &FinalName, FALSE );
119123b7c7b8SHermès Bélusca-Maïto                     NT_ASSERT( NT_SUCCESS( Status ));
119223b7c7b8SHermès Bélusca-Maïto 
119323b7c7b8SHermès Bélusca-Maïto                     Status = RtlUpcaseUnicodeString( &UpcasedFinalName, &UpcasedFinalName, FALSE );
119423b7c7b8SHermès Bélusca-Maïto                     NT_ASSERT( NT_SUCCESS( Status ));
119523b7c7b8SHermès Bélusca-Maïto 
119623b7c7b8SHermès Bélusca-Maïto 
119723b7c7b8SHermès Bélusca-Maïto                     NextFcb = FatFindFcb( IrpContext,
119823b7c7b8SHermès Bélusca-Maïto                                           &Fcb->Specific.Dcb.RootUnicodeNode,
119923b7c7b8SHermès Bélusca-Maïto                                           (PSTRING)&UpcasedFinalName,
120023b7c7b8SHermès Bélusca-Maïto                                           &FileNameOpenedDos );
120123b7c7b8SHermès Bélusca-Maïto                 }
120223b7c7b8SHermès Bélusca-Maïto 
120323b7c7b8SHermès Bélusca-Maïto                 //
120423b7c7b8SHermès Bélusca-Maïto                 //  If we got back an Fcb then we consumed the FinalName
120523b7c7b8SHermès Bélusca-Maïto                 //  legitimately, so the remaining name is now RemainingPart.
120623b7c7b8SHermès Bélusca-Maïto                 //
120723b7c7b8SHermès Bélusca-Maïto 
120823b7c7b8SHermès Bélusca-Maïto                 if (NextFcb != NULL) {
120923b7c7b8SHermès Bélusca-Maïto                     Fcb = NextFcb;
121023b7c7b8SHermès Bélusca-Maïto                     RemainingPart = NextRemainingPart;
121123b7c7b8SHermès Bélusca-Maïto                 }
121223b7c7b8SHermès Bélusca-Maïto 
121323b7c7b8SHermès Bélusca-Maïto                 if ((NextFcb == NULL) ||
121423b7c7b8SHermès Bélusca-Maïto                     (NodeType(NextFcb) == FAT_NTC_FCB) ||
121523b7c7b8SHermès Bélusca-Maïto                     (NextRemainingPart.Length == 0)) {
121623b7c7b8SHermès Bélusca-Maïto 
121723b7c7b8SHermès Bélusca-Maïto                     break;
121823b7c7b8SHermès Bélusca-Maïto                 }
121923b7c7b8SHermès Bélusca-Maïto             }
122023b7c7b8SHermès Bélusca-Maïto 
122123b7c7b8SHermès Bélusca-Maïto             //
122223b7c7b8SHermès Bélusca-Maïto             //  Remaining name cannot start with a backslash
122323b7c7b8SHermès Bélusca-Maïto             //
122423b7c7b8SHermès Bélusca-Maïto 
122523b7c7b8SHermès Bélusca-Maïto             if (RemainingPart.Length && (RemainingPart.Buffer[0] == L'\\')) {
122623b7c7b8SHermès Bélusca-Maïto 
122723b7c7b8SHermès Bélusca-Maïto                 RemainingPart.Length -= sizeof(WCHAR);
122823b7c7b8SHermès Bélusca-Maïto                 RemainingPart.Buffer += 1;
122923b7c7b8SHermès Bélusca-Maïto             }
123023b7c7b8SHermès Bélusca-Maïto 
123123b7c7b8SHermès Bélusca-Maïto             //
123223b7c7b8SHermès Bélusca-Maïto             //  Now verify that everybody up to the longest found prefix is valid.
123323b7c7b8SHermès Bélusca-Maïto             //
123423b7c7b8SHermès Bélusca-Maïto 
123523b7c7b8SHermès Bélusca-Maïto             _SEH2_TRY {
123623b7c7b8SHermès Bélusca-Maïto 
123723b7c7b8SHermès Bélusca-Maïto                 FatVerifyFcb( IrpContext, Fcb );
123823b7c7b8SHermès Bélusca-Maïto 
123923b7c7b8SHermès Bélusca-Maïto             } _SEH2_EXCEPT( (_SEH2_GetExceptionCode() == STATUS_FILE_INVALID) ?
124023b7c7b8SHermès Bélusca-Maïto                       EXCEPTION_EXECUTE_HANDLER :
124123b7c7b8SHermès Bélusca-Maïto                       EXCEPTION_CONTINUE_SEARCH ) {
124223b7c7b8SHermès Bélusca-Maïto 
124323b7c7b8SHermès Bélusca-Maïto                   FatResetExceptionState( IrpContext );
124423b7c7b8SHermès Bélusca-Maïto             } _SEH2_END;
124523b7c7b8SHermès Bélusca-Maïto 
124623b7c7b8SHermès Bélusca-Maïto             if ( Fcb->FcbCondition == FcbGood ) {
124723b7c7b8SHermès Bélusca-Maïto 
124823b7c7b8SHermès Bélusca-Maïto                 //
124923b7c7b8SHermès Bélusca-Maïto                 //  If we are trying to open a paging file and have happened
125023b7c7b8SHermès Bélusca-Maïto                 //  upon the DelayedCloseFcb, make it go away, and try again.
125123b7c7b8SHermès Bélusca-Maïto                 //
125223b7c7b8SHermès Bélusca-Maïto 
125323b7c7b8SHermès Bélusca-Maïto                 if (IsPagingFile && FirstLoop &&
125423b7c7b8SHermès Bélusca-Maïto                     (NodeType(Fcb) == FAT_NTC_FCB) &&
125523b7c7b8SHermès Bélusca-Maïto                     (!IsListEmpty( &FatData.AsyncCloseList ) ||
125623b7c7b8SHermès Bélusca-Maïto                      !IsListEmpty( &FatData.DelayedCloseList ))) {
125723b7c7b8SHermès Bélusca-Maïto 
125823b7c7b8SHermès Bélusca-Maïto                     FatFspClose(Vcb);
125923b7c7b8SHermès Bélusca-Maïto 
126023b7c7b8SHermès Bélusca-Maïto                     FirstLoop = FALSE;
126123b7c7b8SHermès Bélusca-Maïto 
126223b7c7b8SHermès Bélusca-Maïto                     continue;
126323b7c7b8SHermès Bélusca-Maïto 
126423b7c7b8SHermès Bélusca-Maïto                 } else {
126523b7c7b8SHermès Bélusca-Maïto 
126623b7c7b8SHermès Bélusca-Maïto                     break;
126723b7c7b8SHermès Bélusca-Maïto                 }
126823b7c7b8SHermès Bélusca-Maïto 
126923b7c7b8SHermès Bélusca-Maïto             } else {
127023b7c7b8SHermès Bélusca-Maïto 
127123b7c7b8SHermès Bélusca-Maïto                 FatRemoveNames( IrpContext, Fcb );
127223b7c7b8SHermès Bélusca-Maïto             }
127323b7c7b8SHermès Bélusca-Maïto         }
127423b7c7b8SHermès Bélusca-Maïto 
127523b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( Fcb->FcbCondition == FcbGood );
127623b7c7b8SHermès Bélusca-Maïto 
127723b7c7b8SHermès Bélusca-Maïto         //
127823b7c7b8SHermès Bélusca-Maïto         //  If there is already an Fcb for a paging file open and
127923b7c7b8SHermès Bélusca-Maïto         //  it was not already opened as a paging file, we cannot
128023b7c7b8SHermès Bélusca-Maïto         //  continue as it is too difficult to move a live Fcb to
128123b7c7b8SHermès Bélusca-Maïto         //  non-paged pool.
128223b7c7b8SHermès Bélusca-Maïto         //
128323b7c7b8SHermès Bélusca-Maïto 
128423b7c7b8SHermès Bélusca-Maïto         if (IsPagingFile) {
128523b7c7b8SHermès Bélusca-Maïto 
128623b7c7b8SHermès Bélusca-Maïto             if (NodeType(Fcb) == FAT_NTC_FCB &&
128723b7c7b8SHermès Bélusca-Maïto                 !FlagOn( Fcb->FcbState, FCB_STATE_PAGING_FILE )) {
128823b7c7b8SHermès Bélusca-Maïto 
128923b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb.Status = STATUS_SHARING_VIOLATION );
129023b7c7b8SHermès Bélusca-Maïto             }
129123b7c7b8SHermès Bélusca-Maïto 
129223b7c7b8SHermès Bélusca-Maïto         //
129323b7c7b8SHermès Bélusca-Maïto         //  Check for a system file.
129423b7c7b8SHermès Bélusca-Maïto         //
129523b7c7b8SHermès Bélusca-Maïto 
129623b7c7b8SHermès Bélusca-Maïto         } else if (FlagOn( Fcb->FcbState, FCB_STATE_SYSTEM_FILE )) {
129723b7c7b8SHermès Bélusca-Maïto 
129823b7c7b8SHermès Bélusca-Maïto             try_return( Iosb.Status = STATUS_ACCESS_DENIED );
129923b7c7b8SHermès Bélusca-Maïto         }
130023b7c7b8SHermès Bélusca-Maïto 
130123b7c7b8SHermès Bélusca-Maïto         //
130223b7c7b8SHermès Bélusca-Maïto         //  If the longest prefix is pending delete (either the file or
130323b7c7b8SHermès Bélusca-Maïto         //  some higher level directory), we cannot continue.
130423b7c7b8SHermès Bélusca-Maïto         //
130523b7c7b8SHermès Bélusca-Maïto 
130623b7c7b8SHermès Bélusca-Maïto         if (FlagOn( Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE )) {
130723b7c7b8SHermès Bélusca-Maïto 
130823b7c7b8SHermès Bélusca-Maïto             try_return( Iosb.Status = STATUS_DELETE_PENDING );
130923b7c7b8SHermès Bélusca-Maïto         }
131023b7c7b8SHermès Bélusca-Maïto 
131123b7c7b8SHermès Bélusca-Maïto         //
131223b7c7b8SHermès Bélusca-Maïto         //  Now that we've found the longest matching prefix we'll
131323b7c7b8SHermès Bélusca-Maïto         //  check if there isn't any remaining part because that means
131423b7c7b8SHermès Bélusca-Maïto         //  we've located an existing fcb/dcb to open and we can do the open
131523b7c7b8SHermès Bélusca-Maïto         //  without going to the disk
131623b7c7b8SHermès Bélusca-Maïto         //
131723b7c7b8SHermès Bélusca-Maïto 
131823b7c7b8SHermès Bélusca-Maïto         if (RemainingPart.Length == 0) {
131923b7c7b8SHermès Bélusca-Maïto 
132023b7c7b8SHermès Bélusca-Maïto             //
132123b7c7b8SHermès Bélusca-Maïto             //  First check if the user wanted to open the target directory
132223b7c7b8SHermès Bélusca-Maïto             //  and if so then call the subroutine to finish the open.
132323b7c7b8SHermès Bélusca-Maïto             //
132423b7c7b8SHermès Bélusca-Maïto 
132523b7c7b8SHermès Bélusca-Maïto             if (OpenTargetDirectory) {
132623b7c7b8SHermès Bélusca-Maïto 
132723b7c7b8SHermès Bélusca-Maïto                 CollectCreateHitStatistics(Vcb);
132823b7c7b8SHermès Bélusca-Maïto 
132923b7c7b8SHermès Bélusca-Maïto                 Iosb = FatOpenTargetDirectory( IrpContext,
133023b7c7b8SHermès Bélusca-Maïto                                                FileObject,
133123b7c7b8SHermès Bélusca-Maïto                                                Fcb->ParentDcb,
133223b7c7b8SHermès Bélusca-Maïto                                                DesiredAccess,
133323b7c7b8SHermès Bélusca-Maïto                                                ShareAccess,
133423b7c7b8SHermès Bélusca-Maïto                                                TRUE,
133523b7c7b8SHermès Bélusca-Maïto                                                FileNameOpenedDos );
133623b7c7b8SHermès Bélusca-Maïto                 Irp->IoStatus.Information = Iosb.Information;
133723b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb.Status );
133823b7c7b8SHermès Bélusca-Maïto             }
133923b7c7b8SHermès Bélusca-Maïto 
134023b7c7b8SHermès Bélusca-Maïto             //
134123b7c7b8SHermès Bélusca-Maïto             //  We can open an existing fcb/dcb, now we only need to case
134223b7c7b8SHermès Bélusca-Maïto             //  on which type to open.
134323b7c7b8SHermès Bélusca-Maïto             //
134423b7c7b8SHermès Bélusca-Maïto 
134523b7c7b8SHermès Bélusca-Maïto             if (NodeType(Fcb) == FAT_NTC_DCB || NodeType(Fcb) == FAT_NTC_ROOT_DCB) {
134623b7c7b8SHermès Bélusca-Maïto 
134723b7c7b8SHermès Bélusca-Maïto                 //
134823b7c7b8SHermès Bélusca-Maïto                 //  This is a directory we're opening up so check if
134923b7c7b8SHermès Bélusca-Maïto                 //  we were not to open a directory
135023b7c7b8SHermès Bélusca-Maïto                 //
135123b7c7b8SHermès Bélusca-Maïto 
135223b7c7b8SHermès Bélusca-Maïto                 if (NonDirectoryFile) {
135323b7c7b8SHermès Bélusca-Maïto 
135423b7c7b8SHermès Bélusca-Maïto                     DebugTrace(0, Dbg, "Cannot open directory as a file\n", 0);
135523b7c7b8SHermès Bélusca-Maïto 
135623b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb.Status = STATUS_FILE_IS_A_DIRECTORY );
135723b7c7b8SHermès Bélusca-Maïto                 }
135823b7c7b8SHermès Bélusca-Maïto 
135923b7c7b8SHermès Bélusca-Maïto                 DebugTrace(0, Dbg, "Open existing dcb, Dcb = %p\n", Fcb);
136023b7c7b8SHermès Bélusca-Maïto 
136123b7c7b8SHermès Bélusca-Maïto                 CollectCreateHitStatistics(Vcb);
136223b7c7b8SHermès Bélusca-Maïto 
136323b7c7b8SHermès Bélusca-Maïto                 Iosb = FatOpenExistingDcb( IrpContext,
136423b7c7b8SHermès Bélusca-Maïto                                            IrpSp,
136523b7c7b8SHermès Bélusca-Maïto                                            FileObject,
136623b7c7b8SHermès Bélusca-Maïto                                            Vcb,
136723b7c7b8SHermès Bélusca-Maïto                                            (PDCB)Fcb,
136823b7c7b8SHermès Bélusca-Maïto                                            DesiredAccess,
136923b7c7b8SHermès Bélusca-Maïto                                            ShareAccess,
137023b7c7b8SHermès Bélusca-Maïto                                            CreateDisposition,
137123b7c7b8SHermès Bélusca-Maïto                                            NoEaKnowledge,
137223b7c7b8SHermès Bélusca-Maïto                                            DeleteOnClose,
137323b7c7b8SHermès Bélusca-Maïto                                            OpenRequiringOplock,
137423b7c7b8SHermès Bélusca-Maïto                                            FileNameOpenedDos,
137523b7c7b8SHermès Bélusca-Maïto                                            &OplockPostIrp );
137623b7c7b8SHermès Bélusca-Maïto 
137723b7c7b8SHermès Bélusca-Maïto                 if (Iosb.Status != STATUS_PENDING) {
137823b7c7b8SHermès Bélusca-Maïto 
137923b7c7b8SHermès Bélusca-Maïto                     Irp->IoStatus.Information = Iosb.Information;
138023b7c7b8SHermès Bélusca-Maïto 
138123b7c7b8SHermès Bélusca-Maïto                 } else {
138223b7c7b8SHermès Bélusca-Maïto 
138323b7c7b8SHermès Bélusca-Maïto                     DebugTrace(0, Dbg, "Enqueue Irp to FSP\n", 0);
138423b7c7b8SHermès Bélusca-Maïto 
138523b7c7b8SHermès Bélusca-Maïto                     PostIrp = TRUE;
138623b7c7b8SHermès Bélusca-Maïto                 }
138723b7c7b8SHermès Bélusca-Maïto 
138823b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb.Status );
138923b7c7b8SHermès Bélusca-Maïto             }
139023b7c7b8SHermès Bélusca-Maïto 
139123b7c7b8SHermès Bélusca-Maïto             //
139223b7c7b8SHermès Bélusca-Maïto             //  Check if we're trying to open an existing Fcb and that
139323b7c7b8SHermès Bélusca-Maïto             //  the user didn't want to open a directory.  Note that this
139423b7c7b8SHermès Bélusca-Maïto             //  call might actually come back with status_pending because
139523b7c7b8SHermès Bélusca-Maïto             //  the user wanted to supersede or overwrite the file and we
139623b7c7b8SHermès Bélusca-Maïto             //  cannot block.  If it is pending then we do not complete the
139723b7c7b8SHermès Bélusca-Maïto             //  request, and we fall through the bottom to the code that
139823b7c7b8SHermès Bélusca-Maïto             //  dispatches the request to the fsp.
139923b7c7b8SHermès Bélusca-Maïto             //
140023b7c7b8SHermès Bélusca-Maïto 
140123b7c7b8SHermès Bélusca-Maïto             if (NodeType(Fcb) == FAT_NTC_FCB) {
140223b7c7b8SHermès Bélusca-Maïto 
140323b7c7b8SHermès Bélusca-Maïto                 //
140423b7c7b8SHermès Bélusca-Maïto                 //  Check if we were only to open a directory
140523b7c7b8SHermès Bélusca-Maïto                 //
140623b7c7b8SHermès Bélusca-Maïto 
140723b7c7b8SHermès Bélusca-Maïto                 if (OpenDirectory) {
140823b7c7b8SHermès Bélusca-Maïto 
140923b7c7b8SHermès Bélusca-Maïto                     DebugTrace(0, Dbg, "Cannot open file as directory\n", 0);
141023b7c7b8SHermès Bélusca-Maïto 
141123b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb.Status = STATUS_NOT_A_DIRECTORY );
141223b7c7b8SHermès Bélusca-Maïto                 }
141323b7c7b8SHermès Bélusca-Maïto 
141423b7c7b8SHermès Bélusca-Maïto                 DebugTrace(0, Dbg, "Open existing fcb, Fcb = %p\n", Fcb);
141523b7c7b8SHermès Bélusca-Maïto 
141623b7c7b8SHermès Bélusca-Maïto                 if ( TrailingBackslash ) {
141723b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
141823b7c7b8SHermès Bélusca-Maïto                 }
141923b7c7b8SHermès Bélusca-Maïto 
142023b7c7b8SHermès Bélusca-Maïto                 CollectCreateHitStatistics(Vcb);
142123b7c7b8SHermès Bélusca-Maïto 
142223b7c7b8SHermès Bélusca-Maïto                 Iosb = FatOpenExistingFcb( IrpContext,
142323b7c7b8SHermès Bélusca-Maïto                                            IrpSp,
142423b7c7b8SHermès Bélusca-Maïto                                            FileObject,
142523b7c7b8SHermès Bélusca-Maïto                                            Vcb,
142623b7c7b8SHermès Bélusca-Maïto                                            Fcb,
142723b7c7b8SHermès Bélusca-Maïto                                            DesiredAccess,
142823b7c7b8SHermès Bélusca-Maïto                                            ShareAccess,
142923b7c7b8SHermès Bélusca-Maïto                                            AllocationSize,
143023b7c7b8SHermès Bélusca-Maïto                                            EaBuffer,
143123b7c7b8SHermès Bélusca-Maïto                                            EaLength,
143223b7c7b8SHermès Bélusca-Maïto                                            FileAttributes,
143323b7c7b8SHermès Bélusca-Maïto                                            CreateDisposition,
143423b7c7b8SHermès Bélusca-Maïto                                            NoEaKnowledge,
143523b7c7b8SHermès Bélusca-Maïto                                            DeleteOnClose,
143623b7c7b8SHermès Bélusca-Maïto                                            OpenRequiringOplock,
143723b7c7b8SHermès Bélusca-Maïto                                            FileNameOpenedDos,
143823b7c7b8SHermès Bélusca-Maïto                                            &OplockPostIrp );
143923b7c7b8SHermès Bélusca-Maïto 
144023b7c7b8SHermès Bélusca-Maïto                 if (Iosb.Status != STATUS_PENDING) {
144123b7c7b8SHermès Bélusca-Maïto 
144223b7c7b8SHermès Bélusca-Maïto                     //
144323b7c7b8SHermès Bélusca-Maïto                     //  Check if we need to set the cache support flag in
144423b7c7b8SHermès Bélusca-Maïto                     //  the file object
144523b7c7b8SHermès Bélusca-Maïto                     //
144623b7c7b8SHermès Bélusca-Maïto 
144723b7c7b8SHermès Bélusca-Maïto                     if (NT_SUCCESS( Iosb.Status) && !NoIntermediateBuffering) {
144823b7c7b8SHermès Bélusca-Maïto 
144923b7c7b8SHermès Bélusca-Maïto                         FileObject->Flags |= FO_CACHE_SUPPORTED;
145023b7c7b8SHermès Bélusca-Maïto                     }
145123b7c7b8SHermès Bélusca-Maïto 
145223b7c7b8SHermès Bélusca-Maïto                     Irp->IoStatus.Information = Iosb.Information;
145323b7c7b8SHermès Bélusca-Maïto 
145423b7c7b8SHermès Bélusca-Maïto                 } else {
145523b7c7b8SHermès Bélusca-Maïto 
145623b7c7b8SHermès Bélusca-Maïto                     DebugTrace(0, Dbg, "Enqueue Irp to FSP\n", 0);
145723b7c7b8SHermès Bélusca-Maïto 
145823b7c7b8SHermès Bélusca-Maïto                     PostIrp = TRUE;
145923b7c7b8SHermès Bélusca-Maïto                 }
146023b7c7b8SHermès Bélusca-Maïto 
146123b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb.Status );
146223b7c7b8SHermès Bélusca-Maïto             }
146323b7c7b8SHermès Bélusca-Maïto 
146423b7c7b8SHermès Bélusca-Maïto             //
146523b7c7b8SHermès Bélusca-Maïto             //  Not and Fcb or a Dcb so we bug check
146623b7c7b8SHermès Bélusca-Maïto             //
146723b7c7b8SHermès Bélusca-Maïto 
146823b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
146923b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress:28159, "this is a serious corruption if it happens" )
147023b7c7b8SHermès Bélusca-Maïto #endif
147123b7c7b8SHermès Bélusca-Maïto             FatBugCheck( NodeType(Fcb), (ULONG_PTR) Fcb, 0 );
147223b7c7b8SHermès Bélusca-Maïto         }
147323b7c7b8SHermès Bélusca-Maïto 
147423b7c7b8SHermès Bélusca-Maïto         //
147523b7c7b8SHermès Bélusca-Maïto         //  There is more in the name to parse than we have in existing
147623b7c7b8SHermès Bélusca-Maïto         //  fcbs/dcbs.  So now make sure that fcb we got for the largest
147723b7c7b8SHermès Bélusca-Maïto         //  matching prefix is really a dcb otherwise we can't go any
147823b7c7b8SHermès Bélusca-Maïto         //  further
147923b7c7b8SHermès Bélusca-Maïto         //
148023b7c7b8SHermès Bélusca-Maïto 
148123b7c7b8SHermès Bélusca-Maïto         if ((NodeType(Fcb) != FAT_NTC_DCB) && (NodeType(Fcb) != FAT_NTC_ROOT_DCB)) {
148223b7c7b8SHermès Bélusca-Maïto 
148323b7c7b8SHermès Bélusca-Maïto             DebugTrace(0, Dbg, "Cannot open file as subdirectory, Fcb = %p\n", Fcb);
148423b7c7b8SHermès Bélusca-Maïto 
148523b7c7b8SHermès Bélusca-Maïto             try_return( Iosb.Status = STATUS_OBJECT_PATH_NOT_FOUND );
148623b7c7b8SHermès Bélusca-Maïto         }
148723b7c7b8SHermès Bélusca-Maïto 
148823b7c7b8SHermès Bélusca-Maïto         //
148923b7c7b8SHermès Bélusca-Maïto         //  Otherwise we continue on processing the Irp and allowing ourselves
149023b7c7b8SHermès Bélusca-Maïto         //  to block for I/O as necessary.  Find/create additional dcb's for
149123b7c7b8SHermès Bélusca-Maïto         //  the one we're trying to open.  We loop until either remaining part
149223b7c7b8SHermès Bélusca-Maïto         //  is empty or we get a bad filename.  When we exit FinalName is
149323b7c7b8SHermès Bélusca-Maïto         //  the last name in the string we're after, and ParentDcb is the
149423b7c7b8SHermès Bélusca-Maïto         //  parent directory that will contain the opened/created
149523b7c7b8SHermès Bélusca-Maïto         //  file/directory.
149623b7c7b8SHermès Bélusca-Maïto         //
149723b7c7b8SHermès Bélusca-Maïto         //  Make sure the rest of the name is valid in at least the LFN
149823b7c7b8SHermès Bélusca-Maïto         //  character set (which just happens to be that of HPFS).
149923b7c7b8SHermès Bélusca-Maïto         //
150023b7c7b8SHermès Bélusca-Maïto         //  If we are not in ChicagoMode, use FAT semantics.
150123b7c7b8SHermès Bélusca-Maïto         //
150223b7c7b8SHermès Bélusca-Maïto 
150323b7c7b8SHermès Bélusca-Maïto         ParentDcb = Fcb;
150423b7c7b8SHermès Bélusca-Maïto         FirstLoop = TRUE;
150523b7c7b8SHermès Bélusca-Maïto 
150623b7c7b8SHermès Bélusca-Maïto         while (TRUE) {
150723b7c7b8SHermès Bélusca-Maïto 
150823b7c7b8SHermès Bélusca-Maïto             //
150923b7c7b8SHermès Bélusca-Maïto             //  We do one little optimization here on the first iteration of
151023b7c7b8SHermès Bélusca-Maïto             //  the loop since we know that we have already tried to convert
151123b7c7b8SHermès Bélusca-Maïto             //  FinalOemName from the original UNICODE.
151223b7c7b8SHermès Bélusca-Maïto             //
151323b7c7b8SHermès Bélusca-Maïto 
151423b7c7b8SHermès Bélusca-Maïto             if (FirstLoop) {
151523b7c7b8SHermès Bélusca-Maïto 
151623b7c7b8SHermès Bélusca-Maïto                 FirstLoop = FALSE;
151723b7c7b8SHermès Bélusca-Maïto                 RemainingPart = NextRemainingPart;
151823b7c7b8SHermès Bélusca-Maïto                 Status = OemFinalName.Length ? STATUS_SUCCESS : STATUS_UNMAPPABLE_CHARACTER;
151923b7c7b8SHermès Bélusca-Maïto 
152023b7c7b8SHermès Bélusca-Maïto             } else {
152123b7c7b8SHermès Bélusca-Maïto 
152223b7c7b8SHermès Bélusca-Maïto                 //
152323b7c7b8SHermès Bélusca-Maïto                 //  Dissect the remaining part.
152423b7c7b8SHermès Bélusca-Maïto                 //
152523b7c7b8SHermès Bélusca-Maïto 
152623b7c7b8SHermès Bélusca-Maïto                 DebugTrace(0, Dbg, "Dissecting the name %wZ\n", &RemainingPart);
152723b7c7b8SHermès Bélusca-Maïto 
152823b7c7b8SHermès Bélusca-Maïto                 FsRtlDissectName( RemainingPart,
152923b7c7b8SHermès Bélusca-Maïto                                   &FinalName,
153023b7c7b8SHermès Bélusca-Maïto                                   &RemainingPart );
153123b7c7b8SHermès Bélusca-Maïto 
153223b7c7b8SHermès Bélusca-Maïto                 //
153323b7c7b8SHermès Bélusca-Maïto                 //  If RemainingPart starts with a backslash the name is
153423b7c7b8SHermès Bélusca-Maïto                 //  invalid.
153523b7c7b8SHermès Bélusca-Maïto                 //  Check for no more than 255 characters in FinalName
153623b7c7b8SHermès Bélusca-Maïto                 //
153723b7c7b8SHermès Bélusca-Maïto 
153823b7c7b8SHermès Bélusca-Maïto                 if (((RemainingPart.Length != 0) && (RemainingPart.Buffer[0] == L'\\')) ||
153923b7c7b8SHermès Bélusca-Maïto                     (FinalName.Length > 255*sizeof(WCHAR))) {
154023b7c7b8SHermès Bélusca-Maïto 
154123b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
154223b7c7b8SHermès Bélusca-Maïto                 }
154323b7c7b8SHermès Bélusca-Maïto 
154423b7c7b8SHermès Bélusca-Maïto                 //
154523b7c7b8SHermès Bélusca-Maïto                 //  Now, try to convert this one component into Oem.  If it works
154623b7c7b8SHermès Bélusca-Maïto                 //  then that's great, otherwise we have to try with the UNICODE
154723b7c7b8SHermès Bélusca-Maïto                 //  name instead.
154823b7c7b8SHermès Bélusca-Maïto                 //
154923b7c7b8SHermès Bélusca-Maïto 
155023b7c7b8SHermès Bélusca-Maïto                 FatEnsureStringBufferEnough( &OemFinalName,
155123b7c7b8SHermès Bélusca-Maïto                                              FinalName.Length);
155223b7c7b8SHermès Bélusca-Maïto 
155323b7c7b8SHermès Bélusca-Maïto                 Status = RtlUpcaseUnicodeStringToCountedOemString( &OemFinalName, &FinalName, FALSE );
155423b7c7b8SHermès Bélusca-Maïto             }
155523b7c7b8SHermès Bélusca-Maïto 
155623b7c7b8SHermès Bélusca-Maïto             if (NT_SUCCESS(Status)) {
155723b7c7b8SHermès Bélusca-Maïto 
155823b7c7b8SHermès Bélusca-Maïto                 //
155923b7c7b8SHermès Bélusca-Maïto                 //  We'll start by trying to locate the dirent for the name.  Note
156023b7c7b8SHermès Bélusca-Maïto                 //  that we already know that there isn't an Fcb/Dcb for the file
156123b7c7b8SHermès Bélusca-Maïto                 //  otherwise we would have found it when we did our prefix lookup.
156223b7c7b8SHermès Bélusca-Maïto                 //
156323b7c7b8SHermès Bélusca-Maïto 
156423b7c7b8SHermès Bélusca-Maïto                 if (FatIsNameShortOemValid( IrpContext, OemFinalName, FALSE, FALSE, FALSE )) {
156523b7c7b8SHermès Bélusca-Maïto 
156623b7c7b8SHermès Bélusca-Maïto                     FatStringTo8dot3( IrpContext,
156723b7c7b8SHermès Bélusca-Maïto                                       OemFinalName,
156823b7c7b8SHermès Bélusca-Maïto                                       &LocalCcb.OemQueryTemplate.Constant );
156923b7c7b8SHermès Bélusca-Maïto 
157023b7c7b8SHermès Bélusca-Maïto                     LocalCcb.Flags = 0;
157123b7c7b8SHermès Bélusca-Maïto 
157223b7c7b8SHermès Bélusca-Maïto                 } else {
157323b7c7b8SHermès Bélusca-Maïto 
157423b7c7b8SHermès Bélusca-Maïto                     LocalCcb.Flags = CCB_FLAG_SKIP_SHORT_NAME_COMPARE;
157523b7c7b8SHermès Bélusca-Maïto                 }
157623b7c7b8SHermès Bélusca-Maïto 
157723b7c7b8SHermès Bélusca-Maïto             } else {
157823b7c7b8SHermès Bélusca-Maïto 
157923b7c7b8SHermès Bélusca-Maïto                 LocalCcb.Flags = CCB_FLAG_SKIP_SHORT_NAME_COMPARE;
158023b7c7b8SHermès Bélusca-Maïto 
158123b7c7b8SHermès Bélusca-Maïto                 if (Status != STATUS_UNMAPPABLE_CHARACTER) {
158223b7c7b8SHermès Bélusca-Maïto 
158323b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb.Status = Status );
158423b7c7b8SHermès Bélusca-Maïto                 }
158523b7c7b8SHermès Bélusca-Maïto             }
158623b7c7b8SHermès Bélusca-Maïto 
158723b7c7b8SHermès Bélusca-Maïto             //
158823b7c7b8SHermès Bélusca-Maïto             //  Now we know a lot about the final name, so do legal name
158923b7c7b8SHermès Bélusca-Maïto             //  checking here.
159023b7c7b8SHermès Bélusca-Maïto             //
159123b7c7b8SHermès Bélusca-Maïto 
159223b7c7b8SHermès Bélusca-Maïto             if (FatData.ChicagoMode) {
159323b7c7b8SHermès Bélusca-Maïto 
159423b7c7b8SHermès Bélusca-Maïto                 if (!FatIsNameLongUnicodeValid( IrpContext, &FinalName, FALSE, FALSE, FALSE )) {
159523b7c7b8SHermès Bélusca-Maïto 
159623b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
159723b7c7b8SHermès Bélusca-Maïto                 }
159823b7c7b8SHermès Bélusca-Maïto 
159923b7c7b8SHermès Bélusca-Maïto             } else {
160023b7c7b8SHermès Bélusca-Maïto 
160123b7c7b8SHermès Bélusca-Maïto                 if (FlagOn(LocalCcb.Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE)) {
160223b7c7b8SHermès Bélusca-Maïto 
160323b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
160423b7c7b8SHermès Bélusca-Maïto                 }
160523b7c7b8SHermès Bélusca-Maïto             }
160623b7c7b8SHermès Bélusca-Maïto 
160723b7c7b8SHermès Bélusca-Maïto             DebugTrace(0, Dbg, "FinalName is %wZ\n", &FinalName);
160823b7c7b8SHermès Bélusca-Maïto             DebugTrace(0, Dbg, "RemainingPart is %wZ\n", &RemainingPart);
160923b7c7b8SHermès Bélusca-Maïto 
161023b7c7b8SHermès Bélusca-Maïto             FatEnsureStringBufferEnough( &UpcasedFinalName,
161123b7c7b8SHermès Bélusca-Maïto                                          FinalName.Length);
161223b7c7b8SHermès Bélusca-Maïto 
161323b7c7b8SHermès Bélusca-Maïto             if (!NT_SUCCESS(Status = RtlUpcaseUnicodeString( &UpcasedFinalName, &FinalName, FALSE))) {
161423b7c7b8SHermès Bélusca-Maïto 
161523b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb.Status = Status );
161623b7c7b8SHermès Bélusca-Maïto             }
161723b7c7b8SHermès Bélusca-Maïto 
161823b7c7b8SHermès Bélusca-Maïto             LocalCcb.UnicodeQueryTemplate =  UpcasedFinalName;
161923b7c7b8SHermès Bélusca-Maïto             LocalCcb.ContainsWildCards = FALSE;
162023b7c7b8SHermès Bélusca-Maïto 
162123b7c7b8SHermès Bélusca-Maïto             Lfn.Length = 0;
162223b7c7b8SHermès Bélusca-Maïto 
162323b7c7b8SHermès Bélusca-Maïto 
162423b7c7b8SHermès Bélusca-Maïto             FatLocateDirent( IrpContext,
162523b7c7b8SHermès Bélusca-Maïto                              ParentDcb,
162623b7c7b8SHermès Bélusca-Maïto                              &LocalCcb,
162723b7c7b8SHermès Bélusca-Maïto                              0,
162823b7c7b8SHermès Bélusca-Maïto                              &MatchFlags,
162923b7c7b8SHermès Bélusca-Maïto                              &Dirent,
163023b7c7b8SHermès Bélusca-Maïto                              &DirentBcb,
163123b7c7b8SHermès Bélusca-Maïto                              (PVBO)&DirentByteOffset,
163223b7c7b8SHermès Bélusca-Maïto                              &FileNameOpenedDos,
163323b7c7b8SHermès Bélusca-Maïto                              &Lfn,
163423b7c7b8SHermès Bélusca-Maïto                              &OrigLfn);
163523b7c7b8SHermès Bélusca-Maïto 
163623b7c7b8SHermès Bélusca-Maïto             //
163723b7c7b8SHermès Bélusca-Maïto             //  Remember we read this Dcb for error recovery.
163823b7c7b8SHermès Bélusca-Maïto             //
163923b7c7b8SHermès Bélusca-Maïto 
164023b7c7b8SHermès Bélusca-Maïto             FinalDcb = ParentDcb;
164123b7c7b8SHermès Bélusca-Maïto 
164223b7c7b8SHermès Bélusca-Maïto             //
164323b7c7b8SHermès Bélusca-Maïto             //  If the remaining part is now empty then this is the last name
164423b7c7b8SHermès Bélusca-Maïto             //  in the string and the one we want to open
164523b7c7b8SHermès Bélusca-Maïto             //
164623b7c7b8SHermès Bélusca-Maïto 
164723b7c7b8SHermès Bélusca-Maïto             if (RemainingPart.Length == 0) {
164823b7c7b8SHermès Bélusca-Maïto 
164923b7c7b8SHermès Bélusca-Maïto 
165023b7c7b8SHermès Bélusca-Maïto                 break;
165123b7c7b8SHermès Bélusca-Maïto             }
165223b7c7b8SHermès Bélusca-Maïto 
165323b7c7b8SHermès Bélusca-Maïto             //
165423b7c7b8SHermès Bélusca-Maïto             //  We didn't find a dirent, bail.
165523b7c7b8SHermès Bélusca-Maïto             //
165623b7c7b8SHermès Bélusca-Maïto 
165723b7c7b8SHermès Bélusca-Maïto             if (Dirent == NULL) {
165823b7c7b8SHermès Bélusca-Maïto 
165923b7c7b8SHermès Bélusca-Maïto                 Iosb.Status = STATUS_OBJECT_PATH_NOT_FOUND;
166023b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb.Status );
166123b7c7b8SHermès Bélusca-Maïto             }
166223b7c7b8SHermès Bélusca-Maïto 
166323b7c7b8SHermès Bélusca-Maïto             //
166423b7c7b8SHermès Bélusca-Maïto             //  We now have a dirent, make sure it is a directory
166523b7c7b8SHermès Bélusca-Maïto             //
166623b7c7b8SHermès Bélusca-Maïto 
166723b7c7b8SHermès Bélusca-Maïto             if (!FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY )) {
166823b7c7b8SHermès Bélusca-Maïto 
166923b7c7b8SHermès Bélusca-Maïto                 Iosb.Status = STATUS_OBJECT_PATH_NOT_FOUND;
167023b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb.Status );
167123b7c7b8SHermès Bélusca-Maïto             }
167223b7c7b8SHermès Bélusca-Maïto 
167323b7c7b8SHermès Bélusca-Maïto             //
167423b7c7b8SHermès Bélusca-Maïto             //  Compute the LfnByteOffset.
167523b7c7b8SHermès Bélusca-Maïto             //
167623b7c7b8SHermès Bélusca-Maïto 
167723b7c7b8SHermès Bélusca-Maïto             LfnByteOffset = DirentByteOffset -
167823b7c7b8SHermès Bélusca-Maïto                             FAT_LFN_DIRENTS_NEEDED(&OrigLfn) * sizeof(LFN_DIRENT);
167923b7c7b8SHermès Bélusca-Maïto 
168023b7c7b8SHermès Bélusca-Maïto             //
168123b7c7b8SHermès Bélusca-Maïto             //  Create a dcb for the new directory
168223b7c7b8SHermès Bélusca-Maïto             //
168323b7c7b8SHermès Bélusca-Maïto 
168423b7c7b8SHermès Bélusca-Maïto             ParentDcb = FatCreateDcb( IrpContext,
168523b7c7b8SHermès Bélusca-Maïto                                       Vcb,
168623b7c7b8SHermès Bélusca-Maïto                                       ParentDcb,
168723b7c7b8SHermès Bélusca-Maïto                                       LfnByteOffset,
168823b7c7b8SHermès Bélusca-Maïto                                       DirentByteOffset,
168923b7c7b8SHermès Bélusca-Maïto                                       Dirent,
169023b7c7b8SHermès Bélusca-Maïto                                       &Lfn );
169123b7c7b8SHermès Bélusca-Maïto 
169223b7c7b8SHermès Bélusca-Maïto             //
169323b7c7b8SHermès Bélusca-Maïto             //  Remember we created this Dcb for error recovery.
169423b7c7b8SHermès Bélusca-Maïto             //
169523b7c7b8SHermès Bélusca-Maïto 
169623b7c7b8SHermès Bélusca-Maïto             FinalDcb = ParentDcb;
169723b7c7b8SHermès Bélusca-Maïto 
169823b7c7b8SHermès Bélusca-Maïto             FatSetFullNameInFcb( IrpContext, ParentDcb, &FinalName );
169923b7c7b8SHermès Bélusca-Maïto         }
170023b7c7b8SHermès Bélusca-Maïto 
170123b7c7b8SHermès Bélusca-Maïto         //
170223b7c7b8SHermès Bélusca-Maïto         //  First check if the user wanted to open the target directory
170323b7c7b8SHermès Bélusca-Maïto         //  and if so then call the subroutine to finish the open.
170423b7c7b8SHermès Bélusca-Maïto         //
170523b7c7b8SHermès Bélusca-Maïto 
170623b7c7b8SHermès Bélusca-Maïto         if (OpenTargetDirectory) {
170723b7c7b8SHermès Bélusca-Maïto 
170823b7c7b8SHermès Bélusca-Maïto             Iosb = FatOpenTargetDirectory( IrpContext,
170923b7c7b8SHermès Bélusca-Maïto                                            FileObject,
171023b7c7b8SHermès Bélusca-Maïto                                            ParentDcb,
171123b7c7b8SHermès Bélusca-Maïto                                            DesiredAccess,
171223b7c7b8SHermès Bélusca-Maïto                                            ShareAccess,
171323b7c7b8SHermès Bélusca-Maïto                                            Dirent ? TRUE : FALSE,
171423b7c7b8SHermès Bélusca-Maïto                                            FileNameOpenedDos);
171523b7c7b8SHermès Bélusca-Maïto 
171623b7c7b8SHermès Bélusca-Maïto             Irp->IoStatus.Information = Iosb.Information;
171723b7c7b8SHermès Bélusca-Maïto             try_return( Iosb.Status );
171823b7c7b8SHermès Bélusca-Maïto         }
171923b7c7b8SHermès Bélusca-Maïto 
172023b7c7b8SHermès Bélusca-Maïto         if (Dirent != NULL) {
172123b7c7b8SHermès Bélusca-Maïto 
172223b7c7b8SHermès Bélusca-Maïto             //
172323b7c7b8SHermès Bélusca-Maïto             //  Compute the LfnByteOffset.
172423b7c7b8SHermès Bélusca-Maïto             //
172523b7c7b8SHermès Bélusca-Maïto 
172623b7c7b8SHermès Bélusca-Maïto             LfnByteOffset = DirentByteOffset -
172723b7c7b8SHermès Bélusca-Maïto                             FAT_LFN_DIRENTS_NEEDED(&OrigLfn) * sizeof(LFN_DIRENT);
172823b7c7b8SHermès Bélusca-Maïto 
172923b7c7b8SHermès Bélusca-Maïto             //
173023b7c7b8SHermès Bélusca-Maïto             //  We were able to locate an existing dirent entry, so now
173123b7c7b8SHermès Bélusca-Maïto             //  see if it is a directory that we're trying to open.
173223b7c7b8SHermès Bélusca-Maïto             //
173323b7c7b8SHermès Bélusca-Maïto 
173423b7c7b8SHermès Bélusca-Maïto             if (FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY )) {
173523b7c7b8SHermès Bélusca-Maïto 
173623b7c7b8SHermès Bélusca-Maïto                 //
173723b7c7b8SHermès Bélusca-Maïto                 //  Make sure its okay to open a directory
173823b7c7b8SHermès Bélusca-Maïto                 //
173923b7c7b8SHermès Bélusca-Maïto 
174023b7c7b8SHermès Bélusca-Maïto                 if (NonDirectoryFile) {
174123b7c7b8SHermès Bélusca-Maïto 
174223b7c7b8SHermès Bélusca-Maïto                     DebugTrace(0, Dbg, "Cannot open directory as a file\n", 0);
174323b7c7b8SHermès Bélusca-Maïto 
174423b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb.Status = STATUS_FILE_IS_A_DIRECTORY );
174523b7c7b8SHermès Bélusca-Maïto                 }
174623b7c7b8SHermès Bélusca-Maïto 
174723b7c7b8SHermès Bélusca-Maïto                 DebugTrace(0, Dbg, "Open existing directory\n", 0);
174823b7c7b8SHermès Bélusca-Maïto 
174923b7c7b8SHermès Bélusca-Maïto                 Iosb = FatOpenExistingDirectory( IrpContext,
175023b7c7b8SHermès Bélusca-Maïto                                                  IrpSp,
175123b7c7b8SHermès Bélusca-Maïto                                                  FileObject,
175223b7c7b8SHermès Bélusca-Maïto                                                  Vcb,
175323b7c7b8SHermès Bélusca-Maïto                                                  &Fcb,
175423b7c7b8SHermès Bélusca-Maïto                                                  ParentDcb,
175523b7c7b8SHermès Bélusca-Maïto                                                  Dirent,
175623b7c7b8SHermès Bélusca-Maïto                                                  LfnByteOffset,
175723b7c7b8SHermès Bélusca-Maïto                                                  DirentByteOffset,
175823b7c7b8SHermès Bélusca-Maïto                                                  &Lfn,
175923b7c7b8SHermès Bélusca-Maïto                                                  DesiredAccess,
176023b7c7b8SHermès Bélusca-Maïto                                                  ShareAccess,
176123b7c7b8SHermès Bélusca-Maïto                                                  CreateDisposition,
176223b7c7b8SHermès Bélusca-Maïto                                                  NoEaKnowledge,
176323b7c7b8SHermès Bélusca-Maïto                                                  DeleteOnClose,
176423b7c7b8SHermès Bélusca-Maïto                                                  FileNameOpenedDos,
176523b7c7b8SHermès Bélusca-Maïto                                                  OpenRequiringOplock );
176623b7c7b8SHermès Bélusca-Maïto 
176723b7c7b8SHermès Bélusca-Maïto                 Irp->IoStatus.Information = Iosb.Information;
176823b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb.Status );
176923b7c7b8SHermès Bélusca-Maïto             }
177023b7c7b8SHermès Bélusca-Maïto 
177123b7c7b8SHermès Bélusca-Maïto             //
177223b7c7b8SHermès Bélusca-Maïto             //  Otherwise we're trying to open and existing file, and we
177323b7c7b8SHermès Bélusca-Maïto             //  need to check if the user only wanted to open a directory.
177423b7c7b8SHermès Bélusca-Maïto             //
177523b7c7b8SHermès Bélusca-Maïto 
177623b7c7b8SHermès Bélusca-Maïto             if (OpenDirectory) {
177723b7c7b8SHermès Bélusca-Maïto 
177823b7c7b8SHermès Bélusca-Maïto                 DebugTrace(0, Dbg, "Cannot open file as directory\n", 0);
177923b7c7b8SHermès Bélusca-Maïto 
178023b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb.Status = STATUS_NOT_A_DIRECTORY );
178123b7c7b8SHermès Bélusca-Maïto             }
178223b7c7b8SHermès Bélusca-Maïto 
178323b7c7b8SHermès Bélusca-Maïto             DebugTrace(0, Dbg, "Open existing file\n", 0);
178423b7c7b8SHermès Bélusca-Maïto 
178523b7c7b8SHermès Bélusca-Maïto             if ( TrailingBackslash ) {
178623b7c7b8SHermès Bélusca-Maïto                try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
178723b7c7b8SHermès Bélusca-Maïto             }
178823b7c7b8SHermès Bélusca-Maïto 
178923b7c7b8SHermès Bélusca-Maïto 
179023b7c7b8SHermès Bélusca-Maïto             Iosb = FatOpenExistingFile( IrpContext,
179123b7c7b8SHermès Bélusca-Maïto                                         FileObject,
179223b7c7b8SHermès Bélusca-Maïto                                         Vcb,
179323b7c7b8SHermès Bélusca-Maïto                                         &Fcb,
179423b7c7b8SHermès Bélusca-Maïto                                         ParentDcb,
179523b7c7b8SHermès Bélusca-Maïto                                         Dirent,
179623b7c7b8SHermès Bélusca-Maïto                                         LfnByteOffset,
179723b7c7b8SHermès Bélusca-Maïto                                         DirentByteOffset,
179823b7c7b8SHermès Bélusca-Maïto                                         &Lfn,
179923b7c7b8SHermès Bélusca-Maïto                                         &OrigLfn,
180023b7c7b8SHermès Bélusca-Maïto                                         DesiredAccess,
180123b7c7b8SHermès Bélusca-Maïto                                         ShareAccess,
180223b7c7b8SHermès Bélusca-Maïto                                         AllocationSize,
180323b7c7b8SHermès Bélusca-Maïto                                         EaBuffer,
180423b7c7b8SHermès Bélusca-Maïto                                         EaLength,
180523b7c7b8SHermès Bélusca-Maïto                                         FileAttributes,
180623b7c7b8SHermès Bélusca-Maïto                                         CreateDisposition,
180723b7c7b8SHermès Bélusca-Maïto                                         IsPagingFile,
180823b7c7b8SHermès Bélusca-Maïto                                         NoEaKnowledge,
180923b7c7b8SHermès Bélusca-Maïto                                         DeleteOnClose,
181023b7c7b8SHermès Bélusca-Maïto                                         OpenRequiringOplock,
181123b7c7b8SHermès Bélusca-Maïto                                         FileNameOpenedDos );
181223b7c7b8SHermès Bélusca-Maïto 
181323b7c7b8SHermès Bélusca-Maïto             //
181423b7c7b8SHermès Bélusca-Maïto             //  Check if we need to set the cache support flag in
181523b7c7b8SHermès Bélusca-Maïto             //  the file object
181623b7c7b8SHermès Bélusca-Maïto             //
181723b7c7b8SHermès Bélusca-Maïto 
181823b7c7b8SHermès Bélusca-Maïto             if (NT_SUCCESS(Iosb.Status) && !NoIntermediateBuffering) {
181923b7c7b8SHermès Bélusca-Maïto 
182023b7c7b8SHermès Bélusca-Maïto                 FileObject->Flags |= FO_CACHE_SUPPORTED;
182123b7c7b8SHermès Bélusca-Maïto             }
182223b7c7b8SHermès Bélusca-Maïto 
182323b7c7b8SHermès Bélusca-Maïto             Irp->IoStatus.Information = Iosb.Information;
182423b7c7b8SHermès Bélusca-Maïto             try_return( Iosb.Status );
182523b7c7b8SHermès Bélusca-Maïto         }
182623b7c7b8SHermès Bélusca-Maïto 
182723b7c7b8SHermès Bélusca-Maïto         //
182823b7c7b8SHermès Bélusca-Maïto         //  We can't locate a dirent so this is a new file.
182923b7c7b8SHermès Bélusca-Maïto         //
183023b7c7b8SHermès Bélusca-Maïto 
183123b7c7b8SHermès Bélusca-Maïto         //
183223b7c7b8SHermès Bélusca-Maïto         //  Now check to see if we wanted to only open an existing file.
183323b7c7b8SHermès Bélusca-Maïto         //  And then case on whether we wanted to create a file or a directory.
183423b7c7b8SHermès Bélusca-Maïto         //
183523b7c7b8SHermès Bélusca-Maïto 
183623b7c7b8SHermès Bélusca-Maïto         if ((CreateDisposition == FILE_OPEN) ||
183723b7c7b8SHermès Bélusca-Maïto             (CreateDisposition == FILE_OVERWRITE)) {
183823b7c7b8SHermès Bélusca-Maïto 
183923b7c7b8SHermès Bélusca-Maïto             DebugTrace( 0, Dbg, "Cannot open nonexisting file\n", 0);
184023b7c7b8SHermès Bélusca-Maïto 
184123b7c7b8SHermès Bélusca-Maïto             try_return( Iosb.Status = STATUS_OBJECT_NAME_NOT_FOUND );
184223b7c7b8SHermès Bélusca-Maïto         }
184323b7c7b8SHermès Bélusca-Maïto 
184423b7c7b8SHermès Bélusca-Maïto         //
184523b7c7b8SHermès Bélusca-Maïto         //  Skip a few cycles later if we know now that the Oem name is not
184623b7c7b8SHermès Bélusca-Maïto         //  valid 8.3.
184723b7c7b8SHermès Bélusca-Maïto         //
184823b7c7b8SHermès Bélusca-Maïto 
184923b7c7b8SHermès Bélusca-Maïto         if (FlagOn(LocalCcb.Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE)) {
185023b7c7b8SHermès Bélusca-Maïto 
185123b7c7b8SHermès Bélusca-Maïto             OemFinalName.Length = 0;
185223b7c7b8SHermès Bélusca-Maïto         }
185323b7c7b8SHermès Bélusca-Maïto 
185423b7c7b8SHermès Bélusca-Maïto         //
185523b7c7b8SHermès Bélusca-Maïto         //  Determine the granted access for this operation now.
185623b7c7b8SHermès Bélusca-Maïto         //
185723b7c7b8SHermès Bélusca-Maïto 
185823b7c7b8SHermès Bélusca-Maïto         if (!NT_SUCCESS( Iosb.Status = FatCheckSystemSecurityAccess( IrpContext ))) {
185923b7c7b8SHermès Bélusca-Maïto 
186023b7c7b8SHermès Bélusca-Maïto             try_return( Iosb );
186123b7c7b8SHermès Bélusca-Maïto         }
186223b7c7b8SHermès Bélusca-Maïto 
186323b7c7b8SHermès Bélusca-Maïto         if (CreateDirectory) {
186423b7c7b8SHermès Bélusca-Maïto 
186523b7c7b8SHermès Bélusca-Maïto             DebugTrace(0, Dbg, "Create new directory\n", 0);
186623b7c7b8SHermès Bélusca-Maïto 
186723b7c7b8SHermès Bélusca-Maïto             //
186823b7c7b8SHermès Bélusca-Maïto             //  If this media is write protected, don't even try the create.
186923b7c7b8SHermès Bélusca-Maïto             //
187023b7c7b8SHermès Bélusca-Maïto 
187123b7c7b8SHermès Bélusca-Maïto             if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
187223b7c7b8SHermès Bélusca-Maïto 
187323b7c7b8SHermès Bélusca-Maïto                 //
187423b7c7b8SHermès Bélusca-Maïto                 //  Set the real device for the pop-up info, and set the verify
187523b7c7b8SHermès Bélusca-Maïto                 //  bit in the device object, so that we will force a verify
187623b7c7b8SHermès Bélusca-Maïto                 //  in case the user put the correct media back in.
187723b7c7b8SHermès Bélusca-Maïto                 //
187823b7c7b8SHermès Bélusca-Maïto 
187923b7c7b8SHermès Bélusca-Maïto 
188023b7c7b8SHermès Bélusca-Maïto                 IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
188123b7c7b8SHermès Bélusca-Maïto                                               Vcb->Vpb->RealDevice );
188223b7c7b8SHermès Bélusca-Maïto 
188323b7c7b8SHermès Bélusca-Maïto                 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
188423b7c7b8SHermès Bélusca-Maïto 
188523b7c7b8SHermès Bélusca-Maïto                 FatRaiseStatus( IrpContext, STATUS_MEDIA_WRITE_PROTECTED );
188623b7c7b8SHermès Bélusca-Maïto             }
188723b7c7b8SHermès Bélusca-Maïto 
188823b7c7b8SHermès Bélusca-Maïto             //
188923b7c7b8SHermès Bélusca-Maïto             //  Don't allow people to create directories with the
189023b7c7b8SHermès Bélusca-Maïto             //  temporary bit set.
189123b7c7b8SHermès Bélusca-Maïto             //
189223b7c7b8SHermès Bélusca-Maïto 
189323b7c7b8SHermès Bélusca-Maïto             if (TemporaryFile) {
189423b7c7b8SHermès Bélusca-Maïto 
189523b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb.Status = STATUS_INVALID_PARAMETER );
189623b7c7b8SHermès Bélusca-Maïto             }
189723b7c7b8SHermès Bélusca-Maïto 
189823b7c7b8SHermès Bélusca-Maïto             Iosb = FatCreateNewDirectory( IrpContext,
189923b7c7b8SHermès Bélusca-Maïto                                           IrpSp,
190023b7c7b8SHermès Bélusca-Maïto                                           FileObject,
190123b7c7b8SHermès Bélusca-Maïto                                           Vcb,
190223b7c7b8SHermès Bélusca-Maïto                                           ParentDcb,
190323b7c7b8SHermès Bélusca-Maïto                                           &OemFinalName,
190423b7c7b8SHermès Bélusca-Maïto                                           &FinalName,
190523b7c7b8SHermès Bélusca-Maïto                                           DesiredAccess,
190623b7c7b8SHermès Bélusca-Maïto                                           ShareAccess,
190723b7c7b8SHermès Bélusca-Maïto                                           EaBuffer,
190823b7c7b8SHermès Bélusca-Maïto                                           EaLength,
190923b7c7b8SHermès Bélusca-Maïto                                           FileAttributes,
191023b7c7b8SHermès Bélusca-Maïto                                           NoEaKnowledge,
191123b7c7b8SHermès Bélusca-Maïto                                           DeleteOnClose,
191223b7c7b8SHermès Bélusca-Maïto                                           OpenRequiringOplock );
191323b7c7b8SHermès Bélusca-Maïto 
191423b7c7b8SHermès Bélusca-Maïto             Irp->IoStatus.Information = Iosb.Information;
191523b7c7b8SHermès Bélusca-Maïto             try_return( Iosb.Status );
191623b7c7b8SHermès Bélusca-Maïto         }
191723b7c7b8SHermès Bélusca-Maïto 
191823b7c7b8SHermès Bélusca-Maïto         DebugTrace(0, Dbg, "Create new file\n", 0);
191923b7c7b8SHermès Bélusca-Maïto 
192023b7c7b8SHermès Bélusca-Maïto         if ( TrailingBackslash ) {
192123b7c7b8SHermès Bélusca-Maïto 
192223b7c7b8SHermès Bélusca-Maïto             try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
192323b7c7b8SHermès Bélusca-Maïto         }
192423b7c7b8SHermès Bélusca-Maïto 
192523b7c7b8SHermès Bélusca-Maïto         //
192623b7c7b8SHermès Bélusca-Maïto         //  If this media is write protected, don't even try the create.
192723b7c7b8SHermès Bélusca-Maïto         //
192823b7c7b8SHermès Bélusca-Maïto 
192923b7c7b8SHermès Bélusca-Maïto         if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
193023b7c7b8SHermès Bélusca-Maïto 
193123b7c7b8SHermès Bélusca-Maïto             //
193223b7c7b8SHermès Bélusca-Maïto             //  Set the real device for the pop-up info, and set the verify
193323b7c7b8SHermès Bélusca-Maïto             //  bit in the device object, so that we will force a verify
193423b7c7b8SHermès Bélusca-Maïto             //  in case the user put the correct media back in.
193523b7c7b8SHermès Bélusca-Maïto             //
193623b7c7b8SHermès Bélusca-Maïto 
193723b7c7b8SHermès Bélusca-Maïto 
193823b7c7b8SHermès Bélusca-Maïto             IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
193923b7c7b8SHermès Bélusca-Maïto                                           Vcb->Vpb->RealDevice );
194023b7c7b8SHermès Bélusca-Maïto 
194123b7c7b8SHermès Bélusca-Maïto             SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
194223b7c7b8SHermès Bélusca-Maïto 
194323b7c7b8SHermès Bélusca-Maïto             FatRaiseStatus( IrpContext, STATUS_MEDIA_WRITE_PROTECTED );
194423b7c7b8SHermès Bélusca-Maïto         }
194523b7c7b8SHermès Bélusca-Maïto 
194623b7c7b8SHermès Bélusca-Maïto 
194723b7c7b8SHermès Bélusca-Maïto         Iosb = FatCreateNewFile( IrpContext,
194823b7c7b8SHermès Bélusca-Maïto                                  IrpSp,
194923b7c7b8SHermès Bélusca-Maïto                                  FileObject,
195023b7c7b8SHermès Bélusca-Maïto                                  Vcb,
195123b7c7b8SHermès Bélusca-Maïto                                  ParentDcb,
195223b7c7b8SHermès Bélusca-Maïto                                  &OemFinalName,
195323b7c7b8SHermès Bélusca-Maïto                                  &FinalName,
195423b7c7b8SHermès Bélusca-Maïto                                  DesiredAccess,
195523b7c7b8SHermès Bélusca-Maïto                                  ShareAccess,
195623b7c7b8SHermès Bélusca-Maïto                                  AllocationSize,
195723b7c7b8SHermès Bélusca-Maïto                                  EaBuffer,
195823b7c7b8SHermès Bélusca-Maïto                                  EaLength,
195923b7c7b8SHermès Bélusca-Maïto                                  FileAttributes,
196023b7c7b8SHermès Bélusca-Maïto                                  &Lfn,
196123b7c7b8SHermès Bélusca-Maïto                                  IsPagingFile,
196223b7c7b8SHermès Bélusca-Maïto                                  NoEaKnowledge,
196323b7c7b8SHermès Bélusca-Maïto                                  DeleteOnClose,
196423b7c7b8SHermès Bélusca-Maïto                                  OpenRequiringOplock,
196523b7c7b8SHermès Bélusca-Maïto                                  TemporaryFile );
196623b7c7b8SHermès Bélusca-Maïto 
196723b7c7b8SHermès Bélusca-Maïto         //
196823b7c7b8SHermès Bélusca-Maïto         //  Check if we need to set the cache support flag in
196923b7c7b8SHermès Bélusca-Maïto         //  the file object
197023b7c7b8SHermès Bélusca-Maïto         //
197123b7c7b8SHermès Bélusca-Maïto 
197223b7c7b8SHermès Bélusca-Maïto         if (NT_SUCCESS(Iosb.Status) && !NoIntermediateBuffering) {
197323b7c7b8SHermès Bélusca-Maïto 
197423b7c7b8SHermès Bélusca-Maïto             FileObject->Flags |= FO_CACHE_SUPPORTED;
197523b7c7b8SHermès Bélusca-Maïto         }
197623b7c7b8SHermès Bélusca-Maïto 
197723b7c7b8SHermès Bélusca-Maïto         Irp->IoStatus.Information = Iosb.Information;
197823b7c7b8SHermès Bélusca-Maïto 
197923b7c7b8SHermès Bélusca-Maïto     try_exit: NOTHING;
198023b7c7b8SHermès Bélusca-Maïto 
198123b7c7b8SHermès Bélusca-Maïto         //
198223b7c7b8SHermès Bélusca-Maïto         //  This is a Beta Fix.  Do this at a better place later.
198323b7c7b8SHermès Bélusca-Maïto         //
198423b7c7b8SHermès Bélusca-Maïto 
198523b7c7b8SHermès Bélusca-Maïto         if (NT_SUCCESS(Iosb.Status) && !OpenTargetDirectory) {
198623b7c7b8SHermès Bélusca-Maïto 
198723b7c7b8SHermès Bélusca-Maïto             PFCB LocalFcb;
198823b7c7b8SHermès Bélusca-Maïto 
198923b7c7b8SHermès Bélusca-Maïto             //
199023b7c7b8SHermès Bélusca-Maïto             //  If there is an Fcb/Dcb, set the long file name.
199123b7c7b8SHermès Bélusca-Maïto             //
199223b7c7b8SHermès Bélusca-Maïto 
199323b7c7b8SHermès Bélusca-Maïto             LocalFcb = FileObject->FsContext;
199423b7c7b8SHermès Bélusca-Maïto 
199523b7c7b8SHermès Bélusca-Maïto             if (LocalFcb &&
199623b7c7b8SHermès Bélusca-Maïto                 ((NodeType(LocalFcb) == FAT_NTC_FCB) ||
199723b7c7b8SHermès Bélusca-Maïto                  (NodeType(LocalFcb) == FAT_NTC_DCB)) &&
199823b7c7b8SHermès Bélusca-Maïto                 (LocalFcb->FullFileName.Buffer == NULL)) {
199923b7c7b8SHermès Bélusca-Maïto 
200023b7c7b8SHermès Bélusca-Maïto                 FatSetFullNameInFcb( IrpContext, LocalFcb, &FinalName );
200123b7c7b8SHermès Bélusca-Maïto             }
200223b7c7b8SHermès Bélusca-Maïto         }
200323b7c7b8SHermès Bélusca-Maïto 
200423b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
200523b7c7b8SHermès Bélusca-Maïto 
200623b7c7b8SHermès Bélusca-Maïto         DebugUnwind( FatCommonCreate );
200723b7c7b8SHermès Bélusca-Maïto 
200823b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN7)
200923b7c7b8SHermès Bélusca-Maïto 
201023b7c7b8SHermès Bélusca-Maïto         //
201123b7c7b8SHermès Bélusca-Maïto         //  If we're not getting out with success, and if the caller wanted
201223b7c7b8SHermès Bélusca-Maïto         //  atomic create-with-oplock semantics make sure we back out any
201323b7c7b8SHermès Bélusca-Maïto         //  oplock that may have been granted.
201423b7c7b8SHermès Bélusca-Maïto         //
201523b7c7b8SHermès Bélusca-Maïto 
201623b7c7b8SHermès Bélusca-Maïto         if ((AbnormalTermination() ||
201723b7c7b8SHermès Bélusca-Maïto              !NT_SUCCESS( Iosb.Status )) &&
201823b7c7b8SHermès Bélusca-Maïto             OpenRequiringOplock &&
201923b7c7b8SHermès Bélusca-Maïto             (Iosb.Status != STATUS_CANNOT_BREAK_OPLOCK) &&
202023b7c7b8SHermès Bélusca-Maïto             (IrpContext->ExceptionStatus != STATUS_CANNOT_BREAK_OPLOCK) &&
202123b7c7b8SHermès Bélusca-Maïto             (Fcb != NULL) &&
202223b7c7b8SHermès Bélusca-Maïto             FatIsFileOplockable( Fcb )) {
202323b7c7b8SHermès Bélusca-Maïto 
202423b7c7b8SHermès Bélusca-Maïto             FsRtlCheckOplockEx( FatGetFcbOplock(Fcb),
202523b7c7b8SHermès Bélusca-Maïto                                 IrpContext->OriginatingIrp,
202623b7c7b8SHermès Bélusca-Maïto                                 OPLOCK_FLAG_BACK_OUT_ATOMIC_OPLOCK,
202723b7c7b8SHermès Bélusca-Maïto                                 NULL,
202823b7c7b8SHermès Bélusca-Maïto                                 NULL,
202923b7c7b8SHermès Bélusca-Maïto                                 NULL );
203023b7c7b8SHermès Bélusca-Maïto         }
203123b7c7b8SHermès Bélusca-Maïto #endif
203223b7c7b8SHermès Bélusca-Maïto 
203323b7c7b8SHermès Bélusca-Maïto         //
203423b7c7b8SHermès Bélusca-Maïto         //  There used to be a test here - the ASSERT replaces it.  We will
203523b7c7b8SHermès Bélusca-Maïto         //  never have begun enumerating directories if we post the IRP for
203623b7c7b8SHermès Bélusca-Maïto         //  oplock reasons.
203723b7c7b8SHermès Bélusca-Maïto         //
203823b7c7b8SHermès Bélusca-Maïto 
203923b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( !OplockPostIrp || DirentBcb == NULL );
204023b7c7b8SHermès Bélusca-Maïto 
204123b7c7b8SHermès Bélusca-Maïto         FatUnpinBcb( IrpContext, DirentBcb );
204223b7c7b8SHermès Bélusca-Maïto 
204323b7c7b8SHermès Bélusca-Maïto         //
204423b7c7b8SHermès Bélusca-Maïto         //  If we are in an error path, check for any created subdir Dcbs that
204523b7c7b8SHermès Bélusca-Maïto         //  have to be unwound.  Don't whack the root directory.
204623b7c7b8SHermès Bélusca-Maïto         //
204723b7c7b8SHermès Bélusca-Maïto         //  Note this will leave a branch of Dcbs dangling if the directory file
204823b7c7b8SHermès Bélusca-Maïto         //  had not been built on the leaf (case: opening path which has an
204923b7c7b8SHermès Bélusca-Maïto         //  element containing an invalid character name).
205023b7c7b8SHermès Bélusca-Maïto         //
205123b7c7b8SHermès Bélusca-Maïto 
205223b7c7b8SHermès Bélusca-Maïto         if (_SEH2_AbnormalTermination() || !NT_SUCCESS(Iosb.Status)) {
205323b7c7b8SHermès Bélusca-Maïto 
205423b7c7b8SHermès Bélusca-Maïto             ULONG SavedFlags;
205523b7c7b8SHermès Bélusca-Maïto 
205623b7c7b8SHermès Bélusca-Maïto             //
205723b7c7b8SHermès Bélusca-Maïto             //  Before doing the uninitialize, we have to unpin anything
205823b7c7b8SHermès Bélusca-Maïto             //  that has been repinned, but disable writethrough first.  We
205923b7c7b8SHermès Bélusca-Maïto             //  disable raise from unpin-repin since we're already failing.
206023b7c7b8SHermès Bélusca-Maïto             //
206123b7c7b8SHermès Bélusca-Maïto 
206223b7c7b8SHermès Bélusca-Maïto             SavedFlags = IrpContext->Flags;
206323b7c7b8SHermès Bélusca-Maïto 
206423b7c7b8SHermès Bélusca-Maïto             SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_RAISE |
206523b7c7b8SHermès Bélusca-Maïto                                         IRP_CONTEXT_FLAG_DISABLE_WRITE_THROUGH );
206623b7c7b8SHermès Bélusca-Maïto 
206723b7c7b8SHermès Bélusca-Maïto             FatUnpinRepinnedBcbs( IrpContext );
206823b7c7b8SHermès Bélusca-Maïto 
206923b7c7b8SHermès Bélusca-Maïto             if ((FinalDcb != NULL) &&
207023b7c7b8SHermès Bélusca-Maïto                 (NodeType(FinalDcb) == FAT_NTC_DCB) &&
207123b7c7b8SHermès Bélusca-Maïto                 IsListEmpty(&FinalDcb->Specific.Dcb.ParentDcbQueue) &&
207223b7c7b8SHermès Bélusca-Maïto                 (FinalDcb->OpenCount == 0) &&
207323b7c7b8SHermès Bélusca-Maïto                 (FinalDcb->Specific.Dcb.DirectoryFile != NULL)) {
207423b7c7b8SHermès Bélusca-Maïto 
207523b7c7b8SHermès Bélusca-Maïto                 PFILE_OBJECT DirectoryFileObject;
207623b7c7b8SHermès Bélusca-Maïto 
207723b7c7b8SHermès Bélusca-Maïto                 DirectoryFileObject = FinalDcb->Specific.Dcb.DirectoryFile;
207823b7c7b8SHermès Bélusca-Maïto 
207923b7c7b8SHermès Bélusca-Maïto                 FinalDcb->Specific.Dcb.DirectoryFile = NULL;
208023b7c7b8SHermès Bélusca-Maïto 
208123b7c7b8SHermès Bélusca-Maïto                 CcUninitializeCacheMap( DirectoryFileObject, NULL, NULL );
208223b7c7b8SHermès Bélusca-Maïto 
208323b7c7b8SHermès Bélusca-Maïto                 ObDereferenceObject( DirectoryFileObject );
208423b7c7b8SHermès Bélusca-Maïto             }
208523b7c7b8SHermès Bélusca-Maïto 
208623b7c7b8SHermès Bélusca-Maïto             IrpContext->Flags = SavedFlags;
208723b7c7b8SHermès Bélusca-Maïto         }
208823b7c7b8SHermès Bélusca-Maïto 
208923b7c7b8SHermès Bélusca-Maïto         if (_SEH2_AbnormalTermination()) {
209023b7c7b8SHermès Bélusca-Maïto 
209123b7c7b8SHermès Bélusca-Maïto             FatReleaseVcb( IrpContext, Vcb );
209223b7c7b8SHermès Bélusca-Maïto         }
209323b7c7b8SHermès Bélusca-Maïto 
209423b7c7b8SHermès Bélusca-Maïto         //
209523b7c7b8SHermès Bélusca-Maïto         //  Free up any string buffers we allocated
209623b7c7b8SHermès Bélusca-Maïto         //
209723b7c7b8SHermès Bélusca-Maïto 
209823b7c7b8SHermès Bélusca-Maïto         FatFreeStringBuffer( &OemFinalName);
209923b7c7b8SHermès Bélusca-Maïto 
210023b7c7b8SHermès Bélusca-Maïto         FatFreeStringBuffer( &UpcasedFinalName);
210123b7c7b8SHermès Bélusca-Maïto 
210223b7c7b8SHermès Bélusca-Maïto         FatFreeStringBuffer( &Lfn);
210323b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
210423b7c7b8SHermès Bélusca-Maïto 
210523b7c7b8SHermès Bélusca-Maïto     //
210623b7c7b8SHermès Bélusca-Maïto     //  The following code is only executed if we are exiting the
210723b7c7b8SHermès Bélusca-Maïto     //  procedure through a normal termination.  We complete the request
210823b7c7b8SHermès Bélusca-Maïto     //  and if for any reason that bombs out then we need to unreference
210923b7c7b8SHermès Bélusca-Maïto     //  and possibly delete the fcb and ccb.
211023b7c7b8SHermès Bélusca-Maïto     //
211123b7c7b8SHermès Bélusca-Maïto 
211223b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
211323b7c7b8SHermès Bélusca-Maïto 
211423b7c7b8SHermès Bélusca-Maïto         if (PostIrp) {
211523b7c7b8SHermès Bélusca-Maïto 
211623b7c7b8SHermès Bélusca-Maïto             //
211723b7c7b8SHermès Bélusca-Maïto             //  If the Irp hasn't already been posted, do it now.
211823b7c7b8SHermès Bélusca-Maïto             //
211923b7c7b8SHermès Bélusca-Maïto 
212023b7c7b8SHermès Bélusca-Maïto             if (!OplockPostIrp) {
212123b7c7b8SHermès Bélusca-Maïto 
212223b7c7b8SHermès Bélusca-Maïto                 Iosb.Status = FatFsdPostRequest( IrpContext, Irp );
212323b7c7b8SHermès Bélusca-Maïto             }
212423b7c7b8SHermès Bélusca-Maïto 
212523b7c7b8SHermès Bélusca-Maïto         } else {
212623b7c7b8SHermès Bélusca-Maïto 
212723b7c7b8SHermès Bélusca-Maïto             FatUnpinRepinnedBcbs( IrpContext );
212823b7c7b8SHermès Bélusca-Maïto         }
212923b7c7b8SHermès Bélusca-Maïto 
213023b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
213123b7c7b8SHermès Bélusca-Maïto 
213223b7c7b8SHermès Bélusca-Maïto         DebugUnwind( FatCommonCreate-in-FatCompleteRequest );
213323b7c7b8SHermès Bélusca-Maïto 
213423b7c7b8SHermès Bélusca-Maïto         if (_SEH2_AbnormalTermination() ) {
213523b7c7b8SHermès Bélusca-Maïto 
213623b7c7b8SHermès Bélusca-Maïto             PVCB LocalVcb;
213723b7c7b8SHermès Bélusca-Maïto             PFCB LocalFcb;
213823b7c7b8SHermès Bélusca-Maïto             PCCB LocalCcb2;
213923b7c7b8SHermès Bélusca-Maïto             PFILE_OBJECT DirectoryFileObject;
214023b7c7b8SHermès Bélusca-Maïto 
214123b7c7b8SHermès Bélusca-Maïto             //
214223b7c7b8SHermès Bélusca-Maïto             //  Unwind all of our counts.  Note that if a write failed, then
214323b7c7b8SHermès Bélusca-Maïto             //  the volume has been marked for verify, and all volume
214423b7c7b8SHermès Bélusca-Maïto             //  structures will be cleaned up automatically.
214523b7c7b8SHermès Bélusca-Maïto             //
214623b7c7b8SHermès Bélusca-Maïto 
214723b7c7b8SHermès Bélusca-Maïto             (VOID) FatDecodeFileObject( FileObject, &LocalVcb, &LocalFcb, &LocalCcb2 );
214823b7c7b8SHermès Bélusca-Maïto 
214923b7c7b8SHermès Bélusca-Maïto             LocalFcb->UncleanCount -= 1;
215023b7c7b8SHermès Bélusca-Maïto             LocalFcb->OpenCount -= 1;
215123b7c7b8SHermès Bélusca-Maïto             LocalVcb->OpenFileCount -= 1;
215223b7c7b8SHermès Bélusca-Maïto 
215323b7c7b8SHermès Bélusca-Maïto             if (IsFileObjectReadOnly(FileObject)) { LocalVcb->ReadOnlyCount -= 1; }
215423b7c7b8SHermès Bélusca-Maïto 
215523b7c7b8SHermès Bélusca-Maïto 
215623b7c7b8SHermès Bélusca-Maïto             //
215723b7c7b8SHermès Bélusca-Maïto             //  WinSE #307418 "Occasional data corruption when standby/resume
215823b7c7b8SHermès Bélusca-Maïto             //  while copying files to removable FAT formatted media".
215923b7c7b8SHermès Bélusca-Maïto             //  If new file creation request was interrupted by system suspend
216023b7c7b8SHermès Bélusca-Maïto             //  operation we should revert the changes we made to the parent
216123b7c7b8SHermès Bélusca-Maïto             //  directory and to the allocation table.
216223b7c7b8SHermès Bélusca-Maïto             //
216323b7c7b8SHermès Bélusca-Maïto 
216423b7c7b8SHermès Bélusca-Maïto             if (IrpContext->ExceptionStatus == STATUS_VERIFY_REQUIRED &&
216523b7c7b8SHermès Bélusca-Maïto                 NodeType( LocalFcb ) == FAT_NTC_FCB) {
216623b7c7b8SHermès Bélusca-Maïto 
216723b7c7b8SHermès Bélusca-Maïto                 FatTruncateFileAllocation( IrpContext, LocalFcb, 0 );
216823b7c7b8SHermès Bélusca-Maïto 
216923b7c7b8SHermès Bélusca-Maïto                 FatDeleteDirent( IrpContext, LocalFcb, NULL, TRUE );
217023b7c7b8SHermès Bélusca-Maïto             }
217123b7c7b8SHermès Bélusca-Maïto 
217223b7c7b8SHermès Bélusca-Maïto             //
217323b7c7b8SHermès Bélusca-Maïto             //  If we leafed out on a new Fcb we should get rid of it at this point.
217423b7c7b8SHermès Bélusca-Maïto             //
217523b7c7b8SHermès Bélusca-Maïto             //  Since the object isn't being opened, we have to do all of the teardown
217623b7c7b8SHermès Bélusca-Maïto             //  here.  Our close path will not occur for this fileobject. Note this
217723b7c7b8SHermès Bélusca-Maïto             //  will leave a branch of Dcbs dangling since we do it by hand and don't
217823b7c7b8SHermès Bélusca-Maïto             //  chase to the root.
217923b7c7b8SHermès Bélusca-Maïto             //
218023b7c7b8SHermès Bélusca-Maïto 
218123b7c7b8SHermès Bélusca-Maïto             if (LocalFcb->OpenCount == 0 &&
218223b7c7b8SHermès Bélusca-Maïto                 (NodeType( LocalFcb ) == FAT_NTC_FCB ||
218323b7c7b8SHermès Bélusca-Maïto                  IsListEmpty(&LocalFcb->Specific.Dcb.ParentDcbQueue))) {
218423b7c7b8SHermès Bélusca-Maïto 
218523b7c7b8SHermès Bélusca-Maïto                 NT_ASSERT( NodeType( LocalFcb ) != FAT_NTC_ROOT_DCB );
218623b7c7b8SHermès Bélusca-Maïto 
218723b7c7b8SHermès Bélusca-Maïto                 if ( (NodeType( LocalFcb ) == FAT_NTC_DCB) &&
218823b7c7b8SHermès Bélusca-Maïto                      (LocalFcb->Specific.Dcb.DirectoryFile != NULL) ) {
218923b7c7b8SHermès Bélusca-Maïto 
219023b7c7b8SHermès Bélusca-Maïto                     DirectoryFileObject = LocalFcb->Specific.Dcb.DirectoryFile;
219123b7c7b8SHermès Bélusca-Maïto                     LocalFcb->Specific.Dcb.DirectoryFile = NULL;
219223b7c7b8SHermès Bélusca-Maïto 
219323b7c7b8SHermès Bélusca-Maïto                     CcUninitializeCacheMap( DirectoryFileObject,
219423b7c7b8SHermès Bélusca-Maïto                                             &FatLargeZero,
219523b7c7b8SHermès Bélusca-Maïto                                             NULL );
219623b7c7b8SHermès Bélusca-Maïto 
219723b7c7b8SHermès Bélusca-Maïto                     ObDereferenceObject( DirectoryFileObject );
219823b7c7b8SHermès Bélusca-Maïto 
219923b7c7b8SHermès Bélusca-Maïto                 } else {
220023b7c7b8SHermès Bélusca-Maïto                     if (ARGUMENT_PRESENT( FileObject )) {
220123b7c7b8SHermès Bélusca-Maïto                         FileObject->SectionObjectPointer = NULL;
220223b7c7b8SHermès Bélusca-Maïto                     }
220323b7c7b8SHermès Bélusca-Maïto                     FatDeleteFcb( IrpContext, &LocalFcb );
220423b7c7b8SHermès Bélusca-Maïto                 }
220523b7c7b8SHermès Bélusca-Maïto             }
220623b7c7b8SHermès Bélusca-Maïto 
220723b7c7b8SHermès Bélusca-Maïto             FatDeleteCcb( IrpContext, &LocalCcb2 );
220823b7c7b8SHermès Bélusca-Maïto 
220923b7c7b8SHermès Bélusca-Maïto             FatReleaseVcb( IrpContext, LocalVcb );
221023b7c7b8SHermès Bélusca-Maïto 
221123b7c7b8SHermès Bélusca-Maïto         } else {
221223b7c7b8SHermès Bélusca-Maïto 
221323b7c7b8SHermès Bélusca-Maïto             FatReleaseVcb( IrpContext, Vcb );
221423b7c7b8SHermès Bélusca-Maïto 
221523b7c7b8SHermès Bélusca-Maïto             if ( !PostIrp ) {
221623b7c7b8SHermès Bélusca-Maïto 
221723b7c7b8SHermès Bélusca-Maïto                 //
221823b7c7b8SHermès Bélusca-Maïto                 //  If this request is successful and the file was opened
221923b7c7b8SHermès Bélusca-Maïto                 //  for FILE_EXECUTE access, then set the FileObject bit.
222023b7c7b8SHermès Bélusca-Maïto                 //
222123b7c7b8SHermès Bélusca-Maïto 
222223b7c7b8SHermès Bélusca-Maïto                 NT_ASSERT( IrpSp->Parameters.Create.SecurityContext != NULL );
222323b7c7b8SHermès Bélusca-Maïto                 if (FlagOn( *DesiredAccess, FILE_EXECUTE )) {
222423b7c7b8SHermès Bélusca-Maïto 
222523b7c7b8SHermès Bélusca-Maïto                     SetFlag( FileObject->Flags, FO_FILE_FAST_IO_READ );
222623b7c7b8SHermès Bélusca-Maïto                 }
222723b7c7b8SHermès Bélusca-Maïto 
222823b7c7b8SHermès Bélusca-Maïto                 //
222923b7c7b8SHermès Bélusca-Maïto                 //  Lock volume in drive if we opened a paging file, allocating a
223023b7c7b8SHermès Bélusca-Maïto                 //  reserve MDL to guarantee paging file operations can always
223123b7c7b8SHermès Bélusca-Maïto                 //  go forward.
223223b7c7b8SHermès Bélusca-Maïto                 //
223323b7c7b8SHermès Bélusca-Maïto 
223423b7c7b8SHermès Bélusca-Maïto                 if (IsPagingFile && NT_SUCCESS(Iosb.Status)) {
223523b7c7b8SHermès Bélusca-Maïto 
223623b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
223723b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress:28112, "this should be safe" )
223823b7c7b8SHermès Bélusca-Maïto #endif
223923b7c7b8SHermès Bélusca-Maïto                     if (!FatReserveMdl) {
224023b7c7b8SHermès Bélusca-Maïto 
224123b7c7b8SHermès Bélusca-Maïto                         PMDL ReserveMdl = IoAllocateMdl( NULL,
224223b7c7b8SHermès Bélusca-Maïto                                                          FAT_RESERVE_MDL_SIZE * PAGE_SIZE,
224323b7c7b8SHermès Bélusca-Maïto                                                          TRUE,
224423b7c7b8SHermès Bélusca-Maïto                                                          FALSE,
224523b7c7b8SHermès Bélusca-Maïto                                                          NULL );
224623b7c7b8SHermès Bélusca-Maïto 
224723b7c7b8SHermès Bélusca-Maïto                         //
224823b7c7b8SHermès Bélusca-Maïto                         //  Stash the MDL, and if it turned out there was already one there
224923b7c7b8SHermès Bélusca-Maïto                         //  just free what we got.
225023b7c7b8SHermès Bélusca-Maïto                         //
225123b7c7b8SHermès Bélusca-Maïto 
225223b7c7b8SHermès Bélusca-Maïto #ifndef __REACTOS__
225323b7c7b8SHermès Bélusca-Maïto                         InterlockedCompareExchangePointer( &FatReserveMdl, ReserveMdl, NULL );
225423b7c7b8SHermès Bélusca-Maïto #else
225523b7c7b8SHermès Bélusca-Maïto                         InterlockedCompareExchangePointer( (void * volatile*)&FatReserveMdl, ReserveMdl, NULL );
225623b7c7b8SHermès Bélusca-Maïto #endif
225723b7c7b8SHermès Bélusca-Maïto 
225823b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
225923b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress:28112, "this should be safe" )
226023b7c7b8SHermès Bélusca-Maïto #endif
226123b7c7b8SHermès Bélusca-Maïto                         if (FatReserveMdl != ReserveMdl) {
226223b7c7b8SHermès Bélusca-Maïto 
226323b7c7b8SHermès Bélusca-Maïto                             IoFreeMdl( ReserveMdl );
226423b7c7b8SHermès Bélusca-Maïto                         }
226523b7c7b8SHermès Bélusca-Maïto                     }
226623b7c7b8SHermès Bélusca-Maïto 
226723b7c7b8SHermès Bélusca-Maïto                     SetFlag(Vcb->VcbState, VCB_STATE_FLAG_BOOT_OR_PAGING_FILE);
226823b7c7b8SHermès Bélusca-Maïto 
226923b7c7b8SHermès Bélusca-Maïto                     if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA)) {
227023b7c7b8SHermès Bélusca-Maïto 
227123b7c7b8SHermès Bélusca-Maïto                         FatToggleMediaEjectDisable( IrpContext, Vcb, TRUE );
227223b7c7b8SHermès Bélusca-Maïto                     }
227323b7c7b8SHermès Bélusca-Maïto                 }
227423b7c7b8SHermès Bélusca-Maïto 
227523b7c7b8SHermès Bélusca-Maïto             }
227623b7c7b8SHermès Bélusca-Maïto         }
227723b7c7b8SHermès Bélusca-Maïto 
227823b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatCommonCreate -> %08lx\n", Iosb.Status);
227923b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
228023b7c7b8SHermès Bélusca-Maïto 
228123b7c7b8SHermès Bélusca-Maïto     CollectCreateStatistics(Vcb, Iosb.Status);
228223b7c7b8SHermès Bélusca-Maïto 
228323b7c7b8SHermès Bélusca-Maïto     return Iosb.Status;
228423b7c7b8SHermès Bélusca-Maïto }
228523b7c7b8SHermès Bélusca-Maïto 
228623b7c7b8SHermès Bélusca-Maïto //
228723b7c7b8SHermès Bélusca-Maïto //  Internal support routine
228823b7c7b8SHermès Bélusca-Maïto //
228923b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)229023b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
229123b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
229223b7c7b8SHermès Bélusca-Maïto FatOpenVolume (
229323b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
229423b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
229523b7c7b8SHermès Bélusca-Maïto     _Inout_ PVCB Vcb,
229623b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
229723b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
229823b7c7b8SHermès Bélusca-Maïto     _In_ ULONG CreateDisposition
229923b7c7b8SHermès Bélusca-Maïto     )
230023b7c7b8SHermès Bélusca-Maïto 
230123b7c7b8SHermès Bélusca-Maïto /*++
230223b7c7b8SHermès Bélusca-Maïto 
230323b7c7b8SHermès Bélusca-Maïto Routine Description:
230423b7c7b8SHermès Bélusca-Maïto 
230523b7c7b8SHermès Bélusca-Maïto     This routine opens the specified volume for DASD access
230623b7c7b8SHermès Bélusca-Maïto 
230723b7c7b8SHermès Bélusca-Maïto Arguments:
230823b7c7b8SHermès Bélusca-Maïto 
230923b7c7b8SHermès Bélusca-Maïto     FileObject - Supplies the File object
231023b7c7b8SHermès Bélusca-Maïto 
231123b7c7b8SHermès Bélusca-Maïto     Vcb - Supplies the Vcb denoting the volume being opened
231223b7c7b8SHermès Bélusca-Maïto 
231323b7c7b8SHermès Bélusca-Maïto     DesiredAccess - Supplies the desired access of the caller
231423b7c7b8SHermès Bélusca-Maïto 
231523b7c7b8SHermès Bélusca-Maïto     ShareAccess - Supplies the share access of the caller
231623b7c7b8SHermès Bélusca-Maïto 
231723b7c7b8SHermès Bélusca-Maïto     CreateDisposition - Supplies the create disposition for this operation
231823b7c7b8SHermès Bélusca-Maïto 
231923b7c7b8SHermès Bélusca-Maïto Return Value:
232023b7c7b8SHermès Bélusca-Maïto 
232123b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK - Returns the completion status for the operation
232223b7c7b8SHermès Bélusca-Maïto 
232323b7c7b8SHermès Bélusca-Maïto --*/
232423b7c7b8SHermès Bélusca-Maïto 
232523b7c7b8SHermès Bélusca-Maïto {
232623b7c7b8SHermès Bélusca-Maïto     NTSTATUS Status;
232723b7c7b8SHermès Bélusca-Maïto     PIO_STACK_LOCATION IrpSp;
232823b7c7b8SHermès Bélusca-Maïto 
232923b7c7b8SHermès Bélusca-Maïto #ifndef __REACTOS__
233023b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK Iosb = {0,0};
233123b7c7b8SHermès Bélusca-Maïto #else
233223b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK Iosb = {{0}};
233323b7c7b8SHermès Bélusca-Maïto #endif
233423b7c7b8SHermès Bélusca-Maïto 
233523b7c7b8SHermès Bélusca-Maïto     BOOLEAN CleanedVolume = FALSE;
233623b7c7b8SHermès Bélusca-Maïto 
233723b7c7b8SHermès Bélusca-Maïto     //
233823b7c7b8SHermès Bélusca-Maïto     //  The following variables are for abnormal termination
233923b7c7b8SHermès Bélusca-Maïto     //
234023b7c7b8SHermès Bélusca-Maïto 
234123b7c7b8SHermès Bélusca-Maïto     BOOLEAN UnwindShareAccess = FALSE;
234223b7c7b8SHermès Bélusca-Maïto     PCCB UnwindCcb = NULL;
234323b7c7b8SHermès Bélusca-Maïto     BOOLEAN UnwindCounts = FALSE;
234423b7c7b8SHermès Bélusca-Maïto     BOOLEAN UnwindVolumeLock = FALSE;
234523b7c7b8SHermès Bélusca-Maïto 
234623b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
234723b7c7b8SHermès Bélusca-Maïto 
234823b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatOpenVolume...\n", 0);
234923b7c7b8SHermès Bélusca-Maïto 
235023b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
235123b7c7b8SHermès Bélusca-Maïto 
235223b7c7b8SHermès Bélusca-Maïto         //
235323b7c7b8SHermès Bélusca-Maïto         //  Check for proper desired access and rights
235423b7c7b8SHermès Bélusca-Maïto         //
235523b7c7b8SHermès Bélusca-Maïto 
235623b7c7b8SHermès Bélusca-Maïto         if ((CreateDisposition != FILE_OPEN) &&
235723b7c7b8SHermès Bélusca-Maïto             (CreateDisposition != FILE_OPEN_IF)) {
235823b7c7b8SHermès Bélusca-Maïto 
2359*96676ca2STimo Kreuzer             try_return( Status = STATUS_ACCESS_DENIED );
236023b7c7b8SHermès Bélusca-Maïto         }
236123b7c7b8SHermès Bélusca-Maïto 
236223b7c7b8SHermès Bélusca-Maïto         //
236323b7c7b8SHermès Bélusca-Maïto         //  If the user does not want to share write or delete then we will try
236423b7c7b8SHermès Bélusca-Maïto         //  and take out a lock on the volume.
236523b7c7b8SHermès Bélusca-Maïto         //
236623b7c7b8SHermès Bélusca-Maïto 
236723b7c7b8SHermès Bélusca-Maïto         if (!FlagOn(ShareAccess, FILE_SHARE_WRITE) &&
236823b7c7b8SHermès Bélusca-Maïto             !FlagOn(ShareAccess, FILE_SHARE_DELETE)) {
236923b7c7b8SHermès Bélusca-Maïto 
237023b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_VISTA)
237123b7c7b8SHermès Bélusca-Maïto             //
237223b7c7b8SHermès Bélusca-Maïto             //  See if the user has requested write access.  If so, they cannot share
237323b7c7b8SHermès Bélusca-Maïto             //  read.  There is one exception to this.  We allow autochk to get an
237423b7c7b8SHermès Bélusca-Maïto             //  implicit lock on the volume while still allowing readers.  Once the
237523b7c7b8SHermès Bélusca-Maïto             //  the system is booted, though, we do not allow this type of access.
237623b7c7b8SHermès Bélusca-Maïto             //
237723b7c7b8SHermès Bélusca-Maïto 
237823b7c7b8SHermès Bélusca-Maïto             if (FlagOn( *DesiredAccess, (FILE_WRITE_DATA | FILE_APPEND_DATA) ) &&
237923b7c7b8SHermès Bélusca-Maïto                 FsRtlAreVolumeStartupApplicationsComplete()) {
238023b7c7b8SHermès Bélusca-Maïto 
238123b7c7b8SHermès Bélusca-Maïto                 ClearFlag( ShareAccess, FILE_SHARE_READ );
238223b7c7b8SHermès Bélusca-Maïto             }
238323b7c7b8SHermès Bélusca-Maïto #endif
238423b7c7b8SHermès Bélusca-Maïto 
238523b7c7b8SHermès Bélusca-Maïto             //
238623b7c7b8SHermès Bélusca-Maïto             //  Do a quick check here for handles on exclusive open.
238723b7c7b8SHermès Bélusca-Maïto             //
238823b7c7b8SHermès Bélusca-Maïto 
238923b7c7b8SHermès Bélusca-Maïto             if (!FlagOn(ShareAccess, FILE_SHARE_READ) &&
239023b7c7b8SHermès Bélusca-Maïto                 !FatIsHandleCountZero( IrpContext, Vcb )) {
239123b7c7b8SHermès Bélusca-Maïto 
2392*96676ca2STimo Kreuzer                 try_return( Status = STATUS_SHARING_VIOLATION );
239323b7c7b8SHermès Bélusca-Maïto             }
239423b7c7b8SHermès Bélusca-Maïto 
239523b7c7b8SHermès Bélusca-Maïto             //
239623b7c7b8SHermès Bélusca-Maïto             //  Force Mm to get rid of its referenced file objects.
239723b7c7b8SHermès Bélusca-Maïto             //
239823b7c7b8SHermès Bélusca-Maïto 
239923b7c7b8SHermès Bélusca-Maïto             FatFlushFat( IrpContext, Vcb );
240023b7c7b8SHermès Bélusca-Maïto 
240123b7c7b8SHermès Bélusca-Maïto             FatPurgeReferencedFileObjects( IrpContext, Vcb->RootDcb, Flush );
240223b7c7b8SHermès Bélusca-Maïto 
240323b7c7b8SHermès Bélusca-Maïto             //
240423b7c7b8SHermès Bélusca-Maïto             //  If the user also does not want to share read then we check
240523b7c7b8SHermès Bélusca-Maïto             //  if anyone is already using the volume, and if so then we
240623b7c7b8SHermès Bélusca-Maïto             //  deny the access.  If the user wants to share read then
240723b7c7b8SHermès Bélusca-Maïto             //  we allow the current opens to stay provided they are only
240823b7c7b8SHermès Bélusca-Maïto             //  readonly opens and deny further opens.
240923b7c7b8SHermès Bélusca-Maïto             //
241023b7c7b8SHermès Bélusca-Maïto 
241123b7c7b8SHermès Bélusca-Maïto             if (!FlagOn(ShareAccess, FILE_SHARE_READ)) {
241223b7c7b8SHermès Bélusca-Maïto 
241323b7c7b8SHermès Bélusca-Maïto                 if (Vcb->OpenFileCount != 0) {
241423b7c7b8SHermès Bélusca-Maïto 
2415*96676ca2STimo Kreuzer                     try_return( Status = STATUS_SHARING_VIOLATION );
241623b7c7b8SHermès Bélusca-Maïto                 }
241723b7c7b8SHermès Bélusca-Maïto 
241823b7c7b8SHermès Bélusca-Maïto             } else {
241923b7c7b8SHermès Bélusca-Maïto 
242023b7c7b8SHermès Bélusca-Maïto                 if (Vcb->ReadOnlyCount != Vcb->OpenFileCount) {
242123b7c7b8SHermès Bélusca-Maïto 
2422*96676ca2STimo Kreuzer                     try_return( Status = STATUS_SHARING_VIOLATION );
242323b7c7b8SHermès Bélusca-Maïto                 }
242423b7c7b8SHermès Bélusca-Maïto             }
242523b7c7b8SHermès Bélusca-Maïto 
242623b7c7b8SHermès Bélusca-Maïto             //
242723b7c7b8SHermès Bélusca-Maïto             //  Lock the volume
242823b7c7b8SHermès Bélusca-Maïto             //
242923b7c7b8SHermès Bélusca-Maïto 
243023b7c7b8SHermès Bélusca-Maïto             Vcb->VcbState |= VCB_STATE_FLAG_LOCKED;
243123b7c7b8SHermès Bélusca-Maïto             Vcb->FileObjectWithVcbLocked = FileObject;
243223b7c7b8SHermès Bélusca-Maïto             UnwindVolumeLock = TRUE;
243323b7c7b8SHermès Bélusca-Maïto 
243423b7c7b8SHermès Bélusca-Maïto             //
243523b7c7b8SHermès Bélusca-Maïto             //  Clean the volume
243623b7c7b8SHermès Bélusca-Maïto             //
243723b7c7b8SHermès Bélusca-Maïto 
243823b7c7b8SHermès Bélusca-Maïto             CleanedVolume = TRUE;
243923b7c7b8SHermès Bélusca-Maïto 
244023b7c7b8SHermès Bélusca-Maïto         }  else if (FlagOn( *DesiredAccess, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA )) {
244123b7c7b8SHermès Bélusca-Maïto 
244223b7c7b8SHermès Bélusca-Maïto             //
244323b7c7b8SHermès Bélusca-Maïto             //  Flush the volume and let ourselves push the clean bit out if everything
244423b7c7b8SHermès Bélusca-Maïto             //  worked.
244523b7c7b8SHermès Bélusca-Maïto             //
244623b7c7b8SHermès Bélusca-Maïto 
244723b7c7b8SHermès Bélusca-Maïto             if (NT_SUCCESS( FatFlushVolume( IrpContext, Vcb, Flush ))) {
244823b7c7b8SHermès Bélusca-Maïto 
244923b7c7b8SHermès Bélusca-Maïto                 CleanedVolume = TRUE;
245023b7c7b8SHermès Bélusca-Maïto             }
245123b7c7b8SHermès Bélusca-Maïto         }
245223b7c7b8SHermès Bélusca-Maïto 
245323b7c7b8SHermès Bélusca-Maïto         //
245423b7c7b8SHermès Bélusca-Maïto         //  Clean the volume if we believe it safe and reasonable.
245523b7c7b8SHermès Bélusca-Maïto         //
245623b7c7b8SHermès Bélusca-Maïto 
245723b7c7b8SHermès Bélusca-Maïto         if (CleanedVolume &&
245823b7c7b8SHermès Bélusca-Maïto             FlagOn( Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DIRTY ) &&
245923b7c7b8SHermès Bélusca-Maïto             !FlagOn( Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY ) &&
246023b7c7b8SHermès Bélusca-Maïto             !CcIsThereDirtyData(Vcb->Vpb)) {
246123b7c7b8SHermès Bélusca-Maïto 
246223b7c7b8SHermès Bélusca-Maïto             //
246323b7c7b8SHermès Bélusca-Maïto             //  Cancel any pending clean volumes.
246423b7c7b8SHermès Bélusca-Maïto             //
246523b7c7b8SHermès Bélusca-Maïto 
246623b7c7b8SHermès Bélusca-Maïto             (VOID)KeCancelTimer( &Vcb->CleanVolumeTimer );
246723b7c7b8SHermès Bélusca-Maïto             (VOID)KeRemoveQueueDpc( &Vcb->CleanVolumeDpc );
246823b7c7b8SHermès Bélusca-Maïto 
246923b7c7b8SHermès Bélusca-Maïto             FatMarkVolume( IrpContext, Vcb, VolumeClean );
247023b7c7b8SHermès Bélusca-Maïto             ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DIRTY );
247123b7c7b8SHermès Bélusca-Maïto 
247223b7c7b8SHermès Bélusca-Maïto             //
247323b7c7b8SHermès Bélusca-Maïto             //  Unlock the volume if it is removable.
247423b7c7b8SHermès Bélusca-Maïto             //
247523b7c7b8SHermès Bélusca-Maïto 
247623b7c7b8SHermès Bélusca-Maïto             if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA) &&
247723b7c7b8SHermès Bélusca-Maïto                 !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_BOOT_OR_PAGING_FILE)) {
247823b7c7b8SHermès Bélusca-Maïto 
247923b7c7b8SHermès Bélusca-Maïto                 FatToggleMediaEjectDisable( IrpContext, Vcb, FALSE );
248023b7c7b8SHermès Bélusca-Maïto             }
248123b7c7b8SHermès Bélusca-Maïto         }
248223b7c7b8SHermès Bélusca-Maïto 
248323b7c7b8SHermès Bélusca-Maïto         //
248423b7c7b8SHermès Bélusca-Maïto         //  If the volume is already opened by someone then we need to check
248523b7c7b8SHermès Bélusca-Maïto         //  the share access
248623b7c7b8SHermès Bélusca-Maïto         //
248723b7c7b8SHermès Bélusca-Maïto 
248823b7c7b8SHermès Bélusca-Maïto         if (Vcb->DirectAccessOpenCount > 0) {
248923b7c7b8SHermès Bélusca-Maïto 
2490*96676ca2STimo Kreuzer             if (!NT_SUCCESS(Status = IoCheckShareAccess( *DesiredAccess,
249123b7c7b8SHermès Bélusca-Maïto                                                               ShareAccess,
249223b7c7b8SHermès Bélusca-Maïto                                                               FileObject,
249323b7c7b8SHermès Bélusca-Maïto                                                               &Vcb->ShareAccess,
249423b7c7b8SHermès Bélusca-Maïto                                                               TRUE ))) {
249523b7c7b8SHermès Bélusca-Maïto 
2496*96676ca2STimo Kreuzer                 try_return( NOTHING );
249723b7c7b8SHermès Bélusca-Maïto             }
249823b7c7b8SHermès Bélusca-Maïto 
249923b7c7b8SHermès Bélusca-Maïto         } else {
250023b7c7b8SHermès Bélusca-Maïto 
250123b7c7b8SHermès Bélusca-Maïto             IoSetShareAccess( *DesiredAccess,
250223b7c7b8SHermès Bélusca-Maïto                               ShareAccess,
250323b7c7b8SHermès Bélusca-Maïto                               FileObject,
250423b7c7b8SHermès Bélusca-Maïto                               &Vcb->ShareAccess );
250523b7c7b8SHermès Bélusca-Maïto         }
250623b7c7b8SHermès Bélusca-Maïto 
250723b7c7b8SHermès Bélusca-Maïto         UnwindShareAccess = TRUE;
250823b7c7b8SHermès Bélusca-Maïto 
250923b7c7b8SHermès Bélusca-Maïto         //
251023b7c7b8SHermès Bélusca-Maïto         //  Set up the context and section object pointers, and update
251123b7c7b8SHermès Bélusca-Maïto         //  our reference counts
251223b7c7b8SHermès Bélusca-Maïto         //
251323b7c7b8SHermès Bélusca-Maïto 
251423b7c7b8SHermès Bélusca-Maïto         FatSetFileObject( FileObject,
251523b7c7b8SHermès Bélusca-Maïto                           UserVolumeOpen,
251623b7c7b8SHermès Bélusca-Maïto                           Vcb,
251723b7c7b8SHermès Bélusca-Maïto                           UnwindCcb = FatCreateCcb( IrpContext ));
251823b7c7b8SHermès Bélusca-Maïto 
251923b7c7b8SHermès Bélusca-Maïto         FileObject->SectionObjectPointer = &Vcb->SectionObjectPointers;
252023b7c7b8SHermès Bélusca-Maïto 
252123b7c7b8SHermès Bélusca-Maïto         Vcb->DirectAccessOpenCount += 1;
252223b7c7b8SHermès Bélusca-Maïto         Vcb->OpenFileCount += 1;
252323b7c7b8SHermès Bélusca-Maïto         if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount += 1; }
252423b7c7b8SHermès Bélusca-Maïto         UnwindCounts = TRUE;
252523b7c7b8SHermès Bélusca-Maïto         FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
252623b7c7b8SHermès Bélusca-Maïto 
252723b7c7b8SHermès Bélusca-Maïto         //
252823b7c7b8SHermès Bélusca-Maïto         //  At this point the open will succeed, so check if the user is getting explicit access
252923b7c7b8SHermès Bélusca-Maïto         //  to the device.  If not, we will note this so we can deny modifying FSCTL to it.
253023b7c7b8SHermès Bélusca-Maïto         //
253123b7c7b8SHermès Bélusca-Maïto 
253223b7c7b8SHermès Bélusca-Maïto         IrpSp = IoGetCurrentIrpStackLocation( IrpContext->OriginatingIrp );
253323b7c7b8SHermès Bélusca-Maïto         Status = FatExplicitDeviceAccessGranted( IrpContext,
253423b7c7b8SHermès Bélusca-Maïto                                                  Vcb->Vpb->RealDevice,
253523b7c7b8SHermès Bélusca-Maïto                                                  IrpSp->Parameters.Create.SecurityContext->AccessState,
253623b7c7b8SHermès Bélusca-Maïto                                                  (KPROCESSOR_MODE)( FlagOn( IrpSp->Flags, SL_FORCE_ACCESS_CHECK ) ?
253723b7c7b8SHermès Bélusca-Maïto                                                                     UserMode :
253823b7c7b8SHermès Bélusca-Maïto                                                                     IrpContext->OriginatingIrp->RequestorMode ));
253923b7c7b8SHermès Bélusca-Maïto 
254023b7c7b8SHermès Bélusca-Maïto         if (NT_SUCCESS( Status )) {
254123b7c7b8SHermès Bélusca-Maïto 
254223b7c7b8SHermès Bélusca-Maïto             SetFlag( UnwindCcb->Flags, CCB_FLAG_MANAGE_VOLUME_ACCESS );
254323b7c7b8SHermès Bélusca-Maïto         }
254423b7c7b8SHermès Bélusca-Maïto 
254523b7c7b8SHermès Bélusca-Maïto         //
254623b7c7b8SHermès Bélusca-Maïto         //  And set our status to success
254723b7c7b8SHermès Bélusca-Maïto         //
254823b7c7b8SHermès Bélusca-Maïto 
2549*96676ca2STimo Kreuzer         Status = STATUS_SUCCESS;
255023b7c7b8SHermès Bélusca-Maïto         Iosb.Information = FILE_OPENED;
255123b7c7b8SHermès Bélusca-Maïto 
255223b7c7b8SHermès Bélusca-Maïto     try_exit: NOTHING;
255323b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
255423b7c7b8SHermès Bélusca-Maïto 
255523b7c7b8SHermès Bélusca-Maïto         DebugUnwind( FatOpenVolume );
255623b7c7b8SHermès Bélusca-Maïto 
255723b7c7b8SHermès Bélusca-Maïto         //
255823b7c7b8SHermès Bélusca-Maïto         //  If this is an abnormal termination then undo our work
255923b7c7b8SHermès Bélusca-Maïto         //
256023b7c7b8SHermès Bélusca-Maïto 
2561*96676ca2STimo Kreuzer         if (_SEH2_AbnormalTermination() || !NT_SUCCESS(Status)) {
256223b7c7b8SHermès Bélusca-Maïto 
256323b7c7b8SHermès Bélusca-Maïto             if (UnwindCounts) {
256423b7c7b8SHermès Bélusca-Maïto                 Vcb->DirectAccessOpenCount -= 1;
256523b7c7b8SHermès Bélusca-Maïto                 Vcb->OpenFileCount -= 1;
256623b7c7b8SHermès Bélusca-Maïto                 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount -= 1; }
256723b7c7b8SHermès Bélusca-Maïto             }
256823b7c7b8SHermès Bélusca-Maïto             if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
256923b7c7b8SHermès Bélusca-Maïto             if (UnwindShareAccess) { IoRemoveShareAccess( FileObject, &Vcb->ShareAccess ); }
257023b7c7b8SHermès Bélusca-Maïto             if (UnwindVolumeLock) { Vcb->VcbState &= ~VCB_STATE_FLAG_LOCKED; }
257123b7c7b8SHermès Bélusca-Maïto         }
257223b7c7b8SHermès Bélusca-Maïto 
2573*96676ca2STimo Kreuzer         DebugTrace(-1, Dbg, "FatOpenVolume -> Iosb.Status = %08lx\n", Status);
257423b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
257523b7c7b8SHermès Bélusca-Maïto 
2576*96676ca2STimo Kreuzer     Iosb.Status = Status;
257723b7c7b8SHermès Bélusca-Maïto     return Iosb;
257823b7c7b8SHermès Bélusca-Maïto }
257923b7c7b8SHermès Bélusca-Maïto 
258023b7c7b8SHermès Bélusca-Maïto 
258123b7c7b8SHermès Bélusca-Maïto //
258223b7c7b8SHermès Bélusca-Maïto //  Internal support routine
258323b7c7b8SHermès Bélusca-Maïto //
258423b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)258523b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
258623b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
258723b7c7b8SHermès Bélusca-Maïto FatOpenRootDcb (
258823b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
258923b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
259023b7c7b8SHermès Bélusca-Maïto     _Inout_ PVCB Vcb,
259123b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
259223b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
259323b7c7b8SHermès Bélusca-Maïto     _In_ ULONG CreateDisposition
259423b7c7b8SHermès Bélusca-Maïto     )
259523b7c7b8SHermès Bélusca-Maïto 
259623b7c7b8SHermès Bélusca-Maïto /*++
259723b7c7b8SHermès Bélusca-Maïto 
259823b7c7b8SHermès Bélusca-Maïto Routine Description:
259923b7c7b8SHermès Bélusca-Maïto 
260023b7c7b8SHermès Bélusca-Maïto     This routine opens the root dcb for the volume
260123b7c7b8SHermès Bélusca-Maïto 
260223b7c7b8SHermès Bélusca-Maïto Arguments:
260323b7c7b8SHermès Bélusca-Maïto 
260423b7c7b8SHermès Bélusca-Maïto     FileObject - Supplies the File object
260523b7c7b8SHermès Bélusca-Maïto 
260623b7c7b8SHermès Bélusca-Maïto     Vcb - Supplies the Vcb denoting the volume whose dcb is being opened.
260723b7c7b8SHermès Bélusca-Maïto 
260823b7c7b8SHermès Bélusca-Maïto     DesiredAccess - Supplies the desired access of the caller
260923b7c7b8SHermès Bélusca-Maïto 
261023b7c7b8SHermès Bélusca-Maïto     ShareAccess - Supplies the share access of the caller
261123b7c7b8SHermès Bélusca-Maïto 
261223b7c7b8SHermès Bélusca-Maïto     CreateDisposition - Supplies the create disposition for this operation
261323b7c7b8SHermès Bélusca-Maïto 
261423b7c7b8SHermès Bélusca-Maïto Return Value:
261523b7c7b8SHermès Bélusca-Maïto 
261623b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK - Returns the completion status for the operation
261723b7c7b8SHermès Bélusca-Maïto 
261823b7c7b8SHermès Bélusca-Maïto Arguments:
261923b7c7b8SHermès Bélusca-Maïto 
262023b7c7b8SHermès Bélusca-Maïto --*/
262123b7c7b8SHermès Bélusca-Maïto 
262223b7c7b8SHermès Bélusca-Maïto {
262323b7c7b8SHermès Bélusca-Maïto     PDCB RootDcb;
262423b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK Iosb = {0};
262523b7c7b8SHermès Bélusca-Maïto 
262623b7c7b8SHermès Bélusca-Maïto     //
262723b7c7b8SHermès Bélusca-Maïto     //  The following variables are for abnormal termination
262823b7c7b8SHermès Bélusca-Maïto     //
262923b7c7b8SHermès Bélusca-Maïto 
263023b7c7b8SHermès Bélusca-Maïto     BOOLEAN UnwindShareAccess = FALSE;
263123b7c7b8SHermès Bélusca-Maïto     PCCB UnwindCcb = NULL;
263223b7c7b8SHermès Bélusca-Maïto     BOOLEAN UnwindCounts = FALSE;
263323b7c7b8SHermès Bélusca-Maïto     BOOLEAN RootDcbAcquired = FALSE;
263423b7c7b8SHermès Bélusca-Maïto 
263523b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
263623b7c7b8SHermès Bélusca-Maïto 
263723b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatOpenRootDcb...\n", 0);
263823b7c7b8SHermès Bélusca-Maïto 
263923b7c7b8SHermès Bélusca-Maïto     //
264023b7c7b8SHermès Bélusca-Maïto     //  Locate the root dcb
264123b7c7b8SHermès Bélusca-Maïto     //
264223b7c7b8SHermès Bélusca-Maïto 
264323b7c7b8SHermès Bélusca-Maïto     RootDcb = Vcb->RootDcb;
264423b7c7b8SHermès Bélusca-Maïto 
264523b7c7b8SHermès Bélusca-Maïto     //
264623b7c7b8SHermès Bélusca-Maïto     //  Get the Dcb exlcusive.  This is important as cleanup does not
264723b7c7b8SHermès Bélusca-Maïto     //  acquire the Vcb.
264823b7c7b8SHermès Bélusca-Maïto     //
264923b7c7b8SHermès Bélusca-Maïto 
265023b7c7b8SHermès Bélusca-Maïto     (VOID)FatAcquireExclusiveFcb( IrpContext, RootDcb );
265123b7c7b8SHermès Bélusca-Maïto     RootDcbAcquired = TRUE;
265223b7c7b8SHermès Bélusca-Maïto 
265323b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
265423b7c7b8SHermès Bélusca-Maïto 
265523b7c7b8SHermès Bélusca-Maïto         //
265623b7c7b8SHermès Bélusca-Maïto         //  Check the create disposition and desired access
265723b7c7b8SHermès Bélusca-Maïto         //
265823b7c7b8SHermès Bélusca-Maïto 
265923b7c7b8SHermès Bélusca-Maïto         if ((CreateDisposition != FILE_OPEN) &&
266023b7c7b8SHermès Bélusca-Maïto             (CreateDisposition != FILE_OPEN_IF)) {
266123b7c7b8SHermès Bélusca-Maïto 
266223b7c7b8SHermès Bélusca-Maïto             Iosb.Status = STATUS_ACCESS_DENIED;
266323b7c7b8SHermès Bélusca-Maïto             try_return( Iosb );
266423b7c7b8SHermès Bélusca-Maïto         }
266523b7c7b8SHermès Bélusca-Maïto 
266623b7c7b8SHermès Bélusca-Maïto         if (!FatCheckFileAccess( IrpContext,
266723b7c7b8SHermès Bélusca-Maïto                                  RootDcb->DirentFatFlags,
266823b7c7b8SHermès Bélusca-Maïto                                  DesiredAccess)) {
266923b7c7b8SHermès Bélusca-Maïto 
267023b7c7b8SHermès Bélusca-Maïto             Iosb.Status = STATUS_ACCESS_DENIED;
267123b7c7b8SHermès Bélusca-Maïto             try_return( Iosb );
267223b7c7b8SHermès Bélusca-Maïto         }
267323b7c7b8SHermès Bélusca-Maïto 
267423b7c7b8SHermès Bélusca-Maïto         //
267523b7c7b8SHermès Bélusca-Maïto         //  If the Root dcb is already opened by someone then we need
267623b7c7b8SHermès Bélusca-Maïto         //  to check the share access
267723b7c7b8SHermès Bélusca-Maïto         //
267823b7c7b8SHermès Bélusca-Maïto 
267923b7c7b8SHermès Bélusca-Maïto         if (RootDcb->OpenCount > 0) {
268023b7c7b8SHermès Bélusca-Maïto 
268123b7c7b8SHermès Bélusca-Maïto             if (!NT_SUCCESS(Iosb.Status = IoCheckShareAccess( *DesiredAccess,
268223b7c7b8SHermès Bélusca-Maïto                                                               ShareAccess,
268323b7c7b8SHermès Bélusca-Maïto                                                               FileObject,
268423b7c7b8SHermès Bélusca-Maïto                                                               &RootDcb->ShareAccess,
268523b7c7b8SHermès Bélusca-Maïto                                                               TRUE ))) {
268623b7c7b8SHermès Bélusca-Maïto 
268723b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb );
268823b7c7b8SHermès Bélusca-Maïto             }
268923b7c7b8SHermès Bélusca-Maïto 
269023b7c7b8SHermès Bélusca-Maïto         } else {
269123b7c7b8SHermès Bélusca-Maïto 
269223b7c7b8SHermès Bélusca-Maïto             IoSetShareAccess( *DesiredAccess,
269323b7c7b8SHermès Bélusca-Maïto                               ShareAccess,
269423b7c7b8SHermès Bélusca-Maïto                               FileObject,
269523b7c7b8SHermès Bélusca-Maïto                               &RootDcb->ShareAccess );
269623b7c7b8SHermès Bélusca-Maïto         }
269723b7c7b8SHermès Bélusca-Maïto 
269823b7c7b8SHermès Bélusca-Maïto         UnwindShareAccess = TRUE;
269923b7c7b8SHermès Bélusca-Maïto 
270023b7c7b8SHermès Bélusca-Maïto         //
270123b7c7b8SHermès Bélusca-Maïto         //  Setup the context and section object pointers, and update
270223b7c7b8SHermès Bélusca-Maïto         //  our reference counts
270323b7c7b8SHermès Bélusca-Maïto         //
270423b7c7b8SHermès Bélusca-Maïto 
270523b7c7b8SHermès Bélusca-Maïto         FatSetFileObject( FileObject,
270623b7c7b8SHermès Bélusca-Maïto                           UserDirectoryOpen,
270723b7c7b8SHermès Bélusca-Maïto                           RootDcb,
270823b7c7b8SHermès Bélusca-Maïto                           UnwindCcb = FatCreateCcb( IrpContext ));
270923b7c7b8SHermès Bélusca-Maïto 
271023b7c7b8SHermès Bélusca-Maïto         RootDcb->UncleanCount += 1;
271123b7c7b8SHermès Bélusca-Maïto         RootDcb->OpenCount += 1;
271223b7c7b8SHermès Bélusca-Maïto         Vcb->OpenFileCount += 1;
271323b7c7b8SHermès Bélusca-Maïto         if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount += 1; }
271423b7c7b8SHermès Bélusca-Maïto         UnwindCounts = TRUE;
271523b7c7b8SHermès Bélusca-Maïto 
271623b7c7b8SHermès Bélusca-Maïto         //
271723b7c7b8SHermès Bélusca-Maïto         //  And set our status to success
271823b7c7b8SHermès Bélusca-Maïto         //
271923b7c7b8SHermès Bélusca-Maïto 
272023b7c7b8SHermès Bélusca-Maïto         Iosb.Status = STATUS_SUCCESS;
272123b7c7b8SHermès Bélusca-Maïto         Iosb.Information = FILE_OPENED;
272223b7c7b8SHermès Bélusca-Maïto 
272323b7c7b8SHermès Bélusca-Maïto     try_exit: NOTHING;
272423b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
272523b7c7b8SHermès Bélusca-Maïto 
272623b7c7b8SHermès Bélusca-Maïto         DebugUnwind( FatOpenRootDcb );
272723b7c7b8SHermès Bélusca-Maïto 
272823b7c7b8SHermès Bélusca-Maïto         //
272923b7c7b8SHermès Bélusca-Maïto         //  If this is an abnormal termination then undo our work
273023b7c7b8SHermès Bélusca-Maïto         //
273123b7c7b8SHermès Bélusca-Maïto 
273223b7c7b8SHermès Bélusca-Maïto         if (_SEH2_AbnormalTermination()) {
273323b7c7b8SHermès Bélusca-Maïto 
273423b7c7b8SHermès Bélusca-Maïto             if (UnwindCounts) {
273523b7c7b8SHermès Bélusca-Maïto                 RootDcb->UncleanCount -= 1;
273623b7c7b8SHermès Bélusca-Maïto                 RootDcb->OpenCount -= 1;
273723b7c7b8SHermès Bélusca-Maïto                 Vcb->OpenFileCount -= 1;
273823b7c7b8SHermès Bélusca-Maïto                 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount -= 1; }
273923b7c7b8SHermès Bélusca-Maïto             }
274023b7c7b8SHermès Bélusca-Maïto             if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
274123b7c7b8SHermès Bélusca-Maïto             if (UnwindShareAccess) { IoRemoveShareAccess( FileObject, &RootDcb->ShareAccess ); }
274223b7c7b8SHermès Bélusca-Maïto         }
274323b7c7b8SHermès Bélusca-Maïto 
274423b7c7b8SHermès Bélusca-Maïto         if (RootDcbAcquired) {
274523b7c7b8SHermès Bélusca-Maïto 
274623b7c7b8SHermès Bélusca-Maïto             FatReleaseFcb( IrpContext, RootDcb );
274723b7c7b8SHermès Bélusca-Maïto         }
274823b7c7b8SHermès Bélusca-Maïto 
274923b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatOpenRootDcb -> Iosb.Status = %08lx\n", Iosb.Status);
275023b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
275123b7c7b8SHermès Bélusca-Maïto 
275223b7c7b8SHermès Bélusca-Maïto     return Iosb;
275323b7c7b8SHermès Bélusca-Maïto }
275423b7c7b8SHermès Bélusca-Maïto 
275523b7c7b8SHermès Bélusca-Maïto 
275623b7c7b8SHermès Bélusca-Maïto //
275723b7c7b8SHermès Bélusca-Maïto //  Internal support routine
275823b7c7b8SHermès Bélusca-Maïto //
275923b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)276023b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
276123b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
276223b7c7b8SHermès Bélusca-Maïto FatOpenExistingDcb (
276323b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
276423b7c7b8SHermès Bélusca-Maïto     _In_ PIO_STACK_LOCATION IrpSp,
276523b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
276623b7c7b8SHermès Bélusca-Maïto     _Inout_ PVCB Vcb,
276723b7c7b8SHermès Bélusca-Maïto     _Inout_ PDCB Dcb,
276823b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
276923b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
277023b7c7b8SHermès Bélusca-Maïto     _In_ ULONG CreateDisposition,
277123b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN NoEaKnowledge,
277223b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN DeleteOnClose,
277323b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN OpenRequiringOplock,
277423b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN FileNameOpenedDos,
277523b7c7b8SHermès Bélusca-Maïto     _Out_ PBOOLEAN OplockPostIrp
277623b7c7b8SHermès Bélusca-Maïto     )
277723b7c7b8SHermès Bélusca-Maïto 
277823b7c7b8SHermès Bélusca-Maïto /*++
277923b7c7b8SHermès Bélusca-Maïto 
278023b7c7b8SHermès Bélusca-Maïto Routine Description:
278123b7c7b8SHermès Bélusca-Maïto 
278223b7c7b8SHermès Bélusca-Maïto     This routine opens the specified existing dcb
278323b7c7b8SHermès Bélusca-Maïto 
278423b7c7b8SHermès Bélusca-Maïto Arguments:
278523b7c7b8SHermès Bélusca-Maïto 
278623b7c7b8SHermès Bélusca-Maïto     FileObject - Supplies the File object
278723b7c7b8SHermès Bélusca-Maïto 
278823b7c7b8SHermès Bélusca-Maïto     Vcb - Supplies the Vcb denoting the volume containing the dcb
278923b7c7b8SHermès Bélusca-Maïto 
279023b7c7b8SHermès Bélusca-Maïto     Dcb - Supplies the already existing dcb
279123b7c7b8SHermès Bélusca-Maïto 
279223b7c7b8SHermès Bélusca-Maïto     DesiredAccess - Supplies the desired access of the caller
279323b7c7b8SHermès Bélusca-Maïto 
279423b7c7b8SHermès Bélusca-Maïto     ShareAccess - Supplies the share access of the caller
279523b7c7b8SHermès Bélusca-Maïto 
279623b7c7b8SHermès Bélusca-Maïto     CreateDisposition - Supplies the create disposition for this operation
279723b7c7b8SHermès Bélusca-Maïto 
279823b7c7b8SHermès Bélusca-Maïto     NoEaKnowledge - This opener doesn't understand Ea's and we fail this
279923b7c7b8SHermès Bélusca-Maïto         open if the file has NeedEa's.
280023b7c7b8SHermès Bélusca-Maïto 
280123b7c7b8SHermès Bélusca-Maïto     DeleteOnClose - The caller wants the file gone when the handle is closed
280223b7c7b8SHermès Bélusca-Maïto 
280323b7c7b8SHermès Bélusca-Maïto Return Value:
280423b7c7b8SHermès Bélusca-Maïto 
280523b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK - Returns the completion status for the operation
280623b7c7b8SHermès Bélusca-Maïto 
280723b7c7b8SHermès Bélusca-Maïto --*/
280823b7c7b8SHermès Bélusca-Maïto 
280923b7c7b8SHermès Bélusca-Maïto {
281023b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK Iosb = {0};
281123b7c7b8SHermès Bélusca-Maïto     PBCB DirentBcb = NULL;
281223b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent;
281323b7c7b8SHermès Bélusca-Maïto 
281423b7c7b8SHermès Bélusca-Maïto     //
281523b7c7b8SHermès Bélusca-Maïto     //  The following variables are for abnormal termination
281623b7c7b8SHermès Bélusca-Maïto     //
281723b7c7b8SHermès Bélusca-Maïto 
281823b7c7b8SHermès Bélusca-Maïto     BOOLEAN UnwindShareAccess = FALSE;
281923b7c7b8SHermès Bélusca-Maïto     PCCB UnwindCcb = NULL;
282023b7c7b8SHermès Bélusca-Maïto     BOOLEAN DcbAcquired = FALSE;
282123b7c7b8SHermès Bélusca-Maïto 
282223b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION <= NTDDI_WIN7)
282323b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( OpenRequiringOplock );
282423b7c7b8SHermès Bélusca-Maïto #endif
282523b7c7b8SHermès Bélusca-Maïto 
282623b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( IrpSp );
282723b7c7b8SHermès Bélusca-Maïto 
282823b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
282923b7c7b8SHermès Bélusca-Maïto 
283023b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatOpenExistingDcb...\n", 0);
283123b7c7b8SHermès Bélusca-Maïto 
283223b7c7b8SHermès Bélusca-Maïto     //
283323b7c7b8SHermès Bélusca-Maïto     //  Get the Dcb exlcusive.  This is important as cleanup does not
283423b7c7b8SHermès Bélusca-Maïto     //  acquire the Vcb.
283523b7c7b8SHermès Bélusca-Maïto     //
283623b7c7b8SHermès Bélusca-Maïto 
283723b7c7b8SHermès Bélusca-Maïto     (VOID)FatAcquireExclusiveFcb( IrpContext, Dcb );
283823b7c7b8SHermès Bélusca-Maïto     DcbAcquired = TRUE;
283923b7c7b8SHermès Bélusca-Maïto 
284023b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
284123b7c7b8SHermès Bélusca-Maïto 
284223b7c7b8SHermès Bélusca-Maïto 
284323b7c7b8SHermès Bélusca-Maïto         *OplockPostIrp = FALSE;
284423b7c7b8SHermès Bélusca-Maïto 
284523b7c7b8SHermès Bélusca-Maïto         //
284623b7c7b8SHermès Bélusca-Maïto         //  Before spending any noticeable effort, see if we have the odd case
284723b7c7b8SHermès Bélusca-Maïto         //  of someone trying to delete-on-close the root dcb.  This will only
284823b7c7b8SHermès Bélusca-Maïto         //  happen if we're hit with a null-filename relative open via the root.
284923b7c7b8SHermès Bélusca-Maïto         //
285023b7c7b8SHermès Bélusca-Maïto 
285123b7c7b8SHermès Bélusca-Maïto         if (NodeType(Dcb) == FAT_NTC_ROOT_DCB && DeleteOnClose) {
285223b7c7b8SHermès Bélusca-Maïto 
285323b7c7b8SHermès Bélusca-Maïto             Iosb.Status = STATUS_CANNOT_DELETE;
285423b7c7b8SHermès Bélusca-Maïto             try_return( Iosb );
285523b7c7b8SHermès Bélusca-Maïto         }
285623b7c7b8SHermès Bélusca-Maïto 
285723b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN8)
285823b7c7b8SHermès Bélusca-Maïto 
285923b7c7b8SHermès Bélusca-Maïto         //
286023b7c7b8SHermès Bélusca-Maïto         //  Let's make sure that if the caller provided an oplock key that it
286123b7c7b8SHermès Bélusca-Maïto         //  gets stored in the file object.
286223b7c7b8SHermès Bélusca-Maïto         //
286323b7c7b8SHermès Bélusca-Maïto 
286423b7c7b8SHermès Bélusca-Maïto         Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(Dcb),
286523b7c7b8SHermès Bélusca-Maïto                                           IrpContext->OriginatingIrp,
286623b7c7b8SHermès Bélusca-Maïto                                           OPLOCK_FLAG_OPLOCK_KEY_CHECK_ONLY,
286723b7c7b8SHermès Bélusca-Maïto                                           NULL,
286823b7c7b8SHermès Bélusca-Maïto                                           NULL,
286923b7c7b8SHermès Bélusca-Maïto                                           NULL );
287023b7c7b8SHermès Bélusca-Maïto 
287123b7c7b8SHermès Bélusca-Maïto         if (Iosb.Status != STATUS_SUCCESS) {
287223b7c7b8SHermès Bélusca-Maïto 
287323b7c7b8SHermès Bélusca-Maïto             try_return( NOTHING );
287423b7c7b8SHermès Bélusca-Maïto         }
287523b7c7b8SHermès Bélusca-Maïto 
287623b7c7b8SHermès Bélusca-Maïto #endif
287723b7c7b8SHermès Bélusca-Maïto         //
287823b7c7b8SHermès Bélusca-Maïto         //  If the caller has no Ea knowledge, we immediately check for
287923b7c7b8SHermès Bélusca-Maïto         //  Need Ea's on the file.  We don't need to check for ea's on the
288023b7c7b8SHermès Bélusca-Maïto         //  root directory, because it never has any.  Fat32 doesn't have
288123b7c7b8SHermès Bélusca-Maïto         //  any, either.
288223b7c7b8SHermès Bélusca-Maïto         //
288323b7c7b8SHermès Bélusca-Maïto 
288423b7c7b8SHermès Bélusca-Maïto         if (NoEaKnowledge && NodeType(Dcb) != FAT_NTC_ROOT_DCB &&
288523b7c7b8SHermès Bélusca-Maïto             !FatIsFat32(Vcb)) {
288623b7c7b8SHermès Bélusca-Maïto 
288723b7c7b8SHermès Bélusca-Maïto             ULONG NeedEaCount;
288823b7c7b8SHermès Bélusca-Maïto 
288923b7c7b8SHermès Bélusca-Maïto             //
289023b7c7b8SHermès Bélusca-Maïto             //  Get the dirent for the file and then check that the need
289123b7c7b8SHermès Bélusca-Maïto             //  ea count is 0.
289223b7c7b8SHermès Bélusca-Maïto             //
289323b7c7b8SHermès Bélusca-Maïto 
289423b7c7b8SHermès Bélusca-Maïto             FatGetDirentFromFcbOrDcb( IrpContext,
289523b7c7b8SHermès Bélusca-Maïto                                       Dcb,
289623b7c7b8SHermès Bélusca-Maïto                                       FALSE,
289723b7c7b8SHermès Bélusca-Maïto                                       &Dirent,
289823b7c7b8SHermès Bélusca-Maïto                                       &DirentBcb );
289923b7c7b8SHermès Bélusca-Maïto 
290023b7c7b8SHermès Bélusca-Maïto             FatGetNeedEaCount( IrpContext,
290123b7c7b8SHermès Bélusca-Maïto                                Vcb,
290223b7c7b8SHermès Bélusca-Maïto                                Dirent,
290323b7c7b8SHermès Bélusca-Maïto                                &NeedEaCount );
290423b7c7b8SHermès Bélusca-Maïto 
290523b7c7b8SHermès Bélusca-Maïto             FatUnpinBcb( IrpContext, DirentBcb );
290623b7c7b8SHermès Bélusca-Maïto 
290723b7c7b8SHermès Bélusca-Maïto             if (NeedEaCount != 0) {
290823b7c7b8SHermès Bélusca-Maïto 
290923b7c7b8SHermès Bélusca-Maïto                 Iosb.Status = STATUS_ACCESS_DENIED;
291023b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb );
291123b7c7b8SHermès Bélusca-Maïto             }
291223b7c7b8SHermès Bélusca-Maïto         }
291323b7c7b8SHermès Bélusca-Maïto 
291423b7c7b8SHermès Bélusca-Maïto         //
291523b7c7b8SHermès Bélusca-Maïto         //  Check the create disposition and desired access
291623b7c7b8SHermès Bélusca-Maïto         //
291723b7c7b8SHermès Bélusca-Maïto 
291823b7c7b8SHermès Bélusca-Maïto         if ((CreateDisposition != FILE_OPEN) &&
291923b7c7b8SHermès Bélusca-Maïto             (CreateDisposition != FILE_OPEN_IF)) {
292023b7c7b8SHermès Bélusca-Maïto 
292123b7c7b8SHermès Bélusca-Maïto             Iosb.Status = STATUS_OBJECT_NAME_COLLISION;
292223b7c7b8SHermès Bélusca-Maïto             try_return( Iosb );
292323b7c7b8SHermès Bélusca-Maïto         }
292423b7c7b8SHermès Bélusca-Maïto 
292523b7c7b8SHermès Bélusca-Maïto         if (!FatCheckFileAccess( IrpContext,
292623b7c7b8SHermès Bélusca-Maïto                                  Dcb->DirentFatFlags,
292723b7c7b8SHermès Bélusca-Maïto                                  DesiredAccess)) {
292823b7c7b8SHermès Bélusca-Maïto 
292923b7c7b8SHermès Bélusca-Maïto             Iosb.Status = STATUS_ACCESS_DENIED;
293023b7c7b8SHermès Bélusca-Maïto             try_return( Iosb );
293123b7c7b8SHermès Bélusca-Maïto         }
293223b7c7b8SHermès Bélusca-Maïto 
293323b7c7b8SHermès Bélusca-Maïto         //
293423b7c7b8SHermès Bélusca-Maïto         //  If the dcb is already opened by someone then we need
293523b7c7b8SHermès Bélusca-Maïto         //  to check the share access
293623b7c7b8SHermès Bélusca-Maïto         //
293723b7c7b8SHermès Bélusca-Maïto 
293823b7c7b8SHermès Bélusca-Maïto         if (Dcb->OpenCount > 0) {
293923b7c7b8SHermès Bélusca-Maïto 
294023b7c7b8SHermès Bélusca-Maïto             if (!NT_SUCCESS(Iosb.Status = FatCheckShareAccess( IrpContext,
294123b7c7b8SHermès Bélusca-Maïto                                                                FileObject,
294223b7c7b8SHermès Bélusca-Maïto                                                                Dcb,
294323b7c7b8SHermès Bélusca-Maïto                                                                DesiredAccess,
294423b7c7b8SHermès Bélusca-Maïto                                                                ShareAccess ))) {
294523b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN8)
294623b7c7b8SHermès Bélusca-Maïto 
294723b7c7b8SHermès Bélusca-Maïto                 NTSTATUS OplockBreakStatus = STATUS_SUCCESS;
294823b7c7b8SHermès Bélusca-Maïto 
294923b7c7b8SHermès Bélusca-Maïto                 //
295023b7c7b8SHermès Bélusca-Maïto                 //  If we got a sharing violation try to break outstanding handle
295123b7c7b8SHermès Bélusca-Maïto                 //  oplocks and retry the sharing check.  If the caller specified
295223b7c7b8SHermès Bélusca-Maïto                 //  FILE_COMPLETE_IF_OPLOCKED we don't bother breaking the oplock;
295323b7c7b8SHermès Bélusca-Maïto                 //  we just return the sharing violation.
295423b7c7b8SHermès Bélusca-Maïto                 //
295523b7c7b8SHermès Bélusca-Maïto 
295623b7c7b8SHermès Bélusca-Maïto                 if ((Iosb.Status == STATUS_SHARING_VIOLATION) &&
295723b7c7b8SHermès Bélusca-Maïto                     !FlagOn( IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED )) {
295823b7c7b8SHermès Bélusca-Maïto 
295923b7c7b8SHermès Bélusca-Maïto                     OplockBreakStatus = FsRtlOplockBreakH( FatGetFcbOplock(Dcb),
296023b7c7b8SHermès Bélusca-Maïto                                                            IrpContext->OriginatingIrp,
296123b7c7b8SHermès Bélusca-Maïto                                                            0,
296223b7c7b8SHermès Bélusca-Maïto                                                            IrpContext,
296323b7c7b8SHermès Bélusca-Maïto                                                            FatOplockComplete,
296423b7c7b8SHermès Bélusca-Maïto                                                            FatPrePostIrp );
296523b7c7b8SHermès Bélusca-Maïto 
296623b7c7b8SHermès Bélusca-Maïto                     //
296723b7c7b8SHermès Bélusca-Maïto                     //  If FsRtlOplockBreakH returned STATUS_PENDING, then the IRP
296823b7c7b8SHermès Bélusca-Maïto                     //  has been posted and we need to stop working.
296923b7c7b8SHermès Bélusca-Maïto                     //
297023b7c7b8SHermès Bélusca-Maïto 
297123b7c7b8SHermès Bélusca-Maïto                     if (OplockBreakStatus == STATUS_PENDING) {
297223b7c7b8SHermès Bélusca-Maïto 
297323b7c7b8SHermès Bélusca-Maïto                         Iosb.Status = STATUS_PENDING;
297423b7c7b8SHermès Bélusca-Maïto                         *OplockPostIrp = TRUE;
297523b7c7b8SHermès Bélusca-Maïto                         try_return( NOTHING );
297623b7c7b8SHermès Bélusca-Maïto 
297723b7c7b8SHermès Bélusca-Maïto                     //
297823b7c7b8SHermès Bélusca-Maïto                     //  If FsRtlOplockBreakH returned an error we want to return that now.
297923b7c7b8SHermès Bélusca-Maïto                     //
298023b7c7b8SHermès Bélusca-Maïto 
298123b7c7b8SHermès Bélusca-Maïto                     } else if (!NT_SUCCESS( OplockBreakStatus )) {
298223b7c7b8SHermès Bélusca-Maïto 
298323b7c7b8SHermès Bélusca-Maïto                         Iosb.Status = OplockBreakStatus;
298423b7c7b8SHermès Bélusca-Maïto                         try_return( Iosb );
298523b7c7b8SHermès Bélusca-Maïto 
298623b7c7b8SHermès Bélusca-Maïto                     //
298723b7c7b8SHermès Bélusca-Maïto                     //  Otherwise FsRtlOplockBreakH returned STATUS_SUCCESS, indicating
298823b7c7b8SHermès Bélusca-Maïto                     //  that there is no oplock to be broken.  The sharing violation is
298923b7c7b8SHermès Bélusca-Maïto                     //  returned in that case.
299023b7c7b8SHermès Bélusca-Maïto                     //
299123b7c7b8SHermès Bélusca-Maïto 
299223b7c7b8SHermès Bélusca-Maïto                     } else {
299323b7c7b8SHermès Bélusca-Maïto 
299423b7c7b8SHermès Bélusca-Maïto                         NT_ASSERT( OplockBreakStatus == STATUS_SUCCESS );
299523b7c7b8SHermès Bélusca-Maïto 
299623b7c7b8SHermès Bélusca-Maïto                         try_return( Iosb );
299723b7c7b8SHermès Bélusca-Maïto                     }
299823b7c7b8SHermès Bélusca-Maïto 
299923b7c7b8SHermès Bélusca-Maïto                 //
300023b7c7b8SHermès Bélusca-Maïto                 //  The initial sharing check failed with something other than sharing
300123b7c7b8SHermès Bélusca-Maïto                 //  violation (which should never happen, but let's be future-proof),
300223b7c7b8SHermès Bélusca-Maïto                 //  or we *did* get a sharing violation and the caller specified
300323b7c7b8SHermès Bélusca-Maïto                 //  FILE_COMPLETE_IF_OPLOCKED.  Either way this create is over.
300423b7c7b8SHermès Bélusca-Maïto                 //
300523b7c7b8SHermès Bélusca-Maïto 
300623b7c7b8SHermès Bélusca-Maïto                 } else {
300723b7c7b8SHermès Bélusca-Maïto 
300823b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb );
300923b7c7b8SHermès Bélusca-Maïto                 }
301023b7c7b8SHermès Bélusca-Maïto #else
301123b7c7b8SHermès Bélusca-Maïto 
301223b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb );
301323b7c7b8SHermès Bélusca-Maïto #endif
301423b7c7b8SHermès Bélusca-Maïto             }
301523b7c7b8SHermès Bélusca-Maïto         }
301623b7c7b8SHermès Bélusca-Maïto 
301723b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN8)
301823b7c7b8SHermès Bélusca-Maïto 
301923b7c7b8SHermès Bélusca-Maïto         //
302023b7c7b8SHermès Bélusca-Maïto         //  Now check that we can continue based on the oplock state of the
302123b7c7b8SHermès Bélusca-Maïto         //  directory.  If there are no open handles yet we don't need to do
302223b7c7b8SHermès Bélusca-Maïto         //  this check; oplocks can only exist when there are handles.
302323b7c7b8SHermès Bélusca-Maïto         //
302423b7c7b8SHermès Bélusca-Maïto 
302523b7c7b8SHermès Bélusca-Maïto         if (Dcb->UncleanCount != 0) {
302623b7c7b8SHermès Bélusca-Maïto 
302723b7c7b8SHermès Bélusca-Maïto             Iosb.Status = FsRtlCheckOplock( FatGetFcbOplock(Dcb),
302823b7c7b8SHermès Bélusca-Maïto                                             IrpContext->OriginatingIrp,
302923b7c7b8SHermès Bélusca-Maïto                                             IrpContext,
303023b7c7b8SHermès Bélusca-Maïto                                             FatOplockComplete,
303123b7c7b8SHermès Bélusca-Maïto                                             FatPrePostIrp );
303223b7c7b8SHermès Bélusca-Maïto         }
303323b7c7b8SHermès Bélusca-Maïto 
303423b7c7b8SHermès Bélusca-Maïto         //
303523b7c7b8SHermès Bélusca-Maïto         //  if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted
303623b7c7b8SHermès Bélusca-Maïto         //  to service an oplock break and we need to leave now.
303723b7c7b8SHermès Bélusca-Maïto         //
303823b7c7b8SHermès Bélusca-Maïto 
303923b7c7b8SHermès Bélusca-Maïto         if (Iosb.Status == STATUS_PENDING) {
304023b7c7b8SHermès Bélusca-Maïto 
304123b7c7b8SHermès Bélusca-Maïto             *OplockPostIrp = TRUE;
304223b7c7b8SHermès Bélusca-Maïto             try_return( NOTHING );
304323b7c7b8SHermès Bélusca-Maïto         }
304423b7c7b8SHermès Bélusca-Maïto 
304523b7c7b8SHermès Bélusca-Maïto         //
304623b7c7b8SHermès Bélusca-Maïto         //  If the caller wants atomic create-with-oplock semantics, tell
304723b7c7b8SHermès Bélusca-Maïto         //  the oplock package.  We haven't incremented the Fcb's UncleanCount
304823b7c7b8SHermès Bélusca-Maïto         //  for this create yet, so add that in on the call.
304923b7c7b8SHermès Bélusca-Maïto         //
305023b7c7b8SHermès Bélusca-Maïto 
305123b7c7b8SHermès Bélusca-Maïto         if (OpenRequiringOplock &&
305223b7c7b8SHermès Bélusca-Maïto             (Iosb.Status == STATUS_SUCCESS)) {
305323b7c7b8SHermès Bélusca-Maïto 
305423b7c7b8SHermès Bélusca-Maïto             Iosb.Status = FsRtlOplockFsctrl( FatGetFcbOplock(Dcb),
305523b7c7b8SHermès Bélusca-Maïto                                              IrpContext->OriginatingIrp,
305623b7c7b8SHermès Bélusca-Maïto                                              (Dcb->UncleanCount + 1) );
305723b7c7b8SHermès Bélusca-Maïto         }
305823b7c7b8SHermès Bélusca-Maïto 
305923b7c7b8SHermès Bélusca-Maïto         //
306023b7c7b8SHermès Bélusca-Maïto         //  If we've encountered a failure we need to leave.  FsRtlCheckOplock
306123b7c7b8SHermès Bélusca-Maïto         //  will have returned STATUS_OPLOCK_BREAK_IN_PROGRESS if it initiated
306223b7c7b8SHermès Bélusca-Maïto         //  and oplock break and the caller specified FILE_COMPLETE_IF_OPLOCKED
306323b7c7b8SHermès Bélusca-Maïto         //  on the create call.  That's an NT_SUCCESS code, so we need to keep
306423b7c7b8SHermès Bélusca-Maïto         //  going.
306523b7c7b8SHermès Bélusca-Maïto         //
306623b7c7b8SHermès Bélusca-Maïto 
306723b7c7b8SHermès Bélusca-Maïto         if ((Iosb.Status != STATUS_SUCCESS) &&
306823b7c7b8SHermès Bélusca-Maïto             (Iosb.Status != STATUS_OPLOCK_BREAK_IN_PROGRESS)) {
306923b7c7b8SHermès Bélusca-Maïto 
307023b7c7b8SHermès Bélusca-Maïto             try_return( NOTHING );
307123b7c7b8SHermès Bélusca-Maïto         }
307223b7c7b8SHermès Bélusca-Maïto 
307323b7c7b8SHermès Bélusca-Maïto #endif
307423b7c7b8SHermès Bélusca-Maïto 
307523b7c7b8SHermès Bélusca-Maïto         //
307623b7c7b8SHermès Bélusca-Maïto         //  Now that we're done with the oplock work update the share counts.
307723b7c7b8SHermès Bélusca-Maïto         //  If the Dcb isn't yet opened we just set the share access rather than
307823b7c7b8SHermès Bélusca-Maïto         //  update it.
307923b7c7b8SHermès Bélusca-Maïto         //
308023b7c7b8SHermès Bélusca-Maïto 
308123b7c7b8SHermès Bélusca-Maïto         if (Dcb->OpenCount > 0) {
308223b7c7b8SHermès Bélusca-Maïto 
308323b7c7b8SHermès Bélusca-Maïto             IoUpdateShareAccess( FileObject, &Dcb->ShareAccess );
308423b7c7b8SHermès Bélusca-Maïto 
308523b7c7b8SHermès Bélusca-Maïto         } else {
308623b7c7b8SHermès Bélusca-Maïto 
308723b7c7b8SHermès Bélusca-Maïto             IoSetShareAccess( *DesiredAccess,
308823b7c7b8SHermès Bélusca-Maïto                               ShareAccess,
308923b7c7b8SHermès Bélusca-Maïto                               FileObject,
309023b7c7b8SHermès Bélusca-Maïto                               &Dcb->ShareAccess );
309123b7c7b8SHermès Bélusca-Maïto         }
309223b7c7b8SHermès Bélusca-Maïto 
309323b7c7b8SHermès Bélusca-Maïto         UnwindShareAccess = TRUE;
309423b7c7b8SHermès Bélusca-Maïto 
309523b7c7b8SHermès Bélusca-Maïto         //
309623b7c7b8SHermès Bélusca-Maïto         //  Setup the context and section object pointers, and update
309723b7c7b8SHermès Bélusca-Maïto         //  our reference counts
309823b7c7b8SHermès Bélusca-Maïto         //
309923b7c7b8SHermès Bélusca-Maïto 
310023b7c7b8SHermès Bélusca-Maïto         FatSetFileObject( FileObject,
310123b7c7b8SHermès Bélusca-Maïto                           UserDirectoryOpen,
310223b7c7b8SHermès Bélusca-Maïto                           Dcb,
310323b7c7b8SHermès Bélusca-Maïto                           UnwindCcb = FatCreateCcb( IrpContext ));
310423b7c7b8SHermès Bélusca-Maïto 
310523b7c7b8SHermès Bélusca-Maïto         Dcb->UncleanCount += 1;
310623b7c7b8SHermès Bélusca-Maïto         Dcb->OpenCount += 1;
310723b7c7b8SHermès Bélusca-Maïto         Vcb->OpenFileCount += 1;
310823b7c7b8SHermès Bélusca-Maïto         if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount += 1; }
310923b7c7b8SHermès Bélusca-Maïto 
311023b7c7b8SHermès Bélusca-Maïto         //
311123b7c7b8SHermès Bélusca-Maïto         //  Mark the delete on close bit if the caller asked for that.
311223b7c7b8SHermès Bélusca-Maïto         //
311323b7c7b8SHermès Bélusca-Maïto 
311423b7c7b8SHermès Bélusca-Maïto         {
311523b7c7b8SHermès Bélusca-Maïto             PCCB Ccb = (PCCB)FileObject->FsContext2;
311623b7c7b8SHermès Bélusca-Maïto 
311723b7c7b8SHermès Bélusca-Maïto 
311823b7c7b8SHermès Bélusca-Maïto             if (DeleteOnClose) {
311923b7c7b8SHermès Bélusca-Maïto 
312023b7c7b8SHermès Bélusca-Maïto                 SetFlag( Ccb->Flags, CCB_FLAG_DELETE_ON_CLOSE );
312123b7c7b8SHermès Bélusca-Maïto             }
312223b7c7b8SHermès Bélusca-Maïto             if (FileNameOpenedDos) {
312323b7c7b8SHermès Bélusca-Maïto 
312423b7c7b8SHermès Bélusca-Maïto                 SetFlag( Ccb->Flags, CCB_FLAG_OPENED_BY_SHORTNAME );
312523b7c7b8SHermès Bélusca-Maïto             }
312623b7c7b8SHermès Bélusca-Maïto 
312723b7c7b8SHermès Bélusca-Maïto         }
312823b7c7b8SHermès Bélusca-Maïto 
312923b7c7b8SHermès Bélusca-Maïto 
313023b7c7b8SHermès Bélusca-Maïto         //
313123b7c7b8SHermès Bélusca-Maïto         //  In case this was set, clear it now.
313223b7c7b8SHermès Bélusca-Maïto         //
313323b7c7b8SHermès Bélusca-Maïto 
313423b7c7b8SHermès Bélusca-Maïto         ClearFlag(Dcb->FcbState, FCB_STATE_DELAY_CLOSE);
313523b7c7b8SHermès Bélusca-Maïto 
313623b7c7b8SHermès Bélusca-Maïto         //
313723b7c7b8SHermès Bélusca-Maïto         //  And set our status to success
313823b7c7b8SHermès Bélusca-Maïto         //
313923b7c7b8SHermès Bélusca-Maïto 
314023b7c7b8SHermès Bélusca-Maïto         Iosb.Status = STATUS_SUCCESS;
314123b7c7b8SHermès Bélusca-Maïto         Iosb.Information = FILE_OPENED;
314223b7c7b8SHermès Bélusca-Maïto 
314323b7c7b8SHermès Bélusca-Maïto     try_exit: NOTHING;
314423b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
314523b7c7b8SHermès Bélusca-Maïto 
314623b7c7b8SHermès Bélusca-Maïto         DebugUnwind( FatOpenExistingDcb );
314723b7c7b8SHermès Bélusca-Maïto 
314823b7c7b8SHermès Bélusca-Maïto         //
314923b7c7b8SHermès Bélusca-Maïto         //  Unpin the Dirent Bcb if pinned.
315023b7c7b8SHermès Bélusca-Maïto         //
315123b7c7b8SHermès Bélusca-Maïto 
315223b7c7b8SHermès Bélusca-Maïto         FatUnpinBcb( IrpContext, DirentBcb );
315323b7c7b8SHermès Bélusca-Maïto 
315423b7c7b8SHermès Bélusca-Maïto         //
315523b7c7b8SHermès Bélusca-Maïto         //  If this is an abnormal termination then undo our work
315623b7c7b8SHermès Bélusca-Maïto         //
315723b7c7b8SHermès Bélusca-Maïto 
315823b7c7b8SHermès Bélusca-Maïto         if (_SEH2_AbnormalTermination()) {
315923b7c7b8SHermès Bélusca-Maïto 
316023b7c7b8SHermès Bélusca-Maïto             if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
316123b7c7b8SHermès Bélusca-Maïto             if (UnwindShareAccess) { IoRemoveShareAccess( FileObject, &Dcb->ShareAccess ); }
316223b7c7b8SHermès Bélusca-Maïto         }
316323b7c7b8SHermès Bélusca-Maïto 
316423b7c7b8SHermès Bélusca-Maïto         if (DcbAcquired) {
316523b7c7b8SHermès Bélusca-Maïto 
316623b7c7b8SHermès Bélusca-Maïto             FatReleaseFcb( IrpContext, Dcb );
316723b7c7b8SHermès Bélusca-Maïto         }
316823b7c7b8SHermès Bélusca-Maïto 
316923b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatOpenExistingDcb -> Iosb.Status = %08lx\n", Iosb.Status);
317023b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
317123b7c7b8SHermès Bélusca-Maïto 
317223b7c7b8SHermès Bélusca-Maïto     return Iosb;
317323b7c7b8SHermès Bélusca-Maïto }
317423b7c7b8SHermès Bélusca-Maïto 
317523b7c7b8SHermès Bélusca-Maïto 
317623b7c7b8SHermès Bélusca-Maïto //
317723b7c7b8SHermès Bélusca-Maïto //  Internal support routine
317823b7c7b8SHermès Bélusca-Maïto //
317923b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)318023b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
318123b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
318223b7c7b8SHermès Bélusca-Maïto FatOpenExistingFcb (
318323b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
318423b7c7b8SHermès Bélusca-Maïto     _In_ PIO_STACK_LOCATION IrpSp,
318523b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
318623b7c7b8SHermès Bélusca-Maïto     _Inout_ PVCB Vcb,
318723b7c7b8SHermès Bélusca-Maïto     _Inout_ PFCB Fcb,
318823b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
318923b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
319023b7c7b8SHermès Bélusca-Maïto     _In_ ULONG AllocationSize,
319123b7c7b8SHermès Bélusca-Maïto     _In_ PFILE_FULL_EA_INFORMATION EaBuffer,
319223b7c7b8SHermès Bélusca-Maïto     _In_ ULONG EaLength,
319323b7c7b8SHermès Bélusca-Maïto     _In_ USHORT FileAttributes,
319423b7c7b8SHermès Bélusca-Maïto     _In_ ULONG CreateDisposition,
319523b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN NoEaKnowledge,
319623b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN DeleteOnClose,
319723b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN OpenRequiringOplock,
319823b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN FileNameOpenedDos,
319923b7c7b8SHermès Bélusca-Maïto     _Out_ PBOOLEAN OplockPostIrp
320023b7c7b8SHermès Bélusca-Maïto     )
320123b7c7b8SHermès Bélusca-Maïto 
320223b7c7b8SHermès Bélusca-Maïto /*++
320323b7c7b8SHermès Bélusca-Maïto 
320423b7c7b8SHermès Bélusca-Maïto Routine Description:
320523b7c7b8SHermès Bélusca-Maïto 
320623b7c7b8SHermès Bélusca-Maïto     This routine opens the specified existing fcb
320723b7c7b8SHermès Bélusca-Maïto 
320823b7c7b8SHermès Bélusca-Maïto Arguments:
320923b7c7b8SHermès Bélusca-Maïto 
321023b7c7b8SHermès Bélusca-Maïto     FileObject - Supplies the File object
321123b7c7b8SHermès Bélusca-Maïto 
321223b7c7b8SHermès Bélusca-Maïto     Vcb - Supplies the Vcb denoting the volume containing the Fcb
321323b7c7b8SHermès Bélusca-Maïto 
321423b7c7b8SHermès Bélusca-Maïto     Fcb - Supplies the already existing fcb
321523b7c7b8SHermès Bélusca-Maïto 
321623b7c7b8SHermès Bélusca-Maïto     DesiredAccess - Supplies the desired access of the caller
321723b7c7b8SHermès Bélusca-Maïto 
321823b7c7b8SHermès Bélusca-Maïto     ShareAccess - Supplies the share access of the caller
321923b7c7b8SHermès Bélusca-Maïto 
322023b7c7b8SHermès Bélusca-Maïto     AllocationSize - Supplies the initial allocation if the file is being
322123b7c7b8SHermès Bélusca-Maïto         superseded or overwritten
322223b7c7b8SHermès Bélusca-Maïto 
322323b7c7b8SHermès Bélusca-Maïto     EaBuffer - Supplies the Ea set if the file is being superseded or
322423b7c7b8SHermès Bélusca-Maïto         overwritten
322523b7c7b8SHermès Bélusca-Maïto 
322623b7c7b8SHermès Bélusca-Maïto     EaLength - Supplies the size, in byte, of the EaBuffer
322723b7c7b8SHermès Bélusca-Maïto 
322823b7c7b8SHermès Bélusca-Maïto     FileAttributes - Supplies file attributes to use if the file is being
322923b7c7b8SHermès Bélusca-Maïto         superseded or overwritten
323023b7c7b8SHermès Bélusca-Maïto 
323123b7c7b8SHermès Bélusca-Maïto     CreateDisposition - Supplies the create disposition for this operation
323223b7c7b8SHermès Bélusca-Maïto 
323323b7c7b8SHermès Bélusca-Maïto     NoEaKnowledge - This opener doesn't understand Ea's and we fail this
323423b7c7b8SHermès Bélusca-Maïto         open if the file has NeedEa's.
323523b7c7b8SHermès Bélusca-Maïto 
323623b7c7b8SHermès Bélusca-Maïto     DeleteOnClose - The caller wants the file gone when the handle is closed
323723b7c7b8SHermès Bélusca-Maïto 
323823b7c7b8SHermès Bélusca-Maïto     OpenRequiringOplock - The caller provided the FILE_OPEN_REQUIRING_OPLOCK option.
323923b7c7b8SHermès Bélusca-Maïto 
324023b7c7b8SHermès Bélusca-Maïto     FileNameOpenedDos - The caller hit the short side of the name pair finding
324123b7c7b8SHermès Bélusca-Maïto         this file
324223b7c7b8SHermès Bélusca-Maïto 
324323b7c7b8SHermès Bélusca-Maïto     OplockPostIrp - Address to store boolean indicating if the Irp needs to
324423b7c7b8SHermès Bélusca-Maïto         be posted to the Fsp.
324523b7c7b8SHermès Bélusca-Maïto 
324623b7c7b8SHermès Bélusca-Maïto Return Value:
324723b7c7b8SHermès Bélusca-Maïto 
324823b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK - Returns the completion status for the operation
324923b7c7b8SHermès Bélusca-Maïto 
325023b7c7b8SHermès Bélusca-Maïto --*/
325123b7c7b8SHermès Bélusca-Maïto 
325223b7c7b8SHermès Bélusca-Maïto {
325323b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK Iosb = {0};
325423b7c7b8SHermès Bélusca-Maïto 
325523b7c7b8SHermès Bélusca-Maïto     PBCB DirentBcb = NULL;
325623b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent;
325723b7c7b8SHermès Bélusca-Maïto 
325823b7c7b8SHermès Bélusca-Maïto     ACCESS_MASK AddedAccess = 0;
325923b7c7b8SHermès Bélusca-Maïto 
326023b7c7b8SHermès Bélusca-Maïto     //
326123b7c7b8SHermès Bélusca-Maïto     //  The following variables are for abnormal termination
326223b7c7b8SHermès Bélusca-Maïto     //
326323b7c7b8SHermès Bélusca-Maïto 
326423b7c7b8SHermès Bélusca-Maïto     BOOLEAN UnwindShareAccess = FALSE;
326523b7c7b8SHermès Bélusca-Maïto     PCCB UnwindCcb = NULL;
326623b7c7b8SHermès Bélusca-Maïto     BOOLEAN DecrementFcbOpenCount = FALSE;
326723b7c7b8SHermès Bélusca-Maïto     BOOLEAN FcbAcquired = FALSE;
326823b7c7b8SHermès Bélusca-Maïto 
326923b7c7b8SHermès Bélusca-Maïto 
327023b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
327123b7c7b8SHermès Bélusca-Maïto 
327223b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatOpenExistingFcb...\n", 0);
327323b7c7b8SHermès Bélusca-Maïto 
327423b7c7b8SHermès Bélusca-Maïto     //
327523b7c7b8SHermès Bélusca-Maïto     //  Get the Fcb exlcusive.  This is important as cleanup does not
327623b7c7b8SHermès Bélusca-Maïto     //  acquire the Vcb.
327723b7c7b8SHermès Bélusca-Maïto     //
327823b7c7b8SHermès Bélusca-Maïto 
327923b7c7b8SHermès Bélusca-Maïto     (VOID)FatAcquireExclusiveFcb( IrpContext, Fcb );
328023b7c7b8SHermès Bélusca-Maïto     FcbAcquired = TRUE;
328123b7c7b8SHermès Bélusca-Maïto 
328223b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
328323b7c7b8SHermès Bélusca-Maïto 
328423b7c7b8SHermès Bélusca-Maïto 
328523b7c7b8SHermès Bélusca-Maïto         *OplockPostIrp = FALSE;
328623b7c7b8SHermès Bélusca-Maïto 
328723b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN7)
328823b7c7b8SHermès Bélusca-Maïto 
328923b7c7b8SHermès Bélusca-Maïto         //
329023b7c7b8SHermès Bélusca-Maïto         //  Let's make sure that if the caller provided an oplock key that it
329123b7c7b8SHermès Bélusca-Maïto         //  gets stored in the file object.
329223b7c7b8SHermès Bélusca-Maïto         //
329323b7c7b8SHermès Bélusca-Maïto 
329423b7c7b8SHermès Bélusca-Maïto         Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(Fcb),
329523b7c7b8SHermès Bélusca-Maïto                                           IrpContext->OriginatingIrp,
329623b7c7b8SHermès Bélusca-Maïto                                           OPLOCK_FLAG_OPLOCK_KEY_CHECK_ONLY,
329723b7c7b8SHermès Bélusca-Maïto                                           NULL,
329823b7c7b8SHermès Bélusca-Maïto                                           NULL,
329923b7c7b8SHermès Bélusca-Maïto                                           NULL );
330023b7c7b8SHermès Bélusca-Maïto 
330123b7c7b8SHermès Bélusca-Maïto         if (Iosb.Status != STATUS_SUCCESS) {
330223b7c7b8SHermès Bélusca-Maïto 
330323b7c7b8SHermès Bélusca-Maïto             try_return( NOTHING );
330423b7c7b8SHermès Bélusca-Maïto         }
330523b7c7b8SHermès Bélusca-Maïto #endif
330623b7c7b8SHermès Bélusca-Maïto 
330723b7c7b8SHermès Bélusca-Maïto         //
330823b7c7b8SHermès Bélusca-Maïto         //  Take special action if there is a current batch oplock or
330923b7c7b8SHermès Bélusca-Maïto         //  batch oplock break in process on the Fcb.
331023b7c7b8SHermès Bélusca-Maïto         //
331123b7c7b8SHermès Bélusca-Maïto 
331223b7c7b8SHermès Bélusca-Maïto         if (FsRtlCurrentBatchOplock( FatGetFcbOplock(Fcb) )) {
331323b7c7b8SHermès Bélusca-Maïto 
331423b7c7b8SHermès Bélusca-Maïto             //
331523b7c7b8SHermès Bélusca-Maïto             //  We remember if a batch oplock break is underway for the
331623b7c7b8SHermès Bélusca-Maïto             //  case where the sharing check fails.
331723b7c7b8SHermès Bélusca-Maïto             //
331823b7c7b8SHermès Bélusca-Maïto 
331923b7c7b8SHermès Bélusca-Maïto             Iosb.Information = FILE_OPBATCH_BREAK_UNDERWAY;
332023b7c7b8SHermès Bélusca-Maïto 
332123b7c7b8SHermès Bélusca-Maïto             Iosb.Status = FsRtlCheckOplock( FatGetFcbOplock(Fcb),
332223b7c7b8SHermès Bélusca-Maïto                                             IrpContext->OriginatingIrp,
332323b7c7b8SHermès Bélusca-Maïto                                             IrpContext,
332423b7c7b8SHermès Bélusca-Maïto                                             FatOplockComplete,
332523b7c7b8SHermès Bélusca-Maïto                                             FatPrePostIrp );
332623b7c7b8SHermès Bélusca-Maïto 
332723b7c7b8SHermès Bélusca-Maïto             //
332823b7c7b8SHermès Bélusca-Maïto             //  if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted
332923b7c7b8SHermès Bélusca-Maïto             //  to service an oplock break and we need to leave now.
333023b7c7b8SHermès Bélusca-Maïto             //
333123b7c7b8SHermès Bélusca-Maïto 
333223b7c7b8SHermès Bélusca-Maïto             if (Iosb.Status == STATUS_PENDING) {
333323b7c7b8SHermès Bélusca-Maïto 
333423b7c7b8SHermès Bélusca-Maïto                 *OplockPostIrp = TRUE;
333523b7c7b8SHermès Bélusca-Maïto                 try_return( NOTHING );
333623b7c7b8SHermès Bélusca-Maïto             }
333723b7c7b8SHermès Bélusca-Maïto         }
333823b7c7b8SHermès Bélusca-Maïto 
333923b7c7b8SHermès Bélusca-Maïto         //
334023b7c7b8SHermès Bélusca-Maïto         //  Check if the user wanted to create the file, also special case
334123b7c7b8SHermès Bélusca-Maïto         //  the supersede and overwrite options.  Those add additional,
334223b7c7b8SHermès Bélusca-Maïto         //  possibly only implied, desired accesses to the caller, which
334323b7c7b8SHermès Bélusca-Maïto         //  we must be careful to pull back off if the caller did not actually
334423b7c7b8SHermès Bélusca-Maïto         //  request them.
334523b7c7b8SHermès Bélusca-Maïto         //
334623b7c7b8SHermès Bélusca-Maïto         //  In other words, check against the implied access, but do not modify
334723b7c7b8SHermès Bélusca-Maïto         //  share access as a result.
334823b7c7b8SHermès Bélusca-Maïto         //
334923b7c7b8SHermès Bélusca-Maïto 
335023b7c7b8SHermès Bélusca-Maïto         if (CreateDisposition == FILE_CREATE) {
335123b7c7b8SHermès Bélusca-Maïto 
335223b7c7b8SHermès Bélusca-Maïto             Iosb.Status = STATUS_OBJECT_NAME_COLLISION;
335323b7c7b8SHermès Bélusca-Maïto             try_return( Iosb );
335423b7c7b8SHermès Bélusca-Maïto 
335523b7c7b8SHermès Bélusca-Maïto         } else if (CreateDisposition == FILE_SUPERSEDE) {
335623b7c7b8SHermès Bélusca-Maïto 
335723b7c7b8SHermès Bélusca-Maïto             SetFlag( AddedAccess,
335823b7c7b8SHermès Bélusca-Maïto                      DELETE & ~(*DesiredAccess) );
335923b7c7b8SHermès Bélusca-Maïto 
336023b7c7b8SHermès Bélusca-Maïto             *DesiredAccess |= DELETE;
336123b7c7b8SHermès Bélusca-Maïto 
336223b7c7b8SHermès Bélusca-Maïto         } else if ((CreateDisposition == FILE_OVERWRITE) ||
336323b7c7b8SHermès Bélusca-Maïto                    (CreateDisposition == FILE_OVERWRITE_IF)) {
336423b7c7b8SHermès Bélusca-Maïto 
336523b7c7b8SHermès Bélusca-Maïto             SetFlag( AddedAccess,
336623b7c7b8SHermès Bélusca-Maïto                      (FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES) & ~(*DesiredAccess) );
336723b7c7b8SHermès Bélusca-Maïto 
336823b7c7b8SHermès Bélusca-Maïto             *DesiredAccess |= FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES;
336923b7c7b8SHermès Bélusca-Maïto         }
337023b7c7b8SHermès Bélusca-Maïto 
337123b7c7b8SHermès Bélusca-Maïto         //
337223b7c7b8SHermès Bélusca-Maïto         //  Check the desired access
337323b7c7b8SHermès Bélusca-Maïto         //
337423b7c7b8SHermès Bélusca-Maïto 
337523b7c7b8SHermès Bélusca-Maïto         if (!FatCheckFileAccess( IrpContext,
337623b7c7b8SHermès Bélusca-Maïto                                  Fcb->DirentFatFlags,
337723b7c7b8SHermès Bélusca-Maïto                                  DesiredAccess )) {
337823b7c7b8SHermès Bélusca-Maïto 
337923b7c7b8SHermès Bélusca-Maïto             Iosb.Status = STATUS_ACCESS_DENIED;
338023b7c7b8SHermès Bélusca-Maïto             try_return( Iosb );
338123b7c7b8SHermès Bélusca-Maïto         }
338223b7c7b8SHermès Bélusca-Maïto 
338323b7c7b8SHermès Bélusca-Maïto 
338423b7c7b8SHermès Bélusca-Maïto         //
338523b7c7b8SHermès Bélusca-Maïto         //  Check for trying to delete a read only file.
338623b7c7b8SHermès Bélusca-Maïto         //
338723b7c7b8SHermès Bélusca-Maïto 
338823b7c7b8SHermès Bélusca-Maïto         if (DeleteOnClose &&
338923b7c7b8SHermès Bélusca-Maïto             FlagOn( Fcb->DirentFatFlags, FAT_DIRENT_ATTR_READ_ONLY )) {
339023b7c7b8SHermès Bélusca-Maïto 
339123b7c7b8SHermès Bélusca-Maïto             Iosb.Status = STATUS_CANNOT_DELETE;
339223b7c7b8SHermès Bélusca-Maïto             try_return( Iosb );
339323b7c7b8SHermès Bélusca-Maïto         }
339423b7c7b8SHermès Bélusca-Maïto 
339523b7c7b8SHermès Bélusca-Maïto         //
339623b7c7b8SHermès Bélusca-Maïto         //  If we are asked to do an overwrite or supersede operation then
339723b7c7b8SHermès Bélusca-Maïto         //  deny access for files where the file attributes for system and
339823b7c7b8SHermès Bélusca-Maïto         //  hidden do not match
339923b7c7b8SHermès Bélusca-Maïto         //
340023b7c7b8SHermès Bélusca-Maïto 
340123b7c7b8SHermès Bélusca-Maïto         if ((CreateDisposition == FILE_SUPERSEDE) ||
340223b7c7b8SHermès Bélusca-Maïto             (CreateDisposition == FILE_OVERWRITE) ||
340323b7c7b8SHermès Bélusca-Maïto             (CreateDisposition == FILE_OVERWRITE_IF)) {
340423b7c7b8SHermès Bélusca-Maïto 
340523b7c7b8SHermès Bélusca-Maïto             BOOLEAN Hidden;
340623b7c7b8SHermès Bélusca-Maïto             BOOLEAN System;
340723b7c7b8SHermès Bélusca-Maïto 
340823b7c7b8SHermès Bélusca-Maïto             Hidden = BooleanFlagOn(Fcb->DirentFatFlags, FAT_DIRENT_ATTR_HIDDEN );
340923b7c7b8SHermès Bélusca-Maïto             System = BooleanFlagOn(Fcb->DirentFatFlags, FAT_DIRENT_ATTR_SYSTEM );
341023b7c7b8SHermès Bélusca-Maïto 
341123b7c7b8SHermès Bélusca-Maïto             if ((Hidden && !FlagOn(FileAttributes, FILE_ATTRIBUTE_HIDDEN)) ||
341223b7c7b8SHermès Bélusca-Maïto                 (System && !FlagOn(FileAttributes, FILE_ATTRIBUTE_SYSTEM))) {
341323b7c7b8SHermès Bélusca-Maïto 
341423b7c7b8SHermès Bélusca-Maïto                 DebugTrace(0, Dbg, "The hidden and/or system bits do not match\n", 0);
341523b7c7b8SHermès Bélusca-Maïto 
341623b7c7b8SHermès Bélusca-Maïto 
341723b7c7b8SHermès Bélusca-Maïto                 Iosb.Status = STATUS_ACCESS_DENIED;
341823b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb );
341923b7c7b8SHermès Bélusca-Maïto             }
342023b7c7b8SHermès Bélusca-Maïto 
342123b7c7b8SHermès Bélusca-Maïto             //
342223b7c7b8SHermès Bélusca-Maïto             //  If this media is write protected, don't even try the create.
342323b7c7b8SHermès Bélusca-Maïto             //
342423b7c7b8SHermès Bélusca-Maïto 
342523b7c7b8SHermès Bélusca-Maïto             if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
342623b7c7b8SHermès Bélusca-Maïto 
342723b7c7b8SHermès Bélusca-Maïto                 //
342823b7c7b8SHermès Bélusca-Maïto                 //  Set the real device for the pop-up info, and set the verify
342923b7c7b8SHermès Bélusca-Maïto                 //  bit in the device object, so that we will force a verify
343023b7c7b8SHermès Bélusca-Maïto                 //  in case the user put the correct media back in.
343123b7c7b8SHermès Bélusca-Maïto                 //
343223b7c7b8SHermès Bélusca-Maïto 
343323b7c7b8SHermès Bélusca-Maïto                 IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
343423b7c7b8SHermès Bélusca-Maïto                                               Vcb->Vpb->RealDevice );
343523b7c7b8SHermès Bélusca-Maïto 
343623b7c7b8SHermès Bélusca-Maïto                 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
343723b7c7b8SHermès Bélusca-Maïto 
343823b7c7b8SHermès Bélusca-Maïto                 FatRaiseStatus( IrpContext, STATUS_MEDIA_WRITE_PROTECTED );
343923b7c7b8SHermès Bélusca-Maïto             }
344023b7c7b8SHermès Bélusca-Maïto         }
344123b7c7b8SHermès Bélusca-Maïto 
344223b7c7b8SHermès Bélusca-Maïto         //
344323b7c7b8SHermès Bélusca-Maïto         //  Check if the Fcb has the proper share access.  This routine will also
344423b7c7b8SHermès Bélusca-Maïto         //  check for writable user secions if the user did not allow write sharing.
344523b7c7b8SHermès Bélusca-Maïto         //
344623b7c7b8SHermès Bélusca-Maïto 
344723b7c7b8SHermès Bélusca-Maïto         if (!NT_SUCCESS(Iosb.Status = FatCheckShareAccess( IrpContext,
344823b7c7b8SHermès Bélusca-Maïto                                                            FileObject,
344923b7c7b8SHermès Bélusca-Maïto                                                            Fcb,
345023b7c7b8SHermès Bélusca-Maïto                                                            DesiredAccess,
345123b7c7b8SHermès Bélusca-Maïto                                                            ShareAccess ))) {
345223b7c7b8SHermès Bélusca-Maïto 
345323b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN7)
345423b7c7b8SHermès Bélusca-Maïto 
345523b7c7b8SHermès Bélusca-Maïto             NTSTATUS OplockBreakStatus = STATUS_SUCCESS;
345623b7c7b8SHermès Bélusca-Maïto 
345723b7c7b8SHermès Bélusca-Maïto             //
345823b7c7b8SHermès Bélusca-Maïto             //  If we got a sharing violation try to break outstanding handle
345923b7c7b8SHermès Bélusca-Maïto             //  oplocks and retry the sharing check.  If the caller specified
346023b7c7b8SHermès Bélusca-Maïto             //  FILE_COMPLETE_IF_OPLOCKED we don't bother breaking the oplock;
346123b7c7b8SHermès Bélusca-Maïto             //  we just return the sharing violation.
346223b7c7b8SHermès Bélusca-Maïto             //
346323b7c7b8SHermès Bélusca-Maïto 
346423b7c7b8SHermès Bélusca-Maïto             if ((Iosb.Status == STATUS_SHARING_VIOLATION) &&
346523b7c7b8SHermès Bélusca-Maïto                 !FlagOn( IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED )) {
346623b7c7b8SHermès Bélusca-Maïto 
346723b7c7b8SHermès Bélusca-Maïto                 OplockBreakStatus = FsRtlOplockBreakH( FatGetFcbOplock(Fcb),
346823b7c7b8SHermès Bélusca-Maïto                                                        IrpContext->OriginatingIrp,
346923b7c7b8SHermès Bélusca-Maïto                                                        0,
347023b7c7b8SHermès Bélusca-Maïto                                                        IrpContext,
347123b7c7b8SHermès Bélusca-Maïto                                                        FatOplockComplete,
347223b7c7b8SHermès Bélusca-Maïto                                                        FatPrePostIrp );
347323b7c7b8SHermès Bélusca-Maïto 
347423b7c7b8SHermès Bélusca-Maïto                 //
347523b7c7b8SHermès Bélusca-Maïto                 //  If FsRtlOplockBreakH returned STATUS_PENDING, then the IRP
347623b7c7b8SHermès Bélusca-Maïto                 //  has been posted and we need to stop working.
347723b7c7b8SHermès Bélusca-Maïto                 //
347823b7c7b8SHermès Bélusca-Maïto 
347923b7c7b8SHermès Bélusca-Maïto                 if (OplockBreakStatus == STATUS_PENDING) {
348023b7c7b8SHermès Bélusca-Maïto 
348123b7c7b8SHermès Bélusca-Maïto                     Iosb.Status = STATUS_PENDING;
348223b7c7b8SHermès Bélusca-Maïto                     *OplockPostIrp = TRUE;
348323b7c7b8SHermès Bélusca-Maïto                     try_return( NOTHING );
348423b7c7b8SHermès Bélusca-Maïto 
348523b7c7b8SHermès Bélusca-Maïto                 //
348623b7c7b8SHermès Bélusca-Maïto                 //  If FsRtlOplockBreakH returned an error we want to return that now.
348723b7c7b8SHermès Bélusca-Maïto                 //
348823b7c7b8SHermès Bélusca-Maïto 
348923b7c7b8SHermès Bélusca-Maïto                 } else if (!NT_SUCCESS( OplockBreakStatus )) {
349023b7c7b8SHermès Bélusca-Maïto 
349123b7c7b8SHermès Bélusca-Maïto                     Iosb.Status = OplockBreakStatus;
349223b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb );
349323b7c7b8SHermès Bélusca-Maïto 
349423b7c7b8SHermès Bélusca-Maïto                 //
349523b7c7b8SHermès Bélusca-Maïto                 //  Otherwise FsRtlOplockBreakH returned STATUS_SUCCESS, indicating
349623b7c7b8SHermès Bélusca-Maïto                 //  that there is no oplock to be broken.  The sharing violation is
349723b7c7b8SHermès Bélusca-Maïto                 //  returned in that case.
349823b7c7b8SHermès Bélusca-Maïto                 //
349923b7c7b8SHermès Bélusca-Maïto 
350023b7c7b8SHermès Bélusca-Maïto                 } else {
350123b7c7b8SHermès Bélusca-Maïto 
350223b7c7b8SHermès Bélusca-Maïto                     NT_ASSERT( OplockBreakStatus == STATUS_SUCCESS );
350323b7c7b8SHermès Bélusca-Maïto 
350423b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb );
350523b7c7b8SHermès Bélusca-Maïto                 }
350623b7c7b8SHermès Bélusca-Maïto 
350723b7c7b8SHermès Bélusca-Maïto             //
350823b7c7b8SHermès Bélusca-Maïto             //  The initial sharing check failed with something other than sharing
350923b7c7b8SHermès Bélusca-Maïto             //  violation (which should never happen, but let's be future-proof),
351023b7c7b8SHermès Bélusca-Maïto             //  or we *did* get a sharing violation and the caller specified
351123b7c7b8SHermès Bélusca-Maïto             //  FILE_COMPLETE_IF_OPLOCKED.  Either way this create is over.
351223b7c7b8SHermès Bélusca-Maïto             //
351323b7c7b8SHermès Bélusca-Maïto 
351423b7c7b8SHermès Bélusca-Maïto             } else {
351523b7c7b8SHermès Bélusca-Maïto 
351623b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb );
351723b7c7b8SHermès Bélusca-Maïto             }
351823b7c7b8SHermès Bélusca-Maïto 
351923b7c7b8SHermès Bélusca-Maïto #else
352023b7c7b8SHermès Bélusca-Maïto 
352123b7c7b8SHermès Bélusca-Maïto             try_return( Iosb );
352223b7c7b8SHermès Bélusca-Maïto 
352323b7c7b8SHermès Bélusca-Maïto #endif
352423b7c7b8SHermès Bélusca-Maïto         }
352523b7c7b8SHermès Bélusca-Maïto 
352623b7c7b8SHermès Bélusca-Maïto         //
352723b7c7b8SHermès Bélusca-Maïto         //  Now check that we can continue based on the oplock state of the
352823b7c7b8SHermès Bélusca-Maïto         //  file.  If there are no open handles yet we don't need to do this
352923b7c7b8SHermès Bélusca-Maïto         //  check; oplocks can only exist when there are handles.
353023b7c7b8SHermès Bélusca-Maïto         //
353123b7c7b8SHermès Bélusca-Maïto         //  It is important that we modified the DesiredAccess in place so
353223b7c7b8SHermès Bélusca-Maïto         //  that the Oplock check proceeds against any added access we had
353323b7c7b8SHermès Bélusca-Maïto         //  to give the caller.
353423b7c7b8SHermès Bélusca-Maïto         //
353523b7c7b8SHermès Bélusca-Maïto 
353623b7c7b8SHermès Bélusca-Maïto         if (Fcb->UncleanCount != 0) {
353723b7c7b8SHermès Bélusca-Maïto 
353823b7c7b8SHermès Bélusca-Maïto             Iosb.Status = FsRtlCheckOplock( FatGetFcbOplock(Fcb),
353923b7c7b8SHermès Bélusca-Maïto                                             IrpContext->OriginatingIrp,
354023b7c7b8SHermès Bélusca-Maïto                                             IrpContext,
354123b7c7b8SHermès Bélusca-Maïto                                             FatOplockComplete,
354223b7c7b8SHermès Bélusca-Maïto                                             FatPrePostIrp );
354323b7c7b8SHermès Bélusca-Maïto         }
354423b7c7b8SHermès Bélusca-Maïto 
354523b7c7b8SHermès Bélusca-Maïto         //
354623b7c7b8SHermès Bélusca-Maïto         //  if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted
354723b7c7b8SHermès Bélusca-Maïto         //  to service an oplock break and we need to leave now.
354823b7c7b8SHermès Bélusca-Maïto         //
354923b7c7b8SHermès Bélusca-Maïto 
355023b7c7b8SHermès Bélusca-Maïto         if (Iosb.Status == STATUS_PENDING) {
355123b7c7b8SHermès Bélusca-Maïto 
355223b7c7b8SHermès Bélusca-Maïto             *OplockPostIrp = TRUE;
355323b7c7b8SHermès Bélusca-Maïto             try_return( NOTHING );
355423b7c7b8SHermès Bélusca-Maïto         }
355523b7c7b8SHermès Bélusca-Maïto 
355623b7c7b8SHermès Bélusca-Maïto         //
355723b7c7b8SHermès Bélusca-Maïto         //  If the caller wants atomic create-with-oplock semantics, tell
355823b7c7b8SHermès Bélusca-Maïto         //  the oplock package.  We haven't incremented the Fcb's UncleanCount
355923b7c7b8SHermès Bélusca-Maïto         //  for this create yet, so add that in on the call.
356023b7c7b8SHermès Bélusca-Maïto         //
356123b7c7b8SHermès Bélusca-Maïto 
356223b7c7b8SHermès Bélusca-Maïto         if (OpenRequiringOplock &&
356323b7c7b8SHermès Bélusca-Maïto             (Iosb.Status == STATUS_SUCCESS)) {
356423b7c7b8SHermès Bélusca-Maïto 
356523b7c7b8SHermès Bélusca-Maïto             Iosb.Status = FsRtlOplockFsctrl( FatGetFcbOplock(Fcb),
356623b7c7b8SHermès Bélusca-Maïto                                              IrpContext->OriginatingIrp,
356723b7c7b8SHermès Bélusca-Maïto                                              (Fcb->UncleanCount + 1) );
356823b7c7b8SHermès Bélusca-Maïto         }
356923b7c7b8SHermès Bélusca-Maïto 
357023b7c7b8SHermès Bélusca-Maïto         //
357123b7c7b8SHermès Bélusca-Maïto         //  If we've encountered a failure we need to leave.  FsRtlCheckOplock
357223b7c7b8SHermès Bélusca-Maïto         //  will have returned STATUS_OPLOCK_BREAK_IN_PROGRESS if it initiated
357323b7c7b8SHermès Bélusca-Maïto         //  and oplock break and the caller specified FILE_COMPLETE_IF_OPLOCKED
357423b7c7b8SHermès Bélusca-Maïto         //  on the create call.  That's an NT_SUCCESS code, so we need to keep
357523b7c7b8SHermès Bélusca-Maïto         //  going.
357623b7c7b8SHermès Bélusca-Maïto         //
357723b7c7b8SHermès Bélusca-Maïto 
357823b7c7b8SHermès Bélusca-Maïto         if ((Iosb.Status != STATUS_SUCCESS) &&
357923b7c7b8SHermès Bélusca-Maïto             (Iosb.Status != STATUS_OPLOCK_BREAK_IN_PROGRESS)) {
358023b7c7b8SHermès Bélusca-Maïto 
358123b7c7b8SHermès Bélusca-Maïto             try_return( NOTHING );
358223b7c7b8SHermès Bélusca-Maïto         }
358323b7c7b8SHermès Bélusca-Maïto 
358423b7c7b8SHermès Bélusca-Maïto         //
358523b7c7b8SHermès Bélusca-Maïto         //  Set the flag indicating if Fast I/O is possible
358623b7c7b8SHermès Bélusca-Maïto         //
358723b7c7b8SHermès Bélusca-Maïto 
358823b7c7b8SHermès Bélusca-Maïto         Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );
358923b7c7b8SHermès Bélusca-Maïto 
359023b7c7b8SHermès Bélusca-Maïto         //
359123b7c7b8SHermès Bélusca-Maïto         //  If the user wants write access access to the file make sure there
359223b7c7b8SHermès Bélusca-Maïto         //  is not a process mapping this file as an image.  Any attempt to
359323b7c7b8SHermès Bélusca-Maïto         //  delete the file will be stopped in fileinfo.c
359423b7c7b8SHermès Bélusca-Maïto         //
359523b7c7b8SHermès Bélusca-Maïto         //  If the user wants to delete on close, we must check at this
359623b7c7b8SHermès Bélusca-Maïto         //  point though.
359723b7c7b8SHermès Bélusca-Maïto         //
359823b7c7b8SHermès Bélusca-Maïto 
359923b7c7b8SHermès Bélusca-Maïto         if (FlagOn(*DesiredAccess, FILE_WRITE_DATA) || DeleteOnClose) {
360023b7c7b8SHermès Bélusca-Maïto 
360123b7c7b8SHermès Bélusca-Maïto             Fcb->OpenCount += 1;
360223b7c7b8SHermès Bélusca-Maïto             DecrementFcbOpenCount = TRUE;
360323b7c7b8SHermès Bélusca-Maïto 
360423b7c7b8SHermès Bélusca-Maïto             if (!MmFlushImageSection( &Fcb->NonPaged->SectionObjectPointers,
360523b7c7b8SHermès Bélusca-Maïto                                       MmFlushForWrite )) {
360623b7c7b8SHermès Bélusca-Maïto 
360723b7c7b8SHermès Bélusca-Maïto                 Iosb.Status = DeleteOnClose ? STATUS_CANNOT_DELETE :
360823b7c7b8SHermès Bélusca-Maïto                                               STATUS_SHARING_VIOLATION;
360923b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb );
361023b7c7b8SHermès Bélusca-Maïto             }
361123b7c7b8SHermès Bélusca-Maïto         }
361223b7c7b8SHermès Bélusca-Maïto 
361323b7c7b8SHermès Bélusca-Maïto         //
361423b7c7b8SHermès Bélusca-Maïto         //  If this is a non-cached open on a non-paging file, and there
361523b7c7b8SHermès Bélusca-Maïto         //  are no open cached handles, but there is a still a data
361623b7c7b8SHermès Bélusca-Maïto         //  section, attempt a flush and purge operation to avoid cache
361723b7c7b8SHermès Bélusca-Maïto         //  coherency overhead later.  We ignore any I/O errors from
361823b7c7b8SHermès Bélusca-Maïto         //  the flush.
361923b7c7b8SHermès Bélusca-Maïto         //
362023b7c7b8SHermès Bélusca-Maïto         //  We set the CREATE_IN_PROGRESS flag to prevent the Fcb from
362123b7c7b8SHermès Bélusca-Maïto         //  going away out from underneath us.
362223b7c7b8SHermès Bélusca-Maïto         //
362323b7c7b8SHermès Bélusca-Maïto 
362423b7c7b8SHermès Bélusca-Maïto         if (FlagOn( FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING ) &&
362523b7c7b8SHermès Bélusca-Maïto             (Fcb->UncleanCount == Fcb->NonCachedUncleanCount) &&
362623b7c7b8SHermès Bélusca-Maïto             (Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL) &&
362723b7c7b8SHermès Bélusca-Maïto             !FlagOn( Fcb->FcbState, FCB_STATE_PAGING_FILE )) {
362823b7c7b8SHermès Bélusca-Maïto 
362923b7c7b8SHermès Bélusca-Maïto             SetFlag(Fcb->Vcb->VcbState, VCB_STATE_FLAG_CREATE_IN_PROGRESS);
363023b7c7b8SHermès Bélusca-Maïto 
363123b7c7b8SHermès Bélusca-Maïto             CcFlushCache( &Fcb->NonPaged->SectionObjectPointers, NULL, 0, NULL );
363223b7c7b8SHermès Bélusca-Maïto 
363323b7c7b8SHermès Bélusca-Maïto             //
363423b7c7b8SHermès Bélusca-Maïto             //  Grab and release PagingIo to serialize ourselves with the lazy writer.
363523b7c7b8SHermès Bélusca-Maïto             //  This will work to ensure that all IO has completed on the cached
363623b7c7b8SHermès Bélusca-Maïto             //  data and we will succesfully tear away the cache section.
363723b7c7b8SHermès Bélusca-Maïto             //
363823b7c7b8SHermès Bélusca-Maïto 
363923b7c7b8SHermès Bélusca-Maïto             ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource, TRUE);
364023b7c7b8SHermès Bélusca-Maïto             ExReleaseResourceLite( Fcb->Header.PagingIoResource );
364123b7c7b8SHermès Bélusca-Maïto 
364223b7c7b8SHermès Bélusca-Maïto             CcPurgeCacheSection( &Fcb->NonPaged->SectionObjectPointers,
364323b7c7b8SHermès Bélusca-Maïto                                  NULL,
364423b7c7b8SHermès Bélusca-Maïto                                  0,
364523b7c7b8SHermès Bélusca-Maïto                                  FALSE );
364623b7c7b8SHermès Bélusca-Maïto 
364723b7c7b8SHermès Bélusca-Maïto             ClearFlag(Fcb->Vcb->VcbState, VCB_STATE_FLAG_CREATE_IN_PROGRESS);
364823b7c7b8SHermès Bélusca-Maïto         }
364923b7c7b8SHermès Bélusca-Maïto 
365023b7c7b8SHermès Bélusca-Maïto         //
365123b7c7b8SHermès Bélusca-Maïto         //  Check if the user only wanted to open the file
365223b7c7b8SHermès Bélusca-Maïto         //
365323b7c7b8SHermès Bélusca-Maïto 
365423b7c7b8SHermès Bélusca-Maïto         if ((CreateDisposition == FILE_OPEN) ||
365523b7c7b8SHermès Bélusca-Maïto             (CreateDisposition == FILE_OPEN_IF)) {
365623b7c7b8SHermès Bélusca-Maïto 
365723b7c7b8SHermès Bélusca-Maïto             DebugTrace(0, Dbg, "Doing open operation\n", 0);
365823b7c7b8SHermès Bélusca-Maïto 
365923b7c7b8SHermès Bélusca-Maïto             //
366023b7c7b8SHermès Bélusca-Maïto             //  If the caller has no Ea knowledge, we immediately check for
366123b7c7b8SHermès Bélusca-Maïto             //  Need Ea's on the file.
366223b7c7b8SHermès Bélusca-Maïto             //
366323b7c7b8SHermès Bélusca-Maïto 
366423b7c7b8SHermès Bélusca-Maïto             if (NoEaKnowledge && !FatIsFat32(Vcb)) {
366523b7c7b8SHermès Bélusca-Maïto 
366623b7c7b8SHermès Bélusca-Maïto                 ULONG NeedEaCount;
366723b7c7b8SHermès Bélusca-Maïto 
366823b7c7b8SHermès Bélusca-Maïto                 //
366923b7c7b8SHermès Bélusca-Maïto                 //  Get the dirent for the file and then check that the need
367023b7c7b8SHermès Bélusca-Maïto                 //  ea count is 0.
367123b7c7b8SHermès Bélusca-Maïto                 //
367223b7c7b8SHermès Bélusca-Maïto 
367323b7c7b8SHermès Bélusca-Maïto                 FatGetDirentFromFcbOrDcb( IrpContext,
367423b7c7b8SHermès Bélusca-Maïto                                           Fcb,
367523b7c7b8SHermès Bélusca-Maïto                                           FALSE,
367623b7c7b8SHermès Bélusca-Maïto                                           &Dirent,
367723b7c7b8SHermès Bélusca-Maïto                                           &DirentBcb );
367823b7c7b8SHermès Bélusca-Maïto 
367923b7c7b8SHermès Bélusca-Maïto                 FatGetNeedEaCount( IrpContext,
368023b7c7b8SHermès Bélusca-Maïto                                    Vcb,
368123b7c7b8SHermès Bélusca-Maïto                                    Dirent,
368223b7c7b8SHermès Bélusca-Maïto                                    &NeedEaCount );
368323b7c7b8SHermès Bélusca-Maïto 
368423b7c7b8SHermès Bélusca-Maïto                 FatUnpinBcb( IrpContext, DirentBcb );
368523b7c7b8SHermès Bélusca-Maïto 
368623b7c7b8SHermès Bélusca-Maïto                 if (NeedEaCount != 0) {
368723b7c7b8SHermès Bélusca-Maïto 
368823b7c7b8SHermès Bélusca-Maïto                     Iosb.Status = STATUS_ACCESS_DENIED;
368923b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb );
369023b7c7b8SHermès Bélusca-Maïto                 }
369123b7c7b8SHermès Bélusca-Maïto             }
369223b7c7b8SHermès Bélusca-Maïto 
369323b7c7b8SHermès Bélusca-Maïto             //
369423b7c7b8SHermès Bélusca-Maïto             //  Everything checks out okay, so setup the context and
369523b7c7b8SHermès Bélusca-Maïto             //  section object pointers.
369623b7c7b8SHermès Bélusca-Maïto             //
369723b7c7b8SHermès Bélusca-Maïto 
369823b7c7b8SHermès Bélusca-Maïto             FatSetFileObject( FileObject,
369923b7c7b8SHermès Bélusca-Maïto                               UserFileOpen,
370023b7c7b8SHermès Bélusca-Maïto                               Fcb,
370123b7c7b8SHermès Bélusca-Maïto                               UnwindCcb = FatCreateCcb( IrpContext ));
370223b7c7b8SHermès Bélusca-Maïto 
370323b7c7b8SHermès Bélusca-Maïto             FileObject->SectionObjectPointer = &Fcb->NonPaged->SectionObjectPointers;
370423b7c7b8SHermès Bélusca-Maïto 
370523b7c7b8SHermès Bélusca-Maïto             //
370623b7c7b8SHermès Bélusca-Maïto             //  Fill in the information field, the status field is already
370723b7c7b8SHermès Bélusca-Maïto             //  set.
370823b7c7b8SHermès Bélusca-Maïto             //
370923b7c7b8SHermès Bélusca-Maïto 
371023b7c7b8SHermès Bélusca-Maïto             Iosb.Information = FILE_OPENED;
371123b7c7b8SHermès Bélusca-Maïto 
371223b7c7b8SHermès Bélusca-Maïto             try_return( Iosb );
371323b7c7b8SHermès Bélusca-Maïto         }
371423b7c7b8SHermès Bélusca-Maïto 
371523b7c7b8SHermès Bélusca-Maïto         //
371623b7c7b8SHermès Bélusca-Maïto         //  Check if we are to supersede/overwrite the file, we can wait for
371723b7c7b8SHermès Bélusca-Maïto         //  any I/O at this point
371823b7c7b8SHermès Bélusca-Maïto         //
371923b7c7b8SHermès Bélusca-Maïto 
372023b7c7b8SHermès Bélusca-Maïto         if ((CreateDisposition == FILE_SUPERSEDE) ||
372123b7c7b8SHermès Bélusca-Maïto             (CreateDisposition == FILE_OVERWRITE) ||
372223b7c7b8SHermès Bélusca-Maïto             (CreateDisposition == FILE_OVERWRITE_IF)) {
372323b7c7b8SHermès Bélusca-Maïto 
372423b7c7b8SHermès Bélusca-Maïto             NTSTATUS OldStatus;
372523b7c7b8SHermès Bélusca-Maïto 
372623b7c7b8SHermès Bélusca-Maïto             DebugTrace(0, Dbg, "Doing supersede/overwrite operation\n", 0);
372723b7c7b8SHermès Bélusca-Maïto 
372823b7c7b8SHermès Bélusca-Maïto             //
372923b7c7b8SHermès Bélusca-Maïto             //  We remember the previous status code because it may contain
373023b7c7b8SHermès Bélusca-Maïto             //  information about the oplock status.
373123b7c7b8SHermès Bélusca-Maïto             //
373223b7c7b8SHermès Bélusca-Maïto 
373323b7c7b8SHermès Bélusca-Maïto             OldStatus = Iosb.Status;
373423b7c7b8SHermès Bélusca-Maïto 
373523b7c7b8SHermès Bélusca-Maïto             //
373623b7c7b8SHermès Bélusca-Maïto             //  Determine the granted access for this operation now.
373723b7c7b8SHermès Bélusca-Maïto             //
373823b7c7b8SHermès Bélusca-Maïto 
373923b7c7b8SHermès Bélusca-Maïto             if (!NT_SUCCESS( Iosb.Status = FatCheckSystemSecurityAccess( IrpContext ))) {
374023b7c7b8SHermès Bélusca-Maïto 
374123b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb );
374223b7c7b8SHermès Bélusca-Maïto             }
374323b7c7b8SHermès Bélusca-Maïto 
374423b7c7b8SHermès Bélusca-Maïto             //
374523b7c7b8SHermès Bélusca-Maïto             //  And overwrite the file.
374623b7c7b8SHermès Bélusca-Maïto             //
374723b7c7b8SHermès Bélusca-Maïto 
374823b7c7b8SHermès Bélusca-Maïto             Iosb = FatSupersedeOrOverwriteFile( IrpContext,
374923b7c7b8SHermès Bélusca-Maïto                                                 FileObject,
375023b7c7b8SHermès Bélusca-Maïto                                                 Fcb,
375123b7c7b8SHermès Bélusca-Maïto                                                 AllocationSize,
375223b7c7b8SHermès Bélusca-Maïto                                                 EaBuffer,
375323b7c7b8SHermès Bélusca-Maïto                                                 EaLength,
375423b7c7b8SHermès Bélusca-Maïto                                                 FileAttributes,
375523b7c7b8SHermès Bélusca-Maïto                                                 CreateDisposition,
375623b7c7b8SHermès Bélusca-Maïto                                                 NoEaKnowledge );
375723b7c7b8SHermès Bélusca-Maïto 
375823b7c7b8SHermès Bélusca-Maïto             if (Iosb.Status == STATUS_SUCCESS) {
375923b7c7b8SHermès Bélusca-Maïto 
376023b7c7b8SHermès Bélusca-Maïto                 Iosb.Status = OldStatus;
376123b7c7b8SHermès Bélusca-Maïto             }
376223b7c7b8SHermès Bélusca-Maïto 
376323b7c7b8SHermès Bélusca-Maïto             try_return( Iosb );
376423b7c7b8SHermès Bélusca-Maïto         }
376523b7c7b8SHermès Bélusca-Maïto 
376623b7c7b8SHermès Bélusca-Maïto         //
376723b7c7b8SHermès Bélusca-Maïto         //  If we ever get here then the I/O system gave us some bad input
376823b7c7b8SHermès Bélusca-Maïto         //
376923b7c7b8SHermès Bélusca-Maïto 
377023b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
377123b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
377223b7c7b8SHermès Bélusca-Maïto #endif
377323b7c7b8SHermès Bélusca-Maïto         FatBugCheck( CreateDisposition, 0, 0 );
377423b7c7b8SHermès Bélusca-Maïto 
377523b7c7b8SHermès Bélusca-Maïto     try_exit: NOTHING;
377623b7c7b8SHermès Bélusca-Maïto 
377723b7c7b8SHermès Bélusca-Maïto         //
377823b7c7b8SHermès Bélusca-Maïto         //  Update the share access and counts if successful
377923b7c7b8SHermès Bélusca-Maïto         //
378023b7c7b8SHermès Bélusca-Maïto 
378123b7c7b8SHermès Bélusca-Maïto         if ((Iosb.Status != STATUS_PENDING) && NT_SUCCESS(Iosb.Status)) {
378223b7c7b8SHermès Bélusca-Maïto 
378323b7c7b8SHermès Bélusca-Maïto             //
378423b7c7b8SHermès Bélusca-Maïto             //  Now, we may have added some access bits above to indicate the access
378523b7c7b8SHermès Bélusca-Maïto             //  this caller would conflict with (as opposed to what they get) in order
378623b7c7b8SHermès Bélusca-Maïto             //  to perform the overwrite/supersede.  We need to make a call to that will
378723b7c7b8SHermès Bélusca-Maïto             //  recalculate the bits in the fileobject to reflect the real access they
378823b7c7b8SHermès Bélusca-Maïto             //  will get.
378923b7c7b8SHermès Bélusca-Maïto             //
379023b7c7b8SHermès Bélusca-Maïto 
379123b7c7b8SHermès Bélusca-Maïto             if (AddedAccess) {
379223b7c7b8SHermès Bélusca-Maïto 
379323b7c7b8SHermès Bélusca-Maïto                 NTSTATUS Status;
379423b7c7b8SHermès Bélusca-Maïto 
379523b7c7b8SHermès Bélusca-Maïto                 ClearFlag( *DesiredAccess, AddedAccess );
379623b7c7b8SHermès Bélusca-Maïto 
379723b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
379823b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress:28931, "it needs to be there for debug assert" );
379923b7c7b8SHermès Bélusca-Maïto #endif
380023b7c7b8SHermès Bélusca-Maïto                 Status = IoCheckShareAccess( *DesiredAccess,
380123b7c7b8SHermès Bélusca-Maïto                                              ShareAccess,
380223b7c7b8SHermès Bélusca-Maïto                                              FileObject,
380323b7c7b8SHermès Bélusca-Maïto                                              &Fcb->ShareAccess,
380423b7c7b8SHermès Bélusca-Maïto                                              TRUE );
380523b7c7b8SHermès Bélusca-Maïto 
380623b7c7b8SHermès Bélusca-Maïto                 //
380723b7c7b8SHermès Bélusca-Maïto                 //  It must be the case that we are really asking for less access, so
380823b7c7b8SHermès Bélusca-Maïto                 //  any conflict must have been detected before this point.
380923b7c7b8SHermès Bélusca-Maïto                 //
381023b7c7b8SHermès Bélusca-Maïto 
381123b7c7b8SHermès Bélusca-Maïto                 NT_ASSERT( Status == STATUS_SUCCESS );
381223b7c7b8SHermès Bélusca-Maïto 
381323b7c7b8SHermès Bélusca-Maïto             } else {
381423b7c7b8SHermès Bélusca-Maïto 
381523b7c7b8SHermès Bélusca-Maïto                 IoUpdateShareAccess( FileObject, &Fcb->ShareAccess );
381623b7c7b8SHermès Bélusca-Maïto             }
381723b7c7b8SHermès Bélusca-Maïto 
381823b7c7b8SHermès Bélusca-Maïto             UnwindShareAccess = TRUE;
381923b7c7b8SHermès Bélusca-Maïto 
382023b7c7b8SHermès Bélusca-Maïto             //
382123b7c7b8SHermès Bélusca-Maïto             //  In case this was set, clear it now.
382223b7c7b8SHermès Bélusca-Maïto             //
382323b7c7b8SHermès Bélusca-Maïto 
382423b7c7b8SHermès Bélusca-Maïto             ClearFlag(Fcb->FcbState, FCB_STATE_DELAY_CLOSE);
382523b7c7b8SHermès Bélusca-Maïto 
382623b7c7b8SHermès Bélusca-Maïto             Fcb->UncleanCount += 1;
382723b7c7b8SHermès Bélusca-Maïto             Fcb->OpenCount += 1;
382823b7c7b8SHermès Bélusca-Maïto             if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) {
382923b7c7b8SHermès Bélusca-Maïto                 Fcb->NonCachedUncleanCount += 1;
383023b7c7b8SHermès Bélusca-Maïto             }
383123b7c7b8SHermès Bélusca-Maïto             Vcb->OpenFileCount += 1;
383223b7c7b8SHermès Bélusca-Maïto             if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount += 1; }
383323b7c7b8SHermès Bélusca-Maïto 
383423b7c7b8SHermès Bélusca-Maïto             {
383523b7c7b8SHermès Bélusca-Maïto                 PCCB Ccb;
383623b7c7b8SHermès Bélusca-Maïto 
383723b7c7b8SHermès Bélusca-Maïto                 Ccb = (PCCB)FileObject->FsContext2;
383823b7c7b8SHermès Bélusca-Maïto 
383923b7c7b8SHermès Bélusca-Maïto                 //
384023b7c7b8SHermès Bélusca-Maïto                 //  Mark the DeleteOnClose bit if the operation was successful.
384123b7c7b8SHermès Bélusca-Maïto                 //
384223b7c7b8SHermès Bélusca-Maïto 
384323b7c7b8SHermès Bélusca-Maïto                 if ( DeleteOnClose ) {
384423b7c7b8SHermès Bélusca-Maïto 
384523b7c7b8SHermès Bélusca-Maïto                     SetFlag( Ccb->Flags, CCB_FLAG_DELETE_ON_CLOSE );
384623b7c7b8SHermès Bélusca-Maïto                 }
384723b7c7b8SHermès Bélusca-Maïto 
384823b7c7b8SHermès Bélusca-Maïto                 //
384923b7c7b8SHermès Bélusca-Maïto                 //  Mark the OpenedByShortName bit if the operation was successful.
385023b7c7b8SHermès Bélusca-Maïto                 //
385123b7c7b8SHermès Bélusca-Maïto 
385223b7c7b8SHermès Bélusca-Maïto                 if ( FileNameOpenedDos ) {
385323b7c7b8SHermès Bélusca-Maïto 
385423b7c7b8SHermès Bélusca-Maïto                     SetFlag( Ccb->Flags, CCB_FLAG_OPENED_BY_SHORTNAME );
385523b7c7b8SHermès Bélusca-Maïto                 }
385623b7c7b8SHermès Bélusca-Maïto 
385723b7c7b8SHermès Bélusca-Maïto                 //
385823b7c7b8SHermès Bélusca-Maïto                 //  Mark the ManageVolumeAccess bit if the privilege is held.
385923b7c7b8SHermès Bélusca-Maïto                 //
386023b7c7b8SHermès Bélusca-Maïto 
386123b7c7b8SHermès Bélusca-Maïto                 if (FatCheckManageVolumeAccess( IrpContext,
386223b7c7b8SHermès Bélusca-Maïto                                                 IrpSp->Parameters.Create.SecurityContext->AccessState,
386323b7c7b8SHermès Bélusca-Maïto                                                 (KPROCESSOR_MODE)( FlagOn( IrpSp->Flags, SL_FORCE_ACCESS_CHECK ) ?
386423b7c7b8SHermès Bélusca-Maïto                                                                    UserMode :
386523b7c7b8SHermès Bélusca-Maïto                                                                    IrpContext->OriginatingIrp->RequestorMode ))) {
386623b7c7b8SHermès Bélusca-Maïto 
386723b7c7b8SHermès Bélusca-Maïto                     SetFlag( Ccb->Flags, CCB_FLAG_MANAGE_VOLUME_ACCESS );
386823b7c7b8SHermès Bélusca-Maïto                 }
386923b7c7b8SHermès Bélusca-Maïto             }
387023b7c7b8SHermès Bélusca-Maïto 
387123b7c7b8SHermès Bélusca-Maïto 
387223b7c7b8SHermès Bélusca-Maïto         }
387323b7c7b8SHermès Bélusca-Maïto 
387423b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
387523b7c7b8SHermès Bélusca-Maïto 
387623b7c7b8SHermès Bélusca-Maïto         DebugUnwind( FatOpenExistingFcb );
387723b7c7b8SHermès Bélusca-Maïto 
387823b7c7b8SHermès Bélusca-Maïto         //
387923b7c7b8SHermès Bélusca-Maïto         //  Unpin the Dirent Bcb if pinned.
388023b7c7b8SHermès Bélusca-Maïto         //
388123b7c7b8SHermès Bélusca-Maïto 
388223b7c7b8SHermès Bélusca-Maïto         FatUnpinBcb( IrpContext, DirentBcb );
388323b7c7b8SHermès Bélusca-Maïto 
388423b7c7b8SHermès Bélusca-Maïto         //
388523b7c7b8SHermès Bélusca-Maïto         //  If this is an abnormal termination then undo our work
388623b7c7b8SHermès Bélusca-Maïto         //
388723b7c7b8SHermès Bélusca-Maïto 
388823b7c7b8SHermès Bélusca-Maïto         if (_SEH2_AbnormalTermination()) {
388923b7c7b8SHermès Bélusca-Maïto 
389023b7c7b8SHermès Bélusca-Maïto             if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
389123b7c7b8SHermès Bélusca-Maïto             if (UnwindShareAccess) { IoRemoveShareAccess( FileObject, &Fcb->ShareAccess ); }
389223b7c7b8SHermès Bélusca-Maïto         }
389323b7c7b8SHermès Bélusca-Maïto 
389423b7c7b8SHermès Bélusca-Maïto         if (DecrementFcbOpenCount) {
389523b7c7b8SHermès Bélusca-Maïto 
389623b7c7b8SHermès Bélusca-Maïto             Fcb->OpenCount -= 1;
389723b7c7b8SHermès Bélusca-Maïto 
389823b7c7b8SHermès Bélusca-Maïto             if (Fcb->OpenCount == 0) {
389923b7c7b8SHermès Bélusca-Maïto                 if (ARGUMENT_PRESENT( FileObject )) {
390023b7c7b8SHermès Bélusca-Maïto                     FileObject->SectionObjectPointer = NULL;
390123b7c7b8SHermès Bélusca-Maïto                 }
390223b7c7b8SHermès Bélusca-Maïto                 FatDeleteFcb( IrpContext, &Fcb );
390323b7c7b8SHermès Bélusca-Maïto                 FcbAcquired = FALSE;
390423b7c7b8SHermès Bélusca-Maïto             }
390523b7c7b8SHermès Bélusca-Maïto         }
390623b7c7b8SHermès Bélusca-Maïto 
390723b7c7b8SHermès Bélusca-Maïto         if (FcbAcquired) {
390823b7c7b8SHermès Bélusca-Maïto 
390923b7c7b8SHermès Bélusca-Maïto             FatReleaseFcb( IrpContext, Fcb );
391023b7c7b8SHermès Bélusca-Maïto         }
391123b7c7b8SHermès Bélusca-Maïto 
391223b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatOpenExistingFcb -> Iosb.Status = %08lx\n", Iosb.Status);
391323b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
391423b7c7b8SHermès Bélusca-Maïto 
391523b7c7b8SHermès Bélusca-Maïto     return Iosb;
391623b7c7b8SHermès Bélusca-Maïto }
391723b7c7b8SHermès Bélusca-Maïto 
391823b7c7b8SHermès Bélusca-Maïto //
391923b7c7b8SHermès Bélusca-Maïto //  Internal support routine
392023b7c7b8SHermès Bélusca-Maïto //
392123b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)392223b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
392323b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
392423b7c7b8SHermès Bélusca-Maïto FatOpenTargetDirectory (
392523b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
392623b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
392723b7c7b8SHermès Bélusca-Maïto     _Inout_ PDCB Dcb,
392823b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
392923b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
393023b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN DoesNameExist,
393123b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN FileNameOpenedDos
393223b7c7b8SHermès Bélusca-Maïto     )
393323b7c7b8SHermès Bélusca-Maïto 
393423b7c7b8SHermès Bélusca-Maïto /*++
393523b7c7b8SHermès Bélusca-Maïto 
393623b7c7b8SHermès Bélusca-Maïto Routine Description:
393723b7c7b8SHermès Bélusca-Maïto 
393823b7c7b8SHermès Bélusca-Maïto     This routine opens the target directory and replaces the name in the
393923b7c7b8SHermès Bélusca-Maïto     file object with the remaining name.
394023b7c7b8SHermès Bélusca-Maïto 
394123b7c7b8SHermès Bélusca-Maïto Arguments:
394223b7c7b8SHermès Bélusca-Maïto 
394323b7c7b8SHermès Bélusca-Maïto     FileObject - Supplies the File object
394423b7c7b8SHermès Bélusca-Maïto 
394523b7c7b8SHermès Bélusca-Maïto     Dcb - Supplies an already existing dcb that we are going to open
394623b7c7b8SHermès Bélusca-Maïto 
394723b7c7b8SHermès Bélusca-Maïto     DesiredAccess - Supplies the desired access of the caller
394823b7c7b8SHermès Bélusca-Maïto 
394923b7c7b8SHermès Bélusca-Maïto     ShareAccess - Supplies the share access of the caller
395023b7c7b8SHermès Bélusca-Maïto 
395123b7c7b8SHermès Bélusca-Maïto     DoesNameExist - Indicates if the file name already exists in the
395223b7c7b8SHermès Bélusca-Maïto         target directory.
395323b7c7b8SHermès Bélusca-Maïto 
395423b7c7b8SHermès Bélusca-Maïto 
395523b7c7b8SHermès Bélusca-Maïto Return Value:
395623b7c7b8SHermès Bélusca-Maïto 
395723b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK - Returns the completion status for the operation
395823b7c7b8SHermès Bélusca-Maïto 
395923b7c7b8SHermès Bélusca-Maïto --*/
396023b7c7b8SHermès Bélusca-Maïto 
396123b7c7b8SHermès Bélusca-Maïto {
396223b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK Iosb = {0};
396323b7c7b8SHermès Bélusca-Maïto 
396423b7c7b8SHermès Bélusca-Maïto     //
396523b7c7b8SHermès Bélusca-Maïto     //  The following variables are for abnormal termination
396623b7c7b8SHermès Bélusca-Maïto     //
396723b7c7b8SHermès Bélusca-Maïto 
396823b7c7b8SHermès Bélusca-Maïto     BOOLEAN UnwindShareAccess = FALSE;
396923b7c7b8SHermès Bélusca-Maïto     PCCB UnwindCcb = NULL;
397023b7c7b8SHermès Bélusca-Maïto     BOOLEAN DcbAcquired = FALSE;
397123b7c7b8SHermès Bélusca-Maïto 
397223b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
397323b7c7b8SHermès Bélusca-Maïto 
397423b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatOpenTargetDirectory...\n", 0);
397523b7c7b8SHermès Bélusca-Maïto 
397623b7c7b8SHermès Bélusca-Maïto     //
397723b7c7b8SHermès Bélusca-Maïto     //  Get the Dcb exlcusive.  This is important as cleanup does not
397823b7c7b8SHermès Bélusca-Maïto     //  acquire the Vcb.
397923b7c7b8SHermès Bélusca-Maïto     //
398023b7c7b8SHermès Bélusca-Maïto 
398123b7c7b8SHermès Bélusca-Maïto     (VOID)FatAcquireExclusiveFcb( IrpContext, Dcb );
398223b7c7b8SHermès Bélusca-Maïto     DcbAcquired = TRUE;
398323b7c7b8SHermès Bélusca-Maïto 
398423b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
398523b7c7b8SHermès Bélusca-Maïto 
398623b7c7b8SHermès Bélusca-Maïto         ULONG i;
398723b7c7b8SHermès Bélusca-Maïto 
398823b7c7b8SHermès Bélusca-Maïto         //
398923b7c7b8SHermès Bélusca-Maïto         //  If the Dcb is already opened by someone then we need
399023b7c7b8SHermès Bélusca-Maïto         //  to check the share access
399123b7c7b8SHermès Bélusca-Maïto         //
399223b7c7b8SHermès Bélusca-Maïto 
399323b7c7b8SHermès Bélusca-Maïto         if (Dcb->OpenCount > 0) {
399423b7c7b8SHermès Bélusca-Maïto 
399523b7c7b8SHermès Bélusca-Maïto             if (!NT_SUCCESS(Iosb.Status = IoCheckShareAccess( *DesiredAccess,
399623b7c7b8SHermès Bélusca-Maïto                                                               ShareAccess,
399723b7c7b8SHermès Bélusca-Maïto                                                               FileObject,
399823b7c7b8SHermès Bélusca-Maïto                                                               &Dcb->ShareAccess,
399923b7c7b8SHermès Bélusca-Maïto                                                               TRUE ))) {
400023b7c7b8SHermès Bélusca-Maïto 
400123b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb );
400223b7c7b8SHermès Bélusca-Maïto             }
400323b7c7b8SHermès Bélusca-Maïto 
400423b7c7b8SHermès Bélusca-Maïto         } else {
400523b7c7b8SHermès Bélusca-Maïto 
400623b7c7b8SHermès Bélusca-Maïto             IoSetShareAccess( *DesiredAccess,
400723b7c7b8SHermès Bélusca-Maïto                               ShareAccess,
400823b7c7b8SHermès Bélusca-Maïto                               FileObject,
400923b7c7b8SHermès Bélusca-Maïto                               &Dcb->ShareAccess );
401023b7c7b8SHermès Bélusca-Maïto         }
401123b7c7b8SHermès Bélusca-Maïto 
401223b7c7b8SHermès Bélusca-Maïto         UnwindShareAccess = TRUE;
401323b7c7b8SHermès Bélusca-Maïto 
401423b7c7b8SHermès Bélusca-Maïto         //
401523b7c7b8SHermès Bélusca-Maïto         //  Setup the context and section object pointers, and update
401623b7c7b8SHermès Bélusca-Maïto         //  our reference counts
401723b7c7b8SHermès Bélusca-Maïto         //
401823b7c7b8SHermès Bélusca-Maïto 
401923b7c7b8SHermès Bélusca-Maïto         FatSetFileObject( FileObject,
402023b7c7b8SHermès Bélusca-Maïto                           UserDirectoryOpen,
402123b7c7b8SHermès Bélusca-Maïto                           Dcb,
402223b7c7b8SHermès Bélusca-Maïto                           UnwindCcb = FatCreateCcb( IrpContext ));
402323b7c7b8SHermès Bélusca-Maïto 
402423b7c7b8SHermès Bélusca-Maïto         Dcb->UncleanCount += 1;
402523b7c7b8SHermès Bélusca-Maïto         Dcb->OpenCount += 1;
402623b7c7b8SHermès Bélusca-Maïto         Dcb->Vcb->OpenFileCount += 1;
402723b7c7b8SHermès Bélusca-Maïto         if (IsFileObjectReadOnly(FileObject)) { Dcb->Vcb->ReadOnlyCount += 1; }
402823b7c7b8SHermès Bélusca-Maïto 
402923b7c7b8SHermès Bélusca-Maïto         //
403023b7c7b8SHermès Bélusca-Maïto         //  Update the name in the file object, by definition the remaining
403123b7c7b8SHermès Bélusca-Maïto         //  part must be shorter than the original file name so we'll just
403223b7c7b8SHermès Bélusca-Maïto         //  overwrite the file name.
403323b7c7b8SHermès Bélusca-Maïto         //
403423b7c7b8SHermès Bélusca-Maïto 
403523b7c7b8SHermès Bélusca-Maïto         i = FileObject->FileName.Length/sizeof(WCHAR) - 1;
403623b7c7b8SHermès Bélusca-Maïto 
403723b7c7b8SHermès Bélusca-Maïto         //
403823b7c7b8SHermès Bélusca-Maïto         //  Get rid of a trailing backslash
403923b7c7b8SHermès Bélusca-Maïto         //
404023b7c7b8SHermès Bélusca-Maïto 
404123b7c7b8SHermès Bélusca-Maïto         if (FileObject->FileName.Buffer[i] == L'\\') {
404223b7c7b8SHermès Bélusca-Maïto 
404323b7c7b8SHermès Bélusca-Maïto             NT_ASSERT(i != 0);
404423b7c7b8SHermès Bélusca-Maïto 
404523b7c7b8SHermès Bélusca-Maïto             FileObject->FileName.Length -= sizeof(WCHAR);
404623b7c7b8SHermès Bélusca-Maïto             i -= 1;
404723b7c7b8SHermès Bélusca-Maïto         }
404823b7c7b8SHermès Bélusca-Maïto 
404923b7c7b8SHermès Bélusca-Maïto         //
405023b7c7b8SHermès Bélusca-Maïto         //  Find the first non-backslash character.  i will be its index.
405123b7c7b8SHermès Bélusca-Maïto         //
405223b7c7b8SHermès Bélusca-Maïto 
405323b7c7b8SHermès Bélusca-Maïto         while (TRUE) {
405423b7c7b8SHermès Bélusca-Maïto 
405523b7c7b8SHermès Bélusca-Maïto             if (FileObject->FileName.Buffer[i] == L'\\') {
405623b7c7b8SHermès Bélusca-Maïto 
405723b7c7b8SHermès Bélusca-Maïto                 i += 1;
405823b7c7b8SHermès Bélusca-Maïto                 break;
405923b7c7b8SHermès Bélusca-Maïto             }
406023b7c7b8SHermès Bélusca-Maïto 
406123b7c7b8SHermès Bélusca-Maïto             if (i == 0) {
406223b7c7b8SHermès Bélusca-Maïto                 break;
406323b7c7b8SHermès Bélusca-Maïto             }
406423b7c7b8SHermès Bélusca-Maïto 
406523b7c7b8SHermès Bélusca-Maïto             i--;
406623b7c7b8SHermès Bélusca-Maïto         }
406723b7c7b8SHermès Bélusca-Maïto 
406823b7c7b8SHermès Bélusca-Maïto         if (i) {
406923b7c7b8SHermès Bélusca-Maïto 
407023b7c7b8SHermès Bélusca-Maïto             FileObject->FileName.Length -= (USHORT)(i * sizeof(WCHAR));
407123b7c7b8SHermès Bélusca-Maïto 
407223b7c7b8SHermès Bélusca-Maïto             RtlMoveMemory( &FileObject->FileName.Buffer[0],
407323b7c7b8SHermès Bélusca-Maïto                            &FileObject->FileName.Buffer[i],
407423b7c7b8SHermès Bélusca-Maïto                            FileObject->FileName.Length );
407523b7c7b8SHermès Bélusca-Maïto         }
407623b7c7b8SHermès Bélusca-Maïto 
407723b7c7b8SHermès Bélusca-Maïto         //
407823b7c7b8SHermès Bélusca-Maïto         //  And set our status to success
407923b7c7b8SHermès Bélusca-Maïto         //
408023b7c7b8SHermès Bélusca-Maïto 
408123b7c7b8SHermès Bélusca-Maïto         Iosb.Status = STATUS_SUCCESS;
408223b7c7b8SHermès Bélusca-Maïto         Iosb.Information = (DoesNameExist ? FILE_EXISTS : FILE_DOES_NOT_EXIST);
408323b7c7b8SHermès Bélusca-Maïto 
408423b7c7b8SHermès Bélusca-Maïto         if ( ( NT_SUCCESS(Iosb.Status) ) && ( DoesNameExist ) ) {
408523b7c7b8SHermès Bélusca-Maïto             PCCB Ccb;
408623b7c7b8SHermès Bélusca-Maïto 
408723b7c7b8SHermès Bélusca-Maïto             Ccb = (PCCB)FileObject->FsContext2;
408823b7c7b8SHermès Bélusca-Maïto 
408923b7c7b8SHermès Bélusca-Maïto             //
409023b7c7b8SHermès Bélusca-Maïto             //  Mark the OpenedByShortName bit if the operation was successful.
409123b7c7b8SHermès Bélusca-Maïto             //
409223b7c7b8SHermès Bélusca-Maïto 
409323b7c7b8SHermès Bélusca-Maïto             if ( FileNameOpenedDos ) {
409423b7c7b8SHermès Bélusca-Maïto 
409523b7c7b8SHermès Bélusca-Maïto                 SetFlag( Ccb->Flags, CCB_FLAG_OPENED_BY_SHORTNAME );
409623b7c7b8SHermès Bélusca-Maïto             }
409723b7c7b8SHermès Bélusca-Maïto         }
409823b7c7b8SHermès Bélusca-Maïto 
409923b7c7b8SHermès Bélusca-Maïto     try_exit: NOTHING;
410023b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
410123b7c7b8SHermès Bélusca-Maïto 
410223b7c7b8SHermès Bélusca-Maïto         DebugUnwind( FatOpenTargetDirectory );
410323b7c7b8SHermès Bélusca-Maïto 
410423b7c7b8SHermès Bélusca-Maïto         //
410523b7c7b8SHermès Bélusca-Maïto         //  If this is an abnormal termination then undo our work
410623b7c7b8SHermès Bélusca-Maïto         //
410723b7c7b8SHermès Bélusca-Maïto 
410823b7c7b8SHermès Bélusca-Maïto         if (_SEH2_AbnormalTermination()) {
410923b7c7b8SHermès Bélusca-Maïto 
411023b7c7b8SHermès Bélusca-Maïto             if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
411123b7c7b8SHermès Bélusca-Maïto             if (UnwindShareAccess) { IoRemoveShareAccess( FileObject, &Dcb->ShareAccess ); }
411223b7c7b8SHermès Bélusca-Maïto         }
411323b7c7b8SHermès Bélusca-Maïto 
411423b7c7b8SHermès Bélusca-Maïto         if (DcbAcquired) {
411523b7c7b8SHermès Bélusca-Maïto 
411623b7c7b8SHermès Bélusca-Maïto             FatReleaseFcb( IrpContext, Dcb );
411723b7c7b8SHermès Bélusca-Maïto         }
411823b7c7b8SHermès Bélusca-Maïto 
411923b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatOpenTargetDirectory -> Iosb.Status = %08lx\n", Iosb.Status);
412023b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
412123b7c7b8SHermès Bélusca-Maïto 
412223b7c7b8SHermès Bélusca-Maïto     return Iosb;
412323b7c7b8SHermès Bélusca-Maïto }
412423b7c7b8SHermès Bélusca-Maïto 
412523b7c7b8SHermès Bélusca-Maïto 
412623b7c7b8SHermès Bélusca-Maïto 
412723b7c7b8SHermès Bélusca-Maïto //
412823b7c7b8SHermès Bélusca-Maïto //  Internal support routine
412923b7c7b8SHermès Bélusca-Maïto //
413023b7c7b8SHermès Bélusca-Maïto _Success_(return.Status == STATUS_SUCCESS)
_Requires_lock_held_(_Global_critical_region_)413123b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
413223b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
413323b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
413423b7c7b8SHermès Bélusca-Maïto #pragma warning(suppress:6101) // bug in PREFast means the _Success_ annotation is not correctly applied
413523b7c7b8SHermès Bélusca-Maïto #endif
413623b7c7b8SHermès Bélusca-Maïto FatOpenExistingDirectory (
413723b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
413823b7c7b8SHermès Bélusca-Maïto     _In_ PIO_STACK_LOCATION IrpSp,
413923b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
414023b7c7b8SHermès Bélusca-Maïto     _Inout_ PVCB Vcb,
414123b7c7b8SHermès Bélusca-Maïto     _Outptr_result_maybenull_ PDCB *Dcb,
414223b7c7b8SHermès Bélusca-Maïto     _In_ PDCB ParentDcb,
414323b7c7b8SHermès Bélusca-Maïto     _In_ PDIRENT Dirent,
414423b7c7b8SHermès Bélusca-Maïto     _In_ ULONG LfnByteOffset,
414523b7c7b8SHermès Bélusca-Maïto     _In_ ULONG DirentByteOffset,
414623b7c7b8SHermès Bélusca-Maïto     _In_ PUNICODE_STRING Lfn,
414723b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
414823b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
414923b7c7b8SHermès Bélusca-Maïto     _In_ ULONG CreateDisposition,
415023b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN NoEaKnowledge,
415123b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN DeleteOnClose,
415223b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN FileNameOpenedDos,
415323b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN OpenRequiringOplock
415423b7c7b8SHermès Bélusca-Maïto     )
415523b7c7b8SHermès Bélusca-Maïto 
415623b7c7b8SHermès Bélusca-Maïto /*++
415723b7c7b8SHermès Bélusca-Maïto 
415823b7c7b8SHermès Bélusca-Maïto Routine Description:
415923b7c7b8SHermès Bélusca-Maïto 
416023b7c7b8SHermès Bélusca-Maïto     This routine opens the specified directory.  The directory has not
416123b7c7b8SHermès Bélusca-Maïto     previously been opened.
416223b7c7b8SHermès Bélusca-Maïto 
416323b7c7b8SHermès Bélusca-Maïto Arguments:
416423b7c7b8SHermès Bélusca-Maïto 
416523b7c7b8SHermès Bélusca-Maïto     FileObject - Supplies the File object
416623b7c7b8SHermès Bélusca-Maïto 
416723b7c7b8SHermès Bélusca-Maïto     Vcb - Supplies the Vcb denoting the volume containing the dcb
416823b7c7b8SHermès Bélusca-Maïto 
416923b7c7b8SHermès Bélusca-Maïto     Dcb - Returns the newly-created DCB for the file.
417023b7c7b8SHermès Bélusca-Maïto 
417123b7c7b8SHermès Bélusca-Maïto     ParentDcb - Supplies the parent directory containing the subdirectory
417223b7c7b8SHermès Bélusca-Maïto         to be opened
417323b7c7b8SHermès Bélusca-Maïto 
417423b7c7b8SHermès Bélusca-Maïto     DirectoryName - Supplies the file name of the directory being opened.
417523b7c7b8SHermès Bélusca-Maïto 
417623b7c7b8SHermès Bélusca-Maïto     Dirent - Supplies the dirent for the directory being opened
417723b7c7b8SHermès Bélusca-Maïto 
417823b7c7b8SHermès Bélusca-Maïto     LfnByteOffset - Tells where the Lfn begins.  If there is no Lfn
417923b7c7b8SHermès Bélusca-Maïto         this field is the same as DirentByteOffset.
418023b7c7b8SHermès Bélusca-Maïto 
418123b7c7b8SHermès Bélusca-Maïto     DirentByteOffset - Supplies the Vbo of the dirent within its parent
418223b7c7b8SHermès Bélusca-Maïto         directory
418323b7c7b8SHermès Bélusca-Maïto 
418423b7c7b8SHermès Bélusca-Maïto     Lfn - May supply a long name for the file.
418523b7c7b8SHermès Bélusca-Maïto 
418623b7c7b8SHermès Bélusca-Maïto     DesiredAccess - Supplies the desired access of the caller
418723b7c7b8SHermès Bélusca-Maïto 
418823b7c7b8SHermès Bélusca-Maïto     ShareAccess - Supplies the share access of the caller
418923b7c7b8SHermès Bélusca-Maïto 
419023b7c7b8SHermès Bélusca-Maïto     CreateDisposition - Supplies the create disposition for this operation
419123b7c7b8SHermès Bélusca-Maïto 
419223b7c7b8SHermès Bélusca-Maïto     NoEaKnowledge - This opener doesn't understand Ea's and we fail this
419323b7c7b8SHermès Bélusca-Maïto         open if the file has NeedEa's.
419423b7c7b8SHermès Bélusca-Maïto 
419523b7c7b8SHermès Bélusca-Maïto     DeleteOnClose - The caller wants the file gone when the handle is closed
419623b7c7b8SHermès Bélusca-Maïto 
419723b7c7b8SHermès Bélusca-Maïto     OpenRequiringOplock - The caller provided the FILE_OPEN_REQUIRING_OPLOCK option.
419823b7c7b8SHermès Bélusca-Maïto 
419923b7c7b8SHermès Bélusca-Maïto Return Value:
420023b7c7b8SHermès Bélusca-Maïto 
420123b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK - Returns the completion status for the operation
420223b7c7b8SHermès Bélusca-Maïto 
420323b7c7b8SHermès Bélusca-Maïto --*/
420423b7c7b8SHermès Bélusca-Maïto 
420523b7c7b8SHermès Bélusca-Maïto {
420623b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK Iosb = {0};
420723b7c7b8SHermès Bélusca-Maïto 
420823b7c7b8SHermès Bélusca-Maïto     //
420923b7c7b8SHermès Bélusca-Maïto     //  The following variables are for abnormal termination
421023b7c7b8SHermès Bélusca-Maïto     //
421123b7c7b8SHermès Bélusca-Maïto 
421223b7c7b8SHermès Bélusca-Maïto     PDCB UnwindDcb = NULL;
421323b7c7b8SHermès Bélusca-Maïto     PCCB UnwindCcb = NULL;
421423b7c7b8SHermès Bélusca-Maïto 
421523b7c7b8SHermès Bélusca-Maïto     BOOLEAN CountsIncremented = FALSE;
421623b7c7b8SHermès Bélusca-Maïto 
421723b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( DeleteOnClose );
421823b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION <= NTDDI_WIN7)
421923b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( OpenRequiringOplock );
422023b7c7b8SHermès Bélusca-Maïto #endif
422123b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( IrpSp );
422223b7c7b8SHermès Bélusca-Maïto 
422323b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
422423b7c7b8SHermès Bélusca-Maïto 
422523b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatOpenExistingDirectory...\n", 0);
422623b7c7b8SHermès Bélusca-Maïto 
422723b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
422823b7c7b8SHermès Bélusca-Maïto 
422923b7c7b8SHermès Bélusca-Maïto         //
423023b7c7b8SHermès Bélusca-Maïto         //  If the caller has no Ea knowledge, we immediately check for
423123b7c7b8SHermès Bélusca-Maïto         //  Need Ea's on the file.
423223b7c7b8SHermès Bélusca-Maïto         //
423323b7c7b8SHermès Bélusca-Maïto 
423423b7c7b8SHermès Bélusca-Maïto         if (NoEaKnowledge && !FatIsFat32(Vcb)) {
423523b7c7b8SHermès Bélusca-Maïto 
423623b7c7b8SHermès Bélusca-Maïto             ULONG NeedEaCount;
423723b7c7b8SHermès Bélusca-Maïto 
423823b7c7b8SHermès Bélusca-Maïto             FatGetNeedEaCount( IrpContext,
423923b7c7b8SHermès Bélusca-Maïto                                Vcb,
424023b7c7b8SHermès Bélusca-Maïto                                Dirent,
424123b7c7b8SHermès Bélusca-Maïto                                &NeedEaCount );
424223b7c7b8SHermès Bélusca-Maïto 
424323b7c7b8SHermès Bélusca-Maïto             if (NeedEaCount != 0) {
424423b7c7b8SHermès Bélusca-Maïto 
424523b7c7b8SHermès Bélusca-Maïto                 Iosb.Status = STATUS_ACCESS_DENIED;
424623b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb );
424723b7c7b8SHermès Bélusca-Maïto             }
424823b7c7b8SHermès Bélusca-Maïto         }
424923b7c7b8SHermès Bélusca-Maïto 
425023b7c7b8SHermès Bélusca-Maïto         //
425123b7c7b8SHermès Bélusca-Maïto         //  Check the create disposition and desired access
425223b7c7b8SHermès Bélusca-Maïto         //
425323b7c7b8SHermès Bélusca-Maïto 
425423b7c7b8SHermès Bélusca-Maïto         if ((CreateDisposition != FILE_OPEN) &&
425523b7c7b8SHermès Bélusca-Maïto             (CreateDisposition != FILE_OPEN_IF)) {
425623b7c7b8SHermès Bélusca-Maïto 
425723b7c7b8SHermès Bélusca-Maïto             Iosb.Status = STATUS_OBJECT_NAME_COLLISION;
425823b7c7b8SHermès Bélusca-Maïto             try_return( Iosb );
425923b7c7b8SHermès Bélusca-Maïto         }
426023b7c7b8SHermès Bélusca-Maïto 
426123b7c7b8SHermès Bélusca-Maïto         if (!FatCheckFileAccess( IrpContext,
426223b7c7b8SHermès Bélusca-Maïto                                  Dirent->Attributes,
426323b7c7b8SHermès Bélusca-Maïto                                  DesiredAccess)) {
426423b7c7b8SHermès Bélusca-Maïto 
426523b7c7b8SHermès Bélusca-Maïto             Iosb.Status = STATUS_ACCESS_DENIED;
426623b7c7b8SHermès Bélusca-Maïto             try_return( Iosb );
426723b7c7b8SHermès Bélusca-Maïto         }
426823b7c7b8SHermès Bélusca-Maïto 
426923b7c7b8SHermès Bélusca-Maïto         //
427023b7c7b8SHermès Bélusca-Maïto         //  Create a new dcb for the directory
427123b7c7b8SHermès Bélusca-Maïto         //
427223b7c7b8SHermès Bélusca-Maïto 
427323b7c7b8SHermès Bélusca-Maïto         *Dcb = UnwindDcb = FatCreateDcb( IrpContext,
427423b7c7b8SHermès Bélusca-Maïto                                         Vcb,
427523b7c7b8SHermès Bélusca-Maïto                                         ParentDcb,
427623b7c7b8SHermès Bélusca-Maïto                                         LfnByteOffset,
427723b7c7b8SHermès Bélusca-Maïto                                         DirentByteOffset,
427823b7c7b8SHermès Bélusca-Maïto                                         Dirent,
427923b7c7b8SHermès Bélusca-Maïto                                         Lfn );
428023b7c7b8SHermès Bélusca-Maïto 
428123b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN8)
428223b7c7b8SHermès Bélusca-Maïto 
428323b7c7b8SHermès Bélusca-Maïto         //
428423b7c7b8SHermès Bélusca-Maïto         //  Let's make sure that if the caller provided an oplock key that it
428523b7c7b8SHermès Bélusca-Maïto         //  gets stored in the file object.
428623b7c7b8SHermès Bélusca-Maïto         //
428723b7c7b8SHermès Bélusca-Maïto 
428823b7c7b8SHermès Bélusca-Maïto         Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(*Dcb),
428923b7c7b8SHermès Bélusca-Maïto                                           IrpContext->OriginatingIrp,
429023b7c7b8SHermès Bélusca-Maïto                                           OPLOCK_FLAG_OPLOCK_KEY_CHECK_ONLY,
429123b7c7b8SHermès Bélusca-Maïto                                           NULL,
429223b7c7b8SHermès Bélusca-Maïto                                           NULL,
429323b7c7b8SHermès Bélusca-Maïto                                           NULL );
429423b7c7b8SHermès Bélusca-Maïto 
429523b7c7b8SHermès Bélusca-Maïto         //
429623b7c7b8SHermès Bélusca-Maïto         //  If the caller wants atomic create-with-oplock semantics, tell
429723b7c7b8SHermès Bélusca-Maïto         //  the oplock package.  We haven't incremented the Fcb's UncleanCount
429823b7c7b8SHermès Bélusca-Maïto         //  for this create yet, so add that in on the call.
429923b7c7b8SHermès Bélusca-Maïto         //
430023b7c7b8SHermès Bélusca-Maïto 
430123b7c7b8SHermès Bélusca-Maïto         if (OpenRequiringOplock &&
430223b7c7b8SHermès Bélusca-Maïto             (Iosb.Status == STATUS_SUCCESS)) {
430323b7c7b8SHermès Bélusca-Maïto 
430423b7c7b8SHermès Bélusca-Maïto             Iosb.Status = FsRtlOplockFsctrl( FatGetFcbOplock(*Dcb),
430523b7c7b8SHermès Bélusca-Maïto                                              IrpContext->OriginatingIrp,
430623b7c7b8SHermès Bélusca-Maïto                                              ((*Dcb)->UncleanCount + 1) );
430723b7c7b8SHermès Bélusca-Maïto         }
430823b7c7b8SHermès Bélusca-Maïto 
430923b7c7b8SHermès Bélusca-Maïto         //
431023b7c7b8SHermès Bélusca-Maïto         //  Get out if either of the above calls failed.  Raise to trigger
431123b7c7b8SHermès Bélusca-Maïto         //  cleanup of the new Dcb.
431223b7c7b8SHermès Bélusca-Maïto         //
431323b7c7b8SHermès Bélusca-Maïto 
431423b7c7b8SHermès Bélusca-Maïto         if (Iosb.Status != STATUS_SUCCESS) {
431523b7c7b8SHermès Bélusca-Maïto 
431623b7c7b8SHermès Bélusca-Maïto             NT_ASSERT( Iosb.Status != STATUS_PENDING );
431723b7c7b8SHermès Bélusca-Maïto 
431823b7c7b8SHermès Bélusca-Maïto             FatRaiseStatus( IrpContext, Iosb.Status );
431923b7c7b8SHermès Bélusca-Maïto         }
432023b7c7b8SHermès Bélusca-Maïto #endif
432123b7c7b8SHermès Bélusca-Maïto 
432223b7c7b8SHermès Bélusca-Maïto         //
432323b7c7b8SHermès Bélusca-Maïto         //  Setup our share access
432423b7c7b8SHermès Bélusca-Maïto         //
432523b7c7b8SHermès Bélusca-Maïto 
432623b7c7b8SHermès Bélusca-Maïto         IoSetShareAccess( *DesiredAccess,
432723b7c7b8SHermès Bélusca-Maïto                           ShareAccess,
432823b7c7b8SHermès Bélusca-Maïto                           FileObject,
432923b7c7b8SHermès Bélusca-Maïto                           &(*Dcb)->ShareAccess );
433023b7c7b8SHermès Bélusca-Maïto 
433123b7c7b8SHermès Bélusca-Maïto         //
433223b7c7b8SHermès Bélusca-Maïto         //  Setup the context and section object pointers, and update
433323b7c7b8SHermès Bélusca-Maïto         //  our reference counts
433423b7c7b8SHermès Bélusca-Maïto         //
433523b7c7b8SHermès Bélusca-Maïto 
433623b7c7b8SHermès Bélusca-Maïto         FatSetFileObject( FileObject,
433723b7c7b8SHermès Bélusca-Maïto                           UserDirectoryOpen,
433823b7c7b8SHermès Bélusca-Maïto                           (*Dcb),
433923b7c7b8SHermès Bélusca-Maïto                           UnwindCcb = FatCreateCcb( IrpContext ));
434023b7c7b8SHermès Bélusca-Maïto 
434123b7c7b8SHermès Bélusca-Maïto         (*Dcb)->UncleanCount += 1;
434223b7c7b8SHermès Bélusca-Maïto         (*Dcb)->OpenCount += 1;
434323b7c7b8SHermès Bélusca-Maïto         Vcb->OpenFileCount += 1;
434423b7c7b8SHermès Bélusca-Maïto         if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount += 1; }
434523b7c7b8SHermès Bélusca-Maïto 
434623b7c7b8SHermès Bélusca-Maïto         CountsIncremented = TRUE;
434723b7c7b8SHermès Bélusca-Maïto 
434823b7c7b8SHermès Bélusca-Maïto 
434923b7c7b8SHermès Bélusca-Maïto         //
435023b7c7b8SHermès Bélusca-Maïto         //  And set our status to success
435123b7c7b8SHermès Bélusca-Maïto         //
435223b7c7b8SHermès Bélusca-Maïto 
435323b7c7b8SHermès Bélusca-Maïto         Iosb.Status = STATUS_SUCCESS;
435423b7c7b8SHermès Bélusca-Maïto         Iosb.Information = FILE_OPENED;
435523b7c7b8SHermès Bélusca-Maïto 
435623b7c7b8SHermès Bélusca-Maïto         if ( NT_SUCCESS(Iosb.Status) ) {
435723b7c7b8SHermès Bélusca-Maïto             PCCB Ccb;
435823b7c7b8SHermès Bélusca-Maïto 
435923b7c7b8SHermès Bélusca-Maïto             Ccb = (PCCB)FileObject->FsContext2;
436023b7c7b8SHermès Bélusca-Maïto 
436123b7c7b8SHermès Bélusca-Maïto             //
436223b7c7b8SHermès Bélusca-Maïto             //  Mark the OpenedByShortName bit if the operation was successful.
436323b7c7b8SHermès Bélusca-Maïto             //
436423b7c7b8SHermès Bélusca-Maïto 
436523b7c7b8SHermès Bélusca-Maïto             if ( FileNameOpenedDos ) {
436623b7c7b8SHermès Bélusca-Maïto 
436723b7c7b8SHermès Bélusca-Maïto                 SetFlag( Ccb->Flags, CCB_FLAG_OPENED_BY_SHORTNAME );
436823b7c7b8SHermès Bélusca-Maïto             }
436923b7c7b8SHermès Bélusca-Maïto         }
437023b7c7b8SHermès Bélusca-Maïto 
437123b7c7b8SHermès Bélusca-Maïto     try_exit: NOTHING;
437223b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
437323b7c7b8SHermès Bélusca-Maïto 
437423b7c7b8SHermès Bélusca-Maïto         DebugUnwind( FatOpenExistingDirectory );
437523b7c7b8SHermès Bélusca-Maïto 
437623b7c7b8SHermès Bélusca-Maïto         //
437723b7c7b8SHermès Bélusca-Maïto         //  If this is an abnormal termination then undo our work
437823b7c7b8SHermès Bélusca-Maïto         //
437923b7c7b8SHermès Bélusca-Maïto 
438023b7c7b8SHermès Bélusca-Maïto         if (_SEH2_AbnormalTermination()) {
438123b7c7b8SHermès Bélusca-Maïto 
438223b7c7b8SHermès Bélusca-Maïto             if (CountsIncremented) {
438323b7c7b8SHermès Bélusca-Maïto 
438423b7c7b8SHermès Bélusca-Maïto                 (*Dcb)->UncleanCount -= 1;
438523b7c7b8SHermès Bélusca-Maïto                 (*Dcb)->OpenCount -= 1;
438623b7c7b8SHermès Bélusca-Maïto                 Vcb->OpenFileCount -= 1;
438723b7c7b8SHermès Bélusca-Maïto                 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount -= 1; }
438823b7c7b8SHermès Bélusca-Maïto             }
438923b7c7b8SHermès Bélusca-Maïto 
439023b7c7b8SHermès Bélusca-Maïto             if (UnwindDcb != NULL) {
439123b7c7b8SHermès Bélusca-Maïto                 if (ARGUMENT_PRESENT( FileObject )) {
439223b7c7b8SHermès Bélusca-Maïto                     FileObject->SectionObjectPointer = NULL;
439323b7c7b8SHermès Bélusca-Maïto                 }
439423b7c7b8SHermès Bélusca-Maïto                 FatDeleteFcb( IrpContext, &UnwindDcb );
439523b7c7b8SHermès Bélusca-Maïto                 *Dcb = NULL;
439623b7c7b8SHermès Bélusca-Maïto             }
439723b7c7b8SHermès Bélusca-Maïto             if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
439823b7c7b8SHermès Bélusca-Maïto         }
439923b7c7b8SHermès Bélusca-Maïto 
440023b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatOpenExistingDirectory -> Iosb.Status = %08lx\n", Iosb.Status);
440123b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
440223b7c7b8SHermès Bélusca-Maïto 
440323b7c7b8SHermès Bélusca-Maïto     return Iosb;
440423b7c7b8SHermès Bélusca-Maïto }
440523b7c7b8SHermès Bélusca-Maïto 
440623b7c7b8SHermès Bélusca-Maïto 
440723b7c7b8SHermès Bélusca-Maïto //
440823b7c7b8SHermès Bélusca-Maïto //  Internal support routine
440923b7c7b8SHermès Bélusca-Maïto //
441023b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)441123b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
441223b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
441323b7c7b8SHermès Bélusca-Maïto FatOpenExistingFile (
441423b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
441523b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
441623b7c7b8SHermès Bélusca-Maïto     _Inout_ PVCB Vcb,
441723b7c7b8SHermès Bélusca-Maïto     _Outptr_result_maybenull_ PFCB *Fcb,
441823b7c7b8SHermès Bélusca-Maïto     _In_ PDCB ParentDcb,
441923b7c7b8SHermès Bélusca-Maïto     _In_ PDIRENT Dirent,
442023b7c7b8SHermès Bélusca-Maïto     _In_ ULONG LfnByteOffset,
442123b7c7b8SHermès Bélusca-Maïto     _In_ ULONG DirentByteOffset,
442223b7c7b8SHermès Bélusca-Maïto     _In_ PUNICODE_STRING Lfn,
442323b7c7b8SHermès Bélusca-Maïto     _In_ PUNICODE_STRING OrigLfn,
442423b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
442523b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
442623b7c7b8SHermès Bélusca-Maïto     _In_ ULONG AllocationSize,
442723b7c7b8SHermès Bélusca-Maïto     _In_ PFILE_FULL_EA_INFORMATION EaBuffer,
442823b7c7b8SHermès Bélusca-Maïto     _In_ ULONG EaLength,
442923b7c7b8SHermès Bélusca-Maïto     _In_ USHORT FileAttributes,
443023b7c7b8SHermès Bélusca-Maïto     _In_ ULONG CreateDisposition,
443123b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN IsPagingFile,
443223b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN NoEaKnowledge,
443323b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN DeleteOnClose,
443423b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN OpenRequiringOplock,
443523b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN FileNameOpenedDos
443623b7c7b8SHermès Bélusca-Maïto     )
443723b7c7b8SHermès Bélusca-Maïto 
443823b7c7b8SHermès Bélusca-Maïto /*++
443923b7c7b8SHermès Bélusca-Maïto 
444023b7c7b8SHermès Bélusca-Maïto Routine Description:
444123b7c7b8SHermès Bélusca-Maïto 
444223b7c7b8SHermès Bélusca-Maïto     This routine opens the specified file.  The file has not previously
444323b7c7b8SHermès Bélusca-Maïto     been opened.
444423b7c7b8SHermès Bélusca-Maïto 
444523b7c7b8SHermès Bélusca-Maïto Arguments:
444623b7c7b8SHermès Bélusca-Maïto 
444723b7c7b8SHermès Bélusca-Maïto     FileObject - Supplies the File object
444823b7c7b8SHermès Bélusca-Maïto 
444923b7c7b8SHermès Bélusca-Maïto     Vcb - Supplies the Vcb denoting the volume containing the file
445023b7c7b8SHermès Bélusca-Maïto 
445123b7c7b8SHermès Bélusca-Maïto     Fcb - Returns the newly-created FCB for the file.
445223b7c7b8SHermès Bélusca-Maïto 
445323b7c7b8SHermès Bélusca-Maïto     ParentDcb - Supplies the parent directory containing the file to be
445423b7c7b8SHermès Bélusca-Maïto         opened
445523b7c7b8SHermès Bélusca-Maïto 
445623b7c7b8SHermès Bélusca-Maïto     Dirent - Supplies the dirent for the file being opened
445723b7c7b8SHermès Bélusca-Maïto 
445823b7c7b8SHermès Bélusca-Maïto     LfnByteOffset - Tells where the Lfn begins.  If there is no Lfn
445923b7c7b8SHermès Bélusca-Maïto         this field is the same as DirentByteOffset.
446023b7c7b8SHermès Bélusca-Maïto 
446123b7c7b8SHermès Bélusca-Maïto     DirentByteOffset - Supplies the Vbo of the dirent within its parent
446223b7c7b8SHermès Bélusca-Maïto         directory
446323b7c7b8SHermès Bélusca-Maïto 
446423b7c7b8SHermès Bélusca-Maïto     Lfn - May supply a long name for the file.
446523b7c7b8SHermès Bélusca-Maïto 
446623b7c7b8SHermès Bélusca-Maïto     DesiredAccess - Supplies the desired access of the caller
446723b7c7b8SHermès Bélusca-Maïto 
446823b7c7b8SHermès Bélusca-Maïto     ShareAccess - Supplies the share access of the caller
446923b7c7b8SHermès Bélusca-Maïto 
447023b7c7b8SHermès Bélusca-Maïto     AllocationSize - Supplies the initial allocation if the file is being
447123b7c7b8SHermès Bélusca-Maïto         superseded, overwritten, or created.
447223b7c7b8SHermès Bélusca-Maïto 
447323b7c7b8SHermès Bélusca-Maïto     EaBuffer - Supplies the Ea set if the file is being superseded,
447423b7c7b8SHermès Bélusca-Maïto         overwritten, or created.
447523b7c7b8SHermès Bélusca-Maïto 
447623b7c7b8SHermès Bélusca-Maïto     EaLength - Supplies the size, in byte, of the EaBuffer
447723b7c7b8SHermès Bélusca-Maïto 
447823b7c7b8SHermès Bélusca-Maïto     FileAttributes - Supplies file attributes to use if the file is being
447923b7c7b8SHermès Bélusca-Maïto         superseded, overwritten, or created
448023b7c7b8SHermès Bélusca-Maïto 
448123b7c7b8SHermès Bélusca-Maïto     CreateDisposition - Supplies the create disposition for this operation
448223b7c7b8SHermès Bélusca-Maïto 
448323b7c7b8SHermès Bélusca-Maïto     IsPagingFile - Indicates if this is the paging file being opened.
448423b7c7b8SHermès Bélusca-Maïto 
448523b7c7b8SHermès Bélusca-Maïto     NoEaKnowledge - This opener doesn't understand Ea's and we fail this
448623b7c7b8SHermès Bélusca-Maïto         open if the file has NeedEa's.
448723b7c7b8SHermès Bélusca-Maïto 
448823b7c7b8SHermès Bélusca-Maïto     DeleteOnClose - The caller wants the file gone when the handle is closed
448923b7c7b8SHermès Bélusca-Maïto 
449023b7c7b8SHermès Bélusca-Maïto     OpenRequiringOplock - The caller provided the FILE_OPEN_REQUIRING_OPLOCK option.
449123b7c7b8SHermès Bélusca-Maïto 
449223b7c7b8SHermès Bélusca-Maïto     FileNameOpenedDos - The caller opened this file by hitting the 8.3 side
449323b7c7b8SHermès Bélusca-Maïto         of the Lfn/8.3 pair
449423b7c7b8SHermès Bélusca-Maïto 
449523b7c7b8SHermès Bélusca-Maïto Return Value:
449623b7c7b8SHermès Bélusca-Maïto 
449723b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK - Returns the completion status for the operation
449823b7c7b8SHermès Bélusca-Maïto 
449923b7c7b8SHermès Bélusca-Maïto --*/
450023b7c7b8SHermès Bélusca-Maïto 
450123b7c7b8SHermès Bélusca-Maïto {
450223b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK Iosb = {0};
450323b7c7b8SHermès Bélusca-Maïto 
450423b7c7b8SHermès Bélusca-Maïto     ACCESS_MASK AddedAccess = 0;
450523b7c7b8SHermès Bélusca-Maïto 
450623b7c7b8SHermès Bélusca-Maïto     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( IrpContext->OriginatingIrp );
450723b7c7b8SHermès Bélusca-Maïto 
450823b7c7b8SHermès Bélusca-Maïto     //
450923b7c7b8SHermès Bélusca-Maïto     //  The following variables are for abnormal termination
451023b7c7b8SHermès Bélusca-Maïto     //
451123b7c7b8SHermès Bélusca-Maïto 
451223b7c7b8SHermès Bélusca-Maïto     PFCB UnwindFcb = NULL;
451323b7c7b8SHermès Bélusca-Maïto     PCCB UnwindCcb = NULL;
451423b7c7b8SHermès Bélusca-Maïto     BOOLEAN CountsIncremented = FALSE;
451523b7c7b8SHermès Bélusca-Maïto 
451623b7c7b8SHermès Bélusca-Maïto 
451723b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION < NTDDI_WIN7)
451823b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( OpenRequiringOplock );
451923b7c7b8SHermès Bélusca-Maïto #endif
452023b7c7b8SHermès Bélusca-Maïto 
452123b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
452223b7c7b8SHermès Bélusca-Maïto 
452323b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatOpenExistingFile...\n", 0);
452423b7c7b8SHermès Bélusca-Maïto 
452523b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
452623b7c7b8SHermès Bélusca-Maïto 
452723b7c7b8SHermès Bélusca-Maïto         //
452823b7c7b8SHermès Bélusca-Maïto         //  Check if the user wanted to create the file or if access is
452923b7c7b8SHermès Bélusca-Maïto         //  denied
453023b7c7b8SHermès Bélusca-Maïto         //
453123b7c7b8SHermès Bélusca-Maïto 
453223b7c7b8SHermès Bélusca-Maïto         if (CreateDisposition == FILE_CREATE) {
453323b7c7b8SHermès Bélusca-Maïto             Iosb.Status = STATUS_OBJECT_NAME_COLLISION;
453423b7c7b8SHermès Bélusca-Maïto             try_return( Iosb );
453523b7c7b8SHermès Bélusca-Maïto 
453623b7c7b8SHermès Bélusca-Maïto         } else if ((CreateDisposition == FILE_SUPERSEDE) && !IsPagingFile) {
453723b7c7b8SHermès Bélusca-Maïto 
453823b7c7b8SHermès Bélusca-Maïto             SetFlag( AddedAccess,
453923b7c7b8SHermès Bélusca-Maïto                      DELETE & ~(*DesiredAccess) );
454023b7c7b8SHermès Bélusca-Maïto 
454123b7c7b8SHermès Bélusca-Maïto             *DesiredAccess |= DELETE;
454223b7c7b8SHermès Bélusca-Maïto 
454323b7c7b8SHermès Bélusca-Maïto         } else if (((CreateDisposition == FILE_OVERWRITE) ||
454423b7c7b8SHermès Bélusca-Maïto                     (CreateDisposition == FILE_OVERWRITE_IF)) && !IsPagingFile) {
454523b7c7b8SHermès Bélusca-Maïto 
454623b7c7b8SHermès Bélusca-Maïto             SetFlag( AddedAccess,
454723b7c7b8SHermès Bélusca-Maïto                      (FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES) & ~(*DesiredAccess) );
454823b7c7b8SHermès Bélusca-Maïto 
454923b7c7b8SHermès Bélusca-Maïto             *DesiredAccess |= FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES;
455023b7c7b8SHermès Bélusca-Maïto         }
455123b7c7b8SHermès Bélusca-Maïto 
455223b7c7b8SHermès Bélusca-Maïto         if (!FatCheckFileAccess( IrpContext,
455323b7c7b8SHermès Bélusca-Maïto                                  Dirent->Attributes,
455423b7c7b8SHermès Bélusca-Maïto                                  DesiredAccess)) {
455523b7c7b8SHermès Bélusca-Maïto 
455623b7c7b8SHermès Bélusca-Maïto             Iosb.Status = STATUS_ACCESS_DENIED;
455723b7c7b8SHermès Bélusca-Maïto             try_return( Iosb );
455823b7c7b8SHermès Bélusca-Maïto         }
455923b7c7b8SHermès Bélusca-Maïto 
456023b7c7b8SHermès Bélusca-Maïto 
456123b7c7b8SHermès Bélusca-Maïto         //
456223b7c7b8SHermès Bélusca-Maïto         //  Check for trying to delete a read only file.
456323b7c7b8SHermès Bélusca-Maïto         //
456423b7c7b8SHermès Bélusca-Maïto 
456523b7c7b8SHermès Bélusca-Maïto         if (DeleteOnClose &&
456623b7c7b8SHermès Bélusca-Maïto             FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_READ_ONLY )) {
456723b7c7b8SHermès Bélusca-Maïto 
456823b7c7b8SHermès Bélusca-Maïto             Iosb.Status = STATUS_CANNOT_DELETE;
456923b7c7b8SHermès Bélusca-Maïto             try_return( Iosb );
457023b7c7b8SHermès Bélusca-Maïto         }
457123b7c7b8SHermès Bélusca-Maïto 
457223b7c7b8SHermès Bélusca-Maïto         //
457323b7c7b8SHermès Bélusca-Maïto         //  IF we are asked to do an overwrite or supersede operation then
457423b7c7b8SHermès Bélusca-Maïto         //  deny access for files where the file attributes for system and
457523b7c7b8SHermès Bélusca-Maïto         //  hidden do not match
457623b7c7b8SHermès Bélusca-Maïto         //
457723b7c7b8SHermès Bélusca-Maïto 
457823b7c7b8SHermès Bélusca-Maïto         if ((CreateDisposition == FILE_SUPERSEDE) ||
457923b7c7b8SHermès Bélusca-Maïto             (CreateDisposition == FILE_OVERWRITE) ||
458023b7c7b8SHermès Bélusca-Maïto             (CreateDisposition == FILE_OVERWRITE_IF)) {
458123b7c7b8SHermès Bélusca-Maïto 
458223b7c7b8SHermès Bélusca-Maïto             BOOLEAN Hidden;
458323b7c7b8SHermès Bélusca-Maïto             BOOLEAN System;
458423b7c7b8SHermès Bélusca-Maïto 
458523b7c7b8SHermès Bélusca-Maïto             Hidden = BooleanFlagOn(Dirent->Attributes, FAT_DIRENT_ATTR_HIDDEN );
458623b7c7b8SHermès Bélusca-Maïto             System = BooleanFlagOn(Dirent->Attributes, FAT_DIRENT_ATTR_SYSTEM );
458723b7c7b8SHermès Bélusca-Maïto 
458823b7c7b8SHermès Bélusca-Maïto             if ((Hidden && !FlagOn(FileAttributes, FILE_ATTRIBUTE_HIDDEN)) ||
458923b7c7b8SHermès Bélusca-Maïto                 (System && !FlagOn(FileAttributes, FILE_ATTRIBUTE_SYSTEM))) {
459023b7c7b8SHermès Bélusca-Maïto 
459123b7c7b8SHermès Bélusca-Maïto                 DebugTrace(0, Dbg, "The hidden and/or system bits do not match\n", 0);
459223b7c7b8SHermès Bélusca-Maïto 
459323b7c7b8SHermès Bélusca-Maïto                 if ( !IsPagingFile ) {
459423b7c7b8SHermès Bélusca-Maïto 
459523b7c7b8SHermès Bélusca-Maïto                     Iosb.Status = STATUS_ACCESS_DENIED;
459623b7c7b8SHermès Bélusca-Maïto                     try_return( Iosb );
459723b7c7b8SHermès Bélusca-Maïto                 }
459823b7c7b8SHermès Bélusca-Maïto             }
459923b7c7b8SHermès Bélusca-Maïto 
460023b7c7b8SHermès Bélusca-Maïto             //
460123b7c7b8SHermès Bélusca-Maïto             //  If this media is write protected, don't even try the create.
460223b7c7b8SHermès Bélusca-Maïto             //
460323b7c7b8SHermès Bélusca-Maïto 
460423b7c7b8SHermès Bélusca-Maïto             if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
460523b7c7b8SHermès Bélusca-Maïto 
460623b7c7b8SHermès Bélusca-Maïto                 //
460723b7c7b8SHermès Bélusca-Maïto                 //  Set the real device for the pop-up info, and set the verify
460823b7c7b8SHermès Bélusca-Maïto                 //  bit in the device object, so that we will force a verify
460923b7c7b8SHermès Bélusca-Maïto                 //  in case the user put the correct media back in.
461023b7c7b8SHermès Bélusca-Maïto                 //
461123b7c7b8SHermès Bélusca-Maïto 
461223b7c7b8SHermès Bélusca-Maïto 
461323b7c7b8SHermès Bélusca-Maïto                 IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
461423b7c7b8SHermès Bélusca-Maïto                                               Vcb->Vpb->RealDevice );
461523b7c7b8SHermès Bélusca-Maïto 
461623b7c7b8SHermès Bélusca-Maïto                 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
461723b7c7b8SHermès Bélusca-Maïto 
461823b7c7b8SHermès Bélusca-Maïto                 FatRaiseStatus( IrpContext, STATUS_MEDIA_WRITE_PROTECTED );
461923b7c7b8SHermès Bélusca-Maïto             }
462023b7c7b8SHermès Bélusca-Maïto         }
462123b7c7b8SHermès Bélusca-Maïto 
462223b7c7b8SHermès Bélusca-Maïto         //
462323b7c7b8SHermès Bélusca-Maïto         //  Create a new Fcb for the file, and set the file size in
462423b7c7b8SHermès Bélusca-Maïto         //  the fcb.
462523b7c7b8SHermès Bélusca-Maïto         //
462623b7c7b8SHermès Bélusca-Maïto 
462723b7c7b8SHermès Bélusca-Maïto         *Fcb = UnwindFcb = FatCreateFcb( IrpContext,
462823b7c7b8SHermès Bélusca-Maïto                                          Vcb,
462923b7c7b8SHermès Bélusca-Maïto                                          ParentDcb,
463023b7c7b8SHermès Bélusca-Maïto                                          LfnByteOffset,
463123b7c7b8SHermès Bélusca-Maïto                                          DirentByteOffset,
463223b7c7b8SHermès Bélusca-Maïto                                          Dirent,
463323b7c7b8SHermès Bélusca-Maïto                                          Lfn,
463423b7c7b8SHermès Bélusca-Maïto                                          OrigLfn,
463523b7c7b8SHermès Bélusca-Maïto                                          IsPagingFile,
463623b7c7b8SHermès Bélusca-Maïto                                          FALSE );
463723b7c7b8SHermès Bélusca-Maïto 
463823b7c7b8SHermès Bélusca-Maïto 
463923b7c7b8SHermès Bélusca-Maïto         (*Fcb)->Header.ValidDataLength.LowPart = (*Fcb)->Header.FileSize.LowPart;
464023b7c7b8SHermès Bélusca-Maïto 
464123b7c7b8SHermès Bélusca-Maïto         //
464223b7c7b8SHermès Bélusca-Maïto         //  If this is a paging file, lookup the allocation size so that
464323b7c7b8SHermès Bélusca-Maïto         //  the Mcb is always valid
464423b7c7b8SHermès Bélusca-Maïto         //
464523b7c7b8SHermès Bélusca-Maïto 
464623b7c7b8SHermès Bélusca-Maïto         if (IsPagingFile) {
464723b7c7b8SHermès Bélusca-Maïto 
464823b7c7b8SHermès Bélusca-Maïto             FatLookupFileAllocationSize( IrpContext, *Fcb );
464923b7c7b8SHermès Bélusca-Maïto         }
465023b7c7b8SHermès Bélusca-Maïto 
465123b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN7)
465223b7c7b8SHermès Bélusca-Maïto 
465323b7c7b8SHermès Bélusca-Maïto         //
465423b7c7b8SHermès Bélusca-Maïto         //  Let's make sure that if the caller provided an oplock key that it
465523b7c7b8SHermès Bélusca-Maïto         //  gets stored in the file object.
465623b7c7b8SHermès Bélusca-Maïto         //
465723b7c7b8SHermès Bélusca-Maïto 
465823b7c7b8SHermès Bélusca-Maïto         Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(*Fcb),
465923b7c7b8SHermès Bélusca-Maïto                                           IrpContext->OriginatingIrp,
466023b7c7b8SHermès Bélusca-Maïto                                           OPLOCK_FLAG_OPLOCK_KEY_CHECK_ONLY,
466123b7c7b8SHermès Bélusca-Maïto                                           NULL,
466223b7c7b8SHermès Bélusca-Maïto                                           NULL,
466323b7c7b8SHermès Bélusca-Maïto                                           NULL );
466423b7c7b8SHermès Bélusca-Maïto 
466523b7c7b8SHermès Bélusca-Maïto         //
466623b7c7b8SHermès Bélusca-Maïto         //  If the caller wants atomic create-with-oplock semantics, tell
466723b7c7b8SHermès Bélusca-Maïto         //  the oplock package.  We haven't incremented the Fcb's UncleanCount
466823b7c7b8SHermès Bélusca-Maïto         //  for this create yet, so add that in on the call.
466923b7c7b8SHermès Bélusca-Maïto         //
467023b7c7b8SHermès Bélusca-Maïto 
467123b7c7b8SHermès Bélusca-Maïto         if (OpenRequiringOplock &&
467223b7c7b8SHermès Bélusca-Maïto             (Iosb.Status == STATUS_SUCCESS)) {
467323b7c7b8SHermès Bélusca-Maïto 
467423b7c7b8SHermès Bélusca-Maïto             Iosb.Status = FsRtlOplockFsctrl( FatGetFcbOplock(*Fcb),
467523b7c7b8SHermès Bélusca-Maïto                                              IrpContext->OriginatingIrp,
467623b7c7b8SHermès Bélusca-Maïto                                              ((*Fcb)->UncleanCount + 1) );
467723b7c7b8SHermès Bélusca-Maïto         }
467823b7c7b8SHermès Bélusca-Maïto 
467923b7c7b8SHermès Bélusca-Maïto         //
468023b7c7b8SHermès Bélusca-Maïto         //  Get out if either of the above calls failed.  Raise to trigger
468123b7c7b8SHermès Bélusca-Maïto         //  cleanup of the new Fcb.
468223b7c7b8SHermès Bélusca-Maïto         //
468323b7c7b8SHermès Bélusca-Maïto 
468423b7c7b8SHermès Bélusca-Maïto         if (Iosb.Status != STATUS_SUCCESS) {
468523b7c7b8SHermès Bélusca-Maïto 
468623b7c7b8SHermès Bélusca-Maïto             NT_ASSERT( Iosb.Status != STATUS_PENDING );
468723b7c7b8SHermès Bélusca-Maïto 
468823b7c7b8SHermès Bélusca-Maïto             FatRaiseStatus( IrpContext, Iosb.Status );
468923b7c7b8SHermès Bélusca-Maïto         }
469023b7c7b8SHermès Bélusca-Maïto #endif
469123b7c7b8SHermès Bélusca-Maïto 
469223b7c7b8SHermès Bélusca-Maïto         //
469323b7c7b8SHermès Bélusca-Maïto         //  Now case on whether we are to simply open, supersede, or
469423b7c7b8SHermès Bélusca-Maïto         //  overwrite the file.
469523b7c7b8SHermès Bélusca-Maïto         //
469623b7c7b8SHermès Bélusca-Maïto 
469723b7c7b8SHermès Bélusca-Maïto         switch (CreateDisposition) {
469823b7c7b8SHermès Bélusca-Maïto 
469923b7c7b8SHermès Bélusca-Maïto         case FILE_OPEN:
470023b7c7b8SHermès Bélusca-Maïto         case FILE_OPEN_IF:
470123b7c7b8SHermès Bélusca-Maïto 
470223b7c7b8SHermès Bélusca-Maïto             DebugTrace(0, Dbg, "Doing only an open operation\n", 0);
470323b7c7b8SHermès Bélusca-Maïto 
470423b7c7b8SHermès Bélusca-Maïto             //
470523b7c7b8SHermès Bélusca-Maïto             //  If the caller has no Ea knowledge, we immediately check for
470623b7c7b8SHermès Bélusca-Maïto             //  Need Ea's on the file.
470723b7c7b8SHermès Bélusca-Maïto             //
470823b7c7b8SHermès Bélusca-Maïto 
470923b7c7b8SHermès Bélusca-Maïto             if (NoEaKnowledge && !FatIsFat32(Vcb)) {
471023b7c7b8SHermès Bélusca-Maïto 
471123b7c7b8SHermès Bélusca-Maïto                 ULONG NeedEaCount;
471223b7c7b8SHermès Bélusca-Maïto 
471323b7c7b8SHermès Bélusca-Maïto                 FatGetNeedEaCount( IrpContext,
471423b7c7b8SHermès Bélusca-Maïto                                    Vcb,
471523b7c7b8SHermès Bélusca-Maïto                                    Dirent,
471623b7c7b8SHermès Bélusca-Maïto                                    &NeedEaCount );
471723b7c7b8SHermès Bélusca-Maïto 
471823b7c7b8SHermès Bélusca-Maïto                 if (NeedEaCount != 0) {
471923b7c7b8SHermès Bélusca-Maïto 
472023b7c7b8SHermès Bélusca-Maïto                     FatRaiseStatus( IrpContext, STATUS_ACCESS_DENIED );
472123b7c7b8SHermès Bélusca-Maïto                 }
472223b7c7b8SHermès Bélusca-Maïto             }
472323b7c7b8SHermès Bélusca-Maïto 
472423b7c7b8SHermès Bélusca-Maïto             //
472523b7c7b8SHermès Bélusca-Maïto             //  Setup the context and section object pointers.
472623b7c7b8SHermès Bélusca-Maïto             //
472723b7c7b8SHermès Bélusca-Maïto 
472823b7c7b8SHermès Bélusca-Maïto             FatSetFileObject( FileObject,
472923b7c7b8SHermès Bélusca-Maïto                               UserFileOpen,
473023b7c7b8SHermès Bélusca-Maïto                               *Fcb,
473123b7c7b8SHermès Bélusca-Maïto                               UnwindCcb = FatCreateCcb( IrpContext ));
473223b7c7b8SHermès Bélusca-Maïto 
473323b7c7b8SHermès Bélusca-Maïto             FileObject->SectionObjectPointer = &(*Fcb)->NonPaged->SectionObjectPointers;
473423b7c7b8SHermès Bélusca-Maïto 
473523b7c7b8SHermès Bélusca-Maïto             Iosb.Status = STATUS_SUCCESS;
473623b7c7b8SHermès Bélusca-Maïto             Iosb.Information = FILE_OPENED;
473723b7c7b8SHermès Bélusca-Maïto             break;
473823b7c7b8SHermès Bélusca-Maïto 
473923b7c7b8SHermès Bélusca-Maïto         case FILE_SUPERSEDE:
474023b7c7b8SHermès Bélusca-Maïto         case FILE_OVERWRITE:
474123b7c7b8SHermès Bélusca-Maïto         case FILE_OVERWRITE_IF:
474223b7c7b8SHermès Bélusca-Maïto 
474323b7c7b8SHermès Bélusca-Maïto             DebugTrace(0, Dbg, "Doing supersede/overwrite operation\n", 0);
474423b7c7b8SHermès Bélusca-Maïto 
474523b7c7b8SHermès Bélusca-Maïto             //
474623b7c7b8SHermès Bélusca-Maïto             //  Determine the granted access for this operation now.
474723b7c7b8SHermès Bélusca-Maïto             //
474823b7c7b8SHermès Bélusca-Maïto 
474923b7c7b8SHermès Bélusca-Maïto             if (!NT_SUCCESS( Iosb.Status = FatCheckSystemSecurityAccess( IrpContext ))) {
475023b7c7b8SHermès Bélusca-Maïto 
475123b7c7b8SHermès Bélusca-Maïto                 try_return( Iosb );
475223b7c7b8SHermès Bélusca-Maïto             }
475323b7c7b8SHermès Bélusca-Maïto 
475423b7c7b8SHermès Bélusca-Maïto             Iosb = FatSupersedeOrOverwriteFile( IrpContext,
475523b7c7b8SHermès Bélusca-Maïto                                                 FileObject,
475623b7c7b8SHermès Bélusca-Maïto                                                 *Fcb,
475723b7c7b8SHermès Bélusca-Maïto                                                 AllocationSize,
475823b7c7b8SHermès Bélusca-Maïto                                                 EaBuffer,
475923b7c7b8SHermès Bélusca-Maïto                                                 EaLength,
476023b7c7b8SHermès Bélusca-Maïto                                                 FileAttributes,
476123b7c7b8SHermès Bélusca-Maïto                                                 CreateDisposition,
476223b7c7b8SHermès Bélusca-Maïto                                                 NoEaKnowledge );
476323b7c7b8SHermès Bélusca-Maïto             break;
476423b7c7b8SHermès Bélusca-Maïto 
476523b7c7b8SHermès Bélusca-Maïto         default:
476623b7c7b8SHermès Bélusca-Maïto 
476723b7c7b8SHermès Bélusca-Maïto             DebugTrace(0, Dbg, "Illegal Create Disposition\n", 0);
476823b7c7b8SHermès Bélusca-Maïto 
476923b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
477023b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
477123b7c7b8SHermès Bélusca-Maïto #endif
477223b7c7b8SHermès Bélusca-Maïto             FatBugCheck( CreateDisposition, 0, 0 );
477323b7c7b8SHermès Bélusca-Maïto             break;
477423b7c7b8SHermès Bélusca-Maïto         }
477523b7c7b8SHermès Bélusca-Maïto 
477623b7c7b8SHermès Bélusca-Maïto     try_exit: NOTHING;
477723b7c7b8SHermès Bélusca-Maïto 
477823b7c7b8SHermès Bélusca-Maïto         //
477923b7c7b8SHermès Bélusca-Maïto         //  Setup our share access and counts if things were successful.
478023b7c7b8SHermès Bélusca-Maïto         //
478123b7c7b8SHermès Bélusca-Maïto 
478223b7c7b8SHermès Bélusca-Maïto         if ((Iosb.Status != STATUS_PENDING) && NT_SUCCESS( Iosb.Status )) {
478323b7c7b8SHermès Bélusca-Maïto 
478423b7c7b8SHermès Bélusca-Maïto             //
478523b7c7b8SHermès Bélusca-Maïto             //  Remove any virtual access the caller needed to check against, but will
478623b7c7b8SHermès Bélusca-Maïto             //  not really receive.  Overwrite/supersede is a bit of a special case.
478723b7c7b8SHermès Bélusca-Maïto             //
478823b7c7b8SHermès Bélusca-Maïto 
478923b7c7b8SHermès Bélusca-Maïto             ClearFlag( *DesiredAccess, AddedAccess );
479023b7c7b8SHermès Bélusca-Maïto 
479123b7c7b8SHermès Bélusca-Maïto             IoSetShareAccess( *DesiredAccess,
479223b7c7b8SHermès Bélusca-Maïto                               ShareAccess,
479323b7c7b8SHermès Bélusca-Maïto                               FileObject,
479423b7c7b8SHermès Bélusca-Maïto                               &(*Fcb)->ShareAccess );
479523b7c7b8SHermès Bélusca-Maïto 
479623b7c7b8SHermès Bélusca-Maïto             (*Fcb)->UncleanCount += 1;
479723b7c7b8SHermès Bélusca-Maïto             (*Fcb)->OpenCount += 1;
479823b7c7b8SHermès Bélusca-Maïto             if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) {
479923b7c7b8SHermès Bélusca-Maïto                 (*Fcb)->NonCachedUncleanCount += 1;
480023b7c7b8SHermès Bélusca-Maïto             }
480123b7c7b8SHermès Bélusca-Maïto             Vcb->OpenFileCount += 1;
480223b7c7b8SHermès Bélusca-Maïto             if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount += 1; }
480323b7c7b8SHermès Bélusca-Maïto 
480423b7c7b8SHermès Bélusca-Maïto             CountsIncremented = TRUE;
480523b7c7b8SHermès Bélusca-Maïto         }
480623b7c7b8SHermès Bélusca-Maïto 
480723b7c7b8SHermès Bélusca-Maïto         {
480823b7c7b8SHermès Bélusca-Maïto             PCCB Ccb;
480923b7c7b8SHermès Bélusca-Maïto 
481023b7c7b8SHermès Bélusca-Maïto             Ccb = (PCCB)FileObject->FsContext2;
481123b7c7b8SHermès Bélusca-Maïto 
481223b7c7b8SHermès Bélusca-Maïto             if ( NT_SUCCESS(Iosb.Status) ) {
481323b7c7b8SHermès Bélusca-Maïto 
481423b7c7b8SHermès Bélusca-Maïto                 //
481523b7c7b8SHermès Bélusca-Maïto                 //  Mark the DeleteOnClose bit if the operation was successful.
481623b7c7b8SHermès Bélusca-Maïto                 //
481723b7c7b8SHermès Bélusca-Maïto 
481823b7c7b8SHermès Bélusca-Maïto                 if ( DeleteOnClose ) {
481923b7c7b8SHermès Bélusca-Maïto 
482023b7c7b8SHermès Bélusca-Maïto                     SetFlag( Ccb->Flags, CCB_FLAG_DELETE_ON_CLOSE );
482123b7c7b8SHermès Bélusca-Maïto                 }
482223b7c7b8SHermès Bélusca-Maïto 
482323b7c7b8SHermès Bélusca-Maïto                 //
482423b7c7b8SHermès Bélusca-Maïto                 //  Mark the OpenedByShortName bit if the operation was successful.
482523b7c7b8SHermès Bélusca-Maïto                 //
482623b7c7b8SHermès Bélusca-Maïto 
482723b7c7b8SHermès Bélusca-Maïto                 if ( FileNameOpenedDos ) {
482823b7c7b8SHermès Bélusca-Maïto 
482923b7c7b8SHermès Bélusca-Maïto                     SetFlag( Ccb->Flags, CCB_FLAG_OPENED_BY_SHORTNAME );
483023b7c7b8SHermès Bélusca-Maïto                 }
483123b7c7b8SHermès Bélusca-Maïto 
483223b7c7b8SHermès Bélusca-Maïto                 //
483323b7c7b8SHermès Bélusca-Maïto                 //  Mark the ManageVolumeAccess bit if the privilege is held.
483423b7c7b8SHermès Bélusca-Maïto                 //
483523b7c7b8SHermès Bélusca-Maïto 
483623b7c7b8SHermès Bélusca-Maïto                 if (FatCheckManageVolumeAccess( IrpContext,
483723b7c7b8SHermès Bélusca-Maïto                                                 IrpSp->Parameters.Create.SecurityContext->AccessState,
483823b7c7b8SHermès Bélusca-Maïto                                                 (KPROCESSOR_MODE)( FlagOn( IrpSp->Flags, SL_FORCE_ACCESS_CHECK ) ?
483923b7c7b8SHermès Bélusca-Maïto                                                                    UserMode :
484023b7c7b8SHermès Bélusca-Maïto                                                                    IrpContext->OriginatingIrp->RequestorMode ))) {
484123b7c7b8SHermès Bélusca-Maïto 
484223b7c7b8SHermès Bélusca-Maïto                     SetFlag( Ccb->Flags, CCB_FLAG_MANAGE_VOLUME_ACCESS );
484323b7c7b8SHermès Bélusca-Maïto                 }
484423b7c7b8SHermès Bélusca-Maïto 
484523b7c7b8SHermès Bélusca-Maïto             }
484623b7c7b8SHermès Bélusca-Maïto         }
484723b7c7b8SHermès Bélusca-Maïto 
484823b7c7b8SHermès Bélusca-Maïto 
484923b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
485023b7c7b8SHermès Bélusca-Maïto 
485123b7c7b8SHermès Bélusca-Maïto         DebugUnwind( FatOpenExistingFile );
485223b7c7b8SHermès Bélusca-Maïto 
485323b7c7b8SHermès Bélusca-Maïto         //
485423b7c7b8SHermès Bélusca-Maïto         //  If this is an abnormal termination then undo our work
485523b7c7b8SHermès Bélusca-Maïto         //
485623b7c7b8SHermès Bélusca-Maïto 
485723b7c7b8SHermès Bélusca-Maïto         if (_SEH2_AbnormalTermination()) {
485823b7c7b8SHermès Bélusca-Maïto 
485923b7c7b8SHermès Bélusca-Maïto             if (CountsIncremented) {
486023b7c7b8SHermès Bélusca-Maïto                 (*Fcb)->UncleanCount -= 1;
486123b7c7b8SHermès Bélusca-Maïto                 (*Fcb)->OpenCount -= 1;
486223b7c7b8SHermès Bélusca-Maïto                 if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) {
486323b7c7b8SHermès Bélusca-Maïto                     (*Fcb)->NonCachedUncleanCount -= 1;
486423b7c7b8SHermès Bélusca-Maïto                 }
486523b7c7b8SHermès Bélusca-Maïto                 Vcb->OpenFileCount -= 1;
486623b7c7b8SHermès Bélusca-Maïto                 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount -= 1; }
486723b7c7b8SHermès Bélusca-Maïto             }
486823b7c7b8SHermès Bélusca-Maïto 
486923b7c7b8SHermès Bélusca-Maïto             if (UnwindFcb != NULL) {
487023b7c7b8SHermès Bélusca-Maïto                 if (ARGUMENT_PRESENT( FileObject )) {
487123b7c7b8SHermès Bélusca-Maïto                     FileObject->SectionObjectPointer = NULL;
487223b7c7b8SHermès Bélusca-Maïto                 }
487323b7c7b8SHermès Bélusca-Maïto                 FatDeleteFcb( IrpContext, &UnwindFcb );
487423b7c7b8SHermès Bélusca-Maïto                 *Fcb = NULL;
487523b7c7b8SHermès Bélusca-Maïto             }
487623b7c7b8SHermès Bélusca-Maïto 
487723b7c7b8SHermès Bélusca-Maïto             if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
487823b7c7b8SHermès Bélusca-Maïto         }
487923b7c7b8SHermès Bélusca-Maïto 
488023b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatOpenExistingFile -> Iosb.Status = %08lx\n", Iosb.Status);
488123b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
488223b7c7b8SHermès Bélusca-Maïto 
488323b7c7b8SHermès Bélusca-Maïto     return Iosb;
488423b7c7b8SHermès Bélusca-Maïto }
488523b7c7b8SHermès Bélusca-Maïto 
488623b7c7b8SHermès Bélusca-Maïto 
488723b7c7b8SHermès Bélusca-Maïto //
488823b7c7b8SHermès Bélusca-Maïto //  Internal support routine
488923b7c7b8SHermès Bélusca-Maïto //
489023b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)489123b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
489223b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
489323b7c7b8SHermès Bélusca-Maïto FatCreateNewDirectory (
489423b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
489523b7c7b8SHermès Bélusca-Maïto     _In_ PIO_STACK_LOCATION IrpSp,
489623b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
489723b7c7b8SHermès Bélusca-Maïto     _Inout_ PVCB Vcb,
489823b7c7b8SHermès Bélusca-Maïto     _Inout_ PDCB ParentDcb,
489923b7c7b8SHermès Bélusca-Maïto     _In_ POEM_STRING OemName,
490023b7c7b8SHermès Bélusca-Maïto     _In_ PUNICODE_STRING UnicodeName,
490123b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
490223b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
490323b7c7b8SHermès Bélusca-Maïto     _In_ PFILE_FULL_EA_INFORMATION EaBuffer,
490423b7c7b8SHermès Bélusca-Maïto     _In_ ULONG EaLength,
490523b7c7b8SHermès Bélusca-Maïto     _In_ USHORT FileAttributes,
490623b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN NoEaKnowledge,
490723b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN DeleteOnClose,
490823b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN OpenRequiringOplock
490923b7c7b8SHermès Bélusca-Maïto     )
491023b7c7b8SHermès Bélusca-Maïto 
491123b7c7b8SHermès Bélusca-Maïto /*++
491223b7c7b8SHermès Bélusca-Maïto 
491323b7c7b8SHermès Bélusca-Maïto Routine Description:
491423b7c7b8SHermès Bélusca-Maïto 
491523b7c7b8SHermès Bélusca-Maïto     This routine creates a new directory.  The directory has already been
491623b7c7b8SHermès Bélusca-Maïto     verified not to exist yet.
491723b7c7b8SHermès Bélusca-Maïto 
491823b7c7b8SHermès Bélusca-Maïto Arguments:
491923b7c7b8SHermès Bélusca-Maïto 
492023b7c7b8SHermès Bélusca-Maïto     FileObject - Supplies the file object for the newly created directory
492123b7c7b8SHermès Bélusca-Maïto 
492223b7c7b8SHermès Bélusca-Maïto     Vcb - Supplies the Vcb denote the volume to contain the new directory
492323b7c7b8SHermès Bélusca-Maïto 
492423b7c7b8SHermès Bélusca-Maïto     ParentDcb - Supplies the parent directory containg the newly created
492523b7c7b8SHermès Bélusca-Maïto         directory
492623b7c7b8SHermès Bélusca-Maïto 
492723b7c7b8SHermès Bélusca-Maïto     OemName - Supplies the Oem name for the newly created directory.  It may
492823b7c7b8SHermès Bélusca-Maïto         or maynot be 8.3 complient, but will be upcased.
492923b7c7b8SHermès Bélusca-Maïto 
493023b7c7b8SHermès Bélusca-Maïto     UnicodeName - Supplies the Unicode name for the newly created directory.
493123b7c7b8SHermès Bélusca-Maïto         It may or maynot be 8.3 complient.  This name contains the original
493223b7c7b8SHermès Bélusca-Maïto         case information.
493323b7c7b8SHermès Bélusca-Maïto 
493423b7c7b8SHermès Bélusca-Maïto     DesiredAccess - Supplies the desired access of the caller
493523b7c7b8SHermès Bélusca-Maïto 
493623b7c7b8SHermès Bélusca-Maïto     ShareAccess - Supplies the shared access of the caller
493723b7c7b8SHermès Bélusca-Maïto 
493823b7c7b8SHermès Bélusca-Maïto     EaBuffer - Supplies the Ea set for the newly created directory
493923b7c7b8SHermès Bélusca-Maïto 
494023b7c7b8SHermès Bélusca-Maïto     EaLength - Supplies the length, in bytes, of EaBuffer
494123b7c7b8SHermès Bélusca-Maïto 
494223b7c7b8SHermès Bélusca-Maïto     FileAttributes - Supplies the file attributes for the newly created
494323b7c7b8SHermès Bélusca-Maïto         directory.
494423b7c7b8SHermès Bélusca-Maïto 
494523b7c7b8SHermès Bélusca-Maïto     NoEaKnowledge - This opener doesn't understand Ea's and we fail this
494623b7c7b8SHermès Bélusca-Maïto         open if the file has NeedEa's.
494723b7c7b8SHermès Bélusca-Maïto 
494823b7c7b8SHermès Bélusca-Maïto     DeleteOnClose - The caller wants the file gone when the handle is closed
494923b7c7b8SHermès Bélusca-Maïto 
495023b7c7b8SHermès Bélusca-Maïto     OpenRequiringOplock - The caller provided the FILE_OPEN_REQUIRING_OPLOCK option.
495123b7c7b8SHermès Bélusca-Maïto 
495223b7c7b8SHermès Bélusca-Maïto Return Value:
495323b7c7b8SHermès Bélusca-Maïto 
495423b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK - Returns the completion status for the operation
495523b7c7b8SHermès Bélusca-Maïto 
495623b7c7b8SHermès Bélusca-Maïto --*/
495723b7c7b8SHermès Bélusca-Maïto 
495823b7c7b8SHermès Bélusca-Maïto {
495923b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK Iosb;
496023b7c7b8SHermès Bélusca-Maïto 
496123b7c7b8SHermès Bélusca-Maïto     PDCB Dcb = NULL;
496223b7c7b8SHermès Bélusca-Maïto     PCCB Ccb = NULL;
496323b7c7b8SHermès Bélusca-Maïto 
496423b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent = NULL;
496523b7c7b8SHermès Bélusca-Maïto     PBCB DirentBcb = NULL;
496623b7c7b8SHermès Bélusca-Maïto     ULONG DirentsNeeded;
496723b7c7b8SHermès Bélusca-Maïto     ULONG DirentByteOffset;
496823b7c7b8SHermès Bélusca-Maïto 
496923b7c7b8SHermès Bélusca-Maïto     PDIRENT ShortDirent;
497023b7c7b8SHermès Bélusca-Maïto     ULONG ShortDirentByteOffset;
497123b7c7b8SHermès Bélusca-Maïto 
497223b7c7b8SHermès Bélusca-Maïto     USHORT EaHandle;
497323b7c7b8SHermès Bélusca-Maïto 
497423b7c7b8SHermès Bélusca-Maïto     BOOLEAN AllLowerComponent;
497523b7c7b8SHermès Bélusca-Maïto     BOOLEAN AllLowerExtension;
497623b7c7b8SHermès Bélusca-Maïto     BOOLEAN CreateLfn;
497723b7c7b8SHermès Bélusca-Maïto 
497823b7c7b8SHermès Bélusca-Maïto     ULONG BytesInFirstPage = 0;
497923b7c7b8SHermès Bélusca-Maïto     ULONG DirentsInFirstPage = 0;
498023b7c7b8SHermès Bélusca-Maïto     PDIRENT FirstPageDirent = 0;
498123b7c7b8SHermès Bélusca-Maïto 
498223b7c7b8SHermès Bélusca-Maïto     PBCB SecondPageBcb = NULL;
498323b7c7b8SHermès Bélusca-Maïto     ULONG SecondPageOffset;
498423b7c7b8SHermès Bélusca-Maïto     PDIRENT SecondPageDirent = NULL;
498523b7c7b8SHermès Bélusca-Maïto 
498623b7c7b8SHermès Bélusca-Maïto     BOOLEAN DirentFromPool = FALSE;
498723b7c7b8SHermès Bélusca-Maïto 
498823b7c7b8SHermès Bélusca-Maïto 
498923b7c7b8SHermès Bélusca-Maïto     OEM_STRING ShortName;
499023b7c7b8SHermès Bélusca-Maïto     UCHAR ShortNameBuffer[12];
499123b7c7b8SHermès Bélusca-Maïto 
499223b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION <= NTDDI_WIN7)
499323b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( OpenRequiringOplock );
499423b7c7b8SHermès Bélusca-Maïto #endif
499523b7c7b8SHermès Bélusca-Maïto 
499623b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( IrpSp );
499723b7c7b8SHermès Bélusca-Maïto 
499823b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
499923b7c7b8SHermès Bélusca-Maïto 
500023b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatCreateNewDirectory...\n", 0);
500123b7c7b8SHermès Bélusca-Maïto 
500223b7c7b8SHermès Bélusca-Maïto     ShortName.Length = 0;
500323b7c7b8SHermès Bélusca-Maïto     ShortName.MaximumLength = 12;
500423b7c7b8SHermès Bélusca-Maïto     ShortName.Buffer = (PCHAR)&ShortNameBuffer[0];
500523b7c7b8SHermès Bélusca-Maïto 
500623b7c7b8SHermès Bélusca-Maïto     EaHandle = 0;
500723b7c7b8SHermès Bélusca-Maïto 
500823b7c7b8SHermès Bélusca-Maïto     //
500923b7c7b8SHermès Bélusca-Maïto     //  We fail this operation if the caller doesn't understand Ea's.
501023b7c7b8SHermès Bélusca-Maïto     //
501123b7c7b8SHermès Bélusca-Maïto 
501223b7c7b8SHermès Bélusca-Maïto     if (NoEaKnowledge
501323b7c7b8SHermès Bélusca-Maïto         && EaLength > 0) {
501423b7c7b8SHermès Bélusca-Maïto 
501523b7c7b8SHermès Bélusca-Maïto         Iosb.Status = STATUS_ACCESS_DENIED;
501623b7c7b8SHermès Bélusca-Maïto 
501723b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatCreateNewDirectory -> Iosb.Status = %08lx\n", Iosb.Status);
501823b7c7b8SHermès Bélusca-Maïto         return Iosb;
501923b7c7b8SHermès Bélusca-Maïto     }
502023b7c7b8SHermès Bélusca-Maïto 
502123b7c7b8SHermès Bélusca-Maïto     //
502223b7c7b8SHermès Bélusca-Maïto     //  DeleteOnClose and ReadOnly are not compatible.
502323b7c7b8SHermès Bélusca-Maïto     //
502423b7c7b8SHermès Bélusca-Maïto 
502523b7c7b8SHermès Bélusca-Maïto     if (DeleteOnClose && FlagOn(FileAttributes, FAT_DIRENT_ATTR_READ_ONLY)) {
502623b7c7b8SHermès Bélusca-Maïto 
502723b7c7b8SHermès Bélusca-Maïto         Iosb.Status = STATUS_CANNOT_DELETE;
502823b7c7b8SHermès Bélusca-Maïto         return Iosb;
502923b7c7b8SHermès Bélusca-Maïto     }
503023b7c7b8SHermès Bélusca-Maïto 
503123b7c7b8SHermès Bélusca-Maïto     //  Now get the names that we will be using.
503223b7c7b8SHermès Bélusca-Maïto     //
503323b7c7b8SHermès Bélusca-Maïto 
503423b7c7b8SHermès Bélusca-Maïto     FatSelectNames( IrpContext,
503523b7c7b8SHermès Bélusca-Maïto                     ParentDcb,
503623b7c7b8SHermès Bélusca-Maïto                     OemName,
503723b7c7b8SHermès Bélusca-Maïto                     UnicodeName,
503823b7c7b8SHermès Bélusca-Maïto                     &ShortName,
503923b7c7b8SHermès Bélusca-Maïto                     NULL,
504023b7c7b8SHermès Bélusca-Maïto                     &AllLowerComponent,
504123b7c7b8SHermès Bélusca-Maïto                     &AllLowerExtension,
504223b7c7b8SHermès Bélusca-Maïto                     &CreateLfn );
504323b7c7b8SHermès Bélusca-Maïto 
504423b7c7b8SHermès Bélusca-Maïto     //
504523b7c7b8SHermès Bélusca-Maïto     //  If we are not in Chicago mode, ignore the magic bits.
504623b7c7b8SHermès Bélusca-Maïto     //
504723b7c7b8SHermès Bélusca-Maïto 
504823b7c7b8SHermès Bélusca-Maïto     if (!FatData.ChicagoMode) {
504923b7c7b8SHermès Bélusca-Maïto 
505023b7c7b8SHermès Bélusca-Maïto         AllLowerComponent = FALSE;
505123b7c7b8SHermès Bélusca-Maïto         AllLowerExtension = FALSE;
505223b7c7b8SHermès Bélusca-Maïto         CreateLfn = FALSE;
505323b7c7b8SHermès Bélusca-Maïto     }
505423b7c7b8SHermès Bélusca-Maïto 
505523b7c7b8SHermès Bélusca-Maïto     //
505623b7c7b8SHermès Bélusca-Maïto     //  Create/allocate a new dirent
505723b7c7b8SHermès Bélusca-Maïto     //
505823b7c7b8SHermès Bélusca-Maïto 
505923b7c7b8SHermès Bélusca-Maïto     DirentsNeeded = CreateLfn ? FAT_LFN_DIRENTS_NEEDED(UnicodeName) + 1 : 1;
506023b7c7b8SHermès Bélusca-Maïto 
506123b7c7b8SHermès Bélusca-Maïto     DirentByteOffset = FatCreateNewDirent( IrpContext,
506223b7c7b8SHermès Bélusca-Maïto                                            ParentDcb,
506323b7c7b8SHermès Bélusca-Maïto                                            DirentsNeeded,
506423b7c7b8SHermès Bélusca-Maïto                                            FALSE );
506523b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
506623b7c7b8SHermès Bélusca-Maïto 
506723b7c7b8SHermès Bélusca-Maïto         FatPrepareWriteDirectoryFile( IrpContext,
506823b7c7b8SHermès Bélusca-Maïto                                       ParentDcb,
506923b7c7b8SHermès Bélusca-Maïto                                       DirentByteOffset,
507023b7c7b8SHermès Bélusca-Maïto                                       sizeof(DIRENT),
507123b7c7b8SHermès Bélusca-Maïto                                       &DirentBcb,
507223b7c7b8SHermès Bélusca-Maïto #ifndef __REACTOS__
507323b7c7b8SHermès Bélusca-Maïto                                       &Dirent,
507423b7c7b8SHermès Bélusca-Maïto #else
507523b7c7b8SHermès Bélusca-Maïto                                       (PVOID *)&Dirent,
507623b7c7b8SHermès Bélusca-Maïto #endif
507723b7c7b8SHermès Bélusca-Maïto                                       FALSE,
507823b7c7b8SHermès Bélusca-Maïto                                       TRUE,
507923b7c7b8SHermès Bélusca-Maïto                                       &Iosb.Status );
508023b7c7b8SHermès Bélusca-Maïto 
508123b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( NT_SUCCESS( Iosb.Status ) && DirentBcb && Dirent );
508223b7c7b8SHermès Bélusca-Maïto 
508323b7c7b8SHermès Bélusca-Maïto         //
508423b7c7b8SHermès Bélusca-Maïto         //  Deal with the special case of an LFN + Dirent structure crossing
508523b7c7b8SHermès Bélusca-Maïto         //  a page boundry.
508623b7c7b8SHermès Bélusca-Maïto         //
508723b7c7b8SHermès Bélusca-Maïto 
508823b7c7b8SHermès Bélusca-Maïto         if ((DirentByteOffset / PAGE_SIZE) !=
508923b7c7b8SHermès Bélusca-Maïto             ((DirentByteOffset + (DirentsNeeded - 1) * sizeof(DIRENT)) / PAGE_SIZE)) {
509023b7c7b8SHermès Bélusca-Maïto 
509123b7c7b8SHermès Bélusca-Maïto             SecondPageBcb;
509223b7c7b8SHermès Bélusca-Maïto             SecondPageOffset;
509323b7c7b8SHermès Bélusca-Maïto             SecondPageDirent;
509423b7c7b8SHermès Bélusca-Maïto 
509523b7c7b8SHermès Bélusca-Maïto             SecondPageOffset = (DirentByteOffset & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
509623b7c7b8SHermès Bélusca-Maïto 
509723b7c7b8SHermès Bélusca-Maïto             BytesInFirstPage = SecondPageOffset - DirentByteOffset;
509823b7c7b8SHermès Bélusca-Maïto 
509923b7c7b8SHermès Bélusca-Maïto             DirentsInFirstPage = BytesInFirstPage / sizeof(DIRENT);
510023b7c7b8SHermès Bélusca-Maïto 
510123b7c7b8SHermès Bélusca-Maïto             FatPrepareWriteDirectoryFile( IrpContext,
510223b7c7b8SHermès Bélusca-Maïto                                           ParentDcb,
510323b7c7b8SHermès Bélusca-Maïto                                           SecondPageOffset,
510423b7c7b8SHermès Bélusca-Maïto                                           sizeof(DIRENT),
510523b7c7b8SHermès Bélusca-Maïto                                           &SecondPageBcb,
510623b7c7b8SHermès Bélusca-Maïto #ifndef __REACTOS__
510723b7c7b8SHermès Bélusca-Maïto                                           &SecondPageDirent,
510823b7c7b8SHermès Bélusca-Maïto #else
510923b7c7b8SHermès Bélusca-Maïto                                           (PVOID *)&SecondPageDirent,
511023b7c7b8SHermès Bélusca-Maïto #endif
511123b7c7b8SHermès Bélusca-Maïto                                           FALSE,
511223b7c7b8SHermès Bélusca-Maïto                                           TRUE,
511323b7c7b8SHermès Bélusca-Maïto                                           &Iosb.Status );
511423b7c7b8SHermès Bélusca-Maïto 
511523b7c7b8SHermès Bélusca-Maïto             NT_ASSERT( NT_SUCCESS( Iosb.Status ) && SecondPageBcb && SecondPageDirent );
511623b7c7b8SHermès Bélusca-Maïto 
511723b7c7b8SHermès Bélusca-Maïto             FirstPageDirent = Dirent;
511823b7c7b8SHermès Bélusca-Maïto 
511923b7c7b8SHermès Bélusca-Maïto             Dirent = FsRtlAllocatePoolWithTag( PagedPool,
512023b7c7b8SHermès Bélusca-Maïto                                                DirentsNeeded * sizeof(DIRENT),
512123b7c7b8SHermès Bélusca-Maïto                                                TAG_DIRENT );
512223b7c7b8SHermès Bélusca-Maïto 
512323b7c7b8SHermès Bélusca-Maïto             DirentFromPool = TRUE;
512423b7c7b8SHermès Bélusca-Maïto         }
512523b7c7b8SHermès Bélusca-Maïto 
512623b7c7b8SHermès Bélusca-Maïto         //
512723b7c7b8SHermès Bélusca-Maïto         //  Bump up Dirent and DirentByteOffset
512823b7c7b8SHermès Bélusca-Maïto         //
512923b7c7b8SHermès Bélusca-Maïto 
513023b7c7b8SHermès Bélusca-Maïto         ShortDirent = Dirent + DirentsNeeded - 1;
513123b7c7b8SHermès Bélusca-Maïto         ShortDirentByteOffset = DirentByteOffset +
513223b7c7b8SHermès Bélusca-Maïto                                 (DirentsNeeded - 1) * sizeof(DIRENT);
513323b7c7b8SHermès Bélusca-Maïto 
513423b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( NT_SUCCESS( Iosb.Status ));
513523b7c7b8SHermès Bélusca-Maïto 
513623b7c7b8SHermès Bélusca-Maïto 
513723b7c7b8SHermès Bélusca-Maïto         //
513823b7c7b8SHermès Bélusca-Maïto         //  Fill in the fields of the dirent.
513923b7c7b8SHermès Bélusca-Maïto         //
514023b7c7b8SHermès Bélusca-Maïto 
514123b7c7b8SHermès Bélusca-Maïto         FatConstructDirent( IrpContext,
514223b7c7b8SHermès Bélusca-Maïto                             ShortDirent,
514323b7c7b8SHermès Bélusca-Maïto                             &ShortName,
514423b7c7b8SHermès Bélusca-Maïto                             AllLowerComponent,
514523b7c7b8SHermès Bélusca-Maïto                             AllLowerExtension,
514623b7c7b8SHermès Bélusca-Maïto                             CreateLfn ? UnicodeName : NULL,
514723b7c7b8SHermès Bélusca-Maïto                             FileAttributes | FAT_DIRENT_ATTR_DIRECTORY,
514823b7c7b8SHermès Bélusca-Maïto                             TRUE,
514923b7c7b8SHermès Bélusca-Maïto                             NULL );
515023b7c7b8SHermès Bélusca-Maïto 
515123b7c7b8SHermès Bélusca-Maïto         //
515223b7c7b8SHermès Bélusca-Maïto         //  If the dirent crossed pages, we have to do some real gross stuff.
515323b7c7b8SHermès Bélusca-Maïto         //
515423b7c7b8SHermès Bélusca-Maïto 
515523b7c7b8SHermès Bélusca-Maïto         if (DirentFromPool) {
515623b7c7b8SHermès Bélusca-Maïto 
515723b7c7b8SHermès Bélusca-Maïto             RtlCopyMemory( FirstPageDirent, Dirent, BytesInFirstPage );
515823b7c7b8SHermès Bélusca-Maïto 
515923b7c7b8SHermès Bélusca-Maïto             RtlCopyMemory( SecondPageDirent,
516023b7c7b8SHermès Bélusca-Maïto                            Dirent + DirentsInFirstPage,
516123b7c7b8SHermès Bélusca-Maïto                            DirentsNeeded*sizeof(DIRENT) - BytesInFirstPage );
516223b7c7b8SHermès Bélusca-Maïto 
516323b7c7b8SHermès Bélusca-Maïto             ShortDirent = SecondPageDirent + (DirentsNeeded - DirentsInFirstPage) - 1;
516423b7c7b8SHermès Bélusca-Maïto         }
516523b7c7b8SHermès Bélusca-Maïto 
516623b7c7b8SHermès Bélusca-Maïto         //
516723b7c7b8SHermès Bélusca-Maïto         //  Create a new dcb for the directory.
516823b7c7b8SHermès Bélusca-Maïto         //
516923b7c7b8SHermès Bélusca-Maïto 
517023b7c7b8SHermès Bélusca-Maïto         Dcb = FatCreateDcb( IrpContext,
517123b7c7b8SHermès Bélusca-Maïto                             Vcb,
517223b7c7b8SHermès Bélusca-Maïto                             ParentDcb,
517323b7c7b8SHermès Bélusca-Maïto                             DirentByteOffset,
517423b7c7b8SHermès Bélusca-Maïto                             ShortDirentByteOffset,
517523b7c7b8SHermès Bélusca-Maïto                             ShortDirent,
517623b7c7b8SHermès Bélusca-Maïto                             CreateLfn ? UnicodeName : NULL );
517723b7c7b8SHermès Bélusca-Maïto 
517823b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN8)
517923b7c7b8SHermès Bélusca-Maïto         //
518023b7c7b8SHermès Bélusca-Maïto         //  The next three FsRtl calls are for oplock work.  We deliberately
518123b7c7b8SHermès Bélusca-Maïto         //  do these here so that if either call fails we will be able to
518223b7c7b8SHermès Bélusca-Maïto         //  clean up without adding a bunch of code to unwind counts, fix
518323b7c7b8SHermès Bélusca-Maïto         //  the file object, etc.
518423b7c7b8SHermès Bélusca-Maïto         //
518523b7c7b8SHermès Bélusca-Maïto 
518623b7c7b8SHermès Bélusca-Maïto         //
518723b7c7b8SHermès Bélusca-Maïto         //  Let's make sure that if the caller provided an oplock key that it
518823b7c7b8SHermès Bélusca-Maïto         //  gets stored in the file object.
518923b7c7b8SHermès Bélusca-Maïto         //
519023b7c7b8SHermès Bélusca-Maïto 
519123b7c7b8SHermès Bélusca-Maïto         Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(Dcb),
519223b7c7b8SHermès Bélusca-Maïto                                           IrpContext->OriginatingIrp,
519323b7c7b8SHermès Bélusca-Maïto                                           OPLOCK_FLAG_OPLOCK_KEY_CHECK_ONLY,
519423b7c7b8SHermès Bélusca-Maïto                                           NULL,
519523b7c7b8SHermès Bélusca-Maïto                                           NULL,
519623b7c7b8SHermès Bélusca-Maïto                                           NULL );
519723b7c7b8SHermès Bélusca-Maïto 
519823b7c7b8SHermès Bélusca-Maïto         //
519923b7c7b8SHermès Bélusca-Maïto         //  If the caller wants atomic create-with-oplock semantics, tell
520023b7c7b8SHermès Bélusca-Maïto         //  the oplock package.  We haven't incremented the Dcb's UncleanCount
520123b7c7b8SHermès Bélusca-Maïto         //  for this create yet, so add that in on the call.
520223b7c7b8SHermès Bélusca-Maïto         //
520323b7c7b8SHermès Bélusca-Maïto 
520423b7c7b8SHermès Bélusca-Maïto         if (OpenRequiringOplock &&
520523b7c7b8SHermès Bélusca-Maïto             (Iosb.Status == STATUS_SUCCESS)) {
520623b7c7b8SHermès Bélusca-Maïto 
520723b7c7b8SHermès Bélusca-Maïto             Iosb.Status = FsRtlOplockFsctrl( FatGetFcbOplock(Dcb),
520823b7c7b8SHermès Bélusca-Maïto                                              IrpContext->OriginatingIrp,
520923b7c7b8SHermès Bélusca-Maïto                                              (Dcb->UncleanCount + 1) );
521023b7c7b8SHermès Bélusca-Maïto         }
521123b7c7b8SHermès Bélusca-Maïto 
521223b7c7b8SHermès Bélusca-Maïto         //
521323b7c7b8SHermès Bélusca-Maïto         //  Break parent directory oplock.  Directory oplock breaks are always
521423b7c7b8SHermès Bélusca-Maïto         //  advisory, so we will never block/get STATUS_PENDING here.  On the
521523b7c7b8SHermès Bélusca-Maïto         //  off chance this fails with INSUFFICIENT_RESOURCES we do it here
521623b7c7b8SHermès Bélusca-Maïto         //  where we can still tolerate a failure.
521723b7c7b8SHermès Bélusca-Maïto         //
521823b7c7b8SHermès Bélusca-Maïto 
521923b7c7b8SHermès Bélusca-Maïto         if (Iosb.Status == STATUS_SUCCESS) {
522023b7c7b8SHermès Bélusca-Maïto 
522123b7c7b8SHermès Bélusca-Maïto             Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(ParentDcb),
522223b7c7b8SHermès Bélusca-Maïto                                               IrpContext->OriginatingIrp,
522323b7c7b8SHermès Bélusca-Maïto                                               OPLOCK_FLAG_PARENT_OBJECT,
522423b7c7b8SHermès Bélusca-Maïto                                               NULL,
522523b7c7b8SHermès Bélusca-Maïto                                               NULL,
522623b7c7b8SHermès Bélusca-Maïto                                               NULL );
522723b7c7b8SHermès Bélusca-Maïto         }
522823b7c7b8SHermès Bélusca-Maïto 
522923b7c7b8SHermès Bélusca-Maïto         //
523023b7c7b8SHermès Bélusca-Maïto         //  Get out if any of the oplock calls failed.
523123b7c7b8SHermès Bélusca-Maïto         //
523223b7c7b8SHermès Bélusca-Maïto 
523323b7c7b8SHermès Bélusca-Maïto         if (Iosb.Status != STATUS_SUCCESS) {
523423b7c7b8SHermès Bélusca-Maïto 
523523b7c7b8SHermès Bélusca-Maïto             FatRaiseStatus( IrpContext, Iosb.Status );
523623b7c7b8SHermès Bélusca-Maïto         }
523723b7c7b8SHermès Bélusca-Maïto #endif
523823b7c7b8SHermès Bélusca-Maïto 
523923b7c7b8SHermès Bélusca-Maïto         //
524023b7c7b8SHermès Bélusca-Maïto         //  Tentatively add the new Ea's,
524123b7c7b8SHermès Bélusca-Maïto         //
524223b7c7b8SHermès Bélusca-Maïto 
524323b7c7b8SHermès Bélusca-Maïto         if (EaLength > 0) {
524423b7c7b8SHermès Bélusca-Maïto 
524523b7c7b8SHermès Bélusca-Maïto             //
524623b7c7b8SHermès Bélusca-Maïto             //  This returns false if we are trying to create a file
524723b7c7b8SHermès Bélusca-Maïto             //  with Need Ea's and don't understand EA's.
524823b7c7b8SHermès Bélusca-Maïto             //
524923b7c7b8SHermès Bélusca-Maïto 
525023b7c7b8SHermès Bélusca-Maïto             FatCreateEa( IrpContext,
525123b7c7b8SHermès Bélusca-Maïto                          Dcb->Vcb,
525223b7c7b8SHermès Bélusca-Maïto                          (PUCHAR) EaBuffer,
525323b7c7b8SHermès Bélusca-Maïto                          EaLength,
525423b7c7b8SHermès Bélusca-Maïto                          &Dcb->ShortName.Name.Oem,
525523b7c7b8SHermès Bélusca-Maïto                          &EaHandle );
525623b7c7b8SHermès Bélusca-Maïto         }
525723b7c7b8SHermès Bélusca-Maïto 
525823b7c7b8SHermès Bélusca-Maïto         if (!FatIsFat32(Dcb->Vcb)) {
525923b7c7b8SHermès Bélusca-Maïto 
526023b7c7b8SHermès Bélusca-Maïto             ShortDirent->ExtendedAttributes = EaHandle;
526123b7c7b8SHermès Bélusca-Maïto         }
526223b7c7b8SHermès Bélusca-Maïto 
526323b7c7b8SHermès Bélusca-Maïto         //
526423b7c7b8SHermès Bélusca-Maïto         //  After this point we cannot just simply mark the dirent deleted,
526523b7c7b8SHermès Bélusca-Maïto         //  we have to deal with the directory file object.
526623b7c7b8SHermès Bélusca-Maïto         //
526723b7c7b8SHermès Bélusca-Maïto 
526823b7c7b8SHermès Bélusca-Maïto         //
526923b7c7b8SHermès Bélusca-Maïto         //  Make the dirent into a directory.  Note that even if this call
527023b7c7b8SHermès Bélusca-Maïto         //  raises because of disk space, the diectory file object has been
527123b7c7b8SHermès Bélusca-Maïto         //  created.
527223b7c7b8SHermès Bélusca-Maïto         //
527323b7c7b8SHermès Bélusca-Maïto 
527423b7c7b8SHermès Bélusca-Maïto         FatInitializeDirectoryDirent( IrpContext, Dcb, ShortDirent );
527523b7c7b8SHermès Bélusca-Maïto 
527623b7c7b8SHermès Bélusca-Maïto         //
527723b7c7b8SHermès Bélusca-Maïto         //  Setup the context and section object pointers, and update
527823b7c7b8SHermès Bélusca-Maïto         //  our reference counts.  Note that this call cannot fail.
527923b7c7b8SHermès Bélusca-Maïto         //
528023b7c7b8SHermès Bélusca-Maïto 
528123b7c7b8SHermès Bélusca-Maïto         FatSetFileObject( FileObject,
528223b7c7b8SHermès Bélusca-Maïto                           UserDirectoryOpen,
528323b7c7b8SHermès Bélusca-Maïto                           Dcb,
528423b7c7b8SHermès Bélusca-Maïto                           Ccb = FatCreateCcb( IrpContext ) );
528523b7c7b8SHermès Bélusca-Maïto 
528623b7c7b8SHermès Bélusca-Maïto         //
528723b7c7b8SHermès Bélusca-Maïto         //  Initialize the LongFileName if it has not already been set, so that
528823b7c7b8SHermès Bélusca-Maïto         //  FatNotify below won't have to.  If there are filesystem filters
528923b7c7b8SHermès Bélusca-Maïto         //  attached to FAT, the LongFileName could have gotten set if the
529023b7c7b8SHermès Bélusca-Maïto         //  filter queried for name information on this file object while
529123b7c7b8SHermès Bélusca-Maïto         //  watching the IO needed in FatInitializeDirectoryDirent.
529223b7c7b8SHermès Bélusca-Maïto         //
529323b7c7b8SHermès Bélusca-Maïto 
529423b7c7b8SHermès Bélusca-Maïto         if (Dcb->FullFileName.Buffer == NULL) {
529523b7c7b8SHermès Bélusca-Maïto 
529623b7c7b8SHermès Bélusca-Maïto             FatSetFullNameInFcb( IrpContext, Dcb, UnicodeName );
529723b7c7b8SHermès Bélusca-Maïto         }
529823b7c7b8SHermès Bélusca-Maïto 
529923b7c7b8SHermès Bélusca-Maïto         //
530023b7c7b8SHermès Bélusca-Maïto         //  We call the notify package to report that the
530123b7c7b8SHermès Bélusca-Maïto         //  we added a file.
530223b7c7b8SHermès Bélusca-Maïto         //
530323b7c7b8SHermès Bélusca-Maïto 
530423b7c7b8SHermès Bélusca-Maïto         FatNotifyReportChange( IrpContext,
530523b7c7b8SHermès Bélusca-Maïto                                Vcb,
530623b7c7b8SHermès Bélusca-Maïto                                Dcb,
530723b7c7b8SHermès Bélusca-Maïto                                FILE_NOTIFY_CHANGE_DIR_NAME,
530823b7c7b8SHermès Bélusca-Maïto                                FILE_ACTION_ADDED );
530923b7c7b8SHermès Bélusca-Maïto 
531023b7c7b8SHermès Bélusca-Maïto         //
531123b7c7b8SHermès Bélusca-Maïto         //  Setup our share access
531223b7c7b8SHermès Bélusca-Maïto         //
531323b7c7b8SHermès Bélusca-Maïto 
531423b7c7b8SHermès Bélusca-Maïto         IoSetShareAccess( *DesiredAccess,
531523b7c7b8SHermès Bélusca-Maïto                           ShareAccess,
531623b7c7b8SHermès Bélusca-Maïto                           FileObject,
531723b7c7b8SHermès Bélusca-Maïto                           &Dcb->ShareAccess );
531823b7c7b8SHermès Bélusca-Maïto 
531923b7c7b8SHermès Bélusca-Maïto 
532023b7c7b8SHermès Bélusca-Maïto         //
532123b7c7b8SHermès Bélusca-Maïto         //  From this point on, nothing can raise.
532223b7c7b8SHermès Bélusca-Maïto         //
532323b7c7b8SHermès Bélusca-Maïto 
532423b7c7b8SHermès Bélusca-Maïto         Dcb->UncleanCount += 1;
532523b7c7b8SHermès Bélusca-Maïto         Dcb->OpenCount += 1;
532623b7c7b8SHermès Bélusca-Maïto         Vcb->OpenFileCount += 1;
532723b7c7b8SHermès Bélusca-Maïto         if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount += 1; }
532823b7c7b8SHermès Bélusca-Maïto 
532923b7c7b8SHermès Bélusca-Maïto         if (DeleteOnClose) {
533023b7c7b8SHermès Bélusca-Maïto 
533123b7c7b8SHermès Bélusca-Maïto             SetFlag( Ccb->Flags, CCB_FLAG_DELETE_ON_CLOSE );
533223b7c7b8SHermès Bélusca-Maïto         }
533323b7c7b8SHermès Bélusca-Maïto 
533423b7c7b8SHermès Bélusca-Maïto         //
533523b7c7b8SHermès Bélusca-Maïto         //  And set our return status
533623b7c7b8SHermès Bélusca-Maïto         //
533723b7c7b8SHermès Bélusca-Maïto 
533823b7c7b8SHermès Bélusca-Maïto         Iosb.Status = STATUS_SUCCESS;
533923b7c7b8SHermès Bélusca-Maïto         Iosb.Information = FILE_CREATED;
534023b7c7b8SHermès Bélusca-Maïto 
534123b7c7b8SHermès Bélusca-Maïto     } _SEH2_EXCEPT(FatExceptionFilter( IrpContext, _SEH2_GetExceptionInformation() )) {
534223b7c7b8SHermès Bélusca-Maïto 
534323b7c7b8SHermès Bélusca-Maïto         //
534423b7c7b8SHermès Bélusca-Maïto         //  We'll catch all exceptions and handle them below.
534523b7c7b8SHermès Bélusca-Maïto         //
534623b7c7b8SHermès Bélusca-Maïto 
534723b7c7b8SHermès Bélusca-Maïto         Iosb.Status = IrpContext->ExceptionStatus;
534823b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
534923b7c7b8SHermès Bélusca-Maïto 
535023b7c7b8SHermès Bélusca-Maïto     //
535123b7c7b8SHermès Bélusca-Maïto     //  If we failed then undo our work.
535223b7c7b8SHermès Bélusca-Maïto     //
535323b7c7b8SHermès Bélusca-Maïto 
535423b7c7b8SHermès Bélusca-Maïto     if (!NT_SUCCESS( Iosb.Status )) {
535523b7c7b8SHermès Bélusca-Maïto 
535623b7c7b8SHermès Bélusca-Maïto         //
535723b7c7b8SHermès Bélusca-Maïto         //  We always have to delete the Ccb if we created one.
535823b7c7b8SHermès Bélusca-Maïto         //
535923b7c7b8SHermès Bélusca-Maïto 
536023b7c7b8SHermès Bélusca-Maïto         if ( Ccb != NULL ) {
536123b7c7b8SHermès Bélusca-Maïto 
536223b7c7b8SHermès Bélusca-Maïto             FatDeleteCcb( IrpContext, &Ccb );
536323b7c7b8SHermès Bélusca-Maïto         }
536423b7c7b8SHermès Bélusca-Maïto 
536523b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
536623b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress: 28924, "prefast thinks this test is redundant, but DCB can be NULL depending on where we raise" )
536723b7c7b8SHermès Bélusca-Maïto #endif
536823b7c7b8SHermès Bélusca-Maïto         if ( Dcb == NULL) {
536923b7c7b8SHermès Bélusca-Maïto 
537023b7c7b8SHermès Bélusca-Maïto             NT_ASSERT( (ParentDcb->Specific.Dcb.UnusedDirentVbo == 0xffffffff) ||
537123b7c7b8SHermès Bélusca-Maïto                     RtlAreBitsSet( &ParentDcb->Specific.Dcb.FreeDirentBitmap,
537223b7c7b8SHermès Bélusca-Maïto                                    DirentByteOffset / sizeof(DIRENT),
537323b7c7b8SHermès Bélusca-Maïto                                    DirentsNeeded ) );
537423b7c7b8SHermès Bélusca-Maïto 
537523b7c7b8SHermès Bélusca-Maïto             RtlClearBits( &ParentDcb->Specific.Dcb.FreeDirentBitmap,
537623b7c7b8SHermès Bélusca-Maïto                           DirentByteOffset / sizeof(DIRENT),
537723b7c7b8SHermès Bélusca-Maïto                           DirentsNeeded );
537823b7c7b8SHermès Bélusca-Maïto 
537923b7c7b8SHermès Bélusca-Maïto             //
538023b7c7b8SHermès Bélusca-Maïto             //  Mark the dirents deleted.  The codes is complex because of
538123b7c7b8SHermès Bélusca-Maïto             //  dealing with an LFN than crosses a page boundry.
538223b7c7b8SHermès Bélusca-Maïto             //
538323b7c7b8SHermès Bélusca-Maïto 
538423b7c7b8SHermès Bélusca-Maïto             if (Dirent != NULL) {
538523b7c7b8SHermès Bélusca-Maïto 
538623b7c7b8SHermès Bélusca-Maïto                 ULONG i;
538723b7c7b8SHermès Bélusca-Maïto 
538823b7c7b8SHermès Bélusca-Maïto                 //
538923b7c7b8SHermès Bélusca-Maïto                 //  We failed before creating a directory file object.
539023b7c7b8SHermès Bélusca-Maïto                 //  We can just mark the dirent deleted and exit.
539123b7c7b8SHermès Bélusca-Maïto                 //
539223b7c7b8SHermès Bélusca-Maïto 
539323b7c7b8SHermès Bélusca-Maïto                 for (i = 0; i < DirentsNeeded; i++) {
539423b7c7b8SHermès Bélusca-Maïto 
539523b7c7b8SHermès Bélusca-Maïto                     if (DirentFromPool == FALSE) {
539623b7c7b8SHermès Bélusca-Maïto 
539723b7c7b8SHermès Bélusca-Maïto                         //
539823b7c7b8SHermès Bélusca-Maïto                         //  Simple case.
539923b7c7b8SHermès Bélusca-Maïto                         //
540023b7c7b8SHermès Bélusca-Maïto 
540123b7c7b8SHermès Bélusca-Maïto                         Dirent[i].FileName[0] = FAT_DIRENT_DELETED;
540223b7c7b8SHermès Bélusca-Maïto 
540323b7c7b8SHermès Bélusca-Maïto                     } else {
540423b7c7b8SHermès Bélusca-Maïto 
540523b7c7b8SHermès Bélusca-Maïto                         //
540623b7c7b8SHermès Bélusca-Maïto                         //  If the second CcPreparePinWrite failed, we have
540723b7c7b8SHermès Bélusca-Maïto                         //  to stop early.
540823b7c7b8SHermès Bélusca-Maïto                         //
540923b7c7b8SHermès Bélusca-Maïto 
541023b7c7b8SHermès Bélusca-Maïto                         if ((SecondPageBcb == NULL) &&
541123b7c7b8SHermès Bélusca-Maïto                             (i == DirentsInFirstPage)) {
541223b7c7b8SHermès Bélusca-Maïto 
541323b7c7b8SHermès Bélusca-Maïto                             break;
541423b7c7b8SHermès Bélusca-Maïto                         }
541523b7c7b8SHermès Bélusca-Maïto 
541623b7c7b8SHermès Bélusca-Maïto                         //
541723b7c7b8SHermès Bélusca-Maïto                         //  Now conditionally update either page.
541823b7c7b8SHermès Bélusca-Maïto                         //
541923b7c7b8SHermès Bélusca-Maïto 
542023b7c7b8SHermès Bélusca-Maïto                         if (i < DirentsInFirstPage) {
542123b7c7b8SHermès Bélusca-Maïto 
542223b7c7b8SHermès Bélusca-Maïto                             FirstPageDirent[i].FileName[0] = FAT_DIRENT_DELETED;
542323b7c7b8SHermès Bélusca-Maïto 
542423b7c7b8SHermès Bélusca-Maïto                         } else {
542523b7c7b8SHermès Bélusca-Maïto 
542623b7c7b8SHermès Bélusca-Maïto                             SecondPageDirent[i - DirentsInFirstPage].FileName[0] = FAT_DIRENT_DELETED;
542723b7c7b8SHermès Bélusca-Maïto                         }
542823b7c7b8SHermès Bélusca-Maïto                     }
542923b7c7b8SHermès Bélusca-Maïto                 }
543023b7c7b8SHermès Bélusca-Maïto             }
543123b7c7b8SHermès Bélusca-Maïto         }
543223b7c7b8SHermès Bélusca-Maïto     }
543323b7c7b8SHermès Bélusca-Maïto 
543423b7c7b8SHermès Bélusca-Maïto     //
543523b7c7b8SHermès Bélusca-Maïto     //  Just drop the Bcbs we have in the parent right now so if we
543623b7c7b8SHermès Bélusca-Maïto     //  failed to create the directory and we take the path to rip apart
543723b7c7b8SHermès Bélusca-Maïto     //  the partially created child, when we sync-uninit we won't cause
543823b7c7b8SHermès Bélusca-Maïto     //  a lazy writer processing the parent to block on us. This would
543923b7c7b8SHermès Bélusca-Maïto     //  consume one of the lazy writers, one of which must be running free
544023b7c7b8SHermès Bélusca-Maïto     //  in order for us to come back from the sync-uninit.
544123b7c7b8SHermès Bélusca-Maïto     //
544223b7c7b8SHermès Bélusca-Maïto     //  Neat, huh?
544323b7c7b8SHermès Bélusca-Maïto     //
544423b7c7b8SHermès Bélusca-Maïto     //  Granted, the delete dirent below will be marginally less efficient
544523b7c7b8SHermès Bélusca-Maïto     //  since the Bcb may be reclaimed by the time it executes. Life is
544623b7c7b8SHermès Bélusca-Maïto     //  tough.
544723b7c7b8SHermès Bélusca-Maïto     //
544823b7c7b8SHermès Bélusca-Maïto 
544923b7c7b8SHermès Bélusca-Maïto     FatUnpinBcb( IrpContext, DirentBcb );
545023b7c7b8SHermès Bélusca-Maïto     FatUnpinBcb( IrpContext, SecondPageBcb );
545123b7c7b8SHermès Bélusca-Maïto 
545223b7c7b8SHermès Bélusca-Maïto     if (DirentFromPool) {
545323b7c7b8SHermès Bélusca-Maïto 
545423b7c7b8SHermès Bélusca-Maïto         ExFreePool( Dirent );
545523b7c7b8SHermès Bélusca-Maïto     }
545623b7c7b8SHermès Bélusca-Maïto 
545723b7c7b8SHermès Bélusca-Maïto     if (!NT_SUCCESS( Iosb.Status )) {
545823b7c7b8SHermès Bélusca-Maïto 
545923b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
546023b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress: 28924, "prefast thinks this test is redundant, but DCB can be NULL depending on where we raise" )
546123b7c7b8SHermès Bélusca-Maïto #endif
546223b7c7b8SHermès Bélusca-Maïto         if (Dcb != NULL) {
546323b7c7b8SHermès Bélusca-Maïto 
546423b7c7b8SHermès Bélusca-Maïto             //
546523b7c7b8SHermès Bélusca-Maïto             //  We have created the Dcb.  If an error occurred while
546623b7c7b8SHermès Bélusca-Maïto             //  creating the Ea's, there will be no directory file
546723b7c7b8SHermès Bélusca-Maïto             //  object.
546823b7c7b8SHermès Bélusca-Maïto             //
546923b7c7b8SHermès Bélusca-Maïto 
547023b7c7b8SHermès Bélusca-Maïto             PFILE_OBJECT DirectoryFileObject;
547123b7c7b8SHermès Bélusca-Maïto 
547223b7c7b8SHermès Bélusca-Maïto             DirectoryFileObject = Dcb->Specific.Dcb.DirectoryFile;
547323b7c7b8SHermès Bélusca-Maïto 
547423b7c7b8SHermès Bélusca-Maïto             //
547523b7c7b8SHermès Bélusca-Maïto             //  Knock down all of the repinned data so we can begin to destroy
547623b7c7b8SHermès Bélusca-Maïto             //  this failed child.  We don't care about any raising here - we're
547723b7c7b8SHermès Bélusca-Maïto             //  already got a fire going.
547823b7c7b8SHermès Bélusca-Maïto             //
547923b7c7b8SHermès Bélusca-Maïto             //  Note that if we failed to do this, the repinned initial pieces
548023b7c7b8SHermès Bélusca-Maïto             //  of the child would cause the sync-uninit to block forever.
548123b7c7b8SHermès Bélusca-Maïto             //
548223b7c7b8SHermès Bélusca-Maïto             //  A previous spin on this fix had us not make the ./.. creation
548323b7c7b8SHermès Bélusca-Maïto             //  "reversible" (bad term) and thus avoid having the Bcb still
548423b7c7b8SHermès Bélusca-Maïto             //  outstanding.  This wound up causing very bad things to happen
548523b7c7b8SHermès Bélusca-Maïto             //  on DMF floppies when we tried to do a similar yank-down in the
548623b7c7b8SHermès Bélusca-Maïto             //  create path - we want the purge it does to make sure we never
548723b7c7b8SHermès Bélusca-Maïto             //  try to write the bytes out ... it is just a lot cleaner to
548823b7c7b8SHermès Bélusca-Maïto             //  unpinrepin.  I'll leave the reversible logic in place if it ever
548923b7c7b8SHermès Bélusca-Maïto             //  proves useful.
549023b7c7b8SHermès Bélusca-Maïto             //
549123b7c7b8SHermès Bélusca-Maïto 
549223b7c7b8SHermès Bélusca-Maïto             //
549323b7c7b8SHermès Bélusca-Maïto             //  There is a possibility that this may be a generally good idea
549423b7c7b8SHermès Bélusca-Maïto             //  for "live" finally clauses - set in ExceptionFilter, clear in
549523b7c7b8SHermès Bélusca-Maïto             //  ProcessException. Think about this.
549623b7c7b8SHermès Bélusca-Maïto             //
549723b7c7b8SHermès Bélusca-Maïto 
549823b7c7b8SHermès Bélusca-Maïto             SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_RAISE );
549923b7c7b8SHermès Bélusca-Maïto             FatUnpinRepinnedBcbs( IrpContext );
550023b7c7b8SHermès Bélusca-Maïto             ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_RAISE );
550123b7c7b8SHermès Bélusca-Maïto 
550223b7c7b8SHermès Bélusca-Maïto             if (Dcb->FirstClusterOfFile != 0) {
550323b7c7b8SHermès Bélusca-Maïto 
550423b7c7b8SHermès Bélusca-Maïto                 _SEH2_TRY {
550523b7c7b8SHermès Bélusca-Maïto 
550623b7c7b8SHermès Bélusca-Maïto                     Dcb->Header.FileSize.LowPart = 0;
550723b7c7b8SHermès Bélusca-Maïto 
550823b7c7b8SHermès Bélusca-Maïto                     CcSetFileSizes( Dcb->Specific.Dcb.DirectoryFile,
550923b7c7b8SHermès Bélusca-Maïto                                     (PCC_FILE_SIZES)&Dcb->Header.AllocationSize );
551023b7c7b8SHermès Bélusca-Maïto 
551123b7c7b8SHermès Bélusca-Maïto                     //
551223b7c7b8SHermès Bélusca-Maïto                     //  Now zap the allocation backing it.
551323b7c7b8SHermès Bélusca-Maïto                     //
551423b7c7b8SHermès Bélusca-Maïto 
551523b7c7b8SHermès Bélusca-Maïto                     FatTruncateFileAllocation( IrpContext, Dcb, 0 );
551623b7c7b8SHermès Bélusca-Maïto 
551723b7c7b8SHermès Bélusca-Maïto                 } _SEH2_EXCEPT(FatExceptionFilter( IrpContext, _SEH2_GetExceptionInformation() )) {
551823b7c7b8SHermès Bélusca-Maïto 
551923b7c7b8SHermès Bélusca-Maïto                     //
552023b7c7b8SHermès Bélusca-Maïto                     //  We catch all exceptions that Fat catches, but don't do
552123b7c7b8SHermès Bélusca-Maïto                     //  anything with them.
552223b7c7b8SHermès Bélusca-Maïto                     //
552323b7c7b8SHermès Bélusca-Maïto                 } _SEH2_END;
552423b7c7b8SHermès Bélusca-Maïto             }
552523b7c7b8SHermès Bélusca-Maïto 
552623b7c7b8SHermès Bélusca-Maïto             if (DirectoryFileObject != NULL) {
552723b7c7b8SHermès Bélusca-Maïto 
552823b7c7b8SHermès Bélusca-Maïto                 FatSyncUninitializeCacheMap( IrpContext,
552923b7c7b8SHermès Bélusca-Maïto                                              DirectoryFileObject );
553023b7c7b8SHermès Bélusca-Maïto             }
553123b7c7b8SHermès Bélusca-Maïto 
553223b7c7b8SHermès Bélusca-Maïto 
553323b7c7b8SHermès Bélusca-Maïto             _SEH2_TRY {
553423b7c7b8SHermès Bélusca-Maïto 
553523b7c7b8SHermès Bélusca-Maïto                 //
553623b7c7b8SHermès Bélusca-Maïto                 //  Remove the directory entry we made in the parent Dcb.
553723b7c7b8SHermès Bélusca-Maïto                 //
553823b7c7b8SHermès Bélusca-Maïto 
553923b7c7b8SHermès Bélusca-Maïto                 FatDeleteDirent( IrpContext, Dcb, NULL, TRUE );
554023b7c7b8SHermès Bélusca-Maïto 
554123b7c7b8SHermès Bélusca-Maïto                 //
554223b7c7b8SHermès Bélusca-Maïto                 //  FatDeleteDirent can pin and dirty BCBs, so lets unrepin again.
554323b7c7b8SHermès Bélusca-Maïto                 //
554423b7c7b8SHermès Bélusca-Maïto 
554523b7c7b8SHermès Bélusca-Maïto                 FatUnpinRepinnedBcbs( IrpContext );
554623b7c7b8SHermès Bélusca-Maïto 
554723b7c7b8SHermès Bélusca-Maïto             } _SEH2_EXCEPT(FatExceptionFilter( IrpContext, _SEH2_GetExceptionInformation() )) {
554823b7c7b8SHermès Bélusca-Maïto 
554923b7c7b8SHermès Bélusca-Maïto                 //
555023b7c7b8SHermès Bélusca-Maïto                 //  We catch all exceptions that Fat catches, but don't do
555123b7c7b8SHermès Bélusca-Maïto                 //  anything with them.
555223b7c7b8SHermès Bélusca-Maïto                 //
555323b7c7b8SHermès Bélusca-Maïto             } _SEH2_END;
555423b7c7b8SHermès Bélusca-Maïto 
555523b7c7b8SHermès Bélusca-Maïto             //
555623b7c7b8SHermès Bélusca-Maïto             //  Finaly, dereference the directory file object. This will
555723b7c7b8SHermès Bélusca-Maïto             //  cause a close Irp to be processed, blowing away the Fcb.
555823b7c7b8SHermès Bélusca-Maïto             //
555923b7c7b8SHermès Bélusca-Maïto 
556023b7c7b8SHermès Bélusca-Maïto             if (DirectoryFileObject != NULL) {
556123b7c7b8SHermès Bélusca-Maïto 
556223b7c7b8SHermès Bélusca-Maïto                 //
556323b7c7b8SHermès Bélusca-Maïto                 //  Dereference the file object for this DCB.  The DCB will
556423b7c7b8SHermès Bélusca-Maïto                 //  go away when this file object is closed.
556523b7c7b8SHermès Bélusca-Maïto                 //
556623b7c7b8SHermès Bélusca-Maïto 
556723b7c7b8SHermès Bélusca-Maïto                 Dcb->Specific.Dcb.DirectoryFile = NULL;
556823b7c7b8SHermès Bélusca-Maïto                 ObDereferenceObject( DirectoryFileObject );
556923b7c7b8SHermès Bélusca-Maïto 
557023b7c7b8SHermès Bélusca-Maïto             } else {
557123b7c7b8SHermès Bélusca-Maïto 
557223b7c7b8SHermès Bélusca-Maïto                 //
557323b7c7b8SHermès Bélusca-Maïto                 //  This was also a PDK fix.  If the stream file exists, this would
557423b7c7b8SHermès Bélusca-Maïto                 //  be done during the dereference file object operation.  Otherwise
557523b7c7b8SHermès Bélusca-Maïto                 //  we have to remove the Dcb and check if we should remove the parent.
557623b7c7b8SHermès Bélusca-Maïto                 //  For now we will just leave the parent lying around.
557723b7c7b8SHermès Bélusca-Maïto                 //
557823b7c7b8SHermès Bélusca-Maïto 
557923b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
558023b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress: 28924, "prefast thinks this test is redundant, but FileObject can be NULL depending on where we raise" )
558123b7c7b8SHermès Bélusca-Maïto #endif
558223b7c7b8SHermès Bélusca-Maïto                 if (ARGUMENT_PRESENT( FileObject )) {
558323b7c7b8SHermès Bélusca-Maïto                     FileObject->SectionObjectPointer = NULL;
558423b7c7b8SHermès Bélusca-Maïto                 }
558523b7c7b8SHermès Bélusca-Maïto                 FatDeleteFcb( IrpContext, &Dcb );
558623b7c7b8SHermès Bélusca-Maïto             }
558723b7c7b8SHermès Bélusca-Maïto         }
558823b7c7b8SHermès Bélusca-Maïto 
558923b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatCreateNewDirectory -> Iosb.Status = %08lx\n", Iosb.Status);
559023b7c7b8SHermès Bélusca-Maïto 
559123b7c7b8SHermès Bélusca-Maïto         FatRaiseStatus( IrpContext, Iosb.Status );
559223b7c7b8SHermès Bélusca-Maïto     }
559323b7c7b8SHermès Bélusca-Maïto 
559423b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( EaBuffer );
559523b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( EaLength );
559623b7c7b8SHermès Bélusca-Maïto 
559723b7c7b8SHermès Bélusca-Maïto     return Iosb;
559823b7c7b8SHermès Bélusca-Maïto }
559923b7c7b8SHermès Bélusca-Maïto 
560023b7c7b8SHermès Bélusca-Maïto 
560123b7c7b8SHermès Bélusca-Maïto //
560223b7c7b8SHermès Bélusca-Maïto //  Internal support routine
560323b7c7b8SHermès Bélusca-Maïto //
560423b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)560523b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
560623b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
560723b7c7b8SHermès Bélusca-Maïto FatCreateNewFile (
560823b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
560923b7c7b8SHermès Bélusca-Maïto     _In_ PIO_STACK_LOCATION IrpSp,
561023b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
561123b7c7b8SHermès Bélusca-Maïto     _Inout_ PVCB Vcb,
561223b7c7b8SHermès Bélusca-Maïto     _Inout_ PDCB ParentDcb,
561323b7c7b8SHermès Bélusca-Maïto     _In_ POEM_STRING OemName,
561423b7c7b8SHermès Bélusca-Maïto     _In_ PUNICODE_STRING UnicodeName,
561523b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
561623b7c7b8SHermès Bélusca-Maïto     _In_ USHORT ShareAccess,
561723b7c7b8SHermès Bélusca-Maïto     _In_ ULONG AllocationSize,
561823b7c7b8SHermès Bélusca-Maïto     _In_ PFILE_FULL_EA_INFORMATION EaBuffer,
561923b7c7b8SHermès Bélusca-Maïto     _In_ ULONG EaLength,
562023b7c7b8SHermès Bélusca-Maïto     _In_ USHORT FileAttributes,
562123b7c7b8SHermès Bélusca-Maïto     _In_ PUNICODE_STRING LfnBuffer,
562223b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN IsPagingFile,
562323b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN NoEaKnowledge,
562423b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN DeleteOnClose,
562523b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN OpenRequiringOplock,
562623b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN TemporaryFile
562723b7c7b8SHermès Bélusca-Maïto     )
562823b7c7b8SHermès Bélusca-Maïto 
562923b7c7b8SHermès Bélusca-Maïto /*++
563023b7c7b8SHermès Bélusca-Maïto 
563123b7c7b8SHermès Bélusca-Maïto Routine Description:
563223b7c7b8SHermès Bélusca-Maïto 
563323b7c7b8SHermès Bélusca-Maïto     This routine creates a new file.  The file has already been verified
563423b7c7b8SHermès Bélusca-Maïto     not to exist yet.
563523b7c7b8SHermès Bélusca-Maïto 
563623b7c7b8SHermès Bélusca-Maïto Arguments:
563723b7c7b8SHermès Bélusca-Maïto 
563823b7c7b8SHermès Bélusca-Maïto     FileObject - Supplies the file object for the newly created file
563923b7c7b8SHermès Bélusca-Maïto 
564023b7c7b8SHermès Bélusca-Maïto     Vcb - Supplies the Vcb denote the volume to contain the new file
564123b7c7b8SHermès Bélusca-Maïto 
564223b7c7b8SHermès Bélusca-Maïto     ParentDcb - Supplies the parent directory containg the newly created
564323b7c7b8SHermès Bélusca-Maïto         File
564423b7c7b8SHermès Bélusca-Maïto 
564523b7c7b8SHermès Bélusca-Maïto     OemName - Supplies the Oem name for the newly created file.  It may
564623b7c7b8SHermès Bélusca-Maïto         or maynot be 8.3 complient, but will be upcased.
564723b7c7b8SHermès Bélusca-Maïto 
564823b7c7b8SHermès Bélusca-Maïto     UnicodeName - Supplies the Unicode name for the newly created file.
564923b7c7b8SHermès Bélusca-Maïto         It may or maynot be 8.3 complient.  This name contains the original
565023b7c7b8SHermès Bélusca-Maïto         case information.
565123b7c7b8SHermès Bélusca-Maïto 
565223b7c7b8SHermès Bélusca-Maïto     DesiredAccess - Supplies the desired access of the caller
565323b7c7b8SHermès Bélusca-Maïto 
565423b7c7b8SHermès Bélusca-Maïto     ShareAccess - Supplies the shared access of the caller
565523b7c7b8SHermès Bélusca-Maïto 
565623b7c7b8SHermès Bélusca-Maïto     AllocationSize - Supplies the initial allocation size for the file
565723b7c7b8SHermès Bélusca-Maïto 
565823b7c7b8SHermès Bélusca-Maïto     EaBuffer - Supplies the Ea set for the newly created file
565923b7c7b8SHermès Bélusca-Maïto 
566023b7c7b8SHermès Bélusca-Maïto     EaLength - Supplies the length, in bytes, of EaBuffer
566123b7c7b8SHermès Bélusca-Maïto 
566223b7c7b8SHermès Bélusca-Maïto     FileAttributes - Supplies the file attributes for the newly created
566323b7c7b8SHermès Bélusca-Maïto         file
566423b7c7b8SHermès Bélusca-Maïto 
566523b7c7b8SHermès Bélusca-Maïto     LfnBuffer - A MAX_LFN sized buffer for directory searching
566623b7c7b8SHermès Bélusca-Maïto 
566723b7c7b8SHermès Bélusca-Maïto     IsPagingFile - Indicates if this is the paging file being created
566823b7c7b8SHermès Bélusca-Maïto 
566923b7c7b8SHermès Bélusca-Maïto     NoEaKnowledge - This opener doesn't understand Ea's and we fail this
567023b7c7b8SHermès Bélusca-Maïto         open if the file has NeedEa's.
567123b7c7b8SHermès Bélusca-Maïto 
567223b7c7b8SHermès Bélusca-Maïto     DeleteOnClose - The caller wants the file gone when the handle is closed
567323b7c7b8SHermès Bélusca-Maïto 
567423b7c7b8SHermès Bélusca-Maïto     OpenRequiringOplock - The caller provided the FILE_OPEN_REQUIRING_OPLOCK option.
567523b7c7b8SHermès Bélusca-Maïto 
567623b7c7b8SHermès Bélusca-Maïto     TemporaryFile - Signals the lazywriter to not write dirty data unless
567723b7c7b8SHermès Bélusca-Maïto         absolutely has to.
567823b7c7b8SHermès Bélusca-Maïto 
567923b7c7b8SHermès Bélusca-Maïto 
568023b7c7b8SHermès Bélusca-Maïto Return Value:
568123b7c7b8SHermès Bélusca-Maïto 
568223b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK - Returns the completion status for the operation
568323b7c7b8SHermès Bélusca-Maïto 
568423b7c7b8SHermès Bélusca-Maïto --*/
568523b7c7b8SHermès Bélusca-Maïto 
568623b7c7b8SHermès Bélusca-Maïto {
568723b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK Iosb = {0};
568823b7c7b8SHermès Bélusca-Maïto 
568923b7c7b8SHermès Bélusca-Maïto     PFCB Fcb = NULL;
569023b7c7b8SHermès Bélusca-Maïto 
569123b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent = NULL;
569223b7c7b8SHermès Bélusca-Maïto     PBCB DirentBcb = NULL;
569323b7c7b8SHermès Bélusca-Maïto     ULONG DirentsNeeded;
569423b7c7b8SHermès Bélusca-Maïto     ULONG DirentByteOffset;
569523b7c7b8SHermès Bélusca-Maïto 
569623b7c7b8SHermès Bélusca-Maïto     PDIRENT ShortDirent;
569723b7c7b8SHermès Bélusca-Maïto     ULONG ShortDirentByteOffset;
569823b7c7b8SHermès Bélusca-Maïto 
569923b7c7b8SHermès Bélusca-Maïto     USHORT EaHandle;
570023b7c7b8SHermès Bélusca-Maïto 
570123b7c7b8SHermès Bélusca-Maïto     BOOLEAN AllLowerComponent;
570223b7c7b8SHermès Bélusca-Maïto     BOOLEAN AllLowerExtension;
570323b7c7b8SHermès Bélusca-Maïto     BOOLEAN CreateLfn;
570423b7c7b8SHermès Bélusca-Maïto 
570523b7c7b8SHermès Bélusca-Maïto     ULONG BytesInFirstPage = 0;
570623b7c7b8SHermès Bélusca-Maïto     ULONG DirentsInFirstPage = 0;
570723b7c7b8SHermès Bélusca-Maïto     PDIRENT FirstPageDirent = NULL;
570823b7c7b8SHermès Bélusca-Maïto 
570923b7c7b8SHermès Bélusca-Maïto     PBCB SecondPageBcb = NULL;
571023b7c7b8SHermès Bélusca-Maïto     ULONG SecondPageOffset;
571123b7c7b8SHermès Bélusca-Maïto     PDIRENT SecondPageDirent = NULL;
571223b7c7b8SHermès Bélusca-Maïto 
571323b7c7b8SHermès Bélusca-Maïto     BOOLEAN DirentFromPool = FALSE;
571423b7c7b8SHermès Bélusca-Maïto 
571523b7c7b8SHermès Bélusca-Maïto     OEM_STRING ShortName;
571623b7c7b8SHermès Bélusca-Maïto     UCHAR ShortNameBuffer[12];
571723b7c7b8SHermès Bélusca-Maïto 
571823b7c7b8SHermès Bélusca-Maïto     UNICODE_STRING UniTunneledShortName;
571923b7c7b8SHermès Bélusca-Maïto     WCHAR UniTunneledShortNameBuffer[12];
572023b7c7b8SHermès Bélusca-Maïto     UNICODE_STRING UniTunneledLongName;
572123b7c7b8SHermès Bélusca-Maïto     WCHAR UniTunneledLongNameBuffer[26];
572223b7c7b8SHermès Bélusca-Maïto     LARGE_INTEGER TunneledCreationTime;
572323b7c7b8SHermès Bélusca-Maïto     ULONG TunneledDataSize;
572423b7c7b8SHermès Bélusca-Maïto     BOOLEAN HaveTunneledInformation;
572523b7c7b8SHermès Bélusca-Maïto     BOOLEAN UsingTunneledLfn = FALSE;
572623b7c7b8SHermès Bélusca-Maïto 
572723b7c7b8SHermès Bélusca-Maïto     PUNICODE_STRING RealUnicodeName;
572823b7c7b8SHermès Bélusca-Maïto 
572923b7c7b8SHermès Bélusca-Maïto 
573023b7c7b8SHermès Bélusca-Maïto     //
573123b7c7b8SHermès Bélusca-Maïto     //  The following variables are for abnormal termination
573223b7c7b8SHermès Bélusca-Maïto     //
573323b7c7b8SHermès Bélusca-Maïto 
573423b7c7b8SHermès Bélusca-Maïto     PDIRENT UnwindDirent = NULL;
573523b7c7b8SHermès Bélusca-Maïto     PFCB UnwindFcb = NULL;
573623b7c7b8SHermès Bélusca-Maïto     BOOLEAN UnwindAllocation = FALSE;
573723b7c7b8SHermès Bélusca-Maïto     BOOLEAN CountsIncremented = FALSE;
573823b7c7b8SHermès Bélusca-Maïto     PCCB UnwindCcb = NULL;
573923b7c7b8SHermès Bélusca-Maïto 
574023b7c7b8SHermès Bélusca-Maïto     ULONG LocalAbnormalTermination = FALSE;
574123b7c7b8SHermès Bélusca-Maïto 
574223b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION < NTDDI_WIN7)
574323b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( OpenRequiringOplock );
574423b7c7b8SHermès Bélusca-Maïto #endif
574523b7c7b8SHermès Bélusca-Maïto 
574623b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
574723b7c7b8SHermès Bélusca-Maïto 
574823b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatCreateNewFile...\n", 0);
574923b7c7b8SHermès Bélusca-Maïto 
575023b7c7b8SHermès Bélusca-Maïto     ShortName.Length = 0;
575123b7c7b8SHermès Bélusca-Maïto     ShortName.MaximumLength = sizeof(ShortNameBuffer);
575223b7c7b8SHermès Bélusca-Maïto     ShortName.Buffer = (PCHAR)&ShortNameBuffer[0];
575323b7c7b8SHermès Bélusca-Maïto 
575423b7c7b8SHermès Bélusca-Maïto     UniTunneledShortName.Length = 0;
575523b7c7b8SHermès Bélusca-Maïto     UniTunneledShortName.MaximumLength = sizeof(UniTunneledShortNameBuffer);
575623b7c7b8SHermès Bélusca-Maïto     UniTunneledShortName.Buffer = &UniTunneledShortNameBuffer[0];
575723b7c7b8SHermès Bélusca-Maïto 
575823b7c7b8SHermès Bélusca-Maïto     UniTunneledLongName.Length = 0;
575923b7c7b8SHermès Bélusca-Maïto     UniTunneledLongName.MaximumLength = sizeof(UniTunneledLongNameBuffer);
576023b7c7b8SHermès Bélusca-Maïto     UniTunneledLongName.Buffer = &UniTunneledLongNameBuffer[0];
576123b7c7b8SHermès Bélusca-Maïto 
576223b7c7b8SHermès Bélusca-Maïto     EaHandle = 0;
576323b7c7b8SHermès Bélusca-Maïto 
576423b7c7b8SHermès Bélusca-Maïto     //
576523b7c7b8SHermès Bélusca-Maïto     //  We fail this operation if the caller doesn't understand Ea's.
576623b7c7b8SHermès Bélusca-Maïto     //
576723b7c7b8SHermès Bélusca-Maïto 
576823b7c7b8SHermès Bélusca-Maïto     if (NoEaKnowledge
576923b7c7b8SHermès Bélusca-Maïto         && EaLength > 0) {
577023b7c7b8SHermès Bélusca-Maïto 
577123b7c7b8SHermès Bélusca-Maïto         Iosb.Status = STATUS_ACCESS_DENIED;
577223b7c7b8SHermès Bélusca-Maïto 
577323b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatCreateNewFile -> Iosb.Status = %08lx\n", Iosb.Status);
577423b7c7b8SHermès Bélusca-Maïto         return Iosb;
577523b7c7b8SHermès Bélusca-Maïto     }
577623b7c7b8SHermès Bélusca-Maïto 
577723b7c7b8SHermès Bélusca-Maïto     //
577823b7c7b8SHermès Bélusca-Maïto     //  DeleteOnClose and ReadOnly are not compatible.
577923b7c7b8SHermès Bélusca-Maïto     //
578023b7c7b8SHermès Bélusca-Maïto 
578123b7c7b8SHermès Bélusca-Maïto     if (DeleteOnClose && FlagOn(FileAttributes, FAT_DIRENT_ATTR_READ_ONLY)) {
578223b7c7b8SHermès Bélusca-Maïto 
578323b7c7b8SHermès Bélusca-Maïto         Iosb.Status = STATUS_CANNOT_DELETE;
578423b7c7b8SHermès Bélusca-Maïto         return Iosb;
578523b7c7b8SHermès Bélusca-Maïto     }
578623b7c7b8SHermès Bélusca-Maïto 
578723b7c7b8SHermès Bélusca-Maïto     //
578823b7c7b8SHermès Bélusca-Maïto     //  Look in the tunnel cache for names and timestamps to restore
578923b7c7b8SHermès Bélusca-Maïto     //
579023b7c7b8SHermès Bélusca-Maïto 
579123b7c7b8SHermès Bélusca-Maïto     TunneledDataSize = sizeof(LARGE_INTEGER);
579223b7c7b8SHermès Bélusca-Maïto     HaveTunneledInformation = FsRtlFindInTunnelCache( &Vcb->Tunnel,
579323b7c7b8SHermès Bélusca-Maïto                                                       FatDirectoryKey(ParentDcb),
579423b7c7b8SHermès Bélusca-Maïto                                                       UnicodeName,
579523b7c7b8SHermès Bélusca-Maïto                                                       &UniTunneledShortName,
579623b7c7b8SHermès Bélusca-Maïto                                                       &UniTunneledLongName,
579723b7c7b8SHermès Bélusca-Maïto                                                       &TunneledDataSize,
579823b7c7b8SHermès Bélusca-Maïto                                                       &TunneledCreationTime );
579923b7c7b8SHermès Bélusca-Maïto     NT_ASSERT(TunneledDataSize == sizeof(LARGE_INTEGER));
580023b7c7b8SHermès Bélusca-Maïto 
580123b7c7b8SHermès Bélusca-Maïto     //
580223b7c7b8SHermès Bélusca-Maïto     //  Now get the names that we will be using.
580323b7c7b8SHermès Bélusca-Maïto     //
580423b7c7b8SHermès Bélusca-Maïto 
580523b7c7b8SHermès Bélusca-Maïto     FatSelectNames( IrpContext,
580623b7c7b8SHermès Bélusca-Maïto                     ParentDcb,
580723b7c7b8SHermès Bélusca-Maïto                     OemName,
580823b7c7b8SHermès Bélusca-Maïto                     UnicodeName,
580923b7c7b8SHermès Bélusca-Maïto                     &ShortName,
581023b7c7b8SHermès Bélusca-Maïto                     (HaveTunneledInformation? &UniTunneledShortName : NULL),
581123b7c7b8SHermès Bélusca-Maïto                     &AllLowerComponent,
581223b7c7b8SHermès Bélusca-Maïto                     &AllLowerExtension,
581323b7c7b8SHermès Bélusca-Maïto                     &CreateLfn );
581423b7c7b8SHermès Bélusca-Maïto 
581523b7c7b8SHermès Bélusca-Maïto     //
581623b7c7b8SHermès Bélusca-Maïto     //  If we are not in Chicago mode, ignore the magic bits.
581723b7c7b8SHermès Bélusca-Maïto     //
581823b7c7b8SHermès Bélusca-Maïto 
581923b7c7b8SHermès Bélusca-Maïto     RealUnicodeName = UnicodeName;
582023b7c7b8SHermès Bélusca-Maïto 
582123b7c7b8SHermès Bélusca-Maïto     if (!FatData.ChicagoMode) {
582223b7c7b8SHermès Bélusca-Maïto 
582323b7c7b8SHermès Bélusca-Maïto         AllLowerComponent = FALSE;
582423b7c7b8SHermès Bélusca-Maïto         AllLowerExtension = FALSE;
582523b7c7b8SHermès Bélusca-Maïto         CreateLfn = FALSE;
582623b7c7b8SHermès Bélusca-Maïto 
582723b7c7b8SHermès Bélusca-Maïto     } else {
582823b7c7b8SHermès Bélusca-Maïto 
582923b7c7b8SHermès Bélusca-Maïto         //
583023b7c7b8SHermès Bélusca-Maïto         //  If the Unicode name was legal for a short name and we got
583123b7c7b8SHermès Bélusca-Maïto         //  a tunneling hit which had a long name associated which is
583223b7c7b8SHermès Bélusca-Maïto         //  avaliable for use, use it.
583323b7c7b8SHermès Bélusca-Maïto         //
583423b7c7b8SHermès Bélusca-Maïto 
583523b7c7b8SHermès Bélusca-Maïto         if (!CreateLfn &&
583623b7c7b8SHermès Bélusca-Maïto             UniTunneledLongName.Length &&
583723b7c7b8SHermès Bélusca-Maïto             !FatLfnDirentExists(IrpContext, ParentDcb, &UniTunneledLongName, LfnBuffer)) {
583823b7c7b8SHermès Bélusca-Maïto 
583923b7c7b8SHermès Bélusca-Maïto             UsingTunneledLfn = TRUE;
584023b7c7b8SHermès Bélusca-Maïto             CreateLfn = TRUE;
584123b7c7b8SHermès Bélusca-Maïto 
584223b7c7b8SHermès Bélusca-Maïto             RealUnicodeName = &UniTunneledLongName;
584323b7c7b8SHermès Bélusca-Maïto 
584423b7c7b8SHermès Bélusca-Maïto             //
584523b7c7b8SHermès Bélusca-Maïto             //  Short names are always upcase if an LFN exists
584623b7c7b8SHermès Bélusca-Maïto             //
584723b7c7b8SHermès Bélusca-Maïto 
584823b7c7b8SHermès Bélusca-Maïto             AllLowerComponent = FALSE;
584923b7c7b8SHermès Bélusca-Maïto             AllLowerExtension = FALSE;
585023b7c7b8SHermès Bélusca-Maïto         }
585123b7c7b8SHermès Bélusca-Maïto     }
585223b7c7b8SHermès Bélusca-Maïto 
585323b7c7b8SHermès Bélusca-Maïto 
585423b7c7b8SHermès Bélusca-Maïto     //
585523b7c7b8SHermès Bélusca-Maïto     //  Create/allocate a new dirent
585623b7c7b8SHermès Bélusca-Maïto     //
585723b7c7b8SHermès Bélusca-Maïto 
585823b7c7b8SHermès Bélusca-Maïto     DirentsNeeded = CreateLfn ? FAT_LFN_DIRENTS_NEEDED(RealUnicodeName) + 1 : 1;
585923b7c7b8SHermès Bélusca-Maïto 
586023b7c7b8SHermès Bélusca-Maïto     DirentByteOffset = FatCreateNewDirent( IrpContext,
586123b7c7b8SHermès Bélusca-Maïto                                            ParentDcb,
586223b7c7b8SHermès Bélusca-Maïto                                            DirentsNeeded,
586323b7c7b8SHermès Bélusca-Maïto                                            FALSE );
586423b7c7b8SHermès Bélusca-Maïto 
586523b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
586623b7c7b8SHermès Bélusca-Maïto 
586723b7c7b8SHermès Bélusca-Maïto         FatPrepareWriteDirectoryFile( IrpContext,
586823b7c7b8SHermès Bélusca-Maïto                                       ParentDcb,
586923b7c7b8SHermès Bélusca-Maïto                                       DirentByteOffset,
587023b7c7b8SHermès Bélusca-Maïto                                       sizeof(DIRENT),
587123b7c7b8SHermès Bélusca-Maïto                                       &DirentBcb,
587223b7c7b8SHermès Bélusca-Maïto #ifndef __REACTOS__
587323b7c7b8SHermès Bélusca-Maïto                                       &Dirent,
587423b7c7b8SHermès Bélusca-Maïto #else
587523b7c7b8SHermès Bélusca-Maïto                                       (PVOID *)&Dirent,
587623b7c7b8SHermès Bélusca-Maïto #endif
587723b7c7b8SHermès Bélusca-Maïto                                       FALSE,
587823b7c7b8SHermès Bélusca-Maïto                                       TRUE,
587923b7c7b8SHermès Bélusca-Maïto                                       &Iosb.Status );
588023b7c7b8SHermès Bélusca-Maïto 
588123b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( NT_SUCCESS( Iosb.Status ) );
588223b7c7b8SHermès Bélusca-Maïto 
588323b7c7b8SHermès Bélusca-Maïto         UnwindDirent = Dirent;
588423b7c7b8SHermès Bélusca-Maïto 
588523b7c7b8SHermès Bélusca-Maïto         //
588623b7c7b8SHermès Bélusca-Maïto         //  Deal with the special case of an LFN + Dirent structure crossing
588723b7c7b8SHermès Bélusca-Maïto         //  a page boundry.
588823b7c7b8SHermès Bélusca-Maïto         //
588923b7c7b8SHermès Bélusca-Maïto 
589023b7c7b8SHermès Bélusca-Maïto         if ((DirentByteOffset / PAGE_SIZE) !=
589123b7c7b8SHermès Bélusca-Maïto             ((DirentByteOffset + (DirentsNeeded - 1) * sizeof(DIRENT)) / PAGE_SIZE)) {
589223b7c7b8SHermès Bélusca-Maïto 
589323b7c7b8SHermès Bélusca-Maïto             SecondPageBcb;
589423b7c7b8SHermès Bélusca-Maïto             SecondPageOffset;
589523b7c7b8SHermès Bélusca-Maïto             SecondPageDirent;
589623b7c7b8SHermès Bélusca-Maïto 
589723b7c7b8SHermès Bélusca-Maïto             SecondPageOffset = (DirentByteOffset & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
589823b7c7b8SHermès Bélusca-Maïto 
589923b7c7b8SHermès Bélusca-Maïto             BytesInFirstPage = SecondPageOffset - DirentByteOffset;
590023b7c7b8SHermès Bélusca-Maïto 
590123b7c7b8SHermès Bélusca-Maïto             DirentsInFirstPage = BytesInFirstPage / sizeof(DIRENT);
590223b7c7b8SHermès Bélusca-Maïto 
590323b7c7b8SHermès Bélusca-Maïto             FatPrepareWriteDirectoryFile( IrpContext,
590423b7c7b8SHermès Bélusca-Maïto                                           ParentDcb,
590523b7c7b8SHermès Bélusca-Maïto                                           SecondPageOffset,
590623b7c7b8SHermès Bélusca-Maïto                                           sizeof(DIRENT),
590723b7c7b8SHermès Bélusca-Maïto                                           &SecondPageBcb,
590823b7c7b8SHermès Bélusca-Maïto #ifndef __REACTOS__
590923b7c7b8SHermès Bélusca-Maïto                                           &SecondPageDirent,
591023b7c7b8SHermès Bélusca-Maïto #else
591123b7c7b8SHermès Bélusca-Maïto                                           (PVOID *)&SecondPageDirent,
591223b7c7b8SHermès Bélusca-Maïto #endif
591323b7c7b8SHermès Bélusca-Maïto                                           FALSE,
591423b7c7b8SHermès Bélusca-Maïto                                           TRUE,
591523b7c7b8SHermès Bélusca-Maïto                                           &Iosb.Status );
591623b7c7b8SHermès Bélusca-Maïto 
591723b7c7b8SHermès Bélusca-Maïto             NT_ASSERT( NT_SUCCESS( Iosb.Status ) );
591823b7c7b8SHermès Bélusca-Maïto 
591923b7c7b8SHermès Bélusca-Maïto             FirstPageDirent = Dirent;
592023b7c7b8SHermès Bélusca-Maïto 
592123b7c7b8SHermès Bélusca-Maïto             Dirent = FsRtlAllocatePoolWithTag( PagedPool,
592223b7c7b8SHermès Bélusca-Maïto                                                DirentsNeeded * sizeof(DIRENT),
592323b7c7b8SHermès Bélusca-Maïto                                                TAG_DIRENT );
592423b7c7b8SHermès Bélusca-Maïto 
592523b7c7b8SHermès Bélusca-Maïto             DirentFromPool = TRUE;
592623b7c7b8SHermès Bélusca-Maïto         }
592723b7c7b8SHermès Bélusca-Maïto 
592823b7c7b8SHermès Bélusca-Maïto         //
592923b7c7b8SHermès Bélusca-Maïto         //  Bump up Dirent and DirentByteOffset
593023b7c7b8SHermès Bélusca-Maïto         //
593123b7c7b8SHermès Bélusca-Maïto 
593223b7c7b8SHermès Bélusca-Maïto         ShortDirent = Dirent + DirentsNeeded - 1;
593323b7c7b8SHermès Bélusca-Maïto         ShortDirentByteOffset = DirentByteOffset +
593423b7c7b8SHermès Bélusca-Maïto                                 (DirentsNeeded - 1) * sizeof(DIRENT);
593523b7c7b8SHermès Bélusca-Maïto 
593623b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( NT_SUCCESS( Iosb.Status ));
593723b7c7b8SHermès Bélusca-Maïto 
593823b7c7b8SHermès Bélusca-Maïto 
593923b7c7b8SHermès Bélusca-Maïto         //
594023b7c7b8SHermès Bélusca-Maïto         //  Fill in the fields of the dirent.
594123b7c7b8SHermès Bélusca-Maïto         //
594223b7c7b8SHermès Bélusca-Maïto 
594323b7c7b8SHermès Bélusca-Maïto         FatConstructDirent( IrpContext,
594423b7c7b8SHermès Bélusca-Maïto                             ShortDirent,
594523b7c7b8SHermès Bélusca-Maïto                             &ShortName,
594623b7c7b8SHermès Bélusca-Maïto                             AllLowerComponent,
594723b7c7b8SHermès Bélusca-Maïto                             AllLowerExtension,
594823b7c7b8SHermès Bélusca-Maïto                             CreateLfn ? RealUnicodeName : NULL,
594923b7c7b8SHermès Bélusca-Maïto                             (FileAttributes | FILE_ATTRIBUTE_ARCHIVE),
595023b7c7b8SHermès Bélusca-Maïto                             TRUE,
595123b7c7b8SHermès Bélusca-Maïto                             (HaveTunneledInformation ? &TunneledCreationTime : NULL) );
595223b7c7b8SHermès Bélusca-Maïto 
595323b7c7b8SHermès Bélusca-Maïto         //
595423b7c7b8SHermès Bélusca-Maïto         //  If the dirent crossed pages, we have to do some real gross stuff.
595523b7c7b8SHermès Bélusca-Maïto         //
595623b7c7b8SHermès Bélusca-Maïto 
595723b7c7b8SHermès Bélusca-Maïto         if (DirentFromPool) {
595823b7c7b8SHermès Bélusca-Maïto 
595923b7c7b8SHermès Bélusca-Maïto             RtlCopyMemory( FirstPageDirent, Dirent, BytesInFirstPage );
596023b7c7b8SHermès Bélusca-Maïto 
596123b7c7b8SHermès Bélusca-Maïto             RtlCopyMemory( SecondPageDirent,
596223b7c7b8SHermès Bélusca-Maïto                            Dirent + DirentsInFirstPage,
596323b7c7b8SHermès Bélusca-Maïto                            DirentsNeeded*sizeof(DIRENT) - BytesInFirstPage );
596423b7c7b8SHermès Bélusca-Maïto 
596523b7c7b8SHermès Bélusca-Maïto             ShortDirent = SecondPageDirent + (DirentsNeeded - DirentsInFirstPage) - 1;
596623b7c7b8SHermès Bélusca-Maïto         }
596723b7c7b8SHermès Bélusca-Maïto 
596823b7c7b8SHermès Bélusca-Maïto         //
596923b7c7b8SHermès Bélusca-Maïto         //  Create a new Fcb for the file.  Once the Fcb is created we
597023b7c7b8SHermès Bélusca-Maïto         //  will not need to unwind dirent because delete dirent will
597123b7c7b8SHermès Bélusca-Maïto         //  now do the work.
597223b7c7b8SHermès Bélusca-Maïto         //
597323b7c7b8SHermès Bélusca-Maïto 
597423b7c7b8SHermès Bélusca-Maïto         Fcb = UnwindFcb = FatCreateFcb( IrpContext,
597523b7c7b8SHermès Bélusca-Maïto                                         Vcb,
597623b7c7b8SHermès Bélusca-Maïto                                         ParentDcb,
597723b7c7b8SHermès Bélusca-Maïto                                         DirentByteOffset,
597823b7c7b8SHermès Bélusca-Maïto                                         ShortDirentByteOffset,
597923b7c7b8SHermès Bélusca-Maïto                                         ShortDirent,
598023b7c7b8SHermès Bélusca-Maïto                                         CreateLfn ? RealUnicodeName : NULL,
598123b7c7b8SHermès Bélusca-Maïto                                         CreateLfn ? RealUnicodeName : NULL,
598223b7c7b8SHermès Bélusca-Maïto                                         IsPagingFile,
598323b7c7b8SHermès Bélusca-Maïto                                         FALSE );
598423b7c7b8SHermès Bélusca-Maïto         UnwindDirent = NULL;
598523b7c7b8SHermès Bélusca-Maïto 
598623b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN7)
598723b7c7b8SHermès Bélusca-Maïto         //
598823b7c7b8SHermès Bélusca-Maïto         //  The next three FsRtl calls are for oplock work.  We deliberately
598923b7c7b8SHermès Bélusca-Maïto         //  do these here so that if either call fails we will be able to
599023b7c7b8SHermès Bélusca-Maïto         //  clean up without adding a bunch of code to unwind counts, fix
599123b7c7b8SHermès Bélusca-Maïto         //  the file object, etc.
599223b7c7b8SHermès Bélusca-Maïto         //
599323b7c7b8SHermès Bélusca-Maïto 
599423b7c7b8SHermès Bélusca-Maïto         //
599523b7c7b8SHermès Bélusca-Maïto         //  Let's make sure that if the caller provided an oplock key that it
599623b7c7b8SHermès Bélusca-Maïto         //  gets stored in the file object.
599723b7c7b8SHermès Bélusca-Maïto         //
599823b7c7b8SHermès Bélusca-Maïto 
599923b7c7b8SHermès Bélusca-Maïto         Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(Fcb),
600023b7c7b8SHermès Bélusca-Maïto                                           IrpContext->OriginatingIrp,
600123b7c7b8SHermès Bélusca-Maïto                                           OPLOCK_FLAG_OPLOCK_KEY_CHECK_ONLY,
600223b7c7b8SHermès Bélusca-Maïto                                           NULL,
600323b7c7b8SHermès Bélusca-Maïto                                           NULL,
600423b7c7b8SHermès Bélusca-Maïto                                           NULL );
600523b7c7b8SHermès Bélusca-Maïto 
600623b7c7b8SHermès Bélusca-Maïto         //
600723b7c7b8SHermès Bélusca-Maïto         //  If the caller wants atomic create-with-oplock semantics, tell
600823b7c7b8SHermès Bélusca-Maïto         //  the oplock package.  We haven't incremented the Fcb's UncleanCount
600923b7c7b8SHermès Bélusca-Maïto         //  for this create yet, so add that in on the call.
601023b7c7b8SHermès Bélusca-Maïto         //
601123b7c7b8SHermès Bélusca-Maïto 
601223b7c7b8SHermès Bélusca-Maïto         if (OpenRequiringOplock &&
601323b7c7b8SHermès Bélusca-Maïto             (Iosb.Status == STATUS_SUCCESS)) {
601423b7c7b8SHermès Bélusca-Maïto 
601523b7c7b8SHermès Bélusca-Maïto             Iosb.Status = FsRtlOplockFsctrl( FatGetFcbOplock(Fcb),
601623b7c7b8SHermès Bélusca-Maïto                                              IrpContext->OriginatingIrp,
601723b7c7b8SHermès Bélusca-Maïto                                              (Fcb->UncleanCount + 1) );
601823b7c7b8SHermès Bélusca-Maïto         }
601923b7c7b8SHermès Bélusca-Maïto #endif
602023b7c7b8SHermès Bélusca-Maïto 
602123b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN8)
602223b7c7b8SHermès Bélusca-Maïto         //
602323b7c7b8SHermès Bélusca-Maïto         //  Break parent directory oplock.  Directory oplock breaks are always
602423b7c7b8SHermès Bélusca-Maïto         //  advisory, so we will never block/get STATUS_PENDING here.  On the
602523b7c7b8SHermès Bélusca-Maïto         //  off chance this fails with INSUFFICIENT_RESOURCES we do it here
602623b7c7b8SHermès Bélusca-Maïto         //  where we can still tolerate a failure.
602723b7c7b8SHermès Bélusca-Maïto         //
602823b7c7b8SHermès Bélusca-Maïto 
602923b7c7b8SHermès Bélusca-Maïto         if (Iosb.Status == STATUS_SUCCESS) {
603023b7c7b8SHermès Bélusca-Maïto 
603123b7c7b8SHermès Bélusca-Maïto             Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(ParentDcb),
603223b7c7b8SHermès Bélusca-Maïto                                               IrpContext->OriginatingIrp,
603323b7c7b8SHermès Bélusca-Maïto                                               OPLOCK_FLAG_PARENT_OBJECT,
603423b7c7b8SHermès Bélusca-Maïto                                               NULL,
603523b7c7b8SHermès Bélusca-Maïto                                               NULL,
603623b7c7b8SHermès Bélusca-Maïto                                               NULL );
603723b7c7b8SHermès Bélusca-Maïto         }
603823b7c7b8SHermès Bélusca-Maïto 
603923b7c7b8SHermès Bélusca-Maïto         //
604023b7c7b8SHermès Bélusca-Maïto         //  Get out if any of the oplock calls failed.  We raise to provoke
604123b7c7b8SHermès Bélusca-Maïto         //  abnormal termination and ensure that the newly-created Fcb gets
604223b7c7b8SHermès Bélusca-Maïto         //  deleted.
604323b7c7b8SHermès Bélusca-Maïto         //
604423b7c7b8SHermès Bélusca-Maïto 
604523b7c7b8SHermès Bélusca-Maïto         if (Iosb.Status != STATUS_SUCCESS) {
604623b7c7b8SHermès Bélusca-Maïto 
604723b7c7b8SHermès Bélusca-Maïto             FatRaiseStatus( IrpContext, Iosb.Status );
604823b7c7b8SHermès Bélusca-Maïto         }
604923b7c7b8SHermès Bélusca-Maïto #endif
605023b7c7b8SHermès Bélusca-Maïto 
605123b7c7b8SHermès Bélusca-Maïto         //
605223b7c7b8SHermès Bélusca-Maïto         //  If this is a temporary file, note it in the FcbState
605323b7c7b8SHermès Bélusca-Maïto         //
605423b7c7b8SHermès Bélusca-Maïto 
605523b7c7b8SHermès Bélusca-Maïto         if (TemporaryFile) {
605623b7c7b8SHermès Bélusca-Maïto 
605723b7c7b8SHermès Bélusca-Maïto             SetFlag( Fcb->FcbState, FCB_STATE_TEMPORARY );
605823b7c7b8SHermès Bélusca-Maïto         }
605923b7c7b8SHermès Bélusca-Maïto 
606023b7c7b8SHermès Bélusca-Maïto 
606123b7c7b8SHermès Bélusca-Maïto         //
606223b7c7b8SHermès Bélusca-Maïto         //  Add some initial file allocation
606323b7c7b8SHermès Bélusca-Maïto         //
606423b7c7b8SHermès Bélusca-Maïto 
606523b7c7b8SHermès Bélusca-Maïto 
606623b7c7b8SHermès Bélusca-Maïto         FatAddFileAllocation( IrpContext, Fcb, FileObject, AllocationSize );
606723b7c7b8SHermès Bélusca-Maïto 
606823b7c7b8SHermès Bélusca-Maïto 
606923b7c7b8SHermès Bélusca-Maïto         UnwindAllocation = TRUE;
607023b7c7b8SHermès Bélusca-Maïto 
607123b7c7b8SHermès Bélusca-Maïto         Fcb->FcbState |= FCB_STATE_TRUNCATE_ON_CLOSE;
607223b7c7b8SHermès Bélusca-Maïto 
607323b7c7b8SHermès Bélusca-Maïto         //
607423b7c7b8SHermès Bélusca-Maïto         //  Tentatively add the new Ea's
607523b7c7b8SHermès Bélusca-Maïto         //
607623b7c7b8SHermès Bélusca-Maïto 
607723b7c7b8SHermès Bélusca-Maïto         if ( EaLength > 0 ) {
607823b7c7b8SHermès Bélusca-Maïto 
607923b7c7b8SHermès Bélusca-Maïto             FatCreateEa( IrpContext,
608023b7c7b8SHermès Bélusca-Maïto                          Fcb->Vcb,
608123b7c7b8SHermès Bélusca-Maïto                          (PUCHAR) EaBuffer,
608223b7c7b8SHermès Bélusca-Maïto                          EaLength,
608323b7c7b8SHermès Bélusca-Maïto                          &Fcb->ShortName.Name.Oem,
608423b7c7b8SHermès Bélusca-Maïto                          &EaHandle );
608523b7c7b8SHermès Bélusca-Maïto         }
608623b7c7b8SHermès Bélusca-Maïto 
608723b7c7b8SHermès Bélusca-Maïto         if (!FatIsFat32(Fcb->Vcb)) {
608823b7c7b8SHermès Bélusca-Maïto 
608923b7c7b8SHermès Bélusca-Maïto             ShortDirent->ExtendedAttributes = EaHandle;
609023b7c7b8SHermès Bélusca-Maïto         }
609123b7c7b8SHermès Bélusca-Maïto 
609223b7c7b8SHermès Bélusca-Maïto 
609323b7c7b8SHermès Bélusca-Maïto 
609423b7c7b8SHermès Bélusca-Maïto         //
609523b7c7b8SHermès Bélusca-Maïto         //  Initialize the LongFileName right now so that FatNotify
609623b7c7b8SHermès Bélusca-Maïto         //  below won't have to.
609723b7c7b8SHermès Bélusca-Maïto         //
609823b7c7b8SHermès Bélusca-Maïto 
609923b7c7b8SHermès Bélusca-Maïto         if (Fcb->FullFileName.Buffer == NULL) {
610023b7c7b8SHermès Bélusca-Maïto             FatSetFullNameInFcb( IrpContext, Fcb, RealUnicodeName );
610123b7c7b8SHermès Bélusca-Maïto         }
610223b7c7b8SHermès Bélusca-Maïto 
610323b7c7b8SHermès Bélusca-Maïto         //
610423b7c7b8SHermès Bélusca-Maïto         //  Setup the context and section object pointers, and update
610523b7c7b8SHermès Bélusca-Maïto         //  our reference counts
610623b7c7b8SHermès Bélusca-Maïto         //
610723b7c7b8SHermès Bélusca-Maïto 
610823b7c7b8SHermès Bélusca-Maïto         FatSetFileObject( FileObject,
610923b7c7b8SHermès Bélusca-Maïto                           UserFileOpen,
611023b7c7b8SHermès Bélusca-Maïto                           Fcb,
611123b7c7b8SHermès Bélusca-Maïto                           UnwindCcb = FatCreateCcb( IrpContext ));
611223b7c7b8SHermès Bélusca-Maïto 
611323b7c7b8SHermès Bélusca-Maïto         FileObject->SectionObjectPointer = &Fcb->NonPaged->SectionObjectPointers;
611423b7c7b8SHermès Bélusca-Maïto 
611523b7c7b8SHermès Bélusca-Maïto         //
611623b7c7b8SHermès Bélusca-Maïto         //  We call the notify package to report that the
611723b7c7b8SHermès Bélusca-Maïto         //  we added a file.
611823b7c7b8SHermès Bélusca-Maïto         //
611923b7c7b8SHermès Bélusca-Maïto 
612023b7c7b8SHermès Bélusca-Maïto         FatNotifyReportChange( IrpContext,
612123b7c7b8SHermès Bélusca-Maïto                                Vcb,
612223b7c7b8SHermès Bélusca-Maïto                                Fcb,
612323b7c7b8SHermès Bélusca-Maïto                                FILE_NOTIFY_CHANGE_FILE_NAME,
612423b7c7b8SHermès Bélusca-Maïto                                FILE_ACTION_ADDED );
612523b7c7b8SHermès Bélusca-Maïto 
612623b7c7b8SHermès Bélusca-Maïto         //
612723b7c7b8SHermès Bélusca-Maïto         //  Setup our share access
612823b7c7b8SHermès Bélusca-Maïto         //
612923b7c7b8SHermès Bélusca-Maïto 
613023b7c7b8SHermès Bélusca-Maïto         IoSetShareAccess( *DesiredAccess,
613123b7c7b8SHermès Bélusca-Maïto                           ShareAccess,
613223b7c7b8SHermès Bélusca-Maïto                           FileObject,
613323b7c7b8SHermès Bélusca-Maïto                           &Fcb->ShareAccess );
613423b7c7b8SHermès Bélusca-Maïto 
613523b7c7b8SHermès Bélusca-Maïto         Fcb->UncleanCount += 1;
613623b7c7b8SHermès Bélusca-Maïto         Fcb->OpenCount += 1;
613723b7c7b8SHermès Bélusca-Maïto         if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) {
613823b7c7b8SHermès Bélusca-Maïto             Fcb->NonCachedUncleanCount += 1;
613923b7c7b8SHermès Bélusca-Maïto         }
614023b7c7b8SHermès Bélusca-Maïto         Vcb->OpenFileCount += 1;
614123b7c7b8SHermès Bélusca-Maïto         if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount += 1; }
614223b7c7b8SHermès Bélusca-Maïto         CountsIncremented = TRUE;
614323b7c7b8SHermès Bélusca-Maïto 
614423b7c7b8SHermès Bélusca-Maïto 
614523b7c7b8SHermès Bélusca-Maïto         //
614623b7c7b8SHermès Bélusca-Maïto         //  And set our return status
614723b7c7b8SHermès Bélusca-Maïto         //
614823b7c7b8SHermès Bélusca-Maïto 
614923b7c7b8SHermès Bélusca-Maïto         Iosb.Status = STATUS_SUCCESS;
615023b7c7b8SHermès Bélusca-Maïto         Iosb.Information = FILE_CREATED;
615123b7c7b8SHermès Bélusca-Maïto 
615223b7c7b8SHermès Bélusca-Maïto         if ( NT_SUCCESS(Iosb.Status) ) {
615323b7c7b8SHermès Bélusca-Maïto 
615423b7c7b8SHermès Bélusca-Maïto             //
615523b7c7b8SHermès Bélusca-Maïto             //  Mark the DeleteOnClose bit if the operation was successful.
615623b7c7b8SHermès Bélusca-Maïto             //
615723b7c7b8SHermès Bélusca-Maïto 
615823b7c7b8SHermès Bélusca-Maïto             if ( DeleteOnClose ) {
615923b7c7b8SHermès Bélusca-Maïto 
616023b7c7b8SHermès Bélusca-Maïto                 SetFlag( UnwindCcb->Flags, CCB_FLAG_DELETE_ON_CLOSE );
616123b7c7b8SHermès Bélusca-Maïto             }
616223b7c7b8SHermès Bélusca-Maïto 
616323b7c7b8SHermès Bélusca-Maïto             //
616423b7c7b8SHermès Bélusca-Maïto             //  Mark the OpenedByShortName bit if the operation was successful.
616523b7c7b8SHermès Bélusca-Maïto             //  If we created an Lfn, we have some sort of generated short name
616623b7c7b8SHermès Bélusca-Maïto             //  and thus don't consider ourselves to have opened it - though we
616723b7c7b8SHermès Bélusca-Maïto             //  may have had a case mix Lfn "Foo.bar" and generated "FOO.BAR"
616823b7c7b8SHermès Bélusca-Maïto             //
616923b7c7b8SHermès Bélusca-Maïto             //  Unless, of course, we wanted to create a short name and hit an
617023b7c7b8SHermès Bélusca-Maïto             //  associated Lfn in the tunnel cache
617123b7c7b8SHermès Bélusca-Maïto             //
617223b7c7b8SHermès Bélusca-Maïto 
617323b7c7b8SHermès Bélusca-Maïto             if ( !CreateLfn && !UsingTunneledLfn ) {
617423b7c7b8SHermès Bélusca-Maïto 
617523b7c7b8SHermès Bélusca-Maïto                 SetFlag( UnwindCcb->Flags, CCB_FLAG_OPENED_BY_SHORTNAME );
617623b7c7b8SHermès Bélusca-Maïto             }
617723b7c7b8SHermès Bélusca-Maïto 
617823b7c7b8SHermès Bélusca-Maïto             //
617923b7c7b8SHermès Bélusca-Maïto             //  Mark the ManageVolumeAccess bit if the privilege is held.
618023b7c7b8SHermès Bélusca-Maïto             //
618123b7c7b8SHermès Bélusca-Maïto 
618223b7c7b8SHermès Bélusca-Maïto             if (FatCheckManageVolumeAccess( IrpContext,
618323b7c7b8SHermès Bélusca-Maïto                                             IrpSp->Parameters.Create.SecurityContext->AccessState,
618423b7c7b8SHermès Bélusca-Maïto                                             (KPROCESSOR_MODE)( FlagOn( IrpSp->Flags, SL_FORCE_ACCESS_CHECK ) ?
618523b7c7b8SHermès Bélusca-Maïto                                                                UserMode :
618623b7c7b8SHermès Bélusca-Maïto                                                                IrpContext->OriginatingIrp->RequestorMode ))) {
618723b7c7b8SHermès Bélusca-Maïto 
618823b7c7b8SHermès Bélusca-Maïto                 SetFlag( UnwindCcb->Flags, CCB_FLAG_MANAGE_VOLUME_ACCESS );
618923b7c7b8SHermès Bélusca-Maïto             }
619023b7c7b8SHermès Bélusca-Maïto 
619123b7c7b8SHermès Bélusca-Maïto         }
619223b7c7b8SHermès Bélusca-Maïto 
619323b7c7b8SHermès Bélusca-Maïto 
619423b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
619523b7c7b8SHermès Bélusca-Maïto 
619623b7c7b8SHermès Bélusca-Maïto         DebugUnwind( FatCreateNewFile );
619723b7c7b8SHermès Bélusca-Maïto 
619823b7c7b8SHermès Bélusca-Maïto         if (UniTunneledLongName.Buffer != UniTunneledLongNameBuffer) {
619923b7c7b8SHermès Bélusca-Maïto 
620023b7c7b8SHermès Bélusca-Maïto             //
620123b7c7b8SHermès Bélusca-Maïto             //  Tunneling package grew the buffer from pool
620223b7c7b8SHermès Bélusca-Maïto             //
620323b7c7b8SHermès Bélusca-Maïto 
620423b7c7b8SHermès Bélusca-Maïto             ExFreePool( UniTunneledLongName.Buffer );
620523b7c7b8SHermès Bélusca-Maïto         }
620623b7c7b8SHermès Bélusca-Maïto 
620723b7c7b8SHermès Bélusca-Maïto 
620823b7c7b8SHermès Bélusca-Maïto         //
620923b7c7b8SHermès Bélusca-Maïto         //  If this is an abnormal termination then undo our work.
621023b7c7b8SHermès Bélusca-Maïto         //
621123b7c7b8SHermès Bélusca-Maïto         //  The extra exception handling here is complex.  We've got
621223b7c7b8SHermès Bélusca-Maïto         //  two places here where an exception can be thrown again.
621323b7c7b8SHermès Bélusca-Maïto         //
621423b7c7b8SHermès Bélusca-Maïto 
621523b7c7b8SHermès Bélusca-Maïto         LocalAbnormalTermination = _SEH2_AbnormalTermination();
621623b7c7b8SHermès Bélusca-Maïto 
621723b7c7b8SHermès Bélusca-Maïto         if (LocalAbnormalTermination) {
621823b7c7b8SHermès Bélusca-Maïto 
621923b7c7b8SHermès Bélusca-Maïto             if (CountsIncremented) {
622023b7c7b8SHermès Bélusca-Maïto                 Fcb->UncleanCount -= 1;
622123b7c7b8SHermès Bélusca-Maïto                 Fcb->OpenCount -= 1;
622223b7c7b8SHermès Bélusca-Maïto                 if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) {
622323b7c7b8SHermès Bélusca-Maïto                     Fcb->NonCachedUncleanCount -= 1;
622423b7c7b8SHermès Bélusca-Maïto                 }
622523b7c7b8SHermès Bélusca-Maïto                 Vcb->OpenFileCount -= 1;
622623b7c7b8SHermès Bélusca-Maïto                 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount -= 1; }
622723b7c7b8SHermès Bélusca-Maïto             }
622823b7c7b8SHermès Bélusca-Maïto 
622923b7c7b8SHermès Bélusca-Maïto             if (UnwindFcb == NULL) {
623023b7c7b8SHermès Bélusca-Maïto 
623123b7c7b8SHermès Bélusca-Maïto                 NT_ASSERT( (ParentDcb->Specific.Dcb.UnusedDirentVbo == 0xffffffff) ||
623223b7c7b8SHermès Bélusca-Maïto                         RtlAreBitsSet( &ParentDcb->Specific.Dcb.FreeDirentBitmap,
623323b7c7b8SHermès Bélusca-Maïto                                        DirentByteOffset / sizeof(DIRENT),
623423b7c7b8SHermès Bélusca-Maïto                                        DirentsNeeded ) );
623523b7c7b8SHermès Bélusca-Maïto 
623623b7c7b8SHermès Bélusca-Maïto                 RtlClearBits( &ParentDcb->Specific.Dcb.FreeDirentBitmap,
623723b7c7b8SHermès Bélusca-Maïto                               DirentByteOffset / sizeof(DIRENT),
623823b7c7b8SHermès Bélusca-Maïto                               DirentsNeeded );
623923b7c7b8SHermès Bélusca-Maïto             }
624023b7c7b8SHermès Bélusca-Maïto 
624123b7c7b8SHermès Bélusca-Maïto             //
624223b7c7b8SHermès Bélusca-Maïto             //  Mark the dirents deleted.  The code is complex because of
624323b7c7b8SHermès Bélusca-Maïto             //  dealing with an LFN that crosses a page boundary.
624423b7c7b8SHermès Bélusca-Maïto             //
624523b7c7b8SHermès Bélusca-Maïto 
624623b7c7b8SHermès Bélusca-Maïto             if (UnwindDirent != NULL) {
624723b7c7b8SHermès Bélusca-Maïto 
624823b7c7b8SHermès Bélusca-Maïto                 ULONG i;
624923b7c7b8SHermès Bélusca-Maïto 
625023b7c7b8SHermès Bélusca-Maïto                 for (i = 0; i < DirentsNeeded; i++) {
625123b7c7b8SHermès Bélusca-Maïto 
625223b7c7b8SHermès Bélusca-Maïto                     if (DirentFromPool == FALSE) {
625323b7c7b8SHermès Bélusca-Maïto 
625423b7c7b8SHermès Bélusca-Maïto                         //
625523b7c7b8SHermès Bélusca-Maïto                         //  Simple case.
625623b7c7b8SHermès Bélusca-Maïto                         //
625723b7c7b8SHermès Bélusca-Maïto 
625823b7c7b8SHermès Bélusca-Maïto                         Dirent[i].FileName[0] = FAT_DIRENT_DELETED;
625923b7c7b8SHermès Bélusca-Maïto 
626023b7c7b8SHermès Bélusca-Maïto                     } else {
626123b7c7b8SHermès Bélusca-Maïto 
626223b7c7b8SHermès Bélusca-Maïto                         //
626323b7c7b8SHermès Bélusca-Maïto                         //  If the second CcPreparePinWrite failed, we have
626423b7c7b8SHermès Bélusca-Maïto                         //  to stop early.
626523b7c7b8SHermès Bélusca-Maïto                         //
626623b7c7b8SHermès Bélusca-Maïto 
626723b7c7b8SHermès Bélusca-Maïto                         if ((SecondPageBcb == NULL) &&
626823b7c7b8SHermès Bélusca-Maïto                             (i == DirentsInFirstPage)) {
626923b7c7b8SHermès Bélusca-Maïto 
627023b7c7b8SHermès Bélusca-Maïto                             break;
627123b7c7b8SHermès Bélusca-Maïto                         }
627223b7c7b8SHermès Bélusca-Maïto 
627323b7c7b8SHermès Bélusca-Maïto                         //
627423b7c7b8SHermès Bélusca-Maïto                         //  Now conditionally update either page.
627523b7c7b8SHermès Bélusca-Maïto                         //
627623b7c7b8SHermès Bélusca-Maïto 
627723b7c7b8SHermès Bélusca-Maïto                         if (i < DirentsInFirstPage) {
627823b7c7b8SHermès Bélusca-Maïto 
627923b7c7b8SHermès Bélusca-Maïto                             FirstPageDirent[i].FileName[0] = FAT_DIRENT_DELETED;
628023b7c7b8SHermès Bélusca-Maïto 
628123b7c7b8SHermès Bélusca-Maïto                         } else {
628223b7c7b8SHermès Bélusca-Maïto 
628323b7c7b8SHermès Bélusca-Maïto                             SecondPageDirent[i - DirentsInFirstPage].FileName[0] = FAT_DIRENT_DELETED;
628423b7c7b8SHermès Bélusca-Maïto                         }
628523b7c7b8SHermès Bélusca-Maïto                     }
628623b7c7b8SHermès Bélusca-Maïto                 }
628723b7c7b8SHermès Bélusca-Maïto             }
628823b7c7b8SHermès Bélusca-Maïto         }
628923b7c7b8SHermès Bélusca-Maïto 
629023b7c7b8SHermès Bélusca-Maïto         //
629123b7c7b8SHermès Bélusca-Maïto         //  We must handle exceptions in the following fragments and plow on with the
629223b7c7b8SHermès Bélusca-Maïto         //  unwind of this create operation.  This is basically inverted from the
629323b7c7b8SHermès Bélusca-Maïto         //  previous state of the code.  Since AbnormalTermination() changes when we
629423b7c7b8SHermès Bélusca-Maïto         //  enter a new enclosure, we cached the original state ...
629523b7c7b8SHermès Bélusca-Maïto         //
629623b7c7b8SHermès Bélusca-Maïto 
629723b7c7b8SHermès Bélusca-Maïto         _SEH2_TRY {
629823b7c7b8SHermès Bélusca-Maïto 
629923b7c7b8SHermès Bélusca-Maïto             if (LocalAbnormalTermination) {
630023b7c7b8SHermès Bélusca-Maïto                 if (UnwindAllocation) {
630123b7c7b8SHermès Bélusca-Maïto                     FatTruncateFileAllocation( IrpContext, Fcb, 0 );
630223b7c7b8SHermès Bélusca-Maïto                 }
630323b7c7b8SHermès Bélusca-Maïto             }
630423b7c7b8SHermès Bélusca-Maïto 
630523b7c7b8SHermès Bélusca-Maïto         } _SEH2_FINALLY {
630623b7c7b8SHermès Bélusca-Maïto 
630723b7c7b8SHermès Bélusca-Maïto             _SEH2_TRY {
630823b7c7b8SHermès Bélusca-Maïto 
630923b7c7b8SHermès Bélusca-Maïto                 if (LocalAbnormalTermination) {
631023b7c7b8SHermès Bélusca-Maïto                     if (UnwindFcb != NULL) {
631123b7c7b8SHermès Bélusca-Maïto                         FatDeleteDirent( IrpContext, UnwindFcb, NULL, TRUE );
631223b7c7b8SHermès Bélusca-Maïto                     }
631323b7c7b8SHermès Bélusca-Maïto                 }
631423b7c7b8SHermès Bélusca-Maïto 
631523b7c7b8SHermès Bélusca-Maïto             } _SEH2_FINALLY {
631623b7c7b8SHermès Bélusca-Maïto 
631723b7c7b8SHermès Bélusca-Maïto                 if (LocalAbnormalTermination) {
631823b7c7b8SHermès Bélusca-Maïto                     if (UnwindFcb != NULL) {
631923b7c7b8SHermès Bélusca-Maïto                         if (ARGUMENT_PRESENT( FileObject )) {
632023b7c7b8SHermès Bélusca-Maïto                             FileObject->SectionObjectPointer = NULL;
632123b7c7b8SHermès Bélusca-Maïto                         }
632223b7c7b8SHermès Bélusca-Maïto                         FatDeleteFcb( IrpContext, &UnwindFcb );
632323b7c7b8SHermès Bélusca-Maïto                     }
632423b7c7b8SHermès Bélusca-Maïto                     if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
632523b7c7b8SHermès Bélusca-Maïto                 }
632623b7c7b8SHermès Bélusca-Maïto 
632723b7c7b8SHermès Bélusca-Maïto                 //
632823b7c7b8SHermès Bélusca-Maïto                 //  This is the normal cleanup code.
632923b7c7b8SHermès Bélusca-Maïto                 //
633023b7c7b8SHermès Bélusca-Maïto 
633123b7c7b8SHermès Bélusca-Maïto                 FatUnpinBcb( IrpContext, DirentBcb );
633223b7c7b8SHermès Bélusca-Maïto                 FatUnpinBcb( IrpContext, SecondPageBcb );
633323b7c7b8SHermès Bélusca-Maïto 
633423b7c7b8SHermès Bélusca-Maïto                 if (DirentFromPool) {
633523b7c7b8SHermès Bélusca-Maïto 
633623b7c7b8SHermès Bélusca-Maïto                     ExFreePool( Dirent );
633723b7c7b8SHermès Bélusca-Maïto                 }
633823b7c7b8SHermès Bélusca-Maïto 
633923b7c7b8SHermès Bélusca-Maïto             } _SEH2_END;
634023b7c7b8SHermès Bélusca-Maïto         } _SEH2_END;
634123b7c7b8SHermès Bélusca-Maïto 
634223b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatCreateNewFile -> Iosb.Status = %08lx\n", Iosb.Status);
634323b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
634423b7c7b8SHermès Bélusca-Maïto 
634523b7c7b8SHermès Bélusca-Maïto     return Iosb;
634623b7c7b8SHermès Bélusca-Maïto }
634723b7c7b8SHermès Bélusca-Maïto 
634823b7c7b8SHermès Bélusca-Maïto 
634923b7c7b8SHermès Bélusca-Maïto //
635023b7c7b8SHermès Bélusca-Maïto //  Internal support routine
635123b7c7b8SHermès Bélusca-Maïto //
635223b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)635323b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
635423b7c7b8SHermès Bélusca-Maïto IO_STATUS_BLOCK
635523b7c7b8SHermès Bélusca-Maïto FatSupersedeOrOverwriteFile (
635623b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
635723b7c7b8SHermès Bélusca-Maïto     _Inout_ PFILE_OBJECT FileObject,
635823b7c7b8SHermès Bélusca-Maïto     _Inout_ PFCB Fcb,
635923b7c7b8SHermès Bélusca-Maïto     _In_ ULONG AllocationSize,
636023b7c7b8SHermès Bélusca-Maïto     _In_ PFILE_FULL_EA_INFORMATION EaBuffer,
636123b7c7b8SHermès Bélusca-Maïto     _In_ ULONG EaLength,
636223b7c7b8SHermès Bélusca-Maïto     _In_ USHORT FileAttributes,
636323b7c7b8SHermès Bélusca-Maïto     _In_ ULONG CreateDisposition,
636423b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN NoEaKnowledge
636523b7c7b8SHermès Bélusca-Maïto     )
636623b7c7b8SHermès Bélusca-Maïto 
636723b7c7b8SHermès Bélusca-Maïto /*++
636823b7c7b8SHermès Bélusca-Maïto 
636923b7c7b8SHermès Bélusca-Maïto Routine Description:
637023b7c7b8SHermès Bélusca-Maïto 
637123b7c7b8SHermès Bélusca-Maïto     This routine performs a file supersede or overwrite operation.
637223b7c7b8SHermès Bélusca-Maïto 
637323b7c7b8SHermès Bélusca-Maïto Arguments:
637423b7c7b8SHermès Bélusca-Maïto 
637523b7c7b8SHermès Bélusca-Maïto     FileObject - Supplies a pointer to the file object
637623b7c7b8SHermès Bélusca-Maïto 
637723b7c7b8SHermès Bélusca-Maïto     Fcb - Supplies a pointer to the Fcb
637823b7c7b8SHermès Bélusca-Maïto 
637923b7c7b8SHermès Bélusca-Maïto     AllocationSize - Supplies an initial allocation size
638023b7c7b8SHermès Bélusca-Maïto 
638123b7c7b8SHermès Bélusca-Maïto     EaBuffer - Supplies the Ea set for the superseded/overwritten file
638223b7c7b8SHermès Bélusca-Maïto 
638323b7c7b8SHermès Bélusca-Maïto     EaLength - Supplies the length, in bytes, of EaBuffer
638423b7c7b8SHermès Bélusca-Maïto 
638523b7c7b8SHermès Bélusca-Maïto     FileAttributes - Supplies the supersede/overwrite file attributes
638623b7c7b8SHermès Bélusca-Maïto 
638723b7c7b8SHermès Bélusca-Maïto     CreateDisposition - Supplies the create disposition for the file
638823b7c7b8SHermès Bélusca-Maïto         It must be either supersede, overwrite, or overwrite if.
638923b7c7b8SHermès Bélusca-Maïto 
639023b7c7b8SHermès Bélusca-Maïto     NoEaKnowledge - This opener doesn't understand Ea's and we fail this
639123b7c7b8SHermès Bélusca-Maïto         open if the file has NeedEa's.
639223b7c7b8SHermès Bélusca-Maïto 
639323b7c7b8SHermès Bélusca-Maïto Return Value:
639423b7c7b8SHermès Bélusca-Maïto 
639523b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK - Returns the completion status for the operation
639623b7c7b8SHermès Bélusca-Maïto 
639723b7c7b8SHermès Bélusca-Maïto --*/
639823b7c7b8SHermès Bélusca-Maïto 
639923b7c7b8SHermès Bélusca-Maïto {
640023b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK Iosb = {0};
640123b7c7b8SHermès Bélusca-Maïto 
640223b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent;
640323b7c7b8SHermès Bélusca-Maïto     PBCB DirentBcb;
640423b7c7b8SHermès Bélusca-Maïto 
640523b7c7b8SHermès Bélusca-Maïto     USHORT EaHandle = 0;
640623b7c7b8SHermès Bélusca-Maïto     BOOLEAN EaChange = FALSE;
640723b7c7b8SHermès Bélusca-Maïto     BOOLEAN ReleasePaging = FALSE;
640823b7c7b8SHermès Bélusca-Maïto 
640923b7c7b8SHermès Bélusca-Maïto     PCCB Ccb;
641023b7c7b8SHermès Bélusca-Maïto 
641123b7c7b8SHermès Bélusca-Maïto     ULONG NotifyFilter;
641223b7c7b8SHermès Bélusca-Maïto     ULONG HeaderSize = 0;
641323b7c7b8SHermès Bélusca-Maïto     LARGE_INTEGER AllocSize = {0};
641423b7c7b8SHermès Bélusca-Maïto 
641523b7c7b8SHermès Bélusca-Maïto     //
641623b7c7b8SHermès Bélusca-Maïto     //  The following variables are for abnormal termination
641723b7c7b8SHermès Bélusca-Maïto     //
641823b7c7b8SHermès Bélusca-Maïto 
641923b7c7b8SHermès Bélusca-Maïto     PCCB UnwindCcb = NULL;
642023b7c7b8SHermès Bélusca-Maïto     USHORT UnwindEa = 0;
642123b7c7b8SHermès Bélusca-Maïto 
642223b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
642323b7c7b8SHermès Bélusca-Maïto 
642423b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatSupersedeOrOverwriteFile...\n", 0);
642523b7c7b8SHermès Bélusca-Maïto 
642623b7c7b8SHermès Bélusca-Maïto     DirentBcb = NULL;
642723b7c7b8SHermès Bélusca-Maïto 
642823b7c7b8SHermès Bélusca-Maïto     //
642923b7c7b8SHermès Bélusca-Maïto     //  We fail this operation if the caller doesn't understand Ea's.
643023b7c7b8SHermès Bélusca-Maïto     //
643123b7c7b8SHermès Bélusca-Maïto 
643223b7c7b8SHermès Bélusca-Maïto     if (NoEaKnowledge
643323b7c7b8SHermès Bélusca-Maïto         && EaLength > 0) {
643423b7c7b8SHermès Bélusca-Maïto 
643523b7c7b8SHermès Bélusca-Maïto         Iosb.Status = STATUS_ACCESS_DENIED;
643623b7c7b8SHermès Bélusca-Maïto 
643723b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatSupersedeOrOverwriteFile -> Iosb.Status = %08lx\n", Iosb.Status);
643823b7c7b8SHermès Bélusca-Maïto         return Iosb;
643923b7c7b8SHermès Bélusca-Maïto     }
644023b7c7b8SHermès Bélusca-Maïto 
644123b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
644223b7c7b8SHermès Bélusca-Maïto 
644323b7c7b8SHermès Bélusca-Maïto         //
644423b7c7b8SHermès Bélusca-Maïto         //  Before we actually truncate, check to see if the purge
644523b7c7b8SHermès Bélusca-Maïto         //  is going to fail.
644623b7c7b8SHermès Bélusca-Maïto         //
644723b7c7b8SHermès Bélusca-Maïto 
644823b7c7b8SHermès Bélusca-Maïto         if (!MmCanFileBeTruncated( &Fcb->NonPaged->SectionObjectPointers,
644923b7c7b8SHermès Bélusca-Maïto                                    &FatLargeZero )) {
645023b7c7b8SHermès Bélusca-Maïto 
645123b7c7b8SHermès Bélusca-Maïto             try_return( Iosb.Status = STATUS_USER_MAPPED_FILE );
645223b7c7b8SHermès Bélusca-Maïto         }
645323b7c7b8SHermès Bélusca-Maïto 
645423b7c7b8SHermès Bélusca-Maïto         //
645523b7c7b8SHermès Bélusca-Maïto         //  Setup the context and section object pointers, and update
645623b7c7b8SHermès Bélusca-Maïto         //  our reference counts
645723b7c7b8SHermès Bélusca-Maïto         //
645823b7c7b8SHermès Bélusca-Maïto 
645923b7c7b8SHermès Bélusca-Maïto         FatSetFileObject( FileObject,
646023b7c7b8SHermès Bélusca-Maïto                           UserFileOpen,
646123b7c7b8SHermès Bélusca-Maïto                           Fcb,
646223b7c7b8SHermès Bélusca-Maïto                           Ccb = UnwindCcb = FatCreateCcb( IrpContext ));
646323b7c7b8SHermès Bélusca-Maïto 
646423b7c7b8SHermès Bélusca-Maïto         FileObject->SectionObjectPointer = &Fcb->NonPaged->SectionObjectPointers;
646523b7c7b8SHermès Bélusca-Maïto 
646623b7c7b8SHermès Bélusca-Maïto         //
646723b7c7b8SHermès Bélusca-Maïto         //  Since this is an supersede/overwrite, purge the section so
646823b7c7b8SHermès Bélusca-Maïto         //  that mappers will see zeros.  We set the CREATE_IN_PROGRESS flag
646923b7c7b8SHermès Bélusca-Maïto         //  to prevent the Fcb from going away out from underneath us.
647023b7c7b8SHermès Bélusca-Maïto         //
647123b7c7b8SHermès Bélusca-Maïto 
647223b7c7b8SHermès Bélusca-Maïto         SetFlag(Fcb->Vcb->VcbState, VCB_STATE_FLAG_CREATE_IN_PROGRESS);
647323b7c7b8SHermès Bélusca-Maïto 
647423b7c7b8SHermès Bélusca-Maïto         CcPurgeCacheSection( &Fcb->NonPaged->SectionObjectPointers, NULL, 0, FALSE );
647523b7c7b8SHermès Bélusca-Maïto 
647623b7c7b8SHermès Bélusca-Maïto         //
647723b7c7b8SHermès Bélusca-Maïto         //  Tentatively add the new Ea's
647823b7c7b8SHermès Bélusca-Maïto         //
647923b7c7b8SHermès Bélusca-Maïto 
648023b7c7b8SHermès Bélusca-Maïto         if (EaLength > 0) {
648123b7c7b8SHermès Bélusca-Maïto 
648223b7c7b8SHermès Bélusca-Maïto             FatCreateEa( IrpContext,
648323b7c7b8SHermès Bélusca-Maïto                          Fcb->Vcb,
648423b7c7b8SHermès Bélusca-Maïto                          (PUCHAR) EaBuffer,
648523b7c7b8SHermès Bélusca-Maïto                          EaLength,
648623b7c7b8SHermès Bélusca-Maïto                          &Fcb->ShortName.Name.Oem,
648723b7c7b8SHermès Bélusca-Maïto                          &EaHandle );
648823b7c7b8SHermès Bélusca-Maïto 
648923b7c7b8SHermès Bélusca-Maïto             UnwindEa = EaHandle;
649023b7c7b8SHermès Bélusca-Maïto             EaChange = TRUE;
649123b7c7b8SHermès Bélusca-Maïto         }
649223b7c7b8SHermès Bélusca-Maïto 
649323b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN8)
649423b7c7b8SHermès Bélusca-Maïto         //
649523b7c7b8SHermès Bélusca-Maïto         //  Break parent directory oplock.  Directory oplock breaks are always
649623b7c7b8SHermès Bélusca-Maïto         //  advisory, so we will never block/get STATUS_PENDING here.  On the
649723b7c7b8SHermès Bélusca-Maïto         //  off chance this fails with INSUFFICIENT_RESOURCES we do it here
649823b7c7b8SHermès Bélusca-Maïto         //  where we can still tolerate a failure.
649923b7c7b8SHermès Bélusca-Maïto         //
650023b7c7b8SHermès Bélusca-Maïto 
650123b7c7b8SHermès Bélusca-Maïto         Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(Fcb->ParentDcb),
650223b7c7b8SHermès Bélusca-Maïto                                           IrpContext->OriginatingIrp,
650323b7c7b8SHermès Bélusca-Maïto                                           OPLOCK_FLAG_PARENT_OBJECT,
650423b7c7b8SHermès Bélusca-Maïto                                           NULL,
650523b7c7b8SHermès Bélusca-Maïto                                           NULL,
650623b7c7b8SHermès Bélusca-Maïto                                           NULL );
650723b7c7b8SHermès Bélusca-Maïto 
650823b7c7b8SHermès Bélusca-Maïto         if (Iosb.Status != STATUS_SUCCESS) {
650923b7c7b8SHermès Bélusca-Maïto 
651023b7c7b8SHermès Bélusca-Maïto             FatRaiseStatus( IrpContext, Iosb.Status );
651123b7c7b8SHermès Bélusca-Maïto         }
651223b7c7b8SHermès Bélusca-Maïto #endif
651323b7c7b8SHermès Bélusca-Maïto 
651423b7c7b8SHermès Bélusca-Maïto         //
651523b7c7b8SHermès Bélusca-Maïto         //  Now set the new allocation size, we do that by first
651623b7c7b8SHermès Bélusca-Maïto         //  zeroing out the current file size.  Then we truncate and
651723b7c7b8SHermès Bélusca-Maïto         //  allocate up to the new allocation size
651823b7c7b8SHermès Bélusca-Maïto         //
651923b7c7b8SHermès Bélusca-Maïto 
652023b7c7b8SHermès Bélusca-Maïto         (VOID)ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource, TRUE );
652123b7c7b8SHermès Bélusca-Maïto         ReleasePaging = TRUE;
652223b7c7b8SHermès Bélusca-Maïto 
652323b7c7b8SHermès Bélusca-Maïto         Fcb->Header.FileSize.LowPart = 0;
652423b7c7b8SHermès Bélusca-Maïto         Fcb->Header.ValidDataLength.LowPart = 0;
652523b7c7b8SHermès Bélusca-Maïto         Fcb->ValidDataToDisk = 0;
652623b7c7b8SHermès Bélusca-Maïto 
652723b7c7b8SHermès Bélusca-Maïto 
652823b7c7b8SHermès Bélusca-Maïto         //
652923b7c7b8SHermès Bélusca-Maïto         // Validate that the allocation size will work.
653023b7c7b8SHermès Bélusca-Maïto         //
653123b7c7b8SHermès Bélusca-Maïto 
653223b7c7b8SHermès Bélusca-Maïto         AllocSize.QuadPart = AllocationSize;
653323b7c7b8SHermès Bélusca-Maïto         if (!FatIsIoRangeValid( Fcb->Vcb, AllocSize, 0 )) {
653423b7c7b8SHermès Bélusca-Maïto 
653523b7c7b8SHermès Bélusca-Maïto             DebugTrace(-1, Dbg, "Illegal allocation size\n", 0);
653623b7c7b8SHermès Bélusca-Maïto 
653723b7c7b8SHermès Bélusca-Maïto             FatRaiseStatus( IrpContext, STATUS_DISK_FULL );
653823b7c7b8SHermès Bélusca-Maïto         }
653923b7c7b8SHermès Bélusca-Maïto 
654023b7c7b8SHermès Bélusca-Maïto 
654123b7c7b8SHermès Bélusca-Maïto         //
654223b7c7b8SHermès Bélusca-Maïto         //  Tell the cache manager the size went to zero
654323b7c7b8SHermès Bélusca-Maïto         //  This call is unconditional, because MM always wants to know.
654423b7c7b8SHermès Bélusca-Maïto         //
654523b7c7b8SHermès Bélusca-Maïto 
654623b7c7b8SHermès Bélusca-Maïto         CcSetFileSizes( FileObject,
654723b7c7b8SHermès Bélusca-Maïto                         (PCC_FILE_SIZES)&Fcb->Header.AllocationSize );
654823b7c7b8SHermès Bélusca-Maïto 
654923b7c7b8SHermès Bélusca-Maïto         FatTruncateFileAllocation( IrpContext, Fcb, AllocationSize+HeaderSize );
655023b7c7b8SHermès Bélusca-Maïto 
655123b7c7b8SHermès Bélusca-Maïto         ExReleaseResourceLite( Fcb->Header.PagingIoResource );
655223b7c7b8SHermès Bélusca-Maïto         ReleasePaging = FALSE;
655323b7c7b8SHermès Bélusca-Maïto 
655423b7c7b8SHermès Bélusca-Maïto         FatAddFileAllocation( IrpContext, Fcb, FileObject, AllocationSize+HeaderSize );
655523b7c7b8SHermès Bélusca-Maïto 
655623b7c7b8SHermès Bélusca-Maïto         Fcb->FcbState |= FCB_STATE_TRUNCATE_ON_CLOSE;
655723b7c7b8SHermès Bélusca-Maïto 
655823b7c7b8SHermès Bélusca-Maïto         //
655923b7c7b8SHermès Bélusca-Maïto         //  Modify the attributes and time of the file, by first reading
656023b7c7b8SHermès Bélusca-Maïto         //  in the dirent for the file and then updating its attributes
656123b7c7b8SHermès Bélusca-Maïto         //  and time fields.  Note that for supersede we replace the file
656223b7c7b8SHermès Bélusca-Maïto         //  attributes as opposed to adding to them.
656323b7c7b8SHermès Bélusca-Maïto         //
656423b7c7b8SHermès Bélusca-Maïto 
656523b7c7b8SHermès Bélusca-Maïto         FatGetDirentFromFcbOrDcb( IrpContext,
656623b7c7b8SHermès Bélusca-Maïto                                   Fcb,
656723b7c7b8SHermès Bélusca-Maïto                                   FALSE,
656823b7c7b8SHermès Bélusca-Maïto                                   &Dirent,
656923b7c7b8SHermès Bélusca-Maïto                                   &DirentBcb );
657023b7c7b8SHermès Bélusca-Maïto         //
657123b7c7b8SHermès Bélusca-Maïto         //  We should get the dirent since this Fcb is in good condition, verified as
657223b7c7b8SHermès Bélusca-Maïto         //  we crawled down the prefix tree.
657323b7c7b8SHermès Bélusca-Maïto         //
657423b7c7b8SHermès Bélusca-Maïto         //  Update the appropriate dirent fields, and the fcb fields
657523b7c7b8SHermès Bélusca-Maïto         //
657623b7c7b8SHermès Bélusca-Maïto 
657723b7c7b8SHermès Bélusca-Maïto         Dirent->FileSize = 0;
657823b7c7b8SHermès Bélusca-Maïto 
657923b7c7b8SHermès Bélusca-Maïto 
658023b7c7b8SHermès Bélusca-Maïto         FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
658123b7c7b8SHermès Bélusca-Maïto 
658223b7c7b8SHermès Bélusca-Maïto         if (CreateDisposition == FILE_SUPERSEDE) {
658323b7c7b8SHermès Bélusca-Maïto 
658423b7c7b8SHermès Bélusca-Maïto             Dirent->Attributes = (UCHAR)FileAttributes;
658523b7c7b8SHermès Bélusca-Maïto 
658623b7c7b8SHermès Bélusca-Maïto         } else {
658723b7c7b8SHermès Bélusca-Maïto 
658823b7c7b8SHermès Bélusca-Maïto             Dirent->Attributes |= (UCHAR)FileAttributes;
658923b7c7b8SHermès Bélusca-Maïto         }
659023b7c7b8SHermès Bélusca-Maïto 
659123b7c7b8SHermès Bélusca-Maïto         Fcb->DirentFatFlags = Dirent->Attributes;
659223b7c7b8SHermès Bélusca-Maïto 
659323b7c7b8SHermès Bélusca-Maïto         KeQuerySystemTime( &Fcb->LastWriteTime );
659423b7c7b8SHermès Bélusca-Maïto 
659523b7c7b8SHermès Bélusca-Maïto         (VOID)FatNtTimeToFatTime( IrpContext,
659623b7c7b8SHermès Bélusca-Maïto                                   &Fcb->LastWriteTime,
659723b7c7b8SHermès Bélusca-Maïto                                   TRUE,
659823b7c7b8SHermès Bélusca-Maïto                                   &Dirent->LastWriteTime,
659923b7c7b8SHermès Bélusca-Maïto                                   NULL );
660023b7c7b8SHermès Bélusca-Maïto 
660123b7c7b8SHermès Bélusca-Maïto         if (FatData.ChicagoMode) {
660223b7c7b8SHermès Bélusca-Maïto 
660323b7c7b8SHermès Bélusca-Maïto             Dirent->LastAccessDate = Dirent->LastWriteTime.Date;
660423b7c7b8SHermès Bélusca-Maïto         }
660523b7c7b8SHermès Bélusca-Maïto 
660623b7c7b8SHermès Bélusca-Maïto         NotifyFilter = FILE_NOTIFY_CHANGE_LAST_WRITE
660723b7c7b8SHermès Bélusca-Maïto                        | FILE_NOTIFY_CHANGE_ATTRIBUTES
660823b7c7b8SHermès Bélusca-Maïto                        | FILE_NOTIFY_CHANGE_SIZE;
660923b7c7b8SHermès Bélusca-Maïto 
661023b7c7b8SHermès Bélusca-Maïto         //
661123b7c7b8SHermès Bélusca-Maïto         //  And now delete the previous Ea set if there was one.
661223b7c7b8SHermès Bélusca-Maïto         //
661323b7c7b8SHermès Bélusca-Maïto 
661423b7c7b8SHermès Bélusca-Maïto         if (!FatIsFat32(Fcb->Vcb) && Dirent->ExtendedAttributes != 0) {
661523b7c7b8SHermès Bélusca-Maïto 
661623b7c7b8SHermès Bélusca-Maïto             //
661723b7c7b8SHermès Bélusca-Maïto             //  ****    SDK fix, we won't fail this if there is
661823b7c7b8SHermès Bélusca-Maïto             //          an error in the Ea's, we'll just leave
661923b7c7b8SHermès Bélusca-Maïto             //          the orphaned Ea's in the file.
662023b7c7b8SHermès Bélusca-Maïto             //
662123b7c7b8SHermès Bélusca-Maïto 
662223b7c7b8SHermès Bélusca-Maïto             EaChange = TRUE;
662323b7c7b8SHermès Bélusca-Maïto 
662423b7c7b8SHermès Bélusca-Maïto             _SEH2_TRY {
662523b7c7b8SHermès Bélusca-Maïto 
662623b7c7b8SHermès Bélusca-Maïto                 FatDeleteEa( IrpContext,
662723b7c7b8SHermès Bélusca-Maïto                              Fcb->Vcb,
662823b7c7b8SHermès Bélusca-Maïto                              Dirent->ExtendedAttributes,
662923b7c7b8SHermès Bélusca-Maïto                              &Fcb->ShortName.Name.Oem );
663023b7c7b8SHermès Bélusca-Maïto 
663123b7c7b8SHermès Bélusca-Maïto             } _SEH2_EXCEPT( EXCEPTION_EXECUTE_HANDLER ) {
663223b7c7b8SHermès Bélusca-Maïto 
663323b7c7b8SHermès Bélusca-Maïto                   FatResetExceptionState( IrpContext );
663423b7c7b8SHermès Bélusca-Maïto             } _SEH2_END;
663523b7c7b8SHermès Bélusca-Maïto         }
663623b7c7b8SHermès Bélusca-Maïto 
663723b7c7b8SHermès Bélusca-Maïto         //
663823b7c7b8SHermès Bélusca-Maïto         //  Update the extended attributes handle in the dirent.
663923b7c7b8SHermès Bélusca-Maïto         //
664023b7c7b8SHermès Bélusca-Maïto 
664123b7c7b8SHermès Bélusca-Maïto         if (EaChange) {
664223b7c7b8SHermès Bélusca-Maïto 
664323b7c7b8SHermès Bélusca-Maïto             NT_ASSERT(!FatIsFat32(Fcb->Vcb));
664423b7c7b8SHermès Bélusca-Maïto 
664523b7c7b8SHermès Bélusca-Maïto             Dirent->ExtendedAttributes = EaHandle;
664623b7c7b8SHermès Bélusca-Maïto 
664723b7c7b8SHermès Bélusca-Maïto             NotifyFilter |= FILE_NOTIFY_CHANGE_EA;
664823b7c7b8SHermès Bélusca-Maïto         }
664923b7c7b8SHermès Bélusca-Maïto 
665023b7c7b8SHermès Bélusca-Maïto         //
665123b7c7b8SHermès Bélusca-Maïto         //  Now update the dirent to the new ea handle and set the bcb dirty
665223b7c7b8SHermès Bélusca-Maïto         //  Once we do this we can no longer back out the Ea
665323b7c7b8SHermès Bélusca-Maïto         //
665423b7c7b8SHermès Bélusca-Maïto 
665523b7c7b8SHermès Bélusca-Maïto         FatSetDirtyBcb( IrpContext, DirentBcb, Fcb->Vcb, TRUE );
665623b7c7b8SHermès Bélusca-Maïto         UnwindEa = 0;
665723b7c7b8SHermès Bélusca-Maïto 
665823b7c7b8SHermès Bélusca-Maïto         //
665923b7c7b8SHermès Bélusca-Maïto         //  Indicate that the Eas for this file have changed.
666023b7c7b8SHermès Bélusca-Maïto         //
666123b7c7b8SHermès Bélusca-Maïto 
666223b7c7b8SHermès Bélusca-Maïto         Ccb->EaModificationCount += Fcb->EaModificationCount;
666323b7c7b8SHermès Bélusca-Maïto 
666423b7c7b8SHermès Bélusca-Maïto         //
666523b7c7b8SHermès Bélusca-Maïto         //  Check to see if we need to notify outstanding Irps for full
666623b7c7b8SHermès Bélusca-Maïto         //  changes only (i.e., we haven't added, deleted, or renamed the file).
666723b7c7b8SHermès Bélusca-Maïto         //
666823b7c7b8SHermès Bélusca-Maïto 
666923b7c7b8SHermès Bélusca-Maïto         FatNotifyReportChange( IrpContext,
667023b7c7b8SHermès Bélusca-Maïto                                Fcb->Vcb,
667123b7c7b8SHermès Bélusca-Maïto                                Fcb,
667223b7c7b8SHermès Bélusca-Maïto                                NotifyFilter,
667323b7c7b8SHermès Bélusca-Maïto                                FILE_ACTION_MODIFIED );
667423b7c7b8SHermès Bélusca-Maïto 
667523b7c7b8SHermès Bélusca-Maïto         //
667623b7c7b8SHermès Bélusca-Maïto         //  And set our status to success
667723b7c7b8SHermès Bélusca-Maïto         //
667823b7c7b8SHermès Bélusca-Maïto 
667923b7c7b8SHermès Bélusca-Maïto         Iosb.Status = STATUS_SUCCESS;
668023b7c7b8SHermès Bélusca-Maïto 
668123b7c7b8SHermès Bélusca-Maïto         if (CreateDisposition == FILE_SUPERSEDE) {
668223b7c7b8SHermès Bélusca-Maïto 
668323b7c7b8SHermès Bélusca-Maïto             Iosb.Information = FILE_SUPERSEDED;
668423b7c7b8SHermès Bélusca-Maïto 
668523b7c7b8SHermès Bélusca-Maïto         } else {
668623b7c7b8SHermès Bélusca-Maïto 
668723b7c7b8SHermès Bélusca-Maïto             Iosb.Information = FILE_OVERWRITTEN;
668823b7c7b8SHermès Bélusca-Maïto         }
668923b7c7b8SHermès Bélusca-Maïto 
669023b7c7b8SHermès Bélusca-Maïto     try_exit: NOTHING;
669123b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
669223b7c7b8SHermès Bélusca-Maïto 
669323b7c7b8SHermès Bélusca-Maïto         DebugUnwind( FatSupersedeOfOverwriteFile );
669423b7c7b8SHermès Bélusca-Maïto 
669523b7c7b8SHermès Bélusca-Maïto         if (ReleasePaging)  {  ExReleaseResourceLite( Fcb->Header.PagingIoResource );  }
669623b7c7b8SHermès Bélusca-Maïto 
669723b7c7b8SHermès Bélusca-Maïto         //
669823b7c7b8SHermès Bélusca-Maïto         //  If this is an abnormal termination then undo our work.
669923b7c7b8SHermès Bélusca-Maïto         //
670023b7c7b8SHermès Bélusca-Maïto 
670123b7c7b8SHermès Bélusca-Maïto         if (_SEH2_AbnormalTermination()) {
670223b7c7b8SHermès Bélusca-Maïto 
670323b7c7b8SHermès Bélusca-Maïto             if (UnwindEa != 0) { FatDeleteEa( IrpContext, Fcb->Vcb, UnwindEa, &Fcb->ShortName.Name.Oem ); }
670423b7c7b8SHermès Bélusca-Maïto             if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
670523b7c7b8SHermès Bélusca-Maïto         }
670623b7c7b8SHermès Bélusca-Maïto 
670723b7c7b8SHermès Bélusca-Maïto         FatUnpinBcb( IrpContext, DirentBcb );
670823b7c7b8SHermès Bélusca-Maïto 
670923b7c7b8SHermès Bélusca-Maïto         ClearFlag(Fcb->Vcb->VcbState, VCB_STATE_FLAG_CREATE_IN_PROGRESS);
671023b7c7b8SHermès Bélusca-Maïto 
671123b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatSupersedeOrOverwriteFile -> Iosb.Status = %08lx\n", Iosb.Status);
671223b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
671323b7c7b8SHermès Bélusca-Maïto 
671423b7c7b8SHermès Bélusca-Maïto     return Iosb;
671523b7c7b8SHermès Bélusca-Maïto }
671623b7c7b8SHermès Bélusca-Maïto 
671723b7c7b8SHermès Bélusca-Maïto 
671823b7c7b8SHermès Bélusca-Maïto VOID
FatSetFullNameInFcb(_In_ PIRP_CONTEXT IrpContext,_Inout_ PFCB Fcb,_In_ PUNICODE_STRING FinalName)671923b7c7b8SHermès Bélusca-Maïto FatSetFullNameInFcb (
672023b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
672123b7c7b8SHermès Bélusca-Maïto     _Inout_ PFCB Fcb,
672223b7c7b8SHermès Bélusca-Maïto     _In_ PUNICODE_STRING FinalName
672323b7c7b8SHermès Bélusca-Maïto     )
672423b7c7b8SHermès Bélusca-Maïto 
672523b7c7b8SHermès Bélusca-Maïto /*++
672623b7c7b8SHermès Bélusca-Maïto 
672723b7c7b8SHermès Bélusca-Maïto Routine Description:
672823b7c7b8SHermès Bélusca-Maïto 
672923b7c7b8SHermès Bélusca-Maïto     This routine attempts a quick form of the full FatSetFullFileNameInFcb
673023b7c7b8SHermès Bélusca-Maïto     operation.
673123b7c7b8SHermès Bélusca-Maïto 
673223b7c7b8SHermès Bélusca-Maïto     NOTE: this routine is probably not worth the code duplication involved,
673323b7c7b8SHermès Bélusca-Maïto     and is not equipped to handle the cases where the parent doesn't have
673423b7c7b8SHermès Bélusca-Maïto     the full name set up.
673523b7c7b8SHermès Bélusca-Maïto 
673623b7c7b8SHermès Bélusca-Maïto Arguments:
673723b7c7b8SHermès Bélusca-Maïto 
673823b7c7b8SHermès Bélusca-Maïto     Fcb - Supplies a pointer to the Fcb
673923b7c7b8SHermès Bélusca-Maïto 
674023b7c7b8SHermès Bélusca-Maïto     FinalName - Supplies the last component of the path to this Fcb's dirent
674123b7c7b8SHermès Bélusca-Maïto 
674223b7c7b8SHermès Bélusca-Maïto Return Value:
674323b7c7b8SHermès Bélusca-Maïto 
674423b7c7b8SHermès Bélusca-Maïto     None.  May silently fail.
674523b7c7b8SHermès Bélusca-Maïto 
674623b7c7b8SHermès Bélusca-Maïto --*/
674723b7c7b8SHermès Bélusca-Maïto 
674823b7c7b8SHermès Bélusca-Maïto {
674923b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
675023b7c7b8SHermès Bélusca-Maïto 
675123b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( IrpContext );
675223b7c7b8SHermès Bélusca-Maïto 
675323b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( Fcb->FullFileName.Buffer == NULL );
675423b7c7b8SHermès Bélusca-Maïto 
675523b7c7b8SHermès Bélusca-Maïto     //
675623b7c7b8SHermès Bélusca-Maïto     //  Prefer the ExactCaseLongName of the file for this operation, if set.  In
675723b7c7b8SHermès Bélusca-Maïto     //  this way we avoid building the fullname with a short filename.  Several
675823b7c7b8SHermès Bélusca-Maïto     //  operations assume this - the FinalNameLength in particular is the Lfn
675923b7c7b8SHermès Bélusca-Maïto     //  (if existant) length, and we use this to crack the fullname in paths
676023b7c7b8SHermès Bélusca-Maïto     //  such as the FsRtlNotify caller.
676123b7c7b8SHermès Bélusca-Maïto     //
676223b7c7b8SHermès Bélusca-Maïto     //  If the caller specified a particular name and it is short, it is the
676323b7c7b8SHermès Bélusca-Maïto     //  case that the long name was set up.
676423b7c7b8SHermès Bélusca-Maïto     //
676523b7c7b8SHermès Bélusca-Maïto 
676623b7c7b8SHermès Bélusca-Maïto     if (Fcb->ExactCaseLongName.Buffer) {
676723b7c7b8SHermès Bélusca-Maïto 
676823b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( Fcb->ExactCaseLongName.Length != 0 );
676923b7c7b8SHermès Bélusca-Maïto         FinalName = &Fcb->ExactCaseLongName;
677023b7c7b8SHermès Bélusca-Maïto     }
677123b7c7b8SHermès Bélusca-Maïto 
677223b7c7b8SHermès Bélusca-Maïto     //
677323b7c7b8SHermès Bélusca-Maïto     //  Special case the root.
677423b7c7b8SHermès Bélusca-Maïto     //
677523b7c7b8SHermès Bélusca-Maïto 
677623b7c7b8SHermès Bélusca-Maïto     if (NodeType(Fcb->ParentDcb) == FAT_NTC_ROOT_DCB) {
677723b7c7b8SHermès Bélusca-Maïto 
677823b7c7b8SHermès Bélusca-Maïto         Fcb->FullFileName.Length =
677923b7c7b8SHermès Bélusca-Maïto         Fcb->FullFileName.MaximumLength = sizeof(WCHAR) + FinalName->Length;
678023b7c7b8SHermès Bélusca-Maïto 
678123b7c7b8SHermès Bélusca-Maïto         Fcb->FullFileName.Buffer = FsRtlAllocatePoolWithTag( PagedPool,
678223b7c7b8SHermès Bélusca-Maïto                                                              Fcb->FullFileName.Length,
678323b7c7b8SHermès Bélusca-Maïto                                                              TAG_FILENAME_BUFFER );
678423b7c7b8SHermès Bélusca-Maïto 
678523b7c7b8SHermès Bélusca-Maïto         Fcb->FullFileName.Buffer[0] = L'\\';
678623b7c7b8SHermès Bélusca-Maïto 
678723b7c7b8SHermès Bélusca-Maïto         RtlCopyMemory( &Fcb->FullFileName.Buffer[1],
678823b7c7b8SHermès Bélusca-Maïto                        &FinalName->Buffer[0],
678923b7c7b8SHermès Bélusca-Maïto                        FinalName->Length );
679023b7c7b8SHermès Bélusca-Maïto 
679123b7c7b8SHermès Bélusca-Maïto     } else {
679223b7c7b8SHermès Bélusca-Maïto 
679323b7c7b8SHermès Bélusca-Maïto         PUNICODE_STRING Prefix;
679423b7c7b8SHermès Bélusca-Maïto 
679523b7c7b8SHermès Bélusca-Maïto         Prefix = &Fcb->ParentDcb->FullFileName;
679623b7c7b8SHermès Bélusca-Maïto 
679723b7c7b8SHermès Bélusca-Maïto         //
679823b7c7b8SHermès Bélusca-Maïto         //  It is possible our parent's full filename is not set.  Simply fail
679923b7c7b8SHermès Bélusca-Maïto         //  this attempt.
680023b7c7b8SHermès Bélusca-Maïto         //
680123b7c7b8SHermès Bélusca-Maïto 
680223b7c7b8SHermès Bélusca-Maïto         if (Prefix->Buffer == NULL) {
680323b7c7b8SHermès Bélusca-Maïto 
680423b7c7b8SHermès Bélusca-Maïto             return;
680523b7c7b8SHermès Bélusca-Maïto         }
680623b7c7b8SHermès Bélusca-Maïto 
680723b7c7b8SHermès Bélusca-Maïto         Fcb->FullFileName.Length =
680823b7c7b8SHermès Bélusca-Maïto         Fcb->FullFileName.MaximumLength = Prefix->Length + sizeof(WCHAR) + FinalName->Length;
680923b7c7b8SHermès Bélusca-Maïto 
681023b7c7b8SHermès Bélusca-Maïto         Fcb->FullFileName.Buffer = FsRtlAllocatePoolWithTag( PagedPool,
681123b7c7b8SHermès Bélusca-Maïto                                                              Fcb->FullFileName.Length,
681223b7c7b8SHermès Bélusca-Maïto                                                              TAG_FILENAME_BUFFER );
681323b7c7b8SHermès Bélusca-Maïto 
681423b7c7b8SHermès Bélusca-Maïto         RtlCopyMemory( &Fcb->FullFileName.Buffer[0],
681523b7c7b8SHermès Bélusca-Maïto                        &Prefix->Buffer[0],
681623b7c7b8SHermès Bélusca-Maïto                        Prefix->Length );
681723b7c7b8SHermès Bélusca-Maïto 
681823b7c7b8SHermès Bélusca-Maïto         Fcb->FullFileName.Buffer[Prefix->Length / sizeof(WCHAR)] = L'\\';
681923b7c7b8SHermès Bélusca-Maïto 
682023b7c7b8SHermès Bélusca-Maïto         RtlCopyMemory( &Fcb->FullFileName.Buffer[(Prefix->Length / sizeof(WCHAR)) + 1],
682123b7c7b8SHermès Bélusca-Maïto                        &FinalName->Buffer[0],
682223b7c7b8SHermès Bélusca-Maïto                        FinalName->Length );
682323b7c7b8SHermès Bélusca-Maïto 
682423b7c7b8SHermès Bélusca-Maïto     }
682523b7c7b8SHermès Bélusca-Maïto }
682623b7c7b8SHermès Bélusca-Maïto 
682723b7c7b8SHermès Bélusca-Maïto 
682823b7c7b8SHermès Bélusca-Maïto NTSTATUS
FatCheckSystemSecurityAccess(_In_ PIRP_CONTEXT IrpContext)682923b7c7b8SHermès Bélusca-Maïto FatCheckSystemSecurityAccess (
683023b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext
683123b7c7b8SHermès Bélusca-Maïto     )
683223b7c7b8SHermès Bélusca-Maïto {
683323b7c7b8SHermès Bélusca-Maïto     PACCESS_STATE AccessState;
683423b7c7b8SHermès Bélusca-Maïto     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( IrpContext->OriginatingIrp );
683523b7c7b8SHermès Bélusca-Maïto 
683623b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
683723b7c7b8SHermès Bélusca-Maïto 
683823b7c7b8SHermès Bélusca-Maïto     //
683923b7c7b8SHermès Bélusca-Maïto     //  We check if the caller wants ACCESS_SYSTEM_SECURITY access on this
684023b7c7b8SHermès Bélusca-Maïto     //  object and fail the request if he does.
684123b7c7b8SHermès Bélusca-Maïto     //
684223b7c7b8SHermès Bélusca-Maïto 
684323b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( IrpSp->Parameters.Create.SecurityContext != NULL );
684423b7c7b8SHermès Bélusca-Maïto     AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
684523b7c7b8SHermès Bélusca-Maïto 
684623b7c7b8SHermès Bélusca-Maïto     //
684723b7c7b8SHermès Bélusca-Maïto     //  Check if the remaining privilege includes ACCESS_SYSTEM_SECURITY.
684823b7c7b8SHermès Bélusca-Maïto     //
684923b7c7b8SHermès Bélusca-Maïto 
685023b7c7b8SHermès Bélusca-Maïto     if (FlagOn( AccessState->RemainingDesiredAccess, ACCESS_SYSTEM_SECURITY )) {
685123b7c7b8SHermès Bélusca-Maïto 
685223b7c7b8SHermès Bélusca-Maïto         if (!SeSinglePrivilegeCheck( FatSecurityPrivilege,
685323b7c7b8SHermès Bélusca-Maïto                                      UserMode )) {
685423b7c7b8SHermès Bélusca-Maïto 
685523b7c7b8SHermès Bélusca-Maïto             return STATUS_ACCESS_DENIED;
685623b7c7b8SHermès Bélusca-Maïto         }
685723b7c7b8SHermès Bélusca-Maïto 
685823b7c7b8SHermès Bélusca-Maïto         //
685923b7c7b8SHermès Bélusca-Maïto         //  Move this privilege from the Remaining access to Granted access.
686023b7c7b8SHermès Bélusca-Maïto         //
686123b7c7b8SHermès Bélusca-Maïto 
686223b7c7b8SHermès Bélusca-Maïto         ClearFlag( AccessState->RemainingDesiredAccess, ACCESS_SYSTEM_SECURITY );
686323b7c7b8SHermès Bélusca-Maïto         SetFlag( AccessState->PreviouslyGrantedAccess, ACCESS_SYSTEM_SECURITY );
686423b7c7b8SHermès Bélusca-Maïto     }
686523b7c7b8SHermès Bélusca-Maïto 
686623b7c7b8SHermès Bélusca-Maïto     return STATUS_SUCCESS;
686723b7c7b8SHermès Bélusca-Maïto }
686823b7c7b8SHermès Bélusca-Maïto 
686923b7c7b8SHermès Bélusca-Maïto 
687023b7c7b8SHermès Bélusca-Maïto NTSTATUS
FatCheckShareAccess(_In_ PIRP_CONTEXT IrpContext,_In_ PFILE_OBJECT FileObject,_In_ PFCB FcbOrDcb,_In_ PACCESS_MASK DesiredAccess,_In_ ULONG ShareAccess)687123b7c7b8SHermès Bélusca-Maïto FatCheckShareAccess (
687223b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
687323b7c7b8SHermès Bélusca-Maïto     _In_ PFILE_OBJECT FileObject,
687423b7c7b8SHermès Bélusca-Maïto     _In_ PFCB FcbOrDcb,
687523b7c7b8SHermès Bélusca-Maïto     _In_ PACCESS_MASK DesiredAccess,
687623b7c7b8SHermès Bélusca-Maïto     _In_ ULONG ShareAccess
687723b7c7b8SHermès Bélusca-Maïto     )
687823b7c7b8SHermès Bélusca-Maïto 
687923b7c7b8SHermès Bélusca-Maïto /*++
688023b7c7b8SHermès Bélusca-Maïto 
688123b7c7b8SHermès Bélusca-Maïto Routine Description:
688223b7c7b8SHermès Bélusca-Maïto 
688323b7c7b8SHermès Bélusca-Maïto     This routine checks conditions that may result in a sharing violation.
688423b7c7b8SHermès Bélusca-Maïto 
688523b7c7b8SHermès Bélusca-Maïto Arguments:
688623b7c7b8SHermès Bélusca-Maïto 
688723b7c7b8SHermès Bélusca-Maïto     FileObject - Pointer to the file object of the current open request.
688823b7c7b8SHermès Bélusca-Maïto 
688923b7c7b8SHermès Bélusca-Maïto     FcbOrDcb - Supplies a pointer to the Fcb/Dcb.
689023b7c7b8SHermès Bélusca-Maïto 
689123b7c7b8SHermès Bélusca-Maïto     DesiredAccess - Desired access of current open request.
689223b7c7b8SHermès Bélusca-Maïto 
689323b7c7b8SHermès Bélusca-Maïto     ShareAccess - Shared access requested by current open request.
689423b7c7b8SHermès Bélusca-Maïto 
689523b7c7b8SHermès Bélusca-Maïto Return Value:
689623b7c7b8SHermès Bélusca-Maïto 
689723b7c7b8SHermès Bélusca-Maïto     If the accessor has access to the file, STATUS_SUCCESS is returned.
689823b7c7b8SHermès Bélusca-Maïto     Otherwise, STATUS_SHARING_VIOLATION is returned.
689923b7c7b8SHermès Bélusca-Maïto 
690023b7c7b8SHermès Bélusca-Maïto --*/
690123b7c7b8SHermès Bélusca-Maïto 
690223b7c7b8SHermès Bélusca-Maïto {
690323b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
690423b7c7b8SHermès Bélusca-Maïto 
690523b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_VISTA)
690623b7c7b8SHermès Bélusca-Maïto     //
690723b7c7b8SHermès Bélusca-Maïto     //  Do an extra test for writeable user sections if the user did not allow
690823b7c7b8SHermès Bélusca-Maïto     //  write sharing - this is neccessary since a section may exist with no handles
690923b7c7b8SHermès Bélusca-Maïto     //  open to the file its based against.
691023b7c7b8SHermès Bélusca-Maïto     //
691123b7c7b8SHermès Bélusca-Maïto 
691223b7c7b8SHermès Bélusca-Maïto     if ((NodeType( FcbOrDcb ) == FAT_NTC_FCB) &&
691323b7c7b8SHermès Bélusca-Maïto         !FlagOn( ShareAccess, FILE_SHARE_WRITE ) &&
691423b7c7b8SHermès Bélusca-Maïto         FlagOn( *DesiredAccess, FILE_EXECUTE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE | MAXIMUM_ALLOWED ) &&
691523b7c7b8SHermès Bélusca-Maïto         MmDoesFileHaveUserWritableReferences( &FcbOrDcb->NonPaged->SectionObjectPointers )) {
691623b7c7b8SHermès Bélusca-Maïto 
691723b7c7b8SHermès Bélusca-Maïto         return STATUS_SHARING_VIOLATION;
691823b7c7b8SHermès Bélusca-Maïto     }
691923b7c7b8SHermès Bélusca-Maïto #endif
692023b7c7b8SHermès Bélusca-Maïto 
692123b7c7b8SHermès Bélusca-Maïto     //
692223b7c7b8SHermès Bélusca-Maïto     //  Check if the Fcb has the proper share access.
692323b7c7b8SHermès Bélusca-Maïto     //
692423b7c7b8SHermès Bélusca-Maïto 
692523b7c7b8SHermès Bélusca-Maïto     return IoCheckShareAccess( *DesiredAccess,
692623b7c7b8SHermès Bélusca-Maïto                                ShareAccess,
692723b7c7b8SHermès Bélusca-Maïto                                FileObject,
692823b7c7b8SHermès Bélusca-Maïto                                &FcbOrDcb->ShareAccess,
692923b7c7b8SHermès Bélusca-Maïto                                FALSE );
693023b7c7b8SHermès Bélusca-Maïto 
693123b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( IrpContext );
693223b7c7b8SHermès Bélusca-Maïto }
693323b7c7b8SHermès Bélusca-Maïto 
693423b7c7b8SHermès Bélusca-Maïto //
693523b7c7b8SHermès Bélusca-Maïto // Lifted from NTFS.
693623b7c7b8SHermès Bélusca-Maïto //
693723b7c7b8SHermès Bélusca-Maïto 
693823b7c7b8SHermès Bélusca-Maïto NTSTATUS
FatCallSelfCompletionRoutine(__in PDEVICE_OBJECT DeviceObject,__in PIRP Irp,__in PVOID Contxt)693923b7c7b8SHermès Bélusca-Maïto FatCallSelfCompletionRoutine (
694023b7c7b8SHermès Bélusca-Maïto     __in PDEVICE_OBJECT DeviceObject,
694123b7c7b8SHermès Bélusca-Maïto     __in PIRP Irp,
694223b7c7b8SHermès Bélusca-Maïto     __in PVOID Contxt
694323b7c7b8SHermès Bélusca-Maïto     )
694423b7c7b8SHermès Bélusca-Maïto 
694523b7c7b8SHermès Bélusca-Maïto {
694623b7c7b8SHermès Bélusca-Maïto     //
694723b7c7b8SHermès Bélusca-Maïto     //  Set the event so that our call will wake up.
694823b7c7b8SHermès Bélusca-Maïto     //
694923b7c7b8SHermès Bélusca-Maïto 
695023b7c7b8SHermès Bélusca-Maïto     KeSetEvent( (PKEVENT)Contxt, 0, FALSE );
695123b7c7b8SHermès Bélusca-Maïto 
695223b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( DeviceObject );
695323b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( Irp );
695423b7c7b8SHermès Bélusca-Maïto 
695523b7c7b8SHermès Bélusca-Maïto     //
695623b7c7b8SHermès Bélusca-Maïto     //  If we change this return value then FatIoCallSelf needs to reference the
695723b7c7b8SHermès Bélusca-Maïto     //  file object.
695823b7c7b8SHermès Bélusca-Maïto     //
695923b7c7b8SHermès Bélusca-Maïto 
696023b7c7b8SHermès Bélusca-Maïto     return STATUS_MORE_PROCESSING_REQUIRED;
696123b7c7b8SHermès Bélusca-Maïto }
6962