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