mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
sys: notify implementation
This commit is contained in:
parent
88edf5723e
commit
a004e4be10
@ -1699,6 +1699,28 @@ UINT32 FspFileSystemGetEaPackedSize(PFILE_FULL_EA_INFORMATION SingleEa)
|
|||||||
/* magic computations are courtesy of NTFS */
|
/* magic computations are courtesy of NTFS */
|
||||||
return 5 + SingleEa->EaNameLength + SingleEa->EaValueLength;
|
return 5 + SingleEa->EaNameLength + SingleEa->EaValueLength;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Add notify information to a buffer.
|
||||||
|
*
|
||||||
|
* This is a helper for filling a buffer to use with FspFileSystemNotify.
|
||||||
|
*
|
||||||
|
* @param NotifyInfo
|
||||||
|
* The notify information to add.
|
||||||
|
* @param Buffer
|
||||||
|
* Pointer to a buffer that will receive the notify information.
|
||||||
|
* @param Length
|
||||||
|
* Length of buffer.
|
||||||
|
* @param PBytesTransferred [out]
|
||||||
|
* Pointer to a memory location that will receive the actual number of bytes stored. This should
|
||||||
|
* be initialized to 0 prior to the first call to FspFileSystemAddNotifyInfo for a particular
|
||||||
|
* buffer.
|
||||||
|
* @return
|
||||||
|
* TRUE if the notify information was added, FALSE if there was not enough space to add it.
|
||||||
|
* @see
|
||||||
|
* FspFileSystemNotify
|
||||||
|
*/
|
||||||
|
FSP_API BOOLEAN FspFileSystemAddNotifyInfo(FSP_FSCTL_NOTIFY_INFO *NotifyInfo,
|
||||||
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Directory buffering
|
* Directory buffering
|
||||||
|
@ -1866,3 +1866,9 @@ FSP_API BOOLEAN FspFileSystemAddEa(PFILE_FULL_EA_INFORMATION SingleEa,
|
|||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API BOOLEAN FspFileSystemAddNotifyInfo(FSP_FSCTL_NOTIFY_INFO *NotifyInfo,
|
||||||
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
|
||||||
|
{
|
||||||
|
return FspFileSystemAddXxxInfo(NotifyInfo, Buffer, Length, PBytesTransferred);
|
||||||
|
}
|
||||||
|
@ -1068,10 +1068,10 @@ NTSTATUS FspVolumeStop(
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT FsvolDeviceObject;
|
|
||||||
PVOID InputBuffer;
|
|
||||||
ULONG InputBufferLength;
|
|
||||||
WORK_QUEUE_ITEM WorkItem;
|
WORK_QUEUE_ITEM WorkItem;
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject;
|
||||||
|
ULONG InputBufferLength;
|
||||||
|
FSP_FSCTL_DECLSPEC_ALIGN UINT8 InputBuffer[];
|
||||||
} FSP_VOLUME_NOTIFY_WORK_ITEM;
|
} FSP_VOLUME_NOTIFY_WORK_ITEM;
|
||||||
|
|
||||||
NTSTATUS FspVolumeNotify(
|
NTSTATUS FspVolumeNotify(
|
||||||
@ -1108,22 +1108,14 @@ NTSTATUS FspVolumeNotify(
|
|||||||
if (!FspDeviceReference(FsvolDeviceObject))
|
if (!FspDeviceReference(FsvolDeviceObject))
|
||||||
return STATUS_CANCELLED;
|
return STATUS_CANCELLED;
|
||||||
|
|
||||||
NotifyWorkItem = FspAllocNonPaged(sizeof *NotifyWorkItem);
|
NotifyWorkItem = FspAllocNonPaged(
|
||||||
|
FIELD_OFFSET(FSP_VOLUME_NOTIFY_WORK_ITEM, InputBuffer) + InputBufferLength);
|
||||||
if (0 == NotifyWorkItem)
|
if (0 == NotifyWorkItem)
|
||||||
{
|
{
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
NotifyWorkItem->FsvolDeviceObject = FsvolDeviceObject;
|
|
||||||
|
|
||||||
NotifyWorkItem->InputBuffer = FspAllocNonPaged(InputBufferLength);
|
|
||||||
if (0 == NotifyWorkItem->InputBuffer)
|
|
||||||
{
|
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ProbeForRead(InputBuffer, InputBufferLength, 1);
|
ProbeForRead(InputBuffer, InputBufferLength, 1);
|
||||||
@ -1138,17 +1130,14 @@ NTSTATUS FspVolumeNotify(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExInitializeWorkItem(&NotifyWorkItem->WorkItem, FspVolumeNotifyWork, NotifyWorkItem);
|
ExInitializeWorkItem(&NotifyWorkItem->WorkItem, FspVolumeNotifyWork, NotifyWorkItem);
|
||||||
|
NotifyWorkItem->FsvolDeviceObject = FsvolDeviceObject;
|
||||||
ExQueueWorkItem(&NotifyWorkItem->WorkItem, DelayedWorkQueue);
|
ExQueueWorkItem(&NotifyWorkItem->WorkItem, DelayedWorkQueue);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (0 != NotifyWorkItem)
|
if (0 != NotifyWorkItem)
|
||||||
{
|
|
||||||
if (0 != NotifyWorkItem->InputBuffer)
|
|
||||||
FspFree(NotifyWorkItem->InputBuffer);
|
|
||||||
FspFree(NotifyWorkItem);
|
FspFree(NotifyWorkItem);
|
||||||
}
|
|
||||||
|
|
||||||
FspDeviceDereference(FsvolDeviceObject);
|
FspDeviceDereference(FsvolDeviceObject);
|
||||||
|
|
||||||
@ -1202,7 +1191,7 @@ static VOID FspVolumeNotifyWork(PVOID NotifyWorkItem0)
|
|||||||
FSP_VOLUME_NOTIFY_WORK_ITEM *NotifyWorkItem = NotifyWorkItem0;
|
FSP_VOLUME_NOTIFY_WORK_ITEM *NotifyWorkItem = NotifyWorkItem0;
|
||||||
PDEVICE_OBJECT FsvolDeviceObject = NotifyWorkItem->FsvolDeviceObject;
|
PDEVICE_OBJECT FsvolDeviceObject = NotifyWorkItem->FsvolDeviceObject;
|
||||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
FSP_FSCTL_NOTIFY_INFO *NotifyInfo = NotifyWorkItem->InputBuffer;
|
FSP_FSCTL_NOTIFY_INFO *NotifyInfo = (PVOID)NotifyWorkItem->InputBuffer;
|
||||||
PUINT8 NotifyInfoEnd = (PUINT8)NotifyInfo + NotifyWorkItem->InputBufferLength;
|
PUINT8 NotifyInfoEnd = (PUINT8)NotifyInfo + NotifyWorkItem->InputBufferLength;
|
||||||
ULONG NotifyInfoSize;
|
ULONG NotifyInfoSize;
|
||||||
UNICODE_STRING FileName = { 0 }, StreamPart = { 0 }, AbsFileName = { 0 }, FullFileName = { 0 };
|
UNICODE_STRING FileName = { 0 }, StreamPart = { 0 }, AbsFileName = { 0 }, FullFileName = { 0 };
|
||||||
@ -1217,6 +1206,7 @@ static VOID FspVolumeNotifyWork(PVOID NotifyWorkItem0)
|
|||||||
|
|
||||||
if (sizeof(FSP_FSCTL_NOTIFY_INFO) > NotifyInfoSize)
|
if (sizeof(FSP_FSCTL_NOTIFY_INFO) > NotifyInfoSize)
|
||||||
{
|
{
|
||||||
|
/* !!!: we should wait until all pending notify work is done! */
|
||||||
if (1 == InterlockedCompareExchange(&FsvolDeviceExtension->VolumeNotifyLock, 0, 1))
|
if (1 == InterlockedCompareExchange(&FsvolDeviceExtension->VolumeNotifyLock, 0, 1))
|
||||||
FspFsvolDeviceFileRenameReleaseOwner(FsvolDeviceObject, FsvolDeviceObject);
|
FspFsvolDeviceFileRenameReleaseOwner(FsvolDeviceObject, FsvolDeviceObject);
|
||||||
break;
|
break;
|
||||||
@ -1257,7 +1247,7 @@ static VOID FspVolumeNotifyWork(PVOID NotifyWorkItem0)
|
|||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
if (sizeof(WCHAR) * 2/* not empty or root */ <= AbsFileName.Length &&
|
if (sizeof(WCHAR) * 2/* not empty or root */ <= AbsFileName.Length &&
|
||||||
L'\\' == AbsFileName.Buffer[AbsFileName.Length / sizeof(WCHAR) - 1])
|
L'\\' != AbsFileName.Buffer[AbsFileName.Length / sizeof(WCHAR) - 1])
|
||||||
Result = RtlAppendUnicodeToString(&FullFileName, L"\\");
|
Result = RtlAppendUnicodeToString(&FullFileName, L"\\");
|
||||||
}
|
}
|
||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
@ -1273,7 +1263,6 @@ static VOID FspVolumeNotifyWork(PVOID NotifyWorkItem0)
|
|||||||
if (0 != FullFileName.Buffer)
|
if (0 != FullFileName.Buffer)
|
||||||
FspFree(FullFileName.Buffer);
|
FspFree(FullFileName.Buffer);
|
||||||
|
|
||||||
FspFree(NotifyWorkItem->InputBuffer);
|
|
||||||
FspFree(NotifyWorkItem);
|
FspFree(NotifyWorkItem);
|
||||||
|
|
||||||
FspDeviceDereference(FsvolDeviceObject);
|
FspDeviceDereference(FsvolDeviceObject);
|
||||||
|
@ -151,6 +151,109 @@ void notify_timeout_test(void)
|
|||||||
notify_timeout_dotest(MemfsNet);
|
notify_timeout_dotest(MemfsNet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void notify_change_dotest(ULONG Flags)
|
||||||
|
{
|
||||||
|
void *memfs = memfs_start(Flags);
|
||||||
|
FSP_FILE_SYSTEM *FileSystem = MemfsFileSystem(memfs);
|
||||||
|
union
|
||||||
|
{
|
||||||
|
FSP_FSCTL_NOTIFY_INFO V;
|
||||||
|
UINT8 B[1024];
|
||||||
|
} Buffer;
|
||||||
|
ULONG Length = 0;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
FSP_FSCTL_NOTIFY_INFO V;
|
||||||
|
UINT8 B[sizeof(FSP_FSCTL_NOTIFY_INFO) + MAX_PATH * sizeof(WCHAR)];
|
||||||
|
} NotifyInfo;
|
||||||
|
PWSTR FileName;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
Result = FspFileSystemNotifyBegin(FileSystem, 0);
|
||||||
|
ASSERT(STATUS_SUCCESS == Result);
|
||||||
|
|
||||||
|
FileName = L"\\";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = 0;
|
||||||
|
NotifyInfo.V.Action = 0;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
FileName = L"bar";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = 0;
|
||||||
|
NotifyInfo.V.Action = 0;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
FileName = L"baz";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = 0;
|
||||||
|
NotifyInfo.V.Action = 0;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
FileName = L"\\foo";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = 0;
|
||||||
|
NotifyInfo.V.Action = 0;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
FileName = L"bar";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = 0;
|
||||||
|
NotifyInfo.V.Action = 0;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
FileName = L"baz";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = 0;
|
||||||
|
NotifyInfo.V.Action = 0;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
FileName = L"\\foo\\";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = 0;
|
||||||
|
NotifyInfo.V.Action = 0;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
FileName = L"bar";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = 0;
|
||||||
|
NotifyInfo.V.Action = 0;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
FileName = L"baz";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = 0;
|
||||||
|
NotifyInfo.V.Action = 0;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
Result = FspFileSystemNotify(FileSystem, &Buffer.V, Length);
|
||||||
|
ASSERT(STATUS_SUCCESS == Result);
|
||||||
|
|
||||||
|
Result = FspFileSystemNotifyEnd(FileSystem);
|
||||||
|
ASSERT(STATUS_SUCCESS == Result);
|
||||||
|
|
||||||
|
memfs_stop(memfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void notify_change_test(void)
|
||||||
|
{
|
||||||
|
if (WinFspDiskTests)
|
||||||
|
notify_change_dotest(MemfsDisk);
|
||||||
|
if (WinFspNetTests)
|
||||||
|
notify_change_dotest(MemfsNet);
|
||||||
|
}
|
||||||
|
|
||||||
void notify_tests(void)
|
void notify_tests(void)
|
||||||
{
|
{
|
||||||
if (!OptExternal)
|
if (!OptExternal)
|
||||||
@ -158,5 +261,6 @@ void notify_tests(void)
|
|||||||
TEST(notify_abandon_test);
|
TEST(notify_abandon_test);
|
||||||
TEST(notify_abandon_rename_test);
|
TEST(notify_abandon_rename_test);
|
||||||
TEST(notify_timeout_test);
|
TEST(notify_timeout_test);
|
||||||
|
TEST(notify_change_test);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user