sys: IRP_MN_NOTIFY_CHANGE_DIRECTORY: implementation and related changes

This commit is contained in:
Bill Zissimopoulos 2016-03-31 16:30:03 -07:00
parent fdb74e60ee
commit aa81e1ffe5
9 changed files with 308 additions and 33 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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();

View File

@ -571,7 +571,52 @@ static NTSTATUS FspFsvolNotifyChangeDirectory(
{ {
PAGED_CODE(); PAGED_CODE();
/* is this a valid FileObject? */
if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext))
return STATUS_INVALID_DEVICE_REQUEST; 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(

View File

@ -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,

View File

@ -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,28 +835,16 @@ 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);
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
FileNode = FspFsvolDeviceLookupContextByName(FsvolDeviceObject, &Parent);
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
if (0 == FileNode)
return;
NonPaged = FileNode->NonPaged;
/* acquire the DirInfoSpinLock to protect against concurrent FspFileNodeSetDirInfo */ /* acquire the DirInfoSpinLock to protect against concurrent FspFileNodeSetDirInfo */
KeAcquireSpinLock(&NonPaged->DirInfoSpinLock, &Irql); KeAcquireSpinLock(&NonPaged->DirInfoSpinLock, &Irql);
DirInfo = NonPaged->DirInfo; DirInfo = NonPaged->DirInfo;
@ -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();

View File

@ -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);

View File

@ -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)
{ {

View File

@ -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;
} }