mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
sys, dll: extended attributes: checkpoint
This commit is contained in:
parent
778f5f70dc
commit
a811cd2cf8
@ -152,7 +152,7 @@ enum
|
|||||||
UINT32 ReparsePointsAccessCheck:1; /* file system performs reparse point access checks */\
|
UINT32 ReparsePointsAccessCheck:1; /* file system performs reparse point access checks */\
|
||||||
UINT32 NamedStreams:1; /* file system supports named streams */\
|
UINT32 NamedStreams:1; /* file system supports named streams */\
|
||||||
UINT32 HardLinks:1; /* unimplemented; set to 0 */\
|
UINT32 HardLinks:1; /* unimplemented; set to 0 */\
|
||||||
UINT32 ExtendedAttributes:1; /* unimplemented; set to 0 */\
|
UINT32 ExtendedAttributes:1; /* file system supports extended attributes */\
|
||||||
UINT32 ReadOnlyVolume:1;\
|
UINT32 ReadOnlyVolume:1;\
|
||||||
/* kernel-mode flags */\
|
/* kernel-mode flags */\
|
||||||
UINT32 PostCleanupWhenModifiedOnly:1; /* post Cleanup when a file was modified/deleted */\
|
UINT32 PostCleanupWhenModifiedOnly:1; /* post Cleanup when a file was modified/deleted */\
|
||||||
@ -167,6 +167,7 @@ enum
|
|||||||
UINT32 UmReservedFlags:6;\
|
UINT32 UmReservedFlags:6;\
|
||||||
/* additional kernel-mode flags */\
|
/* additional kernel-mode flags */\
|
||||||
UINT32 AllowOpenInKernelMode:1; /* allow kernel mode to open files when possible */\
|
UINT32 AllowOpenInKernelMode:1; /* allow kernel mode to open files when possible */\
|
||||||
|
UINT32 CasePreservedExtendedAttributes:1; /* preserve case of EA (default is UPPERCASE) */\
|
||||||
UINT32 KmReservedFlags:7;\
|
UINT32 KmReservedFlags:7;\
|
||||||
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */\
|
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */\
|
||||||
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
|
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
|
||||||
@ -176,12 +177,14 @@ enum
|
|||||||
UINT32 DirInfoTimeoutValid:1; /* DirInfoTimeout field is valid */\
|
UINT32 DirInfoTimeoutValid:1; /* DirInfoTimeout field is valid */\
|
||||||
UINT32 SecurityTimeoutValid:1; /* SecurityTimeout field is valid*/\
|
UINT32 SecurityTimeoutValid:1; /* SecurityTimeout field is valid*/\
|
||||||
UINT32 StreamInfoTimeoutValid:1; /* StreamInfoTimeout field is valid */\
|
UINT32 StreamInfoTimeoutValid:1; /* StreamInfoTimeout field is valid */\
|
||||||
|
UINT32 EaTimeoutValid:1; /* EaTimeout field is valid */\
|
||||||
UINT32 KmAdditionalReservedFlags:28;\
|
UINT32 KmAdditionalReservedFlags:28;\
|
||||||
UINT32 VolumeInfoTimeout; /* volume info timeout (millis); overrides FileInfoTimeout */\
|
UINT32 VolumeInfoTimeout; /* volume info timeout (millis); overrides FileInfoTimeout */\
|
||||||
UINT32 DirInfoTimeout; /* dir info timeout (millis); overrides FileInfoTimeout */\
|
UINT32 DirInfoTimeout; /* dir info timeout (millis); overrides FileInfoTimeout */\
|
||||||
UINT32 SecurityTimeout; /* security info timeout (millis); overrides FileInfoTimeout */\
|
UINT32 SecurityTimeout; /* security info timeout (millis); overrides FileInfoTimeout */\
|
||||||
UINT32 StreamInfoTimeout; /* stream info timeout (millis); overrides FileInfoTimeout */\
|
UINT32 StreamInfoTimeout; /* stream info timeout (millis); overrides FileInfoTimeout */\
|
||||||
UINT32 Reserved32[3];\
|
UINT32 EaTimeout; /* EA timeout (millis); overrides FileInfoTimeout */\
|
||||||
|
UINT32 Reserved32[2];\
|
||||||
UINT64 Reserved64[2];
|
UINT64 Reserved64[2];
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -261,7 +264,7 @@ typedef struct
|
|||||||
UINT32 DesiredAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */
|
UINT32 DesiredAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */
|
||||||
UINT32 GrantedAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */
|
UINT32 GrantedAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */
|
||||||
UINT32 ShareAccess; /* FILE_SHARE_{READ,WRITE,DELETE} */
|
UINT32 ShareAccess; /* FILE_SHARE_{READ,WRITE,DELETE} */
|
||||||
FSP_FSCTL_TRANSACT_BUF Ea; /* reserved; not currently implemented */
|
FSP_FSCTL_TRANSACT_BUF Ea; /* extended attributes buffer */
|
||||||
UINT32 UserMode:1; /* request originated in user mode */
|
UINT32 UserMode:1; /* request originated in user mode */
|
||||||
UINT32 HasTraversePrivilege:1; /* requestor has TOKEN_HAS_TRAVERSE_PRIVILEGE */
|
UINT32 HasTraversePrivilege:1; /* requestor has TOKEN_HAS_TRAVERSE_PRIVILEGE */
|
||||||
UINT32 HasBackupPrivilege:1; /* requestor has TOKEN_HAS_BACKUP_PRIVILEGE */
|
UINT32 HasBackupPrivilege:1; /* requestor has TOKEN_HAS_BACKUP_PRIVILEGE */
|
||||||
@ -280,6 +283,7 @@ typedef struct
|
|||||||
UINT32 FileAttributes; /* file attributes for overwritten/superseded files */
|
UINT32 FileAttributes; /* file attributes for overwritten/superseded files */
|
||||||
UINT64 AllocationSize; /* allocation size for overwritten/superseded files */
|
UINT64 AllocationSize; /* allocation size for overwritten/superseded files */
|
||||||
UINT32 Supersede:1; /* 0: FILE_OVERWRITE operation, 1: FILE_SUPERSEDE operation */
|
UINT32 Supersede:1; /* 0: FILE_OVERWRITE operation, 1: FILE_SUPERSEDE operation */
|
||||||
|
FSP_FSCTL_TRANSACT_BUF Ea; /* extended attributes buffer */
|
||||||
} Overwrite;
|
} Overwrite;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@ -356,6 +360,17 @@ typedef struct
|
|||||||
} Info;
|
} Info;
|
||||||
} SetInformation;
|
} SetInformation;
|
||||||
struct
|
struct
|
||||||
|
{
|
||||||
|
UINT64 UserContext;
|
||||||
|
UINT64 UserContext2;
|
||||||
|
} QueryEa;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
UINT64 UserContext;
|
||||||
|
UINT64 UserContext2;
|
||||||
|
FSP_FSCTL_TRANSACT_BUF Ea;
|
||||||
|
} SetEa;
|
||||||
|
struct
|
||||||
{
|
{
|
||||||
UINT64 UserContext;
|
UINT64 UserContext;
|
||||||
UINT64 UserContext2;
|
UINT64 UserContext2;
|
||||||
@ -470,6 +485,14 @@ typedef struct
|
|||||||
FSP_FSCTL_FILE_INFO FileInfo; /* valid: File{Allocation,Basic,EndOfFile}Information */
|
FSP_FSCTL_FILE_INFO FileInfo; /* valid: File{Allocation,Basic,EndOfFile}Information */
|
||||||
} SetInformation;
|
} SetInformation;
|
||||||
struct
|
struct
|
||||||
|
{
|
||||||
|
FSP_FSCTL_TRANSACT_BUF Ea;
|
||||||
|
} QueryEa;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
FSP_FSCTL_TRANSACT_BUF Ea; /* Size==0 means no extended atttributed returned */
|
||||||
|
} SetEa;
|
||||||
|
struct
|
||||||
{
|
{
|
||||||
FSP_FSCTL_FILE_INFO FileInfo; /* valid when flushing file (not volume) */
|
FSP_FSCTL_FILE_INFO FileInfo; /* valid when flushing file (not volume) */
|
||||||
} FlushBuffers;
|
} FlushBuffers;
|
||||||
|
@ -85,6 +85,18 @@ typedef struct _REPARSE_DATA_BUFFER
|
|||||||
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
|
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The FILE_FULL_EA_INFORMATION definitions are missing from the user mode headers.
|
||||||
|
*/
|
||||||
|
typedef struct _FILE_FULL_EA_INFORMATION
|
||||||
|
{
|
||||||
|
ULONG NextEntryOffset;
|
||||||
|
UCHAR Flags;
|
||||||
|
UCHAR EaNameLength;
|
||||||
|
USHORT EaValueLength;
|
||||||
|
CHAR EaName[1];
|
||||||
|
} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group File System
|
* @group File System
|
||||||
*
|
*
|
||||||
@ -894,12 +906,131 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
*/
|
*/
|
||||||
NTSTATUS (*SetDelete)(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS (*SetDelete)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileContext, PWSTR FileName, BOOLEAN DeleteFile);
|
PVOID FileContext, PWSTR FileName, BOOLEAN DeleteFile);
|
||||||
|
/**
|
||||||
|
* Create new file or directory.
|
||||||
|
*
|
||||||
|
* This function works like Create, except that it also accepts EA (extended attributes).
|
||||||
|
*
|
||||||
|
* NOTE: If both Create and CreateEx are defined, CreateEx takes precedence.
|
||||||
|
*
|
||||||
|
* @param FileSystem
|
||||||
|
* The file system on which this request is posted.
|
||||||
|
* @param FileName
|
||||||
|
* The name of the file or directory to be created.
|
||||||
|
* @param CreateOptions
|
||||||
|
* Create options for this request. This parameter has the same meaning as the
|
||||||
|
* CreateOptions parameter of the NtCreateFile API. User mode file systems should typically
|
||||||
|
* only be concerned with the flag FILE_DIRECTORY_FILE, which is an instruction to create a
|
||||||
|
* directory rather than a file. Some file systems may also want to pay attention to the
|
||||||
|
* FILE_NO_INTERMEDIATE_BUFFERING and FILE_WRITE_THROUGH flags, although these are
|
||||||
|
* typically handled by the FSD component.
|
||||||
|
* @param GrantedAccess
|
||||||
|
* Determines the specific access rights that have been granted for this request. Upon
|
||||||
|
* receiving this call all access checks have been performed and the user mode file system
|
||||||
|
* need not perform any additional checks. However this parameter may be useful to a user
|
||||||
|
* mode file system; for example the WinFsp-FUSE layer uses this parameter to determine
|
||||||
|
* which flags to use in its POSIX open() call.
|
||||||
|
* @param FileAttributes
|
||||||
|
* File attributes to apply to the newly created file or directory.
|
||||||
|
* @param SecurityDescriptor
|
||||||
|
* Security descriptor to apply to the newly created file or directory. This security
|
||||||
|
* descriptor will always be in self-relative format. Its length can be retrieved using the
|
||||||
|
* Windows GetSecurityDescriptorLength API. Will be NULL for named streams.
|
||||||
|
* @param AllocationSize
|
||||||
|
* Allocation size for the newly created file.
|
||||||
|
* @param Ea
|
||||||
|
* Extended attributes buffer.
|
||||||
|
* @param EaLength
|
||||||
|
* Extended attributes buffer length.
|
||||||
|
* @param PFileContext [out]
|
||||||
|
* Pointer that will receive the file context on successful return from this call.
|
||||||
|
* @param FileInfo [out]
|
||||||
|
* Pointer to a structure that will receive the file information on successful return
|
||||||
|
* from this call. This information includes file attributes, file times, etc.
|
||||||
|
* @return
|
||||||
|
* STATUS_SUCCESS or error code.
|
||||||
|
*/
|
||||||
|
NTSTATUS (*CreateEx)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
|
||||||
|
UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize,
|
||||||
|
PFILE_FULL_EA_INFORMATION Ea, SIZE_T EaLength,
|
||||||
|
PVOID *PFileContext, FSP_FSCTL_FILE_INFO *FileInfo);
|
||||||
|
/**
|
||||||
|
* Overwrite a file.
|
||||||
|
*
|
||||||
|
* This function works like Overwrite, except that it also accepts EA (extended attributes).
|
||||||
|
*
|
||||||
|
* NOTE: If both Overwrite and OverwriteEx are defined, OverwriteEx takes precedence.
|
||||||
|
*
|
||||||
|
* @param FileSystem
|
||||||
|
* The file system on which this request is posted.
|
||||||
|
* @param FileContext
|
||||||
|
* The file context of the file to overwrite.
|
||||||
|
* @param FileAttributes
|
||||||
|
* File attributes to apply to the overwritten file.
|
||||||
|
* @param ReplaceFileAttributes
|
||||||
|
* When TRUE the existing file attributes should be replaced with the new ones.
|
||||||
|
* When FALSE the existing file attributes should be merged (or'ed) with the new ones.
|
||||||
|
* @param AllocationSize
|
||||||
|
* Allocation size for the overwritten file.
|
||||||
|
* @param Ea
|
||||||
|
* Extended attributes buffer.
|
||||||
|
* @param EaLength
|
||||||
|
* Extended attributes buffer length.
|
||||||
|
* @param FileInfo [out]
|
||||||
|
* Pointer to a structure that will receive the file information on successful return
|
||||||
|
* from this call. This information includes file attributes, file times, etc.
|
||||||
|
* @return
|
||||||
|
* STATUS_SUCCESS or error code.
|
||||||
|
*/
|
||||||
|
NTSTATUS (*OverwriteEx)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
PVOID FileContext, UINT32 FileAttributes, BOOLEAN ReplaceFileAttributes, UINT64 AllocationSize,
|
||||||
|
PFILE_FULL_EA_INFORMATION Ea, SIZE_T EaLength,
|
||||||
|
FSP_FSCTL_FILE_INFO *FileInfo);
|
||||||
|
/**
|
||||||
|
* Get extended attributes.
|
||||||
|
*
|
||||||
|
* @param FileSystem
|
||||||
|
* The file system on which this request is posted.
|
||||||
|
* @param FileContext
|
||||||
|
* The file context of the file to get extended attributes for.
|
||||||
|
* @param Ea
|
||||||
|
* Extended attributes buffer.
|
||||||
|
* @param EaLength [in,out]
|
||||||
|
* Extended attributes buffer length.
|
||||||
|
* @return
|
||||||
|
* STATUS_SUCCESS or error code.
|
||||||
|
* @see
|
||||||
|
* SetEa
|
||||||
|
*/
|
||||||
|
NTSTATUS (*GetEa)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
PVOID FileContext,
|
||||||
|
PFILE_FULL_EA_INFORMATION Ea, PSIZE_T PEaLength);
|
||||||
|
/**
|
||||||
|
* Set extended attributes.
|
||||||
|
*
|
||||||
|
* @param FileSystem
|
||||||
|
* The file system on which this request is posted.
|
||||||
|
* @param FileContext
|
||||||
|
* The file context of the file to set extended attributes for.
|
||||||
|
* @param Ea
|
||||||
|
* Extended attributes buffer.
|
||||||
|
* @param EaLength
|
||||||
|
* Extended attributes buffer length.
|
||||||
|
* @return
|
||||||
|
* STATUS_SUCCESS or error code.
|
||||||
|
* @see
|
||||||
|
* GetEa
|
||||||
|
*/
|
||||||
|
NTSTATUS (*SetEa)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
PVOID FileContext,
|
||||||
|
PFILE_FULL_EA_INFORMATION Ea, SIZE_T EaLength);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This ensures that this interface will always contain 64 function pointers.
|
* This ensures that this interface will always contain 64 function pointers.
|
||||||
* Please update when changing the interface as it is important for future compatibility.
|
* Please update when changing the interface as it is important for future compatibility.
|
||||||
*/
|
*/
|
||||||
NTSTATUS (*Reserved[37])();
|
NTSTATUS (*Reserved[33])();
|
||||||
} FSP_FILE_SYSTEM_INTERFACE;
|
} FSP_FILE_SYSTEM_INTERFACE;
|
||||||
FSP_FSCTL_STATIC_ASSERT(sizeof(FSP_FILE_SYSTEM_INTERFACE) == 64 * sizeof(NTSTATUS (*)()),
|
FSP_FSCTL_STATIC_ASSERT(sizeof(FSP_FILE_SYSTEM_INTERFACE) == 64 * sizeof(NTSTATUS (*)()),
|
||||||
"FSP_FILE_SYSTEM_INTERFACE must have 64 entries.");
|
"FSP_FILE_SYSTEM_INTERFACE must have 64 entries.");
|
||||||
@ -1203,6 +1334,10 @@ FSP_API NTSTATUS FspFileSystemOpQueryInformation(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||||
FSP_API NTSTATUS FspFileSystemOpSetInformation(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspFileSystemOpSetInformation(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||||
|
FSP_API NTSTATUS FspFileSystemOpQueryEa(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||||
|
FSP_API NTSTATUS FspFileSystemOpSetEa(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||||
FSP_API NTSTATUS FspFileSystemOpFlushBuffers(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspFileSystemOpFlushBuffers(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||||
FSP_API NTSTATUS FspFileSystemOpQueryVolumeInformation(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspFileSystemOpQueryVolumeInformation(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
@ -161,6 +161,8 @@ FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath,
|
|||||||
FileSystem->Operations[FspFsctlTransactWriteKind] = FspFileSystemOpWrite;
|
FileSystem->Operations[FspFsctlTransactWriteKind] = FspFileSystemOpWrite;
|
||||||
FileSystem->Operations[FspFsctlTransactQueryInformationKind] = FspFileSystemOpQueryInformation;
|
FileSystem->Operations[FspFsctlTransactQueryInformationKind] = FspFileSystemOpQueryInformation;
|
||||||
FileSystem->Operations[FspFsctlTransactSetInformationKind] = FspFileSystemOpSetInformation;
|
FileSystem->Operations[FspFsctlTransactSetInformationKind] = FspFileSystemOpSetInformation;
|
||||||
|
FileSystem->Operations[FspFsctlTransactQueryEaKind] = FspFileSystemOpQueryEa;
|
||||||
|
FileSystem->Operations[FspFsctlTransactSetEaKind] = FspFileSystemOpSetEa;
|
||||||
FileSystem->Operations[FspFsctlTransactFlushBuffersKind] = FspFileSystemOpFlushBuffers;
|
FileSystem->Operations[FspFsctlTransactFlushBuffersKind] = FspFileSystemOpFlushBuffers;
|
||||||
FileSystem->Operations[FspFsctlTransactQueryVolumeInformationKind] = FspFileSystemOpQueryVolumeInformation;
|
FileSystem->Operations[FspFsctlTransactQueryVolumeInformationKind] = FspFileSystemOpQueryVolumeInformation;
|
||||||
FileSystem->Operations[FspFsctlTransactSetVolumeInformationKind] = FspFileSystemOpSetVolumeInformation;
|
FileSystem->Operations[FspFsctlTransactSetVolumeInformationKind] = FspFileSystemOpSetVolumeInformation;
|
||||||
|
@ -436,10 +436,19 @@ static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
memset(&OpenFileInfo, 0, sizeof OpenFileInfo);
|
memset(&OpenFileInfo, 0, sizeof OpenFileInfo);
|
||||||
OpenFileInfo.NormalizedName = (PVOID)Response->Buffer;
|
OpenFileInfo.NormalizedName = (PVOID)Response->Buffer;
|
||||||
OpenFileInfo.NormalizedNameSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
|
OpenFileInfo.NormalizedNameSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
|
||||||
Result = FileSystem->Interface->Create(FileSystem,
|
if (0 != FileSystem->Interface->CreateEx)
|
||||||
(PWSTR)Request->Buffer, Request->Req.Create.CreateOptions, GrantedAccess,
|
Result = FileSystem->Interface->CreateEx(FileSystem,
|
||||||
Request->Req.Create.FileAttributes, OpenDescriptor, Request->Req.Create.AllocationSize,
|
(PWSTR)Request->Buffer, Request->Req.Create.CreateOptions, GrantedAccess,
|
||||||
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
|
Request->Req.Create.FileAttributes, OpenDescriptor, Request->Req.Create.AllocationSize,
|
||||||
|
0 != Request->Req.Create.Ea.Size ?
|
||||||
|
(PVOID)(Request->Buffer + Request->Req.Create.Ea.Offset) : 0,
|
||||||
|
Request->Req.Create.Ea.Size,
|
||||||
|
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
|
||||||
|
else
|
||||||
|
Result = FileSystem->Interface->Create(FileSystem,
|
||||||
|
(PWSTR)Request->Buffer, Request->Req.Create.CreateOptions, GrantedAccess,
|
||||||
|
Request->Req.Create.FileAttributes, OpenDescriptor, Request->Req.Create.AllocationSize,
|
||||||
|
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
FspDeleteSecurityDescriptor(OpenDescriptor, FspCreateSecurityDescriptor);
|
FspDeleteSecurityDescriptor(OpenDescriptor, FspCreateSecurityDescriptor);
|
||||||
@ -574,10 +583,19 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
memset(&OpenFileInfo, 0, sizeof OpenFileInfo);
|
memset(&OpenFileInfo, 0, sizeof OpenFileInfo);
|
||||||
OpenFileInfo.NormalizedName = (PVOID)Response->Buffer;
|
OpenFileInfo.NormalizedName = (PVOID)Response->Buffer;
|
||||||
OpenFileInfo.NormalizedNameSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
|
OpenFileInfo.NormalizedNameSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
|
||||||
Result = FileSystem->Interface->Create(FileSystem,
|
if (0 != FileSystem->Interface->CreateEx)
|
||||||
(PWSTR)Request->Buffer, Request->Req.Create.CreateOptions, GrantedAccess,
|
Result = FileSystem->Interface->CreateEx(FileSystem,
|
||||||
Request->Req.Create.FileAttributes, OpenDescriptor, Request->Req.Create.AllocationSize,
|
(PWSTR)Request->Buffer, Request->Req.Create.CreateOptions, GrantedAccess,
|
||||||
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
|
Request->Req.Create.FileAttributes, OpenDescriptor, Request->Req.Create.AllocationSize,
|
||||||
|
0 != Request->Req.Create.Ea.Size ?
|
||||||
|
(PVOID)(Request->Buffer + Request->Req.Create.Ea.Offset) : 0,
|
||||||
|
Request->Req.Create.Ea.Size,
|
||||||
|
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
|
||||||
|
else
|
||||||
|
Result = FileSystem->Interface->Create(FileSystem,
|
||||||
|
(PWSTR)Request->Buffer, Request->Req.Create.CreateOptions, GrantedAccess,
|
||||||
|
Request->Req.Create.FileAttributes, OpenDescriptor, Request->Req.Create.AllocationSize,
|
||||||
|
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
FspDeleteSecurityDescriptor(OpenDescriptor, FspCreateSecurityDescriptor);
|
FspDeleteSecurityDescriptor(OpenDescriptor, FspCreateSecurityDescriptor);
|
||||||
@ -699,10 +717,19 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
|
|||||||
memset(&OpenFileInfo, 0, sizeof OpenFileInfo);
|
memset(&OpenFileInfo, 0, sizeof OpenFileInfo);
|
||||||
OpenFileInfo.NormalizedName = (PVOID)Response->Buffer;
|
OpenFileInfo.NormalizedName = (PVOID)Response->Buffer;
|
||||||
OpenFileInfo.NormalizedNameSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
|
OpenFileInfo.NormalizedNameSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
|
||||||
Result = FileSystem->Interface->Create(FileSystem,
|
if (0 != FileSystem->Interface->CreateEx)
|
||||||
(PWSTR)Request->Buffer, Request->Req.Create.CreateOptions, GrantedAccess,
|
Result = FileSystem->Interface->CreateEx(FileSystem,
|
||||||
Request->Req.Create.FileAttributes, ObjectDescriptor, Request->Req.Create.AllocationSize,
|
(PWSTR)Request->Buffer, Request->Req.Create.CreateOptions, GrantedAccess,
|
||||||
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
|
Request->Req.Create.FileAttributes, ObjectDescriptor, Request->Req.Create.AllocationSize,
|
||||||
|
0 != Request->Req.Create.Ea.Size ?
|
||||||
|
(PVOID)(Request->Buffer + Request->Req.Create.Ea.Offset) : 0,
|
||||||
|
Request->Req.Create.Ea.Size,
|
||||||
|
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
|
||||||
|
else
|
||||||
|
Result = FileSystem->Interface->Create(FileSystem,
|
||||||
|
(PWSTR)Request->Buffer, Request->Req.Create.CreateOptions, GrantedAccess,
|
||||||
|
Request->Req.Create.FileAttributes, ObjectDescriptor, Request->Req.Create.AllocationSize,
|
||||||
|
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
|
||||||
FspDeleteSecurityDescriptor(ObjectDescriptor, FspCreateSecurityDescriptor);
|
FspDeleteSecurityDescriptor(ObjectDescriptor, FspCreateSecurityDescriptor);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
@ -865,9 +892,9 @@ FSP_API NTSTATUS FspFileSystemOpCreate(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
{
|
{
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
if (0 == FileSystem->Interface->Create ||
|
if ((0 == FileSystem->Interface->Create && 0 == FileSystem->Interface->CreateEx) ||
|
||||||
0 == FileSystem->Interface->Open ||
|
0 == FileSystem->Interface->Open ||
|
||||||
0 == FileSystem->Interface->Overwrite)
|
(0 == FileSystem->Interface->Overwrite && 0 == FileSystem->Interface->OverwriteEx))
|
||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
|
||||||
if (Request->Req.Create.OpenTargetDirectory)
|
if (Request->Req.Create.OpenTargetDirectory)
|
||||||
@ -910,16 +937,27 @@ FSP_API NTSTATUS FspFileSystemOpOverwrite(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
FSP_FSCTL_FILE_INFO FileInfo;
|
FSP_FSCTL_FILE_INFO FileInfo;
|
||||||
|
|
||||||
if (0 == FileSystem->Interface->Overwrite)
|
if (0 == FileSystem->Interface->Overwrite && 0 == FileSystem->Interface->OverwriteEx)
|
||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
|
||||||
memset(&FileInfo, 0, sizeof FileInfo);
|
memset(&FileInfo, 0, sizeof FileInfo);
|
||||||
Result = FileSystem->Interface->Overwrite(FileSystem,
|
if (0 != FileSystem->Interface->OverwriteEx)
|
||||||
(PVOID)ValOfFileContext(Request->Req.Overwrite),
|
Result = FileSystem->Interface->OverwriteEx(FileSystem,
|
||||||
Request->Req.Overwrite.FileAttributes,
|
(PVOID)ValOfFileContext(Request->Req.Overwrite),
|
||||||
Request->Req.Overwrite.Supersede,
|
Request->Req.Overwrite.FileAttributes,
|
||||||
Request->Req.Overwrite.AllocationSize,
|
Request->Req.Overwrite.Supersede,
|
||||||
&FileInfo);
|
Request->Req.Overwrite.AllocationSize,
|
||||||
|
0 != Request->Req.Overwrite.Ea.Size ?
|
||||||
|
(PVOID)(Request->Buffer + Request->Req.Overwrite.Ea.Offset) : 0,
|
||||||
|
Request->Req.Overwrite.Ea.Size,
|
||||||
|
&FileInfo);
|
||||||
|
else
|
||||||
|
Result = FileSystem->Interface->Overwrite(FileSystem,
|
||||||
|
(PVOID)ValOfFileContext(Request->Req.Overwrite),
|
||||||
|
Request->Req.Overwrite.FileAttributes,
|
||||||
|
Request->Req.Overwrite.Supersede,
|
||||||
|
Request->Req.Overwrite.AllocationSize,
|
||||||
|
&FileInfo);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
if (0 != FileSystem->Interface->Close)
|
if (0 != FileSystem->Interface->Close)
|
||||||
@ -1145,6 +1183,18 @@ FSP_API NTSTATUS FspFileSystemOpSetInformation(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspFileSystemOpQueryEa(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspFileSystemOpSetEa(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspFileSystemOpQueryVolumeInformation(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspFileSystemOpQueryVolumeInformation(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||||
{
|
{
|
||||||
|
@ -278,7 +278,7 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
ACCESS_MASK GrantedAccess = AccessState->PreviouslyGrantedAccess;
|
ACCESS_MASK GrantedAccess = AccessState->PreviouslyGrantedAccess;
|
||||||
USHORT ShareAccess = IrpSp->Parameters.Create.ShareAccess;
|
USHORT ShareAccess = IrpSp->Parameters.Create.ShareAccess;
|
||||||
PFILE_FULL_EA_INFORMATION EaBuffer = Irp->AssociatedIrp.SystemBuffer;
|
PFILE_FULL_EA_INFORMATION EaBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
//ULONG EaLength = IrpSp->Parameters.Create.EaLength;
|
ULONG EaLength = IrpSp->Parameters.Create.EaLength;
|
||||||
ULONG Flags = IrpSp->Flags;
|
ULONG Flags = IrpSp->Flags;
|
||||||
KPROCESSOR_MODE RequestorMode =
|
KPROCESSOR_MODE RequestorMode =
|
||||||
FlagOn(Flags, SL_FORCE_ACCESS_CHECK) ? UserMode : Irp->RequestorMode;
|
FlagOn(Flags, SL_FORCE_ACCESS_CHECK) ? UserMode : Irp->RequestorMode;
|
||||||
@ -302,9 +302,23 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
if (FlagOn(CreateOptions, FILE_OPEN_BY_FILE_ID))
|
if (FlagOn(CreateOptions, FILE_OPEN_BY_FILE_ID))
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
/* no EA support currently */
|
/* was an EA buffer specified? */
|
||||||
if (0 != EaBuffer)
|
if (0 != EaBuffer)
|
||||||
return STATUS_EAS_NOT_SUPPORTED;
|
{
|
||||||
|
/* does the file system support EA? */
|
||||||
|
if (FsvolDeviceExtension->VolumeParams.ExtendedAttributes)
|
||||||
|
return STATUS_EAS_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
/* do we need EA knowledge? */
|
||||||
|
if (FlagOn(CreateOptions, FILE_NO_EA_KNOWLEDGE))
|
||||||
|
return STATUS_ACCESS_DENIED;
|
||||||
|
|
||||||
|
/* is the EA buffer valid? */
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Result = IoCheckEaBufferValidity(EaBuffer, EaLength, (PULONG)&Irp->IoStatus.Information);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
/* cannot open a paging file */
|
/* cannot open a paging file */
|
||||||
if (FlagOn(Flags, SL_OPEN_PAGING_FILE))
|
if (FlagOn(Flags, SL_OPEN_PAGING_FILE))
|
||||||
@ -541,6 +555,10 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
SecurityDescriptorSize = 0;
|
SecurityDescriptorSize = 0;
|
||||||
FileAttributes = 0;
|
FileAttributes = 0;
|
||||||
|
|
||||||
|
/* cannot set EA on named stream */
|
||||||
|
EaBuffer = 0;
|
||||||
|
EaLength = 0;
|
||||||
|
|
||||||
/* remember the main file node */
|
/* remember the main file node */
|
||||||
ASSERT(0 == FileNode->MainFileNode);
|
ASSERT(0 == FileNode->MainFileNode);
|
||||||
FileNode->MainFileNode = FileDesc->MainFileObject->FsContext;
|
FileNode->MainFileNode = FileDesc->MainFileObject->FsContext;
|
||||||
@ -558,7 +576,9 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* create the user-mode file system request */
|
/* create the user-mode file system request */
|
||||||
Result = FspIopCreateRequestEx(Irp, &FileNode->FileName, SecurityDescriptorSize,
|
Result = FspIopCreateRequestEx(Irp, &FileNode->FileName,
|
||||||
|
0 != EaBuffer ?
|
||||||
|
FSP_FSCTL_DEFAULT_ALIGN_UP(SecurityDescriptorSize) + EaLength : SecurityDescriptorSize,
|
||||||
FspFsvolCreateRequestFini, &Request);
|
FspFsvolCreateRequestFini, &Request);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
@ -584,19 +604,22 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
FspIopRequestContext(Request, RequestFileDesc) = FileDesc;
|
FspIopRequestContext(Request, RequestFileDesc) = FileDesc;
|
||||||
|
|
||||||
/* populate the Create request */
|
/* populate the Create request */
|
||||||
|
#define NEXTOFS(B) ((B).Offset + FSP_FSCTL_DEFAULT_ALIGN_UP((B).Size))
|
||||||
Request->Kind = FspFsctlTransactCreateKind;
|
Request->Kind = FspFsctlTransactCreateKind;
|
||||||
Request->Req.Create.CreateOptions = CreateOptions;
|
Request->Req.Create.CreateOptions = CreateOptions;
|
||||||
Request->Req.Create.FileAttributes = FileAttributes;
|
Request->Req.Create.FileAttributes = FileAttributes;
|
||||||
Request->Req.Create.SecurityDescriptor.Offset = 0 == SecurityDescriptorSize ? 0 :
|
Request->Req.Create.SecurityDescriptor.Offset = 0 != SecurityDescriptorSize ?
|
||||||
FSP_FSCTL_DEFAULT_ALIGN_UP(Request->FileName.Size);
|
NEXTOFS(Request->FileName) : 0;
|
||||||
Request->Req.Create.SecurityDescriptor.Size = (UINT16)SecurityDescriptorSize;
|
Request->Req.Create.SecurityDescriptor.Size = (UINT16)SecurityDescriptorSize;
|
||||||
Request->Req.Create.AllocationSize = AllocationSize;
|
Request->Req.Create.AllocationSize = AllocationSize;
|
||||||
Request->Req.Create.AccessToken = 0;
|
Request->Req.Create.AccessToken = 0;
|
||||||
Request->Req.Create.DesiredAccess = DesiredAccess;
|
Request->Req.Create.DesiredAccess = DesiredAccess;
|
||||||
Request->Req.Create.GrantedAccess = GrantedAccess;
|
Request->Req.Create.GrantedAccess = GrantedAccess;
|
||||||
Request->Req.Create.ShareAccess = ShareAccess;
|
Request->Req.Create.ShareAccess = ShareAccess;
|
||||||
Request->Req.Create.Ea.Offset = 0;
|
Request->Req.Create.Ea.Offset = 0 != EaBuffer ?
|
||||||
Request->Req.Create.Ea.Size = 0;
|
(0 != Request->Req.Create.SecurityDescriptor.Offset ?
|
||||||
|
NEXTOFS(Request->Req.Create.SecurityDescriptor) : NEXTOFS(Request->FileName)) : 0;
|
||||||
|
Request->Req.Create.Ea.Size = 0 != EaBuffer ? (UINT16)EaLength : 0;
|
||||||
Request->Req.Create.UserMode = UserMode == RequestorMode;
|
Request->Req.Create.UserMode = UserMode == RequestorMode;
|
||||||
Request->Req.Create.HasTraversePrivilege = HasTraversePrivilege;
|
Request->Req.Create.HasTraversePrivilege = HasTraversePrivilege;
|
||||||
Request->Req.Create.HasBackupPrivilege = HasBackupPrivilege;
|
Request->Req.Create.HasBackupPrivilege = HasBackupPrivilege;
|
||||||
@ -605,6 +628,7 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
Request->Req.Create.CaseSensitive = CaseSensitive;
|
Request->Req.Create.CaseSensitive = CaseSensitive;
|
||||||
Request->Req.Create.HasTrailingBackslash = HasTrailingBackslash;
|
Request->Req.Create.HasTrailingBackslash = HasTrailingBackslash;
|
||||||
Request->Req.Create.NamedStream = MainFileName.Length;
|
Request->Req.Create.NamedStream = MainFileName.Length;
|
||||||
|
#undef APPEND
|
||||||
|
|
||||||
Request->Req.Create.AcceptsSecurityDescriptor = 0 == Request->Req.Create.NamedStream &&
|
Request->Req.Create.AcceptsSecurityDescriptor = 0 == Request->Req.Create.NamedStream &&
|
||||||
!!FsvolDeviceExtension->VolumeParams.AllowOpenInKernelMode;
|
!!FsvolDeviceExtension->VolumeParams.AllowOpenInKernelMode;
|
||||||
@ -618,6 +642,11 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
RtlCopyMemory(Request->Buffer + Request->Req.Create.SecurityDescriptor.Offset,
|
RtlCopyMemory(Request->Buffer + Request->Req.Create.SecurityDescriptor.Offset,
|
||||||
SecurityDescriptor, SecurityDescriptorSize);
|
SecurityDescriptor, SecurityDescriptorSize);
|
||||||
|
|
||||||
|
/* copy the EA buffer (if any) into the request */
|
||||||
|
if (0 != EaBuffer)
|
||||||
|
RtlCopyMemory(Request->Buffer + Request->Req.Create.Ea.Offset,
|
||||||
|
EaBuffer, EaLength);
|
||||||
|
|
||||||
/* fix FileNode->FileName if we are doing SL_OPEN_TARGET_DIRECTORY */
|
/* fix FileNode->FileName if we are doing SL_OPEN_TARGET_DIRECTORY */
|
||||||
if (Request->Req.Create.OpenTargetDirectory)
|
if (Request->Req.Create.OpenTargetDirectory)
|
||||||
{
|
{
|
||||||
@ -1081,6 +1110,7 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
}
|
}
|
||||||
|
|
||||||
PVOID RequestDeviceObjectValue = FspIopRequestContext(Request, RequestDeviceObject);
|
PVOID RequestDeviceObjectValue = FspIopRequestContext(Request, RequestDeviceObject);
|
||||||
|
FSP_FSCTL_TRANSACT_BUF Ea = Request->Req.Create.Ea;
|
||||||
|
|
||||||
/* disassociate the FileDesc momentarily from the Request */
|
/* disassociate the FileDesc momentarily from the Request */
|
||||||
FspIopRequestContext(Request, RequestDeviceObject) = 0;
|
FspIopRequestContext(Request, RequestDeviceObject) = 0;
|
||||||
@ -1101,6 +1131,7 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
Request->Req.Overwrite.FileAttributes = FileAttributes;
|
Request->Req.Overwrite.FileAttributes = FileAttributes;
|
||||||
Request->Req.Overwrite.AllocationSize = AllocationSize;
|
Request->Req.Overwrite.AllocationSize = AllocationSize;
|
||||||
Request->Req.Overwrite.Supersede = FILE_SUPERSEDED == Response->IoStatus.Information;
|
Request->Req.Overwrite.Supersede = FILE_SUPERSEDED == Response->IoStatus.Information;
|
||||||
|
Request->Req.Overwrite.Ea = Ea;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Post it as BestEffort.
|
* Post it as BestEffort.
|
||||||
|
@ -317,7 +317,7 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
|||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
|
||||||
LARGE_INTEGER IrpTimeout;
|
LARGE_INTEGER IrpTimeout;
|
||||||
LARGE_INTEGER SecurityTimeout, DirInfoTimeout, StreamInfoTimeout;
|
LARGE_INTEGER SecurityTimeout, DirInfoTimeout, StreamInfoTimeout, EaTimeout;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Volume device initialization is a mess, because of the different ways of
|
* Volume device initialization is a mess, because of the different ways of
|
||||||
@ -379,6 +379,16 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
|||||||
return Result;
|
return Result;
|
||||||
FsvolDeviceExtension->InitDoneStrm = 1;
|
FsvolDeviceExtension->InitDoneStrm = 1;
|
||||||
|
|
||||||
|
/* create our EA meta cache */
|
||||||
|
EaTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.EaTimeout);
|
||||||
|
/* convert millis to nanos */
|
||||||
|
Result = FspMetaCacheCreate(
|
||||||
|
FspFsvolDeviceEaCacheCapacity, FspFsvolDeviceEaCacheItemSizeMax, &EaTimeout,
|
||||||
|
&FsvolDeviceExtension->EaCache);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
FsvolDeviceExtension->InitDoneEa = 1;
|
||||||
|
|
||||||
/* initialize the FSRTL Notify mechanism */
|
/* initialize the FSRTL Notify mechanism */
|
||||||
Result = FspNotifyInitializeSync(&FsvolDeviceExtension->NotifySync);
|
Result = FspNotifyInitializeSync(&FsvolDeviceExtension->NotifySync);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
@ -449,6 +459,10 @@ static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject)
|
|||||||
FspNotifyUninitializeSync(&FsvolDeviceExtension->NotifySync);
|
FspNotifyUninitializeSync(&FsvolDeviceExtension->NotifySync);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* delete the EA meta cache */
|
||||||
|
if (FsvolDeviceExtension->InitDoneEa)
|
||||||
|
FspMetaCacheDelete(FsvolDeviceExtension->EaCache);
|
||||||
|
|
||||||
/* delete the stream info meta cache */
|
/* delete the stream info meta cache */
|
||||||
if (FsvolDeviceExtension->InitDoneStrm)
|
if (FsvolDeviceExtension->InitDoneStrm)
|
||||||
FspMetaCacheDelete(FsvolDeviceExtension->StreamInfoCache);
|
FspMetaCacheDelete(FsvolDeviceExtension->StreamInfoCache);
|
||||||
|
@ -452,12 +452,17 @@ enum
|
|||||||
BOOLEAN FspFileNameIsValid(PUNICODE_STRING Path, ULONG MaxComponentLength,
|
BOOLEAN FspFileNameIsValid(PUNICODE_STRING Path, ULONG MaxComponentLength,
|
||||||
PUNICODE_STRING StreamPart, PULONG StreamType);
|
PUNICODE_STRING StreamPart, PULONG StreamType);
|
||||||
BOOLEAN FspFileNameIsValidPattern(PUNICODE_STRING Pattern, ULONG MaxComponentLength);
|
BOOLEAN FspFileNameIsValidPattern(PUNICODE_STRING Pattern, ULONG MaxComponentLength);
|
||||||
|
BOOLEAN FspEaNameIsValid(PSTRING Name);
|
||||||
VOID FspFileNameSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix);
|
VOID FspFileNameSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix);
|
||||||
#if 0
|
#if 0
|
||||||
NTSTATUS FspFileNameUpcase(
|
NTSTATUS FspFileNameUpcase(
|
||||||
PUNICODE_STRING DestinationName,
|
PUNICODE_STRING DestinationName,
|
||||||
PUNICODE_STRING SourceName,
|
PUNICODE_STRING SourceName,
|
||||||
PCWCH UpcaseTable);
|
PCWCH UpcaseTable);
|
||||||
|
VOID FspEaNameUpcase(
|
||||||
|
PSTRING DestinationName,
|
||||||
|
PSTRING SourceName,
|
||||||
|
PCWCH UpcaseTable);
|
||||||
LONG FspFileNameCompare(
|
LONG FspFileNameCompare(
|
||||||
PUNICODE_STRING Name1,
|
PUNICODE_STRING Name1,
|
||||||
PUNICODE_STRING Name2,
|
PUNICODE_STRING Name2,
|
||||||
@ -470,6 +475,7 @@ BOOLEAN FspFileNameIsPrefix(
|
|||||||
PCWCH UpcaseTable);
|
PCWCH UpcaseTable);
|
||||||
#else
|
#else
|
||||||
#define FspFileNameUpcase(D,S,U) (ASSERT(0 == (U)), RtlUpcaseUnicodeString(D,S,FALSE))
|
#define FspFileNameUpcase(D,S,U) (ASSERT(0 == (U)), RtlUpcaseUnicodeString(D,S,FALSE))
|
||||||
|
#define FspEaNameUpcase(D,S,U) (ASSERT(0 == (U)), RtlUpperString(D,S))
|
||||||
#define FspFileNameCompare(N1,N2,I,U) (ASSERT(0 == (U)), RtlCompareUnicodeString(N1,N2,I))
|
#define FspFileNameCompare(N1,N2,I,U) (ASSERT(0 == (U)), RtlCompareUnicodeString(N1,N2,I))
|
||||||
#define FspFileNameIsPrefix(N1,N2,I,U) (ASSERT(0 == (U)), RtlPrefixUnicodeString(N1,N2,I))
|
#define FspFileNameIsPrefix(N1,N2,I,U) (ASSERT(0 == (U)), RtlPrefixUnicodeString(N1,N2,I))
|
||||||
#endif
|
#endif
|
||||||
@ -997,6 +1003,8 @@ enum
|
|||||||
FspFsvolDeviceDirInfoCacheItemSizeMax = FSP_FSCTL_ALIGN_UP(16384, PAGE_SIZE),
|
FspFsvolDeviceDirInfoCacheItemSizeMax = FSP_FSCTL_ALIGN_UP(16384, PAGE_SIZE),
|
||||||
FspFsvolDeviceStreamInfoCacheCapacity = 100,
|
FspFsvolDeviceStreamInfoCacheCapacity = 100,
|
||||||
FspFsvolDeviceStreamInfoCacheItemSizeMax = FSP_FSCTL_ALIGN_UP(16384, PAGE_SIZE),
|
FspFsvolDeviceStreamInfoCacheItemSizeMax = FSP_FSCTL_ALIGN_UP(16384, PAGE_SIZE),
|
||||||
|
FspFsvolDeviceEaCacheCapacity = 100,
|
||||||
|
FspFsvolDeviceEaCacheItemSizeMax = FSP_FSCTL_ALIGN_UP(16384, PAGE_SIZE),
|
||||||
};
|
};
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -1029,7 +1037,7 @@ typedef struct
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
FSP_DEVICE_EXTENSION Base;
|
FSP_DEVICE_EXTENSION Base;
|
||||||
UINT32 InitDoneFsvrt:1, InitDoneIoq:1, InitDoneSec:1, InitDoneDir:1, InitDoneStrm:1,
|
UINT32 InitDoneFsvrt:1, InitDoneIoq:1, InitDoneSec:1, InitDoneDir:1, InitDoneStrm:1, InitDoneEa:1,
|
||||||
InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1, InitDoneNotify:1, InitDoneStat:1;
|
InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1, InitDoneNotify:1, InitDoneStat:1;
|
||||||
PDEVICE_OBJECT FsctlDeviceObject;
|
PDEVICE_OBJECT FsctlDeviceObject;
|
||||||
PDEVICE_OBJECT FsvrtDeviceObject;
|
PDEVICE_OBJECT FsvrtDeviceObject;
|
||||||
@ -1043,6 +1051,7 @@ typedef struct
|
|||||||
FSP_META_CACHE *SecurityCache;
|
FSP_META_CACHE *SecurityCache;
|
||||||
FSP_META_CACHE *DirInfoCache;
|
FSP_META_CACHE *DirInfoCache;
|
||||||
FSP_META_CACHE *StreamInfoCache;
|
FSP_META_CACHE *StreamInfoCache;
|
||||||
|
FSP_META_CACHE *EaCache;
|
||||||
KSPIN_LOCK ExpirationLock;
|
KSPIN_LOCK ExpirationLock;
|
||||||
WORK_QUEUE_ITEM ExpirationWorkItem;
|
WORK_QUEUE_ITEM ExpirationWorkItem;
|
||||||
BOOLEAN ExpirationInProgress;
|
BOOLEAN ExpirationInProgress;
|
||||||
@ -1271,6 +1280,8 @@ typedef struct FSP_FILE_NODE
|
|||||||
ULONG SecurityChangeNumber;
|
ULONG SecurityChangeNumber;
|
||||||
ULONG DirInfoChangeNumber;
|
ULONG DirInfoChangeNumber;
|
||||||
ULONG StreamInfoChangeNumber;
|
ULONG StreamInfoChangeNumber;
|
||||||
|
UINT64 Ea;
|
||||||
|
ULONG EaChangeNumber;
|
||||||
BOOLEAN TruncateOnClose;
|
BOOLEAN TruncateOnClose;
|
||||||
FILE_LOCK FileLock;
|
FILE_LOCK FileLock;
|
||||||
#if (NTDDI_VERSION < NTDDI_WIN8)
|
#if (NTDDI_VERSION < NTDDI_WIN8)
|
||||||
@ -1309,6 +1320,7 @@ typedef struct
|
|||||||
UNICODE_STRING DirectoryMarker;
|
UNICODE_STRING DirectoryMarker;
|
||||||
UINT64 DirInfo;
|
UINT64 DirInfo;
|
||||||
ULONG DirInfoCacheHint;
|
ULONG DirInfoCacheHint;
|
||||||
|
ULONG EaIndex;
|
||||||
/* stream support */
|
/* stream support */
|
||||||
HANDLE MainFileHandle;
|
HANDLE MainFileHandle;
|
||||||
PFILE_OBJECT MainFileObject;
|
PFILE_OBJECT MainFileObject;
|
||||||
@ -1439,6 +1451,17 @@ ULONG FspFileNodeStreamInfoChangeNumber(FSP_FILE_NODE *FileNode)
|
|||||||
return FileNode->StreamInfoChangeNumber;
|
return FileNode->StreamInfoChangeNumber;
|
||||||
}
|
}
|
||||||
VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode);
|
VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode);
|
||||||
|
BOOLEAN FspFileNodeReferenceEa(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize);
|
||||||
|
VOID FspFileNodeSetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size);
|
||||||
|
BOOLEAN FspFileNodeTrySetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
||||||
|
ULONG EaChangeNumber);
|
||||||
|
static inline
|
||||||
|
ULONG FspFileNodeEaChangeNumber(FSP_FILE_NODE *FileNode)
|
||||||
|
{
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
return FileNode->EaChangeNumber;
|
||||||
|
}
|
||||||
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action,
|
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action,
|
||||||
BOOLEAN InvalidateCaches);
|
BOOLEAN InvalidateCaches);
|
||||||
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
||||||
@ -1471,6 +1494,7 @@ NTSTATUS FspMainFileClose(
|
|||||||
#define FspFileNodeDereferenceSecurity(P) FspMetaCacheDereferenceItemBuffer(P)
|
#define FspFileNodeDereferenceSecurity(P) FspMetaCacheDereferenceItemBuffer(P)
|
||||||
#define FspFileNodeDereferenceDirInfo(P) FspMetaCacheDereferenceItemBuffer(P)
|
#define FspFileNodeDereferenceDirInfo(P) FspMetaCacheDereferenceItemBuffer(P)
|
||||||
#define FspFileNodeDereferenceStreamInfo(P) FspMetaCacheDereferenceItemBuffer(P)
|
#define FspFileNodeDereferenceStreamInfo(P) FspMetaCacheDereferenceItemBuffer(P)
|
||||||
|
#define FspFileNodeDereferenceEa(P) FspMetaCacheDereferenceItemBuffer(P)
|
||||||
#define FspFileNodeUnlockAll(N,F,P) FsRtlFastUnlockAll(&(N)->FileLock, F, P, N)
|
#define FspFileNodeUnlockAll(N,F,P) FsRtlFastUnlockAll(&(N)->FileLock, F, P, N)
|
||||||
#if (NTDDI_VERSION < NTDDI_WIN8)
|
#if (NTDDI_VERSION < NTDDI_WIN8)
|
||||||
#define FspFileNodeAddrOfOplock(N) (&(N)->Oplock)
|
#define FspFileNodeAddrOfOplock(N) (&(N)->Oplock)
|
||||||
|
539
src/sys/ea.c
539
src/sys/ea.c
@ -21,30 +21,359 @@
|
|||||||
|
|
||||||
#include <sys/driver.h>
|
#include <sys/driver.h>
|
||||||
|
|
||||||
|
static VOID FspFsvolQueryEaGetCopy(
|
||||||
|
BOOLEAN CasePreservedExtendedAttributes,
|
||||||
|
BOOLEAN ReturnSingleEntry,
|
||||||
|
PFILE_GET_EA_INFORMATION GetBufBgn, ULONG GetSize,
|
||||||
|
PFILE_FULL_EA_INFORMATION SrcBufBgn, ULONG SrcSize,
|
||||||
|
PFILE_FULL_EA_INFORMATION DstBufBgn, ULONG DstSize,
|
||||||
|
PIO_STATUS_BLOCK IoStatus);
|
||||||
|
static VOID FspFsvolQueryEaIndexCopy(
|
||||||
|
BOOLEAN CasePreservedExtendedAttributes,
|
||||||
|
BOOLEAN ReturnSingleEntry,
|
||||||
|
BOOLEAN IndexSpecified, PULONG PEaIndex,
|
||||||
|
PFILE_FULL_EA_INFORMATION SrcBufBgn, ULONG SrcSize,
|
||||||
|
PFILE_FULL_EA_INFORMATION DstBufBgn, ULONG DstSize,
|
||||||
|
PIO_STATUS_BLOCK IoStatus);
|
||||||
|
static VOID FspFsvolQueryEaCopy(
|
||||||
|
BOOLEAN CasePreservedExtendedAttributes,
|
||||||
|
PIO_STACK_LOCATION IrpSp,
|
||||||
|
PFILE_FULL_EA_INFORMATION SrcBufBgn, ULONG SrcSize,
|
||||||
|
PFILE_FULL_EA_INFORMATION DstBufBgn, ULONG DstSize,
|
||||||
|
PIO_STATUS_BLOCK IoStatus);
|
||||||
static NTSTATUS FspFsvolQueryEa(
|
static NTSTATUS FspFsvolQueryEa(
|
||||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
FSP_IOCMPL_DISPATCH FspFsvolQueryEaComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolQueryEaComplete;
|
||||||
|
static FSP_IOP_REQUEST_FINI FspFsvolQueryEaRequestFini;
|
||||||
static NTSTATUS FspFsvolSetEa(
|
static NTSTATUS FspFsvolSetEa(
|
||||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
FSP_IOCMPL_DISPATCH FspFsvolSetEaComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolSetEaComplete;
|
||||||
|
static FSP_IOP_REQUEST_FINI FspFsvolSetEaRequestFini;
|
||||||
FSP_DRIVER_DISPATCH FspQueryEa;
|
FSP_DRIVER_DISPATCH FspQueryEa;
|
||||||
FSP_DRIVER_DISPATCH FspSetEa;
|
FSP_DRIVER_DISPATCH FspSetEa;
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolQueryEaGetCopy)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolQueryEaIndexCopy)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryEa)
|
#pragma alloc_text(PAGE, FspFsvolQueryEa)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryEaComplete)
|
#pragma alloc_text(PAGE, FspFsvolQueryEaComplete)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolQueryEaRequestFini)
|
||||||
#pragma alloc_text(PAGE, FspFsvolSetEa)
|
#pragma alloc_text(PAGE, FspFsvolSetEa)
|
||||||
#pragma alloc_text(PAGE, FspFsvolSetEaComplete)
|
#pragma alloc_text(PAGE, FspFsvolSetEaComplete)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolSetEaRequestFini)
|
||||||
#pragma alloc_text(PAGE, FspQueryEa)
|
#pragma alloc_text(PAGE, FspQueryEa)
|
||||||
#pragma alloc_text(PAGE, FspSetEa)
|
#pragma alloc_text(PAGE, FspSetEa)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static NTSTATUS FspFsvolQueryEa(
|
enum
|
||||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
{
|
||||||
|
/* QueryEa */
|
||||||
|
RequestFileNode = 0,
|
||||||
|
RequestEaChangeNumber = 1,
|
||||||
|
|
||||||
|
/* SetEa */
|
||||||
|
//RequestFileNode = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static VOID FspFsvolQueryEaGetCopy(
|
||||||
|
BOOLEAN CasePreservedExtendedAttributes,
|
||||||
|
BOOLEAN ReturnSingleEntry,
|
||||||
|
PFILE_GET_EA_INFORMATION GetBufBgn, ULONG GetSize,
|
||||||
|
PFILE_FULL_EA_INFORMATION SrcBufBgn, ULONG SrcSize,
|
||||||
|
PFILE_FULL_EA_INFORMATION DstBufBgn, ULONG DstSize,
|
||||||
|
PIO_STATUS_BLOCK IoStatus)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
PFILE_GET_EA_INFORMATION GetBuf, GetBufEnd = (PVOID)((PUINT8)GetBufBgn + GetSize);
|
||||||
|
PFILE_GET_EA_INFORMATION Get;
|
||||||
|
PFILE_FULL_EA_INFORMATION SrcBuf, SrcBufEnd = (PVOID)((PUINT8)SrcBufBgn + SrcSize);
|
||||||
|
PFILE_FULL_EA_INFORMATION DstBuf, DstBufEnd = (PVOID)((PUINT8)DstBufBgn + DstSize);
|
||||||
|
PFILE_FULL_EA_INFORMATION PrevDstBuf;
|
||||||
|
PVOID Src;
|
||||||
|
STRING GetName, Name;
|
||||||
|
ULONG CopyLength;
|
||||||
|
|
||||||
|
IoStatus->Status = STATUS_SUCCESS;
|
||||||
|
IoStatus->Information = 0;
|
||||||
|
DstBuf = DstBufBgn, PrevDstBuf = 0;
|
||||||
|
for (GetBuf = GetBufBgn;
|
||||||
|
GetBufEnd > GetBuf && 0 != GetBuf->NextEntryOffset;
|
||||||
|
GetBuf = (PVOID)((PUINT8)GetBuf + GetBuf->NextEntryOffset))
|
||||||
|
{
|
||||||
|
GetName.Length = GetName.MaximumLength = GetBuf->EaNameLength;
|
||||||
|
GetName.Buffer = GetBuf->EaName;
|
||||||
|
|
||||||
|
/* ignore duplicate names */
|
||||||
|
for (Get = GetBufBgn;
|
||||||
|
GetBuf > Get;
|
||||||
|
Get = (PVOID)((PUINT8)Get + Get->NextEntryOffset))
|
||||||
|
{
|
||||||
|
Name.Length = Name.MaximumLength = Get->EaNameLength;
|
||||||
|
Name.Buffer = Get->EaName;
|
||||||
|
|
||||||
|
if (RtlEqualString(&GetName, &Name, TRUE/* always case-insensitive */))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (GetBuf > Get)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!FspEaNameIsValid(&GetName))
|
||||||
|
{
|
||||||
|
IoStatus->Status = STATUS_INVALID_EA_NAME;
|
||||||
|
IoStatus->Information = (ULONG)((PUINT8)GetBuf - (PUINT8)GetBufBgn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Src = GetBuf;
|
||||||
|
for (SrcBuf = SrcBufBgn;
|
||||||
|
SrcBufEnd > SrcBuf && 0 != SrcBuf->NextEntryOffset;
|
||||||
|
SrcBuf = (PVOID)((PUINT8)SrcBuf + SrcBuf->NextEntryOffset))
|
||||||
|
{
|
||||||
|
Name.Length = Name.MaximumLength = SrcBuf->EaNameLength;
|
||||||
|
Name.Buffer = SrcBuf->EaName;
|
||||||
|
|
||||||
|
if (RtlEqualString(&GetName, &Name, TRUE/* always case-insensitive */))
|
||||||
|
{
|
||||||
|
Src = SrcBuf;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetBuf != Src)
|
||||||
|
CopyLength = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName) +
|
||||||
|
((PFILE_FULL_EA_INFORMATION)Src)->EaNameLength + 1 +
|
||||||
|
((PFILE_FULL_EA_INFORMATION)Src)->EaValueLength;
|
||||||
|
else
|
||||||
|
CopyLength = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName) +
|
||||||
|
((PFILE_GET_EA_INFORMATION)Src)->EaNameLength + 1;
|
||||||
|
|
||||||
|
if ((PUINT8)DstBuf + CopyLength > (PUINT8)DstBufEnd)
|
||||||
|
{
|
||||||
|
IoStatus->Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlMoveMemory(DstBuf, Src, CopyLength);
|
||||||
|
DstBuf->NextEntryOffset = 0;
|
||||||
|
if (!CasePreservedExtendedAttributes)
|
||||||
|
{
|
||||||
|
Name.Length = Name.MaximumLength = DstBuf->EaNameLength;
|
||||||
|
Name.Buffer = DstBuf->EaName;
|
||||||
|
FspEaNameUpcase(&Name, &Name, 0);
|
||||||
|
}
|
||||||
|
if (0 != PrevDstBuf)
|
||||||
|
PrevDstBuf->NextEntryOffset = (ULONG)((PUINT8)DstBuf - (PUINT8)PrevDstBuf);
|
||||||
|
PrevDstBuf = DstBuf;
|
||||||
|
DstBuf = (PVOID)((PUINT8)DstBuf + CopyLength);
|
||||||
|
|
||||||
|
if (ReturnSingleEntry)
|
||||||
|
break;
|
||||||
|
|
||||||
|
DstBuf = (PVOID)FSP_FSCTL_ALIGN_UP((UINT_PTR)DstBuf, sizeof(ULONG));
|
||||||
|
}
|
||||||
|
|
||||||
|
IoStatus->Information = NT_SUCCESS(IoStatus->Status) ?
|
||||||
|
(ULONG)((PUINT8)DstBuf - (PUINT8)DstBufBgn) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspFsvolQueryEaIndexCopy(
|
||||||
|
BOOLEAN CasePreservedExtendedAttributes,
|
||||||
|
BOOLEAN ReturnSingleEntry,
|
||||||
|
BOOLEAN IndexSpecified, PULONG PEaIndex,
|
||||||
|
PFILE_FULL_EA_INFORMATION SrcBufBgn, ULONG SrcSize,
|
||||||
|
PFILE_FULL_EA_INFORMATION DstBufBgn, ULONG DstSize,
|
||||||
|
PIO_STATUS_BLOCK IoStatus)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
ULONG EaIndex = 1;
|
||||||
|
PFILE_FULL_EA_INFORMATION SrcBuf, SrcBufEnd = (PVOID)((PUINT8)SrcBufBgn + SrcSize);
|
||||||
|
PFILE_FULL_EA_INFORMATION DstBuf, DstBufEnd = (PVOID)((PUINT8)DstBufBgn + DstSize);
|
||||||
|
PFILE_FULL_EA_INFORMATION PrevDstBuf;
|
||||||
|
STRING Name;
|
||||||
|
ULONG CopyLength;
|
||||||
|
|
||||||
|
if (IndexSpecified && 0 == *PEaIndex)
|
||||||
|
{
|
||||||
|
IoStatus->Status = STATUS_NONEXISTENT_EA_ENTRY;
|
||||||
|
IoStatus->Information = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (SrcBuf = SrcBufBgn;
|
||||||
|
EaIndex < *PEaIndex &&
|
||||||
|
SrcBufEnd > SrcBuf && 0 != SrcBuf->NextEntryOffset;
|
||||||
|
SrcBuf = (PVOID)((PUINT8)SrcBuf + SrcBuf->NextEntryOffset), EaIndex++)
|
||||||
|
;
|
||||||
|
|
||||||
|
IoStatus->Status = STATUS_SUCCESS;
|
||||||
|
IoStatus->Information = 0;
|
||||||
|
DstBuf = DstBufBgn, PrevDstBuf = 0;
|
||||||
|
for (;
|
||||||
|
SrcBufEnd > SrcBuf && 0 != SrcBuf->NextEntryOffset;
|
||||||
|
SrcBuf = (PVOID)((PUINT8)SrcBuf + SrcBuf->NextEntryOffset), EaIndex++)
|
||||||
|
{
|
||||||
|
if ((PUINT8)DstBuf + FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName) > (PUINT8)DstBufEnd)
|
||||||
|
break;
|
||||||
|
|
||||||
|
CopyLength = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName) +
|
||||||
|
((PFILE_FULL_EA_INFORMATION)SrcBuf)->EaNameLength + 1 +
|
||||||
|
((PFILE_FULL_EA_INFORMATION)SrcBuf)->EaValueLength;
|
||||||
|
|
||||||
|
if ((PUINT8)DstBuf + CopyLength > (PUINT8)DstBufEnd)
|
||||||
|
{
|
||||||
|
CopyLength = (ULONG)((PUINT8)DstBufEnd - (PUINT8)DstBuf);
|
||||||
|
IoStatus->Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlMoveMemory(DstBuf, SrcBuf, CopyLength);
|
||||||
|
DstBuf->NextEntryOffset = 0;
|
||||||
|
if (!CasePreservedExtendedAttributes)
|
||||||
|
{
|
||||||
|
Name.Length = Name.MaximumLength = DstBuf->EaNameLength;
|
||||||
|
Name.Buffer = DstBuf->EaName;
|
||||||
|
FspEaNameUpcase(&Name, &Name, 0);
|
||||||
|
}
|
||||||
|
if (0 != PrevDstBuf)
|
||||||
|
PrevDstBuf->NextEntryOffset = (ULONG)((PUINT8)DstBuf - (PUINT8)PrevDstBuf);
|
||||||
|
PrevDstBuf = DstBuf;
|
||||||
|
DstBuf = (PVOID)((PUINT8)DstBuf + CopyLength);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(IoStatus->Status) || ReturnSingleEntry)
|
||||||
|
break;
|
||||||
|
|
||||||
|
DstBuf = (PVOID)FSP_FSCTL_ALIGN_UP((UINT_PTR)DstBuf, sizeof(ULONG));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != PrevDstBuf)
|
||||||
|
{
|
||||||
|
*PEaIndex = EaIndex;
|
||||||
|
IoStatus->Information = (ULONG)((PUINT8)DstBuf - (PUINT8)DstBufBgn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (SrcBufBgn == SrcBuf)
|
||||||
|
IoStatus->Status = IndexSpecified ?
|
||||||
|
STATUS_NONEXISTENT_EA_ENTRY : STATUS_NO_EAS_ON_FILE;
|
||||||
|
else if (SrcBufEnd > SrcBuf && 0 != SrcBuf->NextEntryOffset)
|
||||||
|
IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
else
|
||||||
|
IoStatus->Status = IndexSpecified && *PEaIndex != EaIndex ?
|
||||||
|
STATUS_NONEXISTENT_EA_ENTRY : STATUS_NO_MORE_EAS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspFsvolQueryEaCopy(
|
||||||
|
BOOLEAN CasePreservedExtendedAttributes,
|
||||||
|
PIO_STACK_LOCATION IrpSp,
|
||||||
|
PFILE_FULL_EA_INFORMATION SrcBufBgn, ULONG SrcSize,
|
||||||
|
PFILE_FULL_EA_INFORMATION DstBufBgn, ULONG DstSize,
|
||||||
|
PIO_STATUS_BLOCK IoStatus)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
|
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||||
|
BOOLEAN RestartScan = BooleanFlagOn(IrpSp->Flags, SL_RESTART_SCAN);
|
||||||
|
BOOLEAN IndexSpecified = BooleanFlagOn(IrpSp->Flags, SL_INDEX_SPECIFIED);
|
||||||
|
BOOLEAN ReturnSingleEntry = BooleanFlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY);
|
||||||
|
PFILE_GET_EA_INFORMATION EaList = IrpSp->Parameters.QueryEa.EaList;
|
||||||
|
ULONG EaListLength = IrpSp->Parameters.QueryEa.EaListLength;
|
||||||
|
ULONG EaIndex;
|
||||||
|
|
||||||
|
if (0 != EaList)
|
||||||
|
{
|
||||||
|
FspFsvolQueryEaGetCopy(
|
||||||
|
CasePreservedExtendedAttributes,
|
||||||
|
ReturnSingleEntry,
|
||||||
|
EaList, EaListLength,
|
||||||
|
SrcBufBgn, SrcSize,
|
||||||
|
DstBufBgn, DstSize,
|
||||||
|
IoStatus);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (IndexSpecified)
|
||||||
|
EaIndex = IrpSp->Parameters.QueryEa.EaIndex;
|
||||||
|
else if (RestartScan)
|
||||||
|
EaIndex = 0;
|
||||||
|
else
|
||||||
|
EaIndex = FileDesc->EaIndex;
|
||||||
|
FspFsvolQueryEaIndexCopy(
|
||||||
|
CasePreservedExtendedAttributes,
|
||||||
|
ReturnSingleEntry,
|
||||||
|
IndexSpecified, &EaIndex,
|
||||||
|
SrcBufBgn, SrcSize,
|
||||||
|
DstBufBgn, DstSize,
|
||||||
|
IoStatus);
|
||||||
|
if (NT_SUCCESS(IoStatus->Status) || STATUS_BUFFER_OVERFLOW == IoStatus->Status)
|
||||||
|
FileDesc->EaIndex = EaIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsvolQueryEa(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* is this a valid FileObject? */
|
||||||
|
if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext))
|
||||||
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||||
|
PVOID Buffer = Irp->UserBuffer;
|
||||||
|
ULONG Length = IrpSp->Parameters.QueryEa.Length;
|
||||||
|
PVOID EaBuffer;
|
||||||
|
ULONG EaBufferSize;
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||||
|
|
||||||
|
ASSERT(FileNode == FileDesc->FileNode);
|
||||||
|
|
||||||
|
FspFileNodeAcquireExclusive(FileNode, Main);
|
||||||
|
if (FspFileNodeReferenceEa(FileNode, &EaBuffer, &EaBufferSize))
|
||||||
|
{
|
||||||
|
FspFsvolQueryEaCopy(
|
||||||
|
!!FsvolDeviceExtension->VolumeParams.CasePreservedExtendedAttributes,
|
||||||
|
IrpSp,
|
||||||
|
EaBuffer, EaBufferSize,
|
||||||
|
Buffer, Length,
|
||||||
|
&Irp->IoStatus);
|
||||||
|
FspFileNodeDereferenceEa(EaBuffer);
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
|
||||||
|
return Irp->IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFileNodeConvertExclusiveToShared(FileNode, Main);
|
||||||
|
FspFileNodeAcquireShared(FileNode, Pgio);
|
||||||
|
|
||||||
|
Result = FspBufferUserBuffer(Irp, Length, IoWriteAccess);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Full);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = FspIopCreateRequestEx(Irp, 0, 0, FspFsvolQueryEaRequestFini, &Request);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Full);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Request->Kind = FspFsctlTransactQueryEaKind;
|
||||||
|
Request->Req.QueryEa.UserContext = FileNode->UserContext;
|
||||||
|
Request->Req.QueryEa.UserContext2 = FileDesc->UserContext2;
|
||||||
|
|
||||||
|
FspFileNodeSetOwner(FileNode, Full, Request);
|
||||||
|
FspIopRequestContext(Request, RequestFileNode) = FileNode;
|
||||||
|
|
||||||
|
return FSP_STATUS_IOQ_POST;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FspFsvolQueryEaComplete(
|
NTSTATUS FspFsvolQueryEaComplete(
|
||||||
@ -52,15 +381,148 @@ NTSTATUS FspFsvolQueryEaComplete(
|
|||||||
{
|
{
|
||||||
FSP_ENTER_IOC(PAGED_CODE());
|
FSP_ENTER_IOC(PAGED_CODE());
|
||||||
|
|
||||||
FSP_LEAVE_IOC("%s", "");
|
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Result = Response->IoStatus.Status;
|
||||||
|
FSP_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->DeviceObject;
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
PVOID Buffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
ULONG Length = IrpSp->Parameters.QueryEa.Length;
|
||||||
|
PVOID EaBuffer = 0;
|
||||||
|
ULONG EaBufferSize = 0;
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
||||||
|
BOOLEAN Success;
|
||||||
|
|
||||||
|
if (0 != FspIopRequestContext(Request, RequestFileNode))
|
||||||
|
{
|
||||||
|
/* check that the EA buffer we got back is valid */
|
||||||
|
if (Response->Buffer + Response->Rsp.QueryEa.Ea.Size >
|
||||||
|
(PUINT8)Response + Response->Size)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Result = STATUS_EA_LIST_INCONSISTENT;
|
||||||
|
FSP_RETURN();
|
||||||
|
}
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Result = IoCheckEaBufferValidity((PVOID)Response->Buffer, Response->Rsp.QueryEa.Ea.Size,
|
||||||
|
(PULONG)&Irp->IoStatus.Information);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
FSP_RETURN();
|
||||||
|
|
||||||
|
FspIopRequestContext(Request, RequestEaChangeNumber) = (PVOID)
|
||||||
|
FspFileNodeEaChangeNumber(FileNode);
|
||||||
|
FspIopRequestContext(Request, RequestFileNode) = 0;
|
||||||
|
|
||||||
|
FspFileNodeReleaseOwner(FileNode, Full, Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
Success = DEBUGTEST(90) && FspFileNodeTryAcquireExclusive(FileNode, Main);
|
||||||
|
if (!Success)
|
||||||
|
{
|
||||||
|
FspIopRetryCompleteIrp(Irp, Response, &Result);
|
||||||
|
FSP_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
Success = !FspFileNodeTrySetEa(FileNode,
|
||||||
|
Response->Buffer, Response->Rsp.QueryEa.Ea.Size,
|
||||||
|
(ULONG)(UINT_PTR)FspIopRequestContext(Request, RequestEaChangeNumber));
|
||||||
|
Success = Success && FspFileNodeReferenceEa(FileNode, &EaBuffer, &EaBufferSize);
|
||||||
|
if (Success)
|
||||||
|
{
|
||||||
|
FspFsvolQueryEaCopy(
|
||||||
|
!!FsvolDeviceExtension->VolumeParams.CasePreservedExtendedAttributes,
|
||||||
|
IrpSp,
|
||||||
|
EaBuffer, EaBufferSize,
|
||||||
|
Buffer, Length,
|
||||||
|
&Irp->IoStatus);
|
||||||
|
FspFileNodeDereferenceEa(EaBuffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EaBuffer = (PVOID)Response->Buffer;
|
||||||
|
EaBufferSize = Response->Rsp.QueryEa.Ea.Size;
|
||||||
|
FspFsvolQueryEaCopy(
|
||||||
|
!!FsvolDeviceExtension->VolumeParams.CasePreservedExtendedAttributes,
|
||||||
|
IrpSp,
|
||||||
|
EaBuffer, EaBufferSize,
|
||||||
|
Buffer, Length,
|
||||||
|
&Irp->IoStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
|
||||||
|
FSP_LEAVE_IOC("FileObject=%p",
|
||||||
|
IrpSp->FileObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsvolSetEa(
|
static VOID FspFsvolQueryEaRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4])
|
||||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
FSP_FILE_NODE *FileNode = Context[RequestFileNode];
|
||||||
|
|
||||||
|
if (0 != FileNode)
|
||||||
|
FspFileNodeReleaseOwner(FileNode, Full, Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsvolSetEa(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* is this a valid FileObject? */
|
||||||
|
if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext))
|
||||||
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||||
|
PVOID Buffer;
|
||||||
|
ULONG Length = IrpSp->Parameters.SetEa.Length;
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||||
|
|
||||||
|
ASSERT(FileNode == FileDesc->FileNode);
|
||||||
|
|
||||||
|
Result = FspBufferUserBuffer(Irp, Length, IoReadAccess);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
Buffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Result = IoCheckEaBufferValidity(Buffer, Length,
|
||||||
|
(PULONG)&Irp->IoStatus.Information);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
FspFileNodeAcquireExclusive(FileNode, Full);
|
||||||
|
|
||||||
|
Result = FspIopCreateRequestEx(Irp, 0, Length, FspFsvolSetEaRequestFini,
|
||||||
|
&Request);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Full);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Request->Kind = FspFsctlTransactSetEaKind;
|
||||||
|
Request->Req.SetEa.UserContext = FileNode->UserContext;
|
||||||
|
Request->Req.SetEa.UserContext2 = FileDesc->UserContext2;
|
||||||
|
Request->Req.SetEa.Ea.Offset = 0;
|
||||||
|
Request->Req.SetEa.Ea.Size = (UINT16)Length;
|
||||||
|
RtlCopyMemory(Request->Buffer, Buffer, Length);
|
||||||
|
|
||||||
|
FspFileNodeSetOwner(FileNode, Full, Request);
|
||||||
|
FspIopRequestContext(Request, RequestFileNode) = FileNode;
|
||||||
|
|
||||||
|
return FSP_STATUS_IOQ_POST;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FspFsvolSetEaComplete(
|
NTSTATUS FspFsvolSetEaComplete(
|
||||||
@ -68,7 +530,62 @@ NTSTATUS FspFsvolSetEaComplete(
|
|||||||
{
|
{
|
||||||
FSP_ENTER_IOC(PAGED_CODE());
|
FSP_ENTER_IOC(PAGED_CODE());
|
||||||
|
|
||||||
FSP_LEAVE_IOC("%s", "");
|
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Result = Response->IoStatus.Status;
|
||||||
|
FSP_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
||||||
|
BOOLEAN Valid;
|
||||||
|
|
||||||
|
Valid = FALSE;
|
||||||
|
if (0 < Response->Rsp.SetEa.Ea.Size &&
|
||||||
|
Response->Buffer + Response->Rsp.SetEa.Ea.Size <=
|
||||||
|
(PUINT8)Response + Response->Size)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Result = IoCheckEaBufferValidity((PVOID)Response->Buffer, Response->Rsp.QueryEa.Ea.Size,
|
||||||
|
(PULONG)&Irp->IoStatus.Information);
|
||||||
|
Valid = NT_SUCCESS(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if the EA buffer that we got back is valid */
|
||||||
|
if (Valid)
|
||||||
|
{
|
||||||
|
/* update the cached EA */
|
||||||
|
FspFileNodeSetEa(FileNode,
|
||||||
|
Response->Buffer, Response->Rsp.SetEa.Ea.Size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* invalidate the cached EA */
|
||||||
|
FspFileNodeSetEa(FileNode, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFileNodeNotifyChange(FileNode, FILE_NOTIFY_CHANGE_EA, FILE_ACTION_MODIFIED, FALSE);
|
||||||
|
|
||||||
|
FspIopRequestContext(Request, RequestFileNode) = 0;
|
||||||
|
FspFileNodeReleaseOwner(FileNode, Full, Request);
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
FSP_LEAVE_IOC("FileObject=%p",
|
||||||
|
IrpSp->FileObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspFsvolSetEaRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4])
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FSP_FILE_NODE *FileNode = Context[RequestFileNode];
|
||||||
|
|
||||||
|
if (0 != FileNode)
|
||||||
|
FspFileNodeReleaseOwner(FileNode, Full, Request);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FspQueryEa(
|
NTSTATUS FspQueryEa(
|
||||||
@ -84,7 +601,8 @@ NTSTATUS FspQueryEa(
|
|||||||
FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST);
|
FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_LEAVE_MJ("%s", "");
|
FSP_LEAVE_MJ("FileObject=%p",
|
||||||
|
IrpSp->FileObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FspSetEa(
|
NTSTATUS FspSetEa(
|
||||||
@ -100,5 +618,6 @@ NTSTATUS FspSetEa(
|
|||||||
FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST);
|
FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_LEAVE_MJ("%s", "");
|
FSP_LEAVE_MJ("FileObject=%p",
|
||||||
|
IrpSp->FileObject);
|
||||||
}
|
}
|
||||||
|
@ -89,6 +89,10 @@ VOID FspFileNodeSetStreamInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size
|
|||||||
BOOLEAN FspFileNodeTrySetStreamInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
BOOLEAN FspFileNodeTrySetStreamInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
||||||
ULONG StreamInfoChangeNumber);
|
ULONG StreamInfoChangeNumber);
|
||||||
VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode);
|
VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode);
|
||||||
|
BOOLEAN FspFileNodeReferenceEa(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize);
|
||||||
|
VOID FspFileNodeSetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size);
|
||||||
|
BOOLEAN FspFileNodeTrySetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
||||||
|
ULONG EaChangeNumber);
|
||||||
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action,
|
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action,
|
||||||
BOOLEAN InvalidateCaches);
|
BOOLEAN InvalidateCaches);
|
||||||
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
||||||
@ -158,6 +162,9 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
|
|||||||
// !#pragma alloc_text(PAGE, FspFileNodeSetStreamInfo)
|
// !#pragma alloc_text(PAGE, FspFileNodeSetStreamInfo)
|
||||||
// !#pragma alloc_text(PAGE, FspFileNodeTrySetStreamInfo)
|
// !#pragma alloc_text(PAGE, FspFileNodeTrySetStreamInfo)
|
||||||
// !#pragma alloc_text(PAGE, FspFileNodeInvalidateStreamInfo)
|
// !#pragma alloc_text(PAGE, FspFileNodeInvalidateStreamInfo)
|
||||||
|
#pragma alloc_text(PAGE, FspFileNodeReferenceEa)
|
||||||
|
#pragma alloc_text(PAGE, FspFileNodeSetEa)
|
||||||
|
#pragma alloc_text(PAGE, FspFileNodeTrySetEa)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeNotifyChange)
|
#pragma alloc_text(PAGE, FspFileNodeNotifyChange)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeProcessLockIrp)
|
#pragma alloc_text(PAGE, FspFileNodeProcessLockIrp)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeCompleteLockIrp)
|
#pragma alloc_text(PAGE, FspFileNodeCompleteLockIrp)
|
||||||
@ -361,6 +368,7 @@ VOID FspFileNodeDelete(FSP_FILE_NODE *FileNode)
|
|||||||
|
|
||||||
FsRtlTeardownPerStreamContexts(&FileNode->Header);
|
FsRtlTeardownPerStreamContexts(&FileNode->Header);
|
||||||
|
|
||||||
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->EaCache, FileNode->Ea);
|
||||||
FspMetaCacheInvalidateItem(FsvolDeviceExtension->StreamInfoCache, FileNode->NonPaged->StreamInfo);
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->StreamInfoCache, FileNode->NonPaged->StreamInfo);
|
||||||
FspMetaCacheInvalidateItem(FsvolDeviceExtension->DirInfoCache, FileNode->NonPaged->DirInfo);
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->DirInfoCache, FileNode->NonPaged->DirInfo);
|
||||||
FspMetaCacheInvalidateItem(FsvolDeviceExtension->SecurityCache, FileNode->Security);
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->SecurityCache, FileNode->Security);
|
||||||
@ -2115,6 +2123,48 @@ VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode)
|
|||||||
FspMetaCacheInvalidateItem(FsvolDeviceExtension->StreamInfoCache, StreamInfo);
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->StreamInfoCache, StreamInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN FspFileNodeReferenceEa(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||||
|
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
|
||||||
|
|
||||||
|
return FspMetaCacheReferenceItemBuffer(FsvolDeviceExtension->EaCache,
|
||||||
|
FileNode->Ea, PBuffer, PSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspFileNodeSetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||||
|
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
|
||||||
|
|
||||||
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->EaCache, FileNode->Ea);
|
||||||
|
FileNode->Ea = 0 != Buffer ?
|
||||||
|
FspMetaCacheAddItem(FsvolDeviceExtension->EaCache, Buffer, Size) : 0;
|
||||||
|
FileNode->EaChangeNumber++;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN FspFileNodeTrySetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
||||||
|
ULONG EaChangeNumber)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (FspFileNodeEaChangeNumber(FileNode) != EaChangeNumber)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
FspFileNodeSetEa(FileNode, Buffer, Size);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action,
|
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action,
|
||||||
BOOLEAN InvalidateCaches)
|
BOOLEAN InvalidateCaches)
|
||||||
{
|
{
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
BOOLEAN FspFileNameIsValid(PUNICODE_STRING Path, ULONG MaxComponentLength,
|
BOOLEAN FspFileNameIsValid(PUNICODE_STRING Path, ULONG MaxComponentLength,
|
||||||
PUNICODE_STRING StreamPart, PULONG StreamType);
|
PUNICODE_STRING StreamPart, PULONG StreamType);
|
||||||
BOOLEAN FspFileNameIsValidPattern(PUNICODE_STRING Pattern, ULONG MaxComponentLength);
|
BOOLEAN FspFileNameIsValidPattern(PUNICODE_STRING Pattern, ULONG MaxComponentLength);
|
||||||
|
BOOLEAN FspEaNameIsValid(PSTRING Name);
|
||||||
VOID FspFileNameSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix);
|
VOID FspFileNameSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix);
|
||||||
NTSTATUS FspFileNameInExpression(
|
NTSTATUS FspFileNameInExpression(
|
||||||
PUNICODE_STRING Expression,
|
PUNICODE_STRING Expression,
|
||||||
@ -35,6 +36,7 @@ NTSTATUS FspFileNameInExpression(
|
|||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(PAGE, FspFileNameIsValid)
|
#pragma alloc_text(PAGE, FspFileNameIsValid)
|
||||||
#pragma alloc_text(PAGE, FspFileNameIsValidPattern)
|
#pragma alloc_text(PAGE, FspFileNameIsValidPattern)
|
||||||
|
#pragma alloc_text(PAGE, FspEaNameIsValid)
|
||||||
#pragma alloc_text(PAGE, FspFileNameSuffix)
|
#pragma alloc_text(PAGE, FspFileNameSuffix)
|
||||||
#pragma alloc_text(PAGE, FspFileNameInExpression)
|
#pragma alloc_text(PAGE, FspFileNameInExpression)
|
||||||
#endif
|
#endif
|
||||||
@ -191,6 +193,37 @@ BOOLEAN FspFileNameIsValidPattern(PUNICODE_STRING Path, ULONG MaxComponentLength
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN FspEaNameIsValid(PSTRING Name)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* see FastFat's FatIsEaNameValid */
|
||||||
|
|
||||||
|
if (0 == Name->Length || Name->Length > 254)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
PSTR NameEnd, NamePtr;
|
||||||
|
CHAR Char;
|
||||||
|
|
||||||
|
NamePtr = Name->Buffer;
|
||||||
|
NameEnd = NamePtr + Name->Length;
|
||||||
|
|
||||||
|
while (NameEnd > NamePtr)
|
||||||
|
{
|
||||||
|
Char = *NamePtr;
|
||||||
|
|
||||||
|
if (FsRtlIsLeadDbcsCharacter(Char))
|
||||||
|
NamePtr++;
|
||||||
|
else
|
||||||
|
if (!FsRtlIsAnsiCharacterLegalFat(Char, FALSE))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
NamePtr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
VOID FspFileNameSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix)
|
VOID FspFileNameSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
@ -96,7 +96,7 @@ static NTSTATUS FspFsvolQueryFsAttributeInformation(
|
|||||||
(FsvolDeviceExtension->VolumeParams.ReparsePoints ? FILE_SUPPORTS_REPARSE_POINTS : 0) |
|
(FsvolDeviceExtension->VolumeParams.ReparsePoints ? FILE_SUPPORTS_REPARSE_POINTS : 0) |
|
||||||
(FsvolDeviceExtension->VolumeParams.NamedStreams ? FILE_NAMED_STREAMS : 0) |
|
(FsvolDeviceExtension->VolumeParams.NamedStreams ? FILE_NAMED_STREAMS : 0) |
|
||||||
//(FsvolDeviceExtension->VolumeParams.HardLinks ? FILE_SUPPORTS_HARD_LINKS : 0) |
|
//(FsvolDeviceExtension->VolumeParams.HardLinks ? FILE_SUPPORTS_HARD_LINKS : 0) |
|
||||||
//(FsvolDeviceExtension->VolumeParams.ExtendedAttributes ? FILE_SUPPORTS_EXTENDED_ATTRIBUTES : 0) |
|
(FsvolDeviceExtension->VolumeParams.ExtendedAttributes ? FILE_SUPPORTS_EXTENDED_ATTRIBUTES : 0) |
|
||||||
(FsvolDeviceExtension->VolumeParams.ReadOnlyVolume ? FILE_READ_ONLY_VOLUME : 0);
|
(FsvolDeviceExtension->VolumeParams.ReadOnlyVolume ? FILE_READ_ONLY_VOLUME : 0);
|
||||||
Info->MaximumComponentNameLength = FsvolDeviceExtension->VolumeParams.MaxComponentLength;
|
Info->MaximumComponentNameLength = FsvolDeviceExtension->VolumeParams.MaxComponentLength;
|
||||||
|
|
||||||
|
@ -151,6 +151,7 @@ static NTSTATUS FspVolumeCreateNoLock(
|
|||||||
VolumeParams.DirInfoTimeout = VolumeParams.FileInfoTimeout;
|
VolumeParams.DirInfoTimeout = VolumeParams.FileInfoTimeout;
|
||||||
VolumeParams.SecurityTimeout = VolumeParams.FileInfoTimeout;
|
VolumeParams.SecurityTimeout = VolumeParams.FileInfoTimeout;
|
||||||
VolumeParams.StreamInfoTimeout = VolumeParams.FileInfoTimeout;
|
VolumeParams.StreamInfoTimeout = VolumeParams.FileInfoTimeout;
|
||||||
|
VolumeParams.EaTimeout = VolumeParams.FileInfoTimeout;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -162,11 +163,14 @@ static NTSTATUS FspVolumeCreateNoLock(
|
|||||||
VolumeParams.SecurityTimeout = VolumeParams.FileInfoTimeout;
|
VolumeParams.SecurityTimeout = VolumeParams.FileInfoTimeout;
|
||||||
if (!VolumeParams.StreamInfoTimeoutValid)
|
if (!VolumeParams.StreamInfoTimeoutValid)
|
||||||
VolumeParams.StreamInfoTimeout = VolumeParams.FileInfoTimeout;
|
VolumeParams.StreamInfoTimeout = VolumeParams.FileInfoTimeout;
|
||||||
|
if (!VolumeParams.EaTimeoutValid)
|
||||||
|
VolumeParams.EaTimeout = VolumeParams.FileInfoTimeout;
|
||||||
}
|
}
|
||||||
VolumeParams.VolumeInfoTimeoutValid = 1;
|
VolumeParams.VolumeInfoTimeoutValid = 1;
|
||||||
VolumeParams.DirInfoTimeoutValid = 1;
|
VolumeParams.DirInfoTimeoutValid = 1;
|
||||||
VolumeParams.SecurityTimeoutValid = 1;
|
VolumeParams.SecurityTimeoutValid = 1;
|
||||||
VolumeParams.StreamInfoTimeoutValid = 1;
|
VolumeParams.StreamInfoTimeoutValid = 1;
|
||||||
|
VolumeParams.EaTimeoutValid = 1;
|
||||||
if (FILE_DEVICE_NETWORK_FILE_SYSTEM == FsctlDeviceObject->DeviceType)
|
if (FILE_DEVICE_NETWORK_FILE_SYSTEM == FsctlDeviceObject->DeviceType)
|
||||||
{
|
{
|
||||||
VolumeParams.Prefix[sizeof VolumeParams.Prefix / sizeof(WCHAR) - 1] = L'\0';
|
VolumeParams.Prefix[sizeof VolumeParams.Prefix / sizeof(WCHAR) - 1] = L'\0';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user