diff --git a/build/VStudio/winfsp_dll.vcxproj b/build/VStudio/winfsp_dll.vcxproj
index 3ee98e59..ab79246f 100644
--- a/build/VStudio/winfsp_dll.vcxproj
+++ b/build/VStudio/winfsp_dll.vcxproj
@@ -24,7 +24,6 @@
-
diff --git a/build/VStudio/winfsp_dll.vcxproj.filters b/build/VStudio/winfsp_dll.vcxproj.filters
index 61513d10..a9cf81d4 100644
--- a/build/VStudio/winfsp_dll.vcxproj.filters
+++ b/build/VStudio/winfsp_dll.vcxproj.filters
@@ -43,9 +43,6 @@
Source
-
- Source
-
Source
diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h
index 37427431..f4e32901 100644
--- a/inc/winfsp/winfsp.h
+++ b/inc/winfsp/winfsp.h
@@ -50,9 +50,6 @@ typedef VOID FSP_FILE_SYSTEM_DISPATCHER(FSP_FILE_SYSTEM *, FSP_FSCTL_TRANSACT_RE
typedef NTSTATUS FSP_FILE_SYSTEM_OPERATION(FSP_FILE_SYSTEM *, FSP_FSCTL_TRANSACT_REQ *);
typedef struct _FSP_FILE_SYSTEM_INTERFACE
{
- NTSTATUS (*AccessCheck)(FSP_FILE_SYSTEM *FileSystem,
- FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
- DWORD DesiredAccess, PDWORD PGrantedAccess);
NTSTATUS (*GetSecurity)(FSP_FILE_SYSTEM *FileSystem,
PWSTR FileName, PDWORD PFileAttributes,
PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize);
@@ -149,6 +146,24 @@ FSP_API NTSTATUS FspFileSystemSendResponseWithStatus(FSP_FILE_SYSTEM *FileSystem
/*
* File System Operations
*/
+FSP_API PGENERIC_MAPPING FspGetFileGenericMapping(VOID);
+FSP_API NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem,
+ FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
+ DWORD DesiredAccess, PDWORD PGrantedAccess);
+FSP_API NTSTATUS FspShareCheck(FSP_FILE_SYSTEM *FileSystem,
+ FSP_FSCTL_TRANSACT_REQ *Request, DWORD GrantedAccess, FSP_FILE_NODE *FileNode);
+FSP_API NTSTATUS FspFileSystemPreCreateCheck(FSP_FILE_SYSTEM *FileSystem,
+ FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN AllowTraverseCheck, PDWORD PGrantedAccess);
+FSP_API VOID FspFileSystemPostCreateCheck(FSP_FILE_SYSTEM *FileSystem,
+ FSP_FSCTL_TRANSACT_REQ *Request, DWORD GrantedAccess, FSP_FILE_NODE *FileNode);
+FSP_API NTSTATUS FspFileSystemPreOpenCheck(FSP_FILE_SYSTEM *FileSystem,
+ FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN AllowTraverseCheck, PDWORD PGrantedAccess);
+FSP_API NTSTATUS FspFileSystemPostOpenCheck(FSP_FILE_SYSTEM *FileSystem,
+ FSP_FSCTL_TRANSACT_REQ *Request, DWORD GrantedAccess, FSP_FILE_NODE *FileNode);
+FSP_API NTSTATUS FspFileSystemPreOverwriteCheck(FSP_FILE_SYSTEM *FileSystem,
+ FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN AllowTraverseCheck, PDWORD PGrantedAccess);
+FSP_API NTSTATUS FspFileSystemPostOverwriteCheck(FSP_FILE_SYSTEM *FileSystem,
+ FSP_FSCTL_TRANSACT_REQ *Request, DWORD GrantedAccess, FSP_FILE_NODE *FileNode);
FSP_API NTSTATUS FspFileSystemOpCreate(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request);
FSP_API NTSTATUS FspFileSystemOpCleanup(FSP_FILE_SYSTEM *FileSystem,
@@ -163,16 +178,6 @@ FSP_API NTSTATUS FspFileSystemSendCloseResponse(FSP_FILE_SYSTEM *FileSystem,
FSP_API NTSTATUS FspFileSystemSendCleanupResponse(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request);
-/*
- * Access Checks
- */
-FSP_API PGENERIC_MAPPING FspGetFileGenericMapping(VOID);
-FSP_API NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem,
- FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
- DWORD DesiredAccess, PDWORD PGrantedAccess);
-FSP_API NTSTATUS FspShareCheck(FSP_FILE_SYSTEM *FileSystem,
- DWORD GrantedAccess, DWORD ShareAccess, FSP_FILE_NODE *FileNode);
-
/*
* Path Handling
*/
diff --git a/src/dll/access.c b/src/dll/access.c
deleted file mode 100644
index dbd6474a..00000000
--- a/src/dll/access.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/**
- * @file dll/access.c
- *
- * @copyright 2015 Bill Zissimopoulos
- */
-
-#include
-
-static GENERIC_MAPPING FspFileGenericMapping =
-{
- .GenericRead = FILE_GENERIC_READ,
- .GenericWrite = FILE_GENERIC_WRITE,
- .GenericExecute = FILE_GENERIC_EXECUTE,
- .GenericAll = FILE_ALL_ACCESS,
-};
-
-FSP_API PGENERIC_MAPPING FspGetFileGenericMapping(VOID)
-{
- return &FspFileGenericMapping;
-}
-
-static NTSTATUS FspGetSecurity(FSP_FILE_SYSTEM *FileSystem,
- PWSTR FileName, PDWORD PFileAttributes,
- PSECURITY_DESCRIPTOR *PSecurityDescriptor, SIZE_T *PSecurityDescriptorSize)
-{
- for (;;)
- {
- NTSTATUS Result = FileSystem->Interface->GetSecurity(FileSystem,
- FileName, PFileAttributes, *PSecurityDescriptor, PSecurityDescriptorSize);
- if (STATUS_BUFFER_OVERFLOW != Result)
- return Result;
-
- MemFree(*PSecurityDescriptor);
- *PSecurityDescriptor = MemAlloc(*PSecurityDescriptorSize);
- if (0 == *PSecurityDescriptor)
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-}
-
-FSP_API NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem,
- FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
- DWORD DesiredAccess, PDWORD PGrantedAccess)
-{
- if (0 != FileSystem->Interface->AccessCheck)
- return FileSystem->Interface->AccessCheck(FileSystem,
- Request, CheckParentDirectory, AllowTraverseCheck, DesiredAccess, PGrantedAccess);
-
- if (0 == FileSystem->Interface->GetSecurity)
- {
- *PGrantedAccess = DesiredAccess;
- return STATUS_SUCCESS;
- }
-
- NTSTATUS Result;
- PWSTR Parent, Suffix;
- DWORD FileAttributes;
- PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
- SIZE_T SecurityDescriptorSize;
- DWORD PrivilegeSetLength;
- BOOL AccessStatus;
-
- *PGrantedAccess = 0;
-
- if (CheckParentDirectory)
- FspPathSuffix((PWSTR)Request->Buffer, &Parent, &Suffix);
-
- SecurityDescriptorSize = 1024;
- SecurityDescriptor = MemAlloc(SecurityDescriptorSize);
- if (0 == SecurityDescriptor)
- {
- Result = STATUS_INSUFFICIENT_RESOURCES;
- goto exit;
- }
-
- if (AllowTraverseCheck && !Request->Req.Create.HasTraversePrivilege)
- {
- PWSTR Path = (PWSTR)Request->Buffer, Prefix;
- DWORD TraverseAccess;
-
- for (;;)
- {
- FspPathPrefix(Path, &Prefix, &Path);
- if (L'\0' == Path[0])
- {
- FspPathCombine((PWSTR)Request->Buffer, Path);
- break;
- }
-
- Prefix = L'\0' == Prefix[0] ? L"\\" : (PWSTR)Request->Buffer;
- Result = FspGetSecurity(FileSystem, Prefix, 0,
- &SecurityDescriptor, &SecurityDescriptorSize);
-
- FspPathCombine((PWSTR)Request->Buffer, Path);
-
- if (!NT_SUCCESS(Result))
- {
- if (STATUS_OBJECT_NAME_NOT_FOUND == Result)
- Result = STATUS_OBJECT_PATH_NOT_FOUND;
- goto exit;
- }
-
- if (AccessCheck(SecurityDescriptor, (HANDLE)Request->Req.Create.AccessToken, FILE_TRAVERSE,
- &FspFileGenericMapping, 0, &PrivilegeSetLength, &TraverseAccess, &AccessStatus))
- Result = AccessStatus ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
- else
- Result = FspNtStatusFromWin32(GetLastError());
-
- if (!NT_SUCCESS(Result))
- goto exit;
- }
- }
-
- Result = FspGetSecurity(FileSystem, (PWSTR)Request->Buffer, &FileAttributes,
- &SecurityDescriptor, &SecurityDescriptorSize);
- if (!NT_SUCCESS(Result))
- goto exit;
-
- if (CheckParentDirectory)
- {
- if (0 == (FileAttributes && FILE_ATTRIBUTE_DIRECTORY))
- return STATUS_NOT_A_DIRECTORY;
- }
- else
- {
- if ((Request->Req.Create.CreateOptions & FILE_DIRECTORY_FILE) &&
- 0 == (FileAttributes && FILE_ATTRIBUTE_DIRECTORY))
- return STATUS_NOT_A_DIRECTORY;
- if ((Request->Req.Create.CreateOptions & FILE_NON_DIRECTORY_FILE) &&
- 0 != (FileAttributes && FILE_ATTRIBUTE_DIRECTORY))
- return STATUS_NOT_A_DIRECTORY;
- }
-
- if (0 != (FileAttributes && FILE_ATTRIBUTE_READONLY))
- {
- if (DesiredAccess &
- (FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD))
- {
- Result = STATUS_ACCESS_DENIED;
- goto exit;
- }
- if (Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE)
- {
- Result = STATUS_CANNOT_DELETE;
- goto exit;
- }
- }
-
- if (AccessCheck(SecurityDescriptor, (HANDLE)Request->Req.Create.AccessToken, DesiredAccess,
- &FspFileGenericMapping, 0, &PrivilegeSetLength, PGrantedAccess, &AccessStatus))
- Result = AccessStatus ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
- else
- Result = FspNtStatusFromWin32(GetLastError());
-
-exit:
- MemFree(SecurityDescriptor);
-
- if (CheckParentDirectory)
- FspPathCombine((PWSTR)Request->Buffer, Suffix);
-
- return Result;
-}
-
-FSP_API NTSTATUS FspShareCheck(FSP_FILE_SYSTEM *FileSystem,
- DWORD GrantedAccess, DWORD ShareAccess, FSP_FILE_NODE *FileNode)
-{
- BOOLEAN ReadAccess, WriteAccess, DeleteAccess;
- BOOLEAN SharedRead, SharedWrite, SharedDelete;
- ULONG OpenCount;
-
- ReadAccess = 0 != (GrantedAccess & (FILE_READ_DATA | FILE_EXECUTE));
- WriteAccess = 0 != (GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA));
- DeleteAccess = 0 != (GrantedAccess & DELETE);
-
- if (ReadAccess || WriteAccess || DeleteAccess)
- {
- SharedRead = 0 != (ShareAccess & FILE_SHARE_READ);
- SharedWrite = 0 != (ShareAccess & FILE_SHARE_WRITE);
- SharedDelete = 0 != (ShareAccess & FILE_SHARE_DELETE);
-
- OpenCount = FileNode->ShareAccess.OpenCount;
-
- /*
- * IF ReadAccess AND there are already some exclusive readers
- * OR WriteAccess AND there are already some exclusive writers
- * OR DeleteAccess AND there are already some exclusive deleters
- * OR exclusive read requested AND there are already some readers
- * OR exclusive write requested AND there are already some writers
- * OR exclusive delete requested AND there are already some deleters
- */
- if (ReadAccess && (FileNode->ShareAccess.SharedRead < OpenCount))
- return STATUS_SHARING_VIOLATION;
- if (WriteAccess && (FileNode->ShareAccess.SharedWrite < OpenCount))
- return STATUS_SHARING_VIOLATION;
- if (DeleteAccess && (FileNode->ShareAccess.SharedDelete < OpenCount))
- return STATUS_SHARING_VIOLATION;
- if (!SharedRead && 0 != FileNode->ShareAccess.Readers)
- return STATUS_SHARING_VIOLATION;
- if (!SharedWrite && 0 != FileNode->ShareAccess.Writers)
- return STATUS_SHARING_VIOLATION;
- if (!SharedDelete && 0 != FileNode->ShareAccess.Deleters)
- return STATUS_SHARING_VIOLATION;
-
- FileNode->ShareAccess.OpenCount++;
- FileNode->ShareAccess.Readers += ReadAccess;
- FileNode->ShareAccess.Writers += WriteAccess;
- FileNode->ShareAccess.Deleters += DeleteAccess;
- FileNode->ShareAccess.SharedRead += SharedRead;
- FileNode->ShareAccess.SharedWrite += SharedWrite;
- FileNode->ShareAccess.SharedDelete += SharedDelete;
- }
-
- return STATUS_SUCCESS;
-}
diff --git a/src/dll/create.c b/src/dll/create.c
index a039b7d7..8b98f8ea 100644
--- a/src/dll/create.c
+++ b/src/dll/create.c
@@ -6,19 +6,221 @@
#include
-static inline
-BOOLEAN FspIsRootDirectory(PWSTR FileName)
+static GENERIC_MAPPING FspFileGenericMapping =
{
- for (PWSTR Pointer = FileName; *Pointer; Pointer++)
- if (L'\\' != *Pointer)
- return FALSE;
- return TRUE;
+ .GenericRead = FILE_GENERIC_READ,
+ .GenericWrite = FILE_GENERIC_WRITE,
+ .GenericExecute = FILE_GENERIC_EXECUTE,
+ .GenericAll = FILE_ALL_ACCESS,
+};
+
+FSP_API PGENERIC_MAPPING FspGetFileGenericMapping(VOID)
+{
+ return &FspFileGenericMapping;
}
-static inline
-NTSTATUS FspCreateCheck(FSP_FILE_SYSTEM *FileSystem,
- FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN AllowTraverseCheck,
- PDWORD PGrantedAccess)
+static NTSTATUS FspGetSecurity(FSP_FILE_SYSTEM *FileSystem,
+ PWSTR FileName, PDWORD PFileAttributes,
+ PSECURITY_DESCRIPTOR *PSecurityDescriptor, SIZE_T *PSecurityDescriptorSize)
+{
+ for (;;)
+ {
+ NTSTATUS Result = FileSystem->Interface->GetSecurity(FileSystem,
+ FileName, PFileAttributes, *PSecurityDescriptor, PSecurityDescriptorSize);
+ if (STATUS_BUFFER_OVERFLOW != Result)
+ return Result;
+
+ MemFree(*PSecurityDescriptor);
+ *PSecurityDescriptor = MemAlloc(*PSecurityDescriptorSize);
+ if (0 == *PSecurityDescriptor)
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+}
+
+FSP_API NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem,
+ FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
+ DWORD DesiredAccess, PDWORD PGrantedAccess)
+{
+ if (0 == FileSystem->Interface->GetSecurity)
+ {
+ *PGrantedAccess = DesiredAccess;
+ return STATUS_SUCCESS;
+ }
+
+ NTSTATUS Result;
+ PWSTR Parent, Suffix, Prefix, Remain;
+ DWORD FileAttributes;
+ PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
+ SIZE_T SecurityDescriptorSize;
+ DWORD PrivilegeSetLength;
+ DWORD TraverseAccess;
+ BOOL AccessStatus;
+
+ *PGrantedAccess = 0;
+
+ if (CheckParentDirectory)
+ FspPathSuffix((PWSTR)Request->Buffer, &Parent, &Suffix);
+
+ SecurityDescriptorSize = 1024;
+ SecurityDescriptor = MemAlloc(SecurityDescriptorSize);
+ if (0 == SecurityDescriptor)
+ {
+ Result = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit;
+ }
+
+ if (AllowTraverseCheck && !Request->Req.Create.HasTraversePrivilege)
+ {
+ Remain = (PWSTR)Request->Buffer;
+ for (;;)
+ {
+ FspPathPrefix(Remain, &Prefix, &Remain);
+ if (L'\0' == Remain[0])
+ {
+ FspPathCombine((PWSTR)Request->Buffer, Remain);
+ break;
+ }
+
+ Prefix = L'\0' == Prefix[0] ? L"\\" : (PWSTR)Request->Buffer;
+ Result = FspGetSecurity(FileSystem, Prefix, 0,
+ &SecurityDescriptor, &SecurityDescriptorSize);
+
+ FspPathCombine((PWSTR)Request->Buffer, Remain);
+
+ if (!NT_SUCCESS(Result))
+ {
+ if (STATUS_OBJECT_NAME_NOT_FOUND == Result)
+ Result = STATUS_OBJECT_PATH_NOT_FOUND;
+ goto exit;
+ }
+
+ if (AccessCheck(SecurityDescriptor, (HANDLE)Request->Req.Create.AccessToken, FILE_TRAVERSE,
+ &FspFileGenericMapping, 0, &PrivilegeSetLength, &TraverseAccess, &AccessStatus))
+ Result = AccessStatus ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
+ else
+ Result = FspNtStatusFromWin32(GetLastError());
+
+ if (!NT_SUCCESS(Result))
+ goto exit;
+ }
+ }
+
+ Result = FspGetSecurity(FileSystem, (PWSTR)Request->Buffer, &FileAttributes,
+ &SecurityDescriptor, &SecurityDescriptorSize);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ if (AccessCheck(SecurityDescriptor, (HANDLE)Request->Req.Create.AccessToken, DesiredAccess,
+ &FspFileGenericMapping, 0, &PrivilegeSetLength, PGrantedAccess, &AccessStatus))
+ Result = AccessStatus ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
+ else
+ Result = FspNtStatusFromWin32(GetLastError());
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ if (CheckParentDirectory)
+ {
+ if (0 == (FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ Result = STATUS_NOT_A_DIRECTORY;
+ goto exit;
+ }
+ }
+ else
+ {
+ if ((Request->Req.Create.CreateOptions & FILE_DIRECTORY_FILE) &&
+ 0 == (FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ Result = STATUS_NOT_A_DIRECTORY;
+ goto exit;
+ }
+ if ((Request->Req.Create.CreateOptions & FILE_NON_DIRECTORY_FILE) &&
+ 0 != (FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ Result = STATUS_FILE_IS_A_DIRECTORY;
+ goto exit;
+ }
+ }
+
+ if (0 != (FileAttributes & FILE_ATTRIBUTE_READONLY))
+ {
+ if (DesiredAccess &
+ (FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD))
+ {
+ Result = STATUS_ACCESS_DENIED;
+ goto exit;
+ }
+ if (Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE)
+ {
+ Result = STATUS_CANNOT_DELETE;
+ goto exit;
+ }
+ }
+
+exit:
+ MemFree(SecurityDescriptor);
+
+ if (CheckParentDirectory)
+ FspPathCombine((PWSTR)Request->Buffer, Suffix);
+
+ return Result;
+}
+
+FSP_API NTSTATUS FspShareCheck(FSP_FILE_SYSTEM *FileSystem,
+ FSP_FSCTL_TRANSACT_REQ *Request, DWORD GrantedAccess, FSP_FILE_NODE *FileNode)
+{
+ DWORD ShareAccess = Request->Req.Create.ShareAccess;
+ BOOLEAN ReadAccess, WriteAccess, DeleteAccess;
+ BOOLEAN SharedRead, SharedWrite, SharedDelete;
+ ULONG OpenCount;
+
+ ReadAccess = 0 != (GrantedAccess & (FILE_READ_DATA | FILE_EXECUTE));
+ WriteAccess = 0 != (GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA));
+ DeleteAccess = 0 != (GrantedAccess & DELETE);
+
+ if (ReadAccess || WriteAccess || DeleteAccess)
+ {
+ SharedRead = 0 != (ShareAccess & FILE_SHARE_READ);
+ SharedWrite = 0 != (ShareAccess & FILE_SHARE_WRITE);
+ SharedDelete = 0 != (ShareAccess & FILE_SHARE_DELETE);
+
+ OpenCount = FileNode->ShareAccess.OpenCount;
+
+ /*
+ * IF ReadAccess AND there are already some exclusive readers
+ * OR WriteAccess AND there are already some exclusive writers
+ * OR DeleteAccess AND there are already some exclusive deleters
+ * OR exclusive read requested AND there are already some readers
+ * OR exclusive write requested AND there are already some writers
+ * OR exclusive delete requested AND there are already some deleters
+ */
+ if (ReadAccess && (FileNode->ShareAccess.SharedRead < OpenCount))
+ return STATUS_SHARING_VIOLATION;
+ if (WriteAccess && (FileNode->ShareAccess.SharedWrite < OpenCount))
+ return STATUS_SHARING_VIOLATION;
+ if (DeleteAccess && (FileNode->ShareAccess.SharedDelete < OpenCount))
+ return STATUS_SHARING_VIOLATION;
+ if (!SharedRead && 0 != FileNode->ShareAccess.Readers)
+ return STATUS_SHARING_VIOLATION;
+ if (!SharedWrite && 0 != FileNode->ShareAccess.Writers)
+ return STATUS_SHARING_VIOLATION;
+ if (!SharedDelete && 0 != FileNode->ShareAccess.Deleters)
+ return STATUS_SHARING_VIOLATION;
+
+ FileNode->ShareAccess.OpenCount++;
+ FileNode->ShareAccess.Readers += ReadAccess;
+ FileNode->ShareAccess.Writers += WriteAccess;
+ FileNode->ShareAccess.Deleters += DeleteAccess;
+ FileNode->ShareAccess.SharedRead += SharedRead;
+ FileNode->ShareAccess.SharedWrite += SharedWrite;
+ FileNode->ShareAccess.SharedDelete += SharedDelete;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+FSP_API NTSTATUS FspFileSystemPreCreateCheck(FSP_FILE_SYSTEM *FileSystem,
+ FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN AllowTraverseCheck, PDWORD PGrantedAccess)
{
NTSTATUS Result;
@@ -33,17 +235,73 @@ NTSTATUS FspCreateCheck(FSP_FILE_SYSTEM *FileSystem,
return Result;
}
+FSP_API VOID FspFileSystemPostCreateCheck(FSP_FILE_SYSTEM *FileSystem,
+ FSP_FSCTL_TRANSACT_REQ *Request, DWORD GrantedAccess, FSP_FILE_NODE *FileNode)
+{
+ memset(&FileNode->Flags, 0, sizeof FileNode->Flags);
+ memset(&FileNode->ShareAccess, 0, sizeof FileNode->ShareAccess);
+
+ FspShareCheck(FileSystem, Request, GrantedAccess, FileNode);
+}
+
+FSP_API NTSTATUS FspFileSystemPreOpenCheck(FSP_FILE_SYSTEM *FileSystem,
+ FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN AllowTraverseCheck, PDWORD PGrantedAccess)
+{
+ return FspAccessCheck(FileSystem, Request, FALSE, AllowTraverseCheck,
+ Request->Req.Create.DesiredAccess, PGrantedAccess);
+}
+
+FSP_API NTSTATUS FspFileSystemPostOpenCheck(FSP_FILE_SYSTEM *FileSystem,
+ FSP_FSCTL_TRANSACT_REQ *Request, DWORD GrantedAccess, FSP_FILE_NODE *FileNode)
+{
+ return FspShareCheck(FileSystem, Request, GrantedAccess, FileNode);
+}
+
+FSP_API NTSTATUS FspFileSystemPreOverwriteCheck(FSP_FILE_SYSTEM *FileSystem,
+ FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN AllowTraverseCheck, PDWORD PGrantedAccess)
+{
+ NTSTATUS Result;
+ BOOLEAN Supersede = FILE_SUPERSEDE == ((Request->Req.Create.CreateOptions >> 24) & 0xff);
+
+ Result = FspAccessCheck(FileSystem, Request, FALSE, AllowTraverseCheck,
+ Request->Req.Create.DesiredAccess | (Supersede ? DELETE : FILE_WRITE_DATA),
+ PGrantedAccess);
+ if (NT_SUCCESS(Result))
+ {
+ if (0 == (Request->Req.Create.DesiredAccess & MAXIMUM_ALLOWED))
+ *PGrantedAccess &= Supersede ?
+ (~DELETE | (Request->Req.Create.DesiredAccess & DELETE)) :
+ (~FILE_WRITE_DATA | (Request->Req.Create.DesiredAccess & FILE_WRITE_DATA));
+ }
+
+ return Result;
+}
+
+FSP_API NTSTATUS FspFileSystemPostOverwriteCheck(FSP_FILE_SYSTEM *FileSystem,
+ FSP_FSCTL_TRANSACT_REQ *Request, DWORD GrantedAccess, FSP_FILE_NODE *FileNode)
+{
+ return FspShareCheck(FileSystem, Request, GrantedAccess, FileNode);
+}
+
+static BOOLEAN FspIsRootDirectory(PWSTR FileName)
+{
+ for (PWSTR Pointer = FileName; *Pointer; Pointer++)
+ if (L'\\' != *Pointer)
+ return FALSE;
+ return TRUE;
+}
+
static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request)
{
- if (FspIsRootDirectory((PWSTR)Request->Buffer))
- return STATUS_ACCESS_DENIED;
-
NTSTATUS Result;
DWORD GrantedAccess;
FSP_FILE_NODE *FileNode;
- Result = FspCreateCheck(FileSystem, Request, TRUE, &GrantedAccess);
+ if (FspIsRootDirectory((PWSTR)Request->Buffer))
+ return STATUS_ACCESS_DENIED;
+
+ Result = FspFileSystemPreCreateCheck(FileSystem, Request, TRUE, &GrantedAccess);
if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
@@ -51,10 +309,7 @@ static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem,
if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
- memset(&FileNode->Flags, 0, sizeof FileNode->Flags);
- memset(&FileNode->ShareAccess, 0, sizeof FileNode->ShareAccess);
-
- FspShareCheck(FileSystem, GrantedAccess, Request->Req.Create.ShareAccess, FileNode);
+ FspFileSystemPostCreateCheck(FileSystem, Request, GrantedAccess, FileNode);
return FspFileSystemSendCreateResponse(FileSystem, Request,
FILE_CREATED, FileNode, GrantedAccess);
@@ -67,8 +322,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpen(FSP_FILE_SYSTEM *FileSystem,
DWORD GrantedAccess;
FSP_FILE_NODE *FileNode;
- Result = FspAccessCheck(FileSystem, Request, FALSE, TRUE,
- Request->Req.Create.DesiredAccess, &GrantedAccess);
+ Result = FspFileSystemPreOpenCheck(FileSystem, Request, TRUE, &GrantedAccess);
if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
@@ -76,7 +330,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpen(FSP_FILE_SYSTEM *FileSystem,
if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
- Result = FspShareCheck(FileSystem, GrantedAccess, Request->Req.Create.ShareAccess, FileNode);
+ Result = FspFileSystemPostOpenCheck(FileSystem, Request, GrantedAccess, FileNode);
if (!NT_SUCCESS(Result))
{
if (0 != FileSystem->Interface->Close)
@@ -96,8 +350,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
FSP_FILE_NODE *FileNode;
BOOLEAN Create = FALSE;
- Result = FspAccessCheck(FileSystem, Request, FALSE, TRUE,
- Request->Req.Create.DesiredAccess, &GrantedAccess);
+ Result = FspFileSystemPreOpenCheck(FileSystem, Request, TRUE, &GrantedAccess);
if (!NT_SUCCESS(Result))
{
if (STATUS_OBJECT_NAME_NOT_FOUND != Result)
@@ -114,6 +367,16 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
Create = TRUE;
}
+ else
+ {
+ Result = FspFileSystemPostOpenCheck(FileSystem, Request, GrantedAccess, FileNode);
+ if (!NT_SUCCESS(Result))
+ {
+ if (0 != FileSystem->Interface->Close)
+ FileSystem->Interface->Close(FileSystem, Request, FileNode);
+ return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
+ }
+ }
}
if (Create)
@@ -121,7 +384,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
if (FspIsRootDirectory((PWSTR)Request->Buffer))
return STATUS_ACCESS_DENIED;
- Result = FspCreateCheck(FileSystem, Request, FALSE, &GrantedAccess);
+ Result = FspFileSystemPreCreateCheck(FileSystem, Request, FALSE, &GrantedAccess);
if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
@@ -129,16 +392,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
- memset(&FileNode->Flags, 0, sizeof FileNode->Flags);
- memset(&FileNode->ShareAccess, 0, sizeof FileNode->ShareAccess);
- }
-
- Result = FspShareCheck(FileSystem, GrantedAccess, Request->Req.Create.ShareAccess, FileNode);
- if (!NT_SUCCESS(Result))
- {
- if (0 != FileSystem->Interface->Close)
- FileSystem->Interface->Close(FileSystem, Request, FileNode);
- return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
+ FspFileSystemPostCreateCheck(FileSystem, Request, GrantedAccess, FileNode);
}
return FspFileSystemSendCreateResponse(FileSystem, Request,
@@ -146,31 +400,25 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
}
static NTSTATUS FspFileSystemOpCreate_FileOverwrite(FSP_FILE_SYSTEM *FileSystem,
- FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN Supersede)
+ FSP_FSCTL_TRANSACT_REQ *Request)
{
- if (FspIsRootDirectory((PWSTR)Request->Buffer))
- return STATUS_ACCESS_DENIED;
-
NTSTATUS Result;
DWORD GrantedAccess;
FSP_FILE_NODE *FileNode;
+ BOOLEAN Supersede = FILE_SUPERSEDE == ((Request->Req.Create.CreateOptions >> 24) & 0xff);
- Result = FspAccessCheck(FileSystem, Request, FALSE, TRUE,
- Request->Req.Create.DesiredAccess | (Supersede ? DELETE : FILE_WRITE_DATA),
- &GrantedAccess);
+ if (FspIsRootDirectory((PWSTR)Request->Buffer))
+ return STATUS_ACCESS_DENIED;
+
+ Result = FspFileSystemPreOverwriteCheck(FileSystem, Request, TRUE, &GrantedAccess);
if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
- if (0 == (Request->Req.Create.DesiredAccess & MAXIMUM_ALLOWED))
- GrantedAccess &= Supersede ?
- (~DELETE | (Request->Req.Create.DesiredAccess & DELETE)) :
- (~FILE_WRITE_DATA | (Request->Req.Create.DesiredAccess & FILE_WRITE_DATA));
-
Result = FileSystem->Interface->Open(FileSystem, Request, &FileNode);
if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
- Result = FspShareCheck(FileSystem, GrantedAccess, Request->Req.Create.ShareAccess, FileNode);
+ Result = FspFileSystemPostOverwriteCheck(FileSystem, Request, GrantedAccess, FileNode);
if (!NT_SUCCESS(Result))
{
if (0 != FileSystem->Interface->Close)
@@ -193,28 +441,21 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwrite(FSP_FILE_SYSTEM *FileSystem,
static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request)
{
- if (FspIsRootDirectory((PWSTR)Request->Buffer))
- return STATUS_ACCESS_DENIED;
-
NTSTATUS Result;
DWORD GrantedAccess;
FSP_FILE_NODE *FileNode;
BOOLEAN Create = FALSE;
- Result = FspAccessCheck(FileSystem, Request, FALSE, TRUE,
- Request->Req.Create.DesiredAccess | FILE_WRITE_DATA,
- &GrantedAccess);
+ if (FspIsRootDirectory((PWSTR)Request->Buffer))
+ return STATUS_ACCESS_DENIED;
+
+ Result = FspFileSystemPreOverwriteCheck(FileSystem, Request, TRUE, &GrantedAccess);
if (!NT_SUCCESS(Result))
{
if (STATUS_OBJECT_NAME_NOT_FOUND != Result)
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
Create = TRUE;
}
- else
- {
- if (0 == (Request->Req.Create.DesiredAccess & MAXIMUM_ALLOWED))
- GrantedAccess &= ~FILE_WRITE_DATA | (Request->Req.Create.DesiredAccess & FILE_WRITE_DATA);
- }
if (!Create)
{
@@ -225,11 +466,29 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
Create = TRUE;
}
+ else
+ {
+ Result = FspFileSystemPostOverwriteCheck(FileSystem, Request, GrantedAccess, FileNode);
+ if (!NT_SUCCESS(Result))
+ {
+ if (0 != FileSystem->Interface->Close)
+ FileSystem->Interface->Close(FileSystem, Request, FileNode);
+ return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
+ }
+
+ Result = FileSystem->Interface->Overwrite(FileSystem, Request, FALSE, FileNode);
+ if (!NT_SUCCESS(Result))
+ {
+ if (0 != FileSystem->Interface->Close)
+ FileSystem->Interface->Close(FileSystem, Request, FileNode);
+ return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
+ }
+ }
}
if (Create)
{
- Result = FspCreateCheck(FileSystem, Request, FALSE, &GrantedAccess);
+ Result = FspFileSystemPreCreateCheck(FileSystem, Request, FALSE, &GrantedAccess);
if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
@@ -237,27 +496,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
- memset(&FileNode->Flags, 0, sizeof FileNode->Flags);
- memset(&FileNode->ShareAccess, 0, sizeof FileNode->ShareAccess);
- }
-
- Result = FspShareCheck(FileSystem, GrantedAccess, Request->Req.Create.ShareAccess, FileNode);
- if (!NT_SUCCESS(Result))
- {
- if (0 != FileSystem->Interface->Close)
- FileSystem->Interface->Close(FileSystem, Request, FileNode);
- return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
- }
-
- if (!Create)
- {
- Result = FileSystem->Interface->Overwrite(FileSystem, Request, FALSE, FileNode);
- if (!NT_SUCCESS(Result))
- {
- if (0 != FileSystem->Interface->Close)
- FileSystem->Interface->Close(FileSystem, Request, FileNode);
- return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
- }
+ FspFileSystemPostCreateCheck(FileSystem, Request, GrantedAccess, FileNode);
}
return FspFileSystemSendCreateResponse(FileSystem, Request,
@@ -267,15 +506,15 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
static NTSTATUS FspFileSystemOpCreate_FileOpenTargetDirectory(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request)
{
- if (FspIsRootDirectory((PWSTR)Request->Buffer))
- return STATUS_ACCESS_DENIED;
-
NTSTATUS Result;
PWSTR Parent, Suffix;
DWORD GrantedAccess;
FSP_FILE_NODE *FileNode;
UINT_PTR Information;
+ if (FspIsRootDirectory((PWSTR)Request->Buffer))
+ return STATUS_ACCESS_DENIED;
+
Result = FspAccessCheck(FileSystem, Request, TRUE, TRUE,
Request->Req.Create.DesiredAccess, &GrantedAccess);
if (!NT_SUCCESS(Result))
@@ -287,7 +526,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenTargetDirectory(FSP_FILE_SYSTEM *F
if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
- Result = FspShareCheck(FileSystem, GrantedAccess, Request->Req.Create.ShareAccess, FileNode);
+ Result = FspFileSystemPostOpenCheck(FileSystem, Request, GrantedAccess, FileNode);
if (!NT_SUCCESS(Result))
{
if (0 != FileSystem->Interface->Close)
@@ -326,9 +565,9 @@ FSP_API NTSTATUS FspFileSystemOpCreate(FSP_FILE_SYSTEM *FileSystem,
case FILE_OPEN_IF:
return FspFileSystemOpCreate_FileOpenIf(FileSystem, Request);
case FILE_OVERWRITE:
- return FspFileSystemOpCreate_FileOverwrite(FileSystem, Request, FALSE);
+ return FspFileSystemOpCreate_FileOverwrite(FileSystem, Request);
case FILE_SUPERSEDE:
- return FspFileSystemOpCreate_FileOverwrite(FileSystem, Request, TRUE);
+ return FspFileSystemOpCreate_FileOverwrite(FileSystem, Request);
case FILE_OVERWRITE_IF:
return FspFileSystemOpCreate_FileOverwriteIf(FileSystem, Request);
default: