mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	sys: IRP_MN_NOTIFY_CHANGE_DIRECTORY: implementation and related changes
This commit is contained in:
		| @@ -73,6 +73,20 @@ static NTSTATUS FspFsvolCleanup( | |||||||
|  |  | ||||||
|     FspFileNodeCleanup(FileNode, FileObject, &DeletePending); |     FspFileNodeCleanup(FileNode, FileObject, &DeletePending); | ||||||
|  |  | ||||||
|  |     /* if this is a directory inform the FSRTL Notify mechanism */ | ||||||
|  |     if (FileNode->IsDirectory) | ||||||
|  |     { | ||||||
|  |         FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = | ||||||
|  |             FspFsvolDeviceExtension(FsvolDeviceObject); | ||||||
|  |  | ||||||
|  |         if (DeletePending) | ||||||
|  |             FspNotifyDeletePending( | ||||||
|  |                 FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList, FileNode); | ||||||
|  |  | ||||||
|  |         FspNotifyCleanup( | ||||||
|  |             FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList, FileDesc); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /* create the user-mode file system request; MustSucceed because IRP_MJ_CLEANUP cannot fail */ |     /* create the user-mode file system request; MustSucceed because IRP_MJ_CLEANUP cannot fail */ | ||||||
|     FspIopCreateRequestMustSucceedEx(Irp, DeletePending ? &FileNode->FileName : 0, 0, |     FspIopCreateRequestMustSucceedEx(Irp, DeletePending ? &FileNode->FileName : 0, 0, | ||||||
|         FspFsvolCleanupRequestFini, &Request); |         FspFsvolCleanupRequestFini, &Request); | ||||||
|   | |||||||
| @@ -337,6 +337,7 @@ static NTSTATUS FspFsvolCreateNoLock( | |||||||
|     FileDesc->CaseSensitive = |     FileDesc->CaseSensitive = | ||||||
|         0 != FsvolDeviceExtension->VolumeParams.CaseSensitiveSearch || |         0 != FsvolDeviceExtension->VolumeParams.CaseSensitiveSearch || | ||||||
|         BooleanFlagOn(Flags, SL_CASE_SENSITIVE); |         BooleanFlagOn(Flags, SL_CASE_SENSITIVE); | ||||||
|  |     FileDesc->HasTraversePrivilege = HasTraversePrivilege; | ||||||
|     FspFsvolDeviceFileRenameSetOwner(FsvolDeviceObject, Request); |     FspFsvolDeviceFileRenameSetOwner(FsvolDeviceObject, Request); | ||||||
|     FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject; |     FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject; | ||||||
|     FspIopRequestContext(Request, RequestFileDesc) = FileDesc; |     FspIopRequestContext(Request, RequestFileDesc) = FileDesc; | ||||||
|   | |||||||
| @@ -50,9 +50,9 @@ VOID FspFsvolDeviceDeleteContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STR | |||||||
| static RTL_AVL_COMPARE_ROUTINE FspFsvolDeviceCompareContextByName; | static RTL_AVL_COMPARE_ROUTINE FspFsvolDeviceCompareContextByName; | ||||||
| static RTL_AVL_ALLOCATE_ROUTINE FspFsvolDeviceAllocateContextByName; | static RTL_AVL_ALLOCATE_ROUTINE FspFsvolDeviceAllocateContextByName; | ||||||
| static RTL_AVL_FREE_ROUTINE FspFsvolDeviceFreeContextByName; | static RTL_AVL_FREE_ROUTINE FspFsvolDeviceFreeContextByName; | ||||||
| VOID FspFsvolGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo); | VOID FspFsvolDeviceGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo); | ||||||
| BOOLEAN FspFsvolTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo); | BOOLEAN FspFsvolDeviceTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo); | ||||||
| VOID FspFsvolSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo); | VOID FspFsvolDeviceSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo); | ||||||
| NTSTATUS FspDeviceCopyList( | NTSTATUS FspDeviceCopyList( | ||||||
|     PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount); |     PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount); | ||||||
| VOID FspDeviceDeleteList( | VOID FspDeviceDeleteList( | ||||||
| @@ -346,6 +346,13 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject) | |||||||
|         return Result; |         return Result; | ||||||
|     FsvolDeviceExtension->InitDoneDir = 1; |     FsvolDeviceExtension->InitDoneDir = 1; | ||||||
|  |  | ||||||
|  |     /* initialize the FSRTL Notify mechanism */ | ||||||
|  |     Result = FspNotifyInitializeSync(&FsvolDeviceExtension->NotifySync); | ||||||
|  |     if (!NT_SUCCESS(Result)) | ||||||
|  |         return Result; | ||||||
|  |     InitializeListHead(&FsvolDeviceExtension->NotifyList); | ||||||
|  |     FsvolDeviceExtension->InitDoneNotify = 1; | ||||||
|  |  | ||||||
|     /* initialize our context table */ |     /* initialize our context table */ | ||||||
|     ExInitializeResourceLite(&FsvolDeviceExtension->FileRenameResource); |     ExInitializeResourceLite(&FsvolDeviceExtension->FileRenameResource); | ||||||
|     ExInitializeResourceLite(&FsvolDeviceExtension->ContextTableResource); |     ExInitializeResourceLite(&FsvolDeviceExtension->ContextTableResource); | ||||||
| @@ -395,6 +402,14 @@ static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject) | |||||||
|     if (FsvolDeviceExtension->InitDoneTimer) |     if (FsvolDeviceExtension->InitDoneTimer) | ||||||
|         IoStopTimer(DeviceObject); |         IoStopTimer(DeviceObject); | ||||||
|  |  | ||||||
|  |     /* uninitialize the FSRTL Notify mechanism */ | ||||||
|  |     if (FsvolDeviceExtension->InitDoneNotify) | ||||||
|  |     { | ||||||
|  |         FspNotifyCleanupAll( | ||||||
|  |             FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList); | ||||||
|  |         FspNotifyUninitializeSync(&FsvolDeviceExtension->NotifySync); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /* delete the directory meta cache */ |     /* delete the directory meta cache */ | ||||||
|     if (FsvolDeviceExtension->InitDoneDir) |     if (FsvolDeviceExtension->InitDoneDir) | ||||||
|         FspMetaCacheDelete(FsvolDeviceExtension->DirInfoCache); |         FspMetaCacheDelete(FsvolDeviceExtension->DirInfoCache); | ||||||
| @@ -753,7 +768,7 @@ static VOID NTAPI FspFsvolDeviceFreeContextByName( | |||||||
|     PAGED_CODE(); |     PAGED_CODE(); | ||||||
| } | } | ||||||
|  |  | ||||||
| VOID FspFsvolGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo) | VOID FspFsvolDeviceGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo) | ||||||
| { | { | ||||||
|     // !PAGED_CODE(); |     // !PAGED_CODE(); | ||||||
|  |  | ||||||
| @@ -770,7 +785,7 @@ VOID FspFsvolGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *V | |||||||
|  |  | ||||||
| #pragma warning(push) | #pragma warning(push) | ||||||
| #pragma warning(disable:4701) /* disable idiotic warning! */ | #pragma warning(disable:4701) /* disable idiotic warning! */ | ||||||
| BOOLEAN FspFsvolTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo) | BOOLEAN FspFsvolDeviceTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo) | ||||||
| { | { | ||||||
|     // !PAGED_CODE(); |     // !PAGED_CODE(); | ||||||
|  |  | ||||||
| @@ -796,7 +811,7 @@ BOOLEAN FspFsvolTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_I | |||||||
| } | } | ||||||
| #pragma warning(pop) | #pragma warning(pop) | ||||||
|  |  | ||||||
| VOID FspFsvolSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo) | VOID FspFsvolDeviceSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo) | ||||||
| { | { | ||||||
|     // !PAGED_CODE(); |     // !PAGED_CODE(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -571,7 +571,52 @@ static NTSTATUS FspFsvolNotifyChangeDirectory( | |||||||
| { | { | ||||||
|     PAGED_CODE(); |     PAGED_CODE(); | ||||||
|  |  | ||||||
|     return STATUS_INVALID_DEVICE_REQUEST; |     /* 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; | ||||||
|  |     ULONG CompletionFilter = IrpSp->Parameters.NotifyDirectory.CompletionFilter; | ||||||
|  |     BOOLEAN WatchTree = BooleanFlagOn(IrpSp->Flags, SL_WATCH_TREE); | ||||||
|  |     BOOLEAN DeletePending; | ||||||
|  |  | ||||||
|  |     ASSERT(FileNode == FileDesc->FileNode); | ||||||
|  |  | ||||||
|  |     /* only directory files can be watched */ | ||||||
|  |     if (!FileNode->IsDirectory) | ||||||
|  |         return STATUS_INVALID_PARAMETER; | ||||||
|  |  | ||||||
|  |     /* only processes with traverse privilege can watch trees! */ | ||||||
|  |     if (WatchTree && !FileDesc->HasTraversePrivilege) | ||||||
|  |         return STATUS_ACCESS_DENIED; | ||||||
|  |  | ||||||
|  |     /* stop now if the directory is pending deletion */ | ||||||
|  |     DeletePending = 0 != FileNode->DeletePending; | ||||||
|  |     MemoryBarrier(); | ||||||
|  |     if (DeletePending) | ||||||
|  |         return STATUS_DELETE_PENDING; | ||||||
|  |  | ||||||
|  |     FspFileNodeAcquireExclusive(FileNode, Main); | ||||||
|  |  | ||||||
|  |     Result = FspNotifyChangeDirectory( | ||||||
|  |         FsvolDeviceExtension->NotifySync, | ||||||
|  |         &FsvolDeviceExtension->NotifyList, | ||||||
|  |         FileDesc, | ||||||
|  |         &FileNode->FileName, | ||||||
|  |         WatchTree, | ||||||
|  |         CompletionFilter, | ||||||
|  |         Irp); | ||||||
|  |  | ||||||
|  |     FspFileNodeRelease(FileNode, Main); | ||||||
|  |  | ||||||
|  |     if (NT_SUCCESS(Result)) | ||||||
|  |         Result = STATUS_PENDING; | ||||||
|  |  | ||||||
|  |     return Result; | ||||||
| } | } | ||||||
|  |  | ||||||
| static NTSTATUS FspFsvolDirectoryControl( | static NTSTATUS FspFsvolDirectoryControl( | ||||||
|   | |||||||
| @@ -411,6 +411,40 @@ NTSTATUS FspCcMdlWriteComplete(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffse | |||||||
| NTSTATUS FspQuerySecurityDescriptorInfo(SECURITY_INFORMATION SecurityInformation, | NTSTATUS FspQuerySecurityDescriptorInfo(SECURITY_INFORMATION SecurityInformation, | ||||||
|     PSECURITY_DESCRIPTOR SecurityDescriptor, PULONG PLength, |     PSECURITY_DESCRIPTOR SecurityDescriptor, PULONG PLength, | ||||||
|     PSECURITY_DESCRIPTOR ObjectsSecurityDescriptor); |     PSECURITY_DESCRIPTOR ObjectsSecurityDescriptor); | ||||||
|  | NTSTATUS FspNotifyInitializeSync(PNOTIFY_SYNC *NotifySync); | ||||||
|  | NTSTATUS FspNotifyFullChangeDirectory( | ||||||
|  |     PNOTIFY_SYNC NotifySync, | ||||||
|  |     PLIST_ENTRY NotifyList, | ||||||
|  |     PVOID FsContext, | ||||||
|  |     PSTRING FullDirectoryName, | ||||||
|  |     BOOLEAN WatchTree, | ||||||
|  |     BOOLEAN IgnoreBuffer, | ||||||
|  |     ULONG CompletionFilter, | ||||||
|  |     PIRP NotifyIrp, | ||||||
|  |     PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback, | ||||||
|  |     PSECURITY_SUBJECT_CONTEXT SubjectContext); | ||||||
|  | NTSTATUS FspNotifyFullReportChange( | ||||||
|  |     PNOTIFY_SYNC NotifySync, | ||||||
|  |     PLIST_ENTRY NotifyList, | ||||||
|  |     PSTRING FullTargetName, | ||||||
|  |     USHORT TargetNameOffset, | ||||||
|  |     PSTRING StreamName, | ||||||
|  |     PSTRING NormalizedParentName, | ||||||
|  |     ULONG FilterMatch, | ||||||
|  |     ULONG Action, | ||||||
|  |     PVOID TargetContext); | ||||||
|  | #define FspNotifyUninitializeSync(NS)\ | ||||||
|  |     FsRtlNotifyUninitializeSync(NS) | ||||||
|  | #define FspNotifyCleanupAll(NS, NL)\ | ||||||
|  |     FsRtlNotifyCleanupAll(NS, NL) | ||||||
|  | #define FspNotifyChangeDirectory(NS, NL, FC, FN, WT, CF, I)\ | ||||||
|  |     FspNotifyFullChangeDirectory(NS, NL, FC, (PSTRING)FN, WT, FALSE, CF, I, 0, 0) | ||||||
|  | #define FspNotifyCleanup(NS, NL, FC)\ | ||||||
|  |     FsRtlNotifyCleanup(NS, NL, FC) | ||||||
|  | #define FspNotifyDeletePending(NS, NL, FC)\ | ||||||
|  |     FspNotifyFullChangeDirectory(NS, NL, FC, 0, 0, FALSE, 0, 0, 0, 0) | ||||||
|  | #define FspNotifyReportChange(NS, NL, FN, FO, SN, F, A)\ | ||||||
|  |     FspNotifyFullReportChange(NS, NL, (PSTRING)FN, FO, (PSTRING)SN, 0, F, A, 0) | ||||||
|  |  | ||||||
| /* utility: synchronous work queue */ | /* utility: synchronous work queue */ | ||||||
| typedef struct | typedef struct | ||||||
| @@ -665,7 +699,7 @@ typedef struct | |||||||
| { | { | ||||||
|     FSP_DEVICE_EXTENSION Base; |     FSP_DEVICE_EXTENSION Base; | ||||||
|     UINT32 InitDoneFsvrt:1, InitDoneDelRsc:1, InitDoneIoq:1, InitDoneSec:1, InitDoneDir:1, |     UINT32 InitDoneFsvrt:1, InitDoneDelRsc:1, InitDoneIoq:1, InitDoneSec:1, InitDoneDir:1, | ||||||
|         InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1; |         InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1, InitDoneNotify:1; | ||||||
|     PDEVICE_OBJECT FsctlDeviceObject; |     PDEVICE_OBJECT FsctlDeviceObject; | ||||||
|     PDEVICE_OBJECT FsvrtDeviceObject; |     PDEVICE_OBJECT FsvrtDeviceObject; | ||||||
|     HANDLE MupHandle; |     HANDLE MupHandle; | ||||||
| @@ -691,6 +725,8 @@ typedef struct | |||||||
|     KSPIN_LOCK InfoSpinLock; |     KSPIN_LOCK InfoSpinLock; | ||||||
|     UINT64 InfoExpirationTime; |     UINT64 InfoExpirationTime; | ||||||
|     FSP_FSCTL_VOLUME_INFO VolumeInfo; |     FSP_FSCTL_VOLUME_INFO VolumeInfo; | ||||||
|  |     PNOTIFY_SYNC NotifySync; | ||||||
|  |     LIST_ENTRY NotifyList; | ||||||
| } FSP_FSVOL_DEVICE_EXTENSION; | } FSP_FSVOL_DEVICE_EXTENSION; | ||||||
| static inline | static inline | ||||||
| FSP_DEVICE_EXTENSION *FspDeviceExtension(PDEVICE_OBJECT DeviceObject) | FSP_DEVICE_EXTENSION *FspDeviceExtension(PDEVICE_OBJECT DeviceObject) | ||||||
| @@ -733,9 +769,9 @@ PVOID FspFsvolDeviceInsertContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_ST | |||||||
|     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted); |     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted); | ||||||
| VOID FspFsvolDeviceDeleteContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, | VOID FspFsvolDeviceDeleteContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, | ||||||
|     PBOOLEAN PDeleted); |     PBOOLEAN PDeleted); | ||||||
| VOID FspFsvolGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo); | VOID FspFsvolDeviceGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo); | ||||||
| BOOLEAN FspFsvolTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo); | BOOLEAN FspFsvolDeviceTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo); | ||||||
| VOID FspFsvolSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo); | VOID FspFsvolDeviceSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo); | ||||||
| NTSTATUS FspDeviceCopyList( | NTSTATUS FspDeviceCopyList( | ||||||
|     PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount); |     PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount); | ||||||
| VOID FspDeviceDeleteList( | VOID FspDeviceDeleteList( | ||||||
| @@ -835,6 +871,7 @@ typedef struct | |||||||
|     FSP_FILE_NODE *FileNode; |     FSP_FILE_NODE *FileNode; | ||||||
|     UINT64 UserContext2; |     UINT64 UserContext2; | ||||||
|     BOOLEAN CaseSensitive; |     BOOLEAN CaseSensitive; | ||||||
|  |     BOOLEAN HasTraversePrivilege; | ||||||
|     BOOLEAN DeleteOnClose; |     BOOLEAN DeleteOnClose; | ||||||
|     BOOLEAN DirectoryHasSuchFile; |     BOOLEAN DirectoryHasSuchFile; | ||||||
|     UNICODE_STRING DirectoryPattern; |     UNICODE_STRING DirectoryPattern; | ||||||
| @@ -890,7 +927,8 @@ BOOLEAN FspFileNodeReferenceDirInfo(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PU | |||||||
| VOID FspFileNodeSetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size); | VOID FspFileNodeSetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size); | ||||||
| BOOLEAN FspFileNodeTrySetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size, | BOOLEAN FspFileNodeTrySetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size, | ||||||
|     ULONG DirInfoChangeNumber); |     ULONG DirInfoChangeNumber); | ||||||
| VOID FspFileNodeInvalidateParentDirInfo(FSP_FILE_NODE *FileNode); | VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, | ||||||
|  |     ULONG Filter, ULONG Action); | ||||||
| NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc); | NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc); | ||||||
| VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc); | VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc); | ||||||
| NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc, | NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc, | ||||||
|   | |||||||
| @@ -42,7 +42,9 @@ BOOLEAN FspFileNodeReferenceDirInfo(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PU | |||||||
| VOID FspFileNodeSetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size); | VOID FspFileNodeSetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size); | ||||||
| BOOLEAN FspFileNodeTrySetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size, | BOOLEAN FspFileNodeTrySetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size, | ||||||
|     ULONG DirInfoChangeNumber); |     ULONG DirInfoChangeNumber); | ||||||
| VOID FspFileNodeInvalidateParentDirInfo(FSP_FILE_NODE *FileNode); | static VOID FspFileNodeInvalidateDirInfo(FSP_FILE_NODE *FileNode); | ||||||
|  | VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, | ||||||
|  |     ULONG Filter, ULONG Action); | ||||||
| NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc); | NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc); | ||||||
| VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc); | VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc); | ||||||
| NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc, | NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc, | ||||||
| @@ -76,7 +78,8 @@ NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc, | |||||||
| // !#pragma alloc_text(PAGE, FspFileNodeReferenceDirInfo) | // !#pragma alloc_text(PAGE, FspFileNodeReferenceDirInfo) | ||||||
| // !#pragma alloc_text(PAGE, FspFileNodeSetDirInfo) | // !#pragma alloc_text(PAGE, FspFileNodeSetDirInfo) | ||||||
| // !#pragma alloc_text(PAGE, FspFileNodeTrySetDirInfo) | // !#pragma alloc_text(PAGE, FspFileNodeTrySetDirInfo) | ||||||
| // !#pragma alloc_text(PAGE, FspFileNodeInvalidateParentDirInfo) | // !#pragma alloc_text(PAGE, FspFileNodeInvalidateDirInfo) | ||||||
|  | #pragma alloc_text(PAGE, FspFileNodeNotifyChange) | ||||||
| #pragma alloc_text(PAGE, FspFileDescCreate) | #pragma alloc_text(PAGE, FspFileDescCreate) | ||||||
| #pragma alloc_text(PAGE, FspFileDescDelete) | #pragma alloc_text(PAGE, FspFileDescDelete) | ||||||
| #pragma alloc_text(PAGE, FspFileDescResetDirectoryPattern) | #pragma alloc_text(PAGE, FspFileDescResetDirectoryPattern) | ||||||
| @@ -814,7 +817,7 @@ VOID FspFileNodeSetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size) | |||||||
|         FspMetaCacheAddItem(FsvolDeviceExtension->DirInfoCache, Buffer, Size) : 0; |         FspMetaCacheAddItem(FsvolDeviceExtension->DirInfoCache, Buffer, Size) : 0; | ||||||
|     FileNode->DirInfoChangeNumber++; |     FileNode->DirInfoChangeNumber++; | ||||||
|  |  | ||||||
|     /* acquire the DirInfoSpinLock to protect against concurrent FspFileNodeInvalidateParentDirInfo*/ |     /* acquire the DirInfoSpinLock to protect against concurrent FspFileNodeInvalidateDirInfo */ | ||||||
|     KeAcquireSpinLock(&NonPaged->DirInfoSpinLock, &Irql); |     KeAcquireSpinLock(&NonPaged->DirInfoSpinLock, &Irql); | ||||||
|     NonPaged->DirInfo = DirInfo; |     NonPaged->DirInfo = DirInfo; | ||||||
|     KeReleaseSpinLock(&NonPaged->DirInfoSpinLock, Irql); |     KeReleaseSpinLock(&NonPaged->DirInfoSpinLock, Irql); | ||||||
| @@ -832,29 +835,17 @@ BOOLEAN FspFileNodeTrySetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG S | |||||||
|     return TRUE; |     return TRUE; | ||||||
| } | } | ||||||
|  |  | ||||||
| VOID FspFileNodeInvalidateParentDirInfo(FSP_FILE_NODE *FileNode) | static VOID FspFileNodeInvalidateDirInfo(FSP_FILE_NODE *FileNode) | ||||||
| { | { | ||||||
|     // !PAGED_CODE(); |     // !PAGED_CODE(); | ||||||
|  |  | ||||||
|     PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject; |     PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject; | ||||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); |     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); | ||||||
|     UNICODE_STRING Parent, Suffix; |     FSP_FILE_NODE_NONPAGED *NonPaged = FileNode->NonPaged; | ||||||
|     FSP_FILE_NODE_NONPAGED *NonPaged; |  | ||||||
|     KIRQL Irql; |     KIRQL Irql; | ||||||
|     UINT64 DirInfo; |     UINT64 DirInfo; | ||||||
|  |  | ||||||
|     FspUnicodePathSuffix(&FileNode->FileName, &Parent, &Suffix); |     /* acquire the DirInfoSpinLock to protect against concurrent FspFileNodeSetDirInfo */ | ||||||
|  |  | ||||||
|     FspFsvolDeviceLockContextTable(FsvolDeviceObject); |  | ||||||
|     FileNode = FspFsvolDeviceLookupContextByName(FsvolDeviceObject, &Parent); |  | ||||||
|     FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); |  | ||||||
|  |  | ||||||
|     if (0 == FileNode) |  | ||||||
|         return; |  | ||||||
|  |  | ||||||
|     NonPaged = FileNode->NonPaged; |  | ||||||
|  |  | ||||||
|     /* acquire the DirInfoSpinLock to protect against concurrent FspFileNodeSetDirInfo*/ |  | ||||||
|     KeAcquireSpinLock(&NonPaged->DirInfoSpinLock, &Irql); |     KeAcquireSpinLock(&NonPaged->DirInfoSpinLock, &Irql); | ||||||
|     DirInfo = NonPaged->DirInfo; |     DirInfo = NonPaged->DirInfo; | ||||||
|     KeReleaseSpinLock(&NonPaged->DirInfoSpinLock, Irql); |     KeReleaseSpinLock(&NonPaged->DirInfoSpinLock, Irql); | ||||||
| @@ -862,6 +853,46 @@ VOID FspFileNodeInvalidateParentDirInfo(FSP_FILE_NODE *FileNode) | |||||||
|     FspMetaCacheInvalidateItem(FsvolDeviceExtension->DirInfoCache, DirInfo); |     FspMetaCacheInvalidateItem(FsvolDeviceExtension->DirInfoCache, DirInfo); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, | ||||||
|  |     ULONG Filter, ULONG Action) | ||||||
|  | { | ||||||
|  |     PAGED_CODE(); | ||||||
|  |  | ||||||
|  |     PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject; | ||||||
|  |     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); | ||||||
|  |     UNICODE_STRING Parent, Suffix; | ||||||
|  |     FSP_FILE_NODE *ParentNode; | ||||||
|  |  | ||||||
|  |     FspUnicodePathSuffix(&FileNode->FileName, &Parent, &Suffix); | ||||||
|  |  | ||||||
|  |     switch (Action) | ||||||
|  |     { | ||||||
|  |     case FILE_ACTION_ADDED: | ||||||
|  |     case FILE_ACTION_REMOVED: | ||||||
|  |     case FILE_ACTION_MODIFIED: | ||||||
|  |     case FILE_ACTION_RENAMED_OLD_NAME: | ||||||
|  |     case FILE_ACTION_RENAMED_NEW_NAME: | ||||||
|  |         FspFsvolDeviceLockContextTable(FsvolDeviceObject); | ||||||
|  |         ParentNode = FspFsvolDeviceLookupContextByName(FsvolDeviceObject, &Parent); | ||||||
|  |         if (0 != ParentNode) | ||||||
|  |             FspFileNodeReference(ParentNode); | ||||||
|  |         FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); | ||||||
|  |  | ||||||
|  |         if (0 != ParentNode) | ||||||
|  |         { | ||||||
|  |             FspFileNodeInvalidateDirInfo(ParentNode); | ||||||
|  |             FspFileNodeReference(ParentNode); | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     FspNotifyReportChange( | ||||||
|  |         FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList, | ||||||
|  |         &FileNode->FileName, | ||||||
|  |         (USHORT)((PUINT8)Suffix.Buffer - (PUINT8)FileNode->FileName.Buffer), | ||||||
|  |         0, Filter, Action); | ||||||
|  | } | ||||||
|  |  | ||||||
| NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc) | NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc) | ||||||
| { | { | ||||||
|     PAGED_CODE(); |     PAGED_CODE(); | ||||||
|   | |||||||
| @@ -790,6 +790,17 @@ static NTSTATUS FspFsvolSetDispositionInformationSuccess( | |||||||
|     FileNode->DeletePending = Info->DeleteFile; |     FileNode->DeletePending = Info->DeleteFile; | ||||||
|     FileObject->DeletePending = Info->DeleteFile; |     FileObject->DeletePending = Info->DeleteFile; | ||||||
|  |  | ||||||
|  |     /* fastfat does this, although it seems unnecessary */ | ||||||
|  | #if 1 | ||||||
|  |     if (FileNode->IsDirectory && Info->DeleteFile) | ||||||
|  |     { | ||||||
|  |         FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = | ||||||
|  |             FspFsvolDeviceExtension(IrpSp->DeviceObject); | ||||||
|  |         FspNotifyDeletePending( | ||||||
|  |             FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList, FileNode); | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     FspIopRequestContext(Request, RequestFileNode) = 0; |     FspIopRequestContext(Request, RequestFileNode) = 0; | ||||||
|     FspFileNodeReleaseOwner(FileNode, Full, Request); |     FspFileNodeReleaseOwner(FileNode, Full, Request); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										120
									
								
								src/sys/util.c
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								src/sys/util.c
									
									
									
									
									
								
							| @@ -32,6 +32,28 @@ NTSTATUS FspCcMdlWriteComplete(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffse | |||||||
| NTSTATUS FspQuerySecurityDescriptorInfo(SECURITY_INFORMATION SecurityInformation, | NTSTATUS FspQuerySecurityDescriptorInfo(SECURITY_INFORMATION SecurityInformation, | ||||||
|     PSECURITY_DESCRIPTOR SecurityDescriptor, PULONG PLength, |     PSECURITY_DESCRIPTOR SecurityDescriptor, PULONG PLength, | ||||||
|     PSECURITY_DESCRIPTOR ObjectsSecurityDescriptor); |     PSECURITY_DESCRIPTOR ObjectsSecurityDescriptor); | ||||||
|  | NTSTATUS FspNotifyInitializeSync(PNOTIFY_SYNC *NotifySync); | ||||||
|  | NTSTATUS FspNotifyFullChangeDirectory( | ||||||
|  |     PNOTIFY_SYNC NotifySync, | ||||||
|  |     PLIST_ENTRY NotifyList, | ||||||
|  |     PVOID FsContext, | ||||||
|  |     PSTRING FullDirectoryName, | ||||||
|  |     BOOLEAN WatchTree, | ||||||
|  |     BOOLEAN IgnoreBuffer, | ||||||
|  |     ULONG CompletionFilter, | ||||||
|  |     PIRP NotifyIrp, | ||||||
|  |     PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback, | ||||||
|  |     PSECURITY_SUBJECT_CONTEXT SubjectContext); | ||||||
|  | NTSTATUS FspNotifyFullReportChange( | ||||||
|  |     PNOTIFY_SYNC NotifySync, | ||||||
|  |     PLIST_ENTRY NotifyList, | ||||||
|  |     PSTRING FullTargetName, | ||||||
|  |     USHORT TargetNameOffset, | ||||||
|  |     PSTRING StreamName, | ||||||
|  |     PSTRING NormalizedParentName, | ||||||
|  |     ULONG FilterMatch, | ||||||
|  |     ULONG Action, | ||||||
|  |     PVOID TargetContext); | ||||||
| VOID FspInitializeSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem, | VOID FspInitializeSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem, | ||||||
|     PWORKER_THREAD_ROUTINE Routine, PVOID Context); |     PWORKER_THREAD_ROUTINE Routine, PVOID Context); | ||||||
| VOID FspExecuteSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem); | VOID FspExecuteSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem); | ||||||
| @@ -62,6 +84,9 @@ VOID FspSafeMdlDelete(FSP_SAFE_MDL *SafeMdl); | |||||||
| #pragma alloc_text(PAGE, FspCcPrepareMdlWrite) | #pragma alloc_text(PAGE, FspCcPrepareMdlWrite) | ||||||
| #pragma alloc_text(PAGE, FspCcMdlWriteComplete) | #pragma alloc_text(PAGE, FspCcMdlWriteComplete) | ||||||
| #pragma alloc_text(PAGE, FspQuerySecurityDescriptorInfo) | #pragma alloc_text(PAGE, FspQuerySecurityDescriptorInfo) | ||||||
|  | #pragma alloc_text(PAGE, FspNotifyInitializeSync) | ||||||
|  | #pragma alloc_text(PAGE, FspNotifyFullChangeDirectory) | ||||||
|  | #pragma alloc_text(PAGE, FspNotifyFullReportChange) | ||||||
| #pragma alloc_text(PAGE, FspInitializeSynchronousWorkItem) | #pragma alloc_text(PAGE, FspInitializeSynchronousWorkItem) | ||||||
| #pragma alloc_text(PAGE, FspExecuteSynchronousWorkItem) | #pragma alloc_text(PAGE, FspExecuteSynchronousWorkItem) | ||||||
| #pragma alloc_text(PAGE, FspExecuteSynchronousWorkItemRoutine) | #pragma alloc_text(PAGE, FspExecuteSynchronousWorkItemRoutine) | ||||||
| @@ -525,6 +550,101 @@ NTSTATUS FspQuerySecurityDescriptorInfo(SECURITY_INFORMATION SecurityInformation | |||||||
|     return STATUS_BUFFER_TOO_SMALL == Result ? STATUS_BUFFER_OVERFLOW : Result; |     return STATUS_BUFFER_TOO_SMALL == Result ? STATUS_BUFFER_OVERFLOW : Result; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | NTSTATUS FspNotifyInitializeSync(PNOTIFY_SYNC *NotifySync) | ||||||
|  | { | ||||||
|  |     PAGED_CODE(); | ||||||
|  |  | ||||||
|  |     NTSTATUS Result; | ||||||
|  |  | ||||||
|  |     try | ||||||
|  |     { | ||||||
|  |         FsRtlNotifyInitializeSync(NotifySync); | ||||||
|  |         Result = STATUS_SUCCESS; | ||||||
|  |     } | ||||||
|  |     except (EXCEPTION_EXECUTE_HANDLER) | ||||||
|  |     { | ||||||
|  |         Result = GetExceptionCode(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return Result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | NTSTATUS FspNotifyFullChangeDirectory( | ||||||
|  |     PNOTIFY_SYNC NotifySync, | ||||||
|  |     PLIST_ENTRY NotifyList, | ||||||
|  |     PVOID FsContext, | ||||||
|  |     PSTRING FullDirectoryName, | ||||||
|  |     BOOLEAN WatchTree, | ||||||
|  |     BOOLEAN IgnoreBuffer, | ||||||
|  |     ULONG CompletionFilter, | ||||||
|  |     PIRP NotifyIrp, | ||||||
|  |     PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback, | ||||||
|  |     PSECURITY_SUBJECT_CONTEXT SubjectContext) | ||||||
|  | { | ||||||
|  |     PAGED_CODE(); | ||||||
|  |  | ||||||
|  |     NTSTATUS Result; | ||||||
|  |  | ||||||
|  |     try | ||||||
|  |     { | ||||||
|  |         FsRtlNotifyFullChangeDirectory( | ||||||
|  |             NotifySync, | ||||||
|  |             NotifyList, | ||||||
|  |             FsContext, | ||||||
|  |             FullDirectoryName, | ||||||
|  |             WatchTree, | ||||||
|  |             IgnoreBuffer, | ||||||
|  |             CompletionFilter, | ||||||
|  |             NotifyIrp, | ||||||
|  |             TraverseCallback, | ||||||
|  |             SubjectContext); | ||||||
|  |         Result = STATUS_SUCCESS; | ||||||
|  |     } | ||||||
|  |     except (EXCEPTION_EXECUTE_HANDLER) | ||||||
|  |     { | ||||||
|  |         Result = GetExceptionCode(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return Result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | NTSTATUS FspNotifyFullReportChange( | ||||||
|  |     PNOTIFY_SYNC NotifySync, | ||||||
|  |     PLIST_ENTRY NotifyList, | ||||||
|  |     PSTRING FullTargetName, | ||||||
|  |     USHORT TargetNameOffset, | ||||||
|  |     PSTRING StreamName, | ||||||
|  |     PSTRING NormalizedParentName, | ||||||
|  |     ULONG FilterMatch, | ||||||
|  |     ULONG Action, | ||||||
|  |     PVOID TargetContext) | ||||||
|  | { | ||||||
|  |     PAGED_CODE(); | ||||||
|  |  | ||||||
|  |     NTSTATUS Result; | ||||||
|  |  | ||||||
|  |     try | ||||||
|  |     { | ||||||
|  |         FspNotifyFullReportChange( | ||||||
|  |             NotifySync, | ||||||
|  |             NotifyList, | ||||||
|  |             FullTargetName, | ||||||
|  |             TargetNameOffset, | ||||||
|  |             StreamName, | ||||||
|  |             NormalizedParentName, | ||||||
|  |             FilterMatch, | ||||||
|  |             Action, | ||||||
|  |             TargetContext); | ||||||
|  |         Result = STATUS_SUCCESS; | ||||||
|  |     } | ||||||
|  |     except (EXCEPTION_EXECUTE_HANDLER) | ||||||
|  |     { | ||||||
|  |         Result = GetExceptionCode(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return Result; | ||||||
|  | } | ||||||
|  |  | ||||||
| VOID FspInitializeSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem, | VOID FspInitializeSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem, | ||||||
|     PWORKER_THREAD_ROUTINE Routine, PVOID Context) |     PWORKER_THREAD_ROUTINE Routine, PVOID Context) | ||||||
| { | { | ||||||
|   | |||||||
| @@ -50,7 +50,7 @@ FSP_DRIVER_DISPATCH FspSetVolumeInformation; | |||||||
|     FSP_FSCTL_VOLUME_INFO VolumeInfoBuf;\ |     FSP_FSCTL_VOLUME_INFO VolumeInfoBuf;\ | ||||||
|     if (0 == VolumeInfo)                \ |     if (0 == VolumeInfo)                \ | ||||||
|     {                                   \ |     {                                   \ | ||||||
|         if (!FspFsvolTryGetVolumeInfo(FsvolDeviceObject, &VolumeInfoBuf))\ |         if (!FspFsvolDeviceTryGetVolumeInfo(FsvolDeviceObject, &VolumeInfoBuf))\ | ||||||
|             return FSP_STATUS_IOQ_POST; \ |             return FSP_STATUS_IOQ_POST; \ | ||||||
|         VolumeInfo = &VolumeInfoBuf;    \ |         VolumeInfo = &VolumeInfoBuf;    \ | ||||||
|     } |     } | ||||||
| @@ -267,7 +267,7 @@ NTSTATUS FspFsvolQueryVolumeInformationComplete( | |||||||
|     PUINT8 Buffer = Irp->AssociatedIrp.SystemBuffer; |     PUINT8 Buffer = Irp->AssociatedIrp.SystemBuffer; | ||||||
|     PUINT8 BufferEnd = Buffer + IrpSp->Parameters.QueryFile.Length; |     PUINT8 BufferEnd = Buffer + IrpSp->Parameters.QueryFile.Length; | ||||||
|  |  | ||||||
|     FspFsvolSetVolumeInfo(FsvolDeviceObject, &Response->Rsp.QueryVolumeInformation.VolumeInfo); |     FspFsvolDeviceSetVolumeInfo(FsvolDeviceObject, &Response->Rsp.QueryVolumeInformation.VolumeInfo); | ||||||
|  |  | ||||||
|     switch (IrpSp->Parameters.QueryVolume.FsInformationClass) |     switch (IrpSp->Parameters.QueryVolume.FsInformationClass) | ||||||
|     { |     { | ||||||
| @@ -323,7 +323,7 @@ static NTSTATUS FspFsvolSetFsLabelInformation( | |||||||
|         ((PWSTR)Request->Buffer)[Info->VolumeLabelLength / sizeof(WCHAR)] = L'\0'; |         ((PWSTR)Request->Buffer)[Info->VolumeLabelLength / sizeof(WCHAR)] = L'\0'; | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|         FspFsvolSetVolumeInfo(FsvolDeviceObject, &Response->Rsp.SetVolumeInformation.VolumeInfo); |         FspFsvolDeviceSetVolumeInfo(FsvolDeviceObject, &Response->Rsp.SetVolumeInformation.VolumeInfo); | ||||||
|  |  | ||||||
|     return STATUS_SUCCESS; |     return STATUS_SUCCESS; | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user