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 */
|
||||
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
|
||||
|
@ -1866,3 +1866,9 @@ FSP_API BOOLEAN FspFileSystemAddEa(PFILE_FULL_EA_INFORMATION SingleEa,
|
||||
|
||||
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
|
||||
{
|
||||
PDEVICE_OBJECT FsvolDeviceObject;
|
||||
PVOID InputBuffer;
|
||||
ULONG InputBufferLength;
|
||||
WORK_QUEUE_ITEM WorkItem;
|
||||
PDEVICE_OBJECT FsvolDeviceObject;
|
||||
ULONG InputBufferLength;
|
||||
FSP_FSCTL_DECLSPEC_ALIGN UINT8 InputBuffer[];
|
||||
} FSP_VOLUME_NOTIFY_WORK_ITEM;
|
||||
|
||||
NTSTATUS FspVolumeNotify(
|
||||
@ -1108,22 +1108,14 @@ NTSTATUS FspVolumeNotify(
|
||||
if (!FspDeviceReference(FsvolDeviceObject))
|
||||
return STATUS_CANCELLED;
|
||||
|
||||
NotifyWorkItem = FspAllocNonPaged(sizeof *NotifyWorkItem);
|
||||
NotifyWorkItem = FspAllocNonPaged(
|
||||
FIELD_OFFSET(FSP_VOLUME_NOTIFY_WORK_ITEM, InputBuffer) + InputBufferLength);
|
||||
if (0 == NotifyWorkItem)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
NotifyWorkItem->FsvolDeviceObject = FsvolDeviceObject;
|
||||
|
||||
NotifyWorkItem->InputBuffer = FspAllocNonPaged(InputBufferLength);
|
||||
if (0 == NotifyWorkItem->InputBuffer)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ProbeForRead(InputBuffer, InputBufferLength, 1);
|
||||
@ -1138,17 +1130,14 @@ NTSTATUS FspVolumeNotify(
|
||||
}
|
||||
|
||||
ExInitializeWorkItem(&NotifyWorkItem->WorkItem, FspVolumeNotifyWork, NotifyWorkItem);
|
||||
NotifyWorkItem->FsvolDeviceObject = FsvolDeviceObject;
|
||||
ExQueueWorkItem(&NotifyWorkItem->WorkItem, DelayedWorkQueue);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
fail:
|
||||
if (0 != NotifyWorkItem)
|
||||
{
|
||||
if (0 != NotifyWorkItem->InputBuffer)
|
||||
FspFree(NotifyWorkItem->InputBuffer);
|
||||
FspFree(NotifyWorkItem);
|
||||
}
|
||||
|
||||
FspDeviceDereference(FsvolDeviceObject);
|
||||
|
||||
@ -1202,7 +1191,7 @@ static VOID FspVolumeNotifyWork(PVOID NotifyWorkItem0)
|
||||
FSP_VOLUME_NOTIFY_WORK_ITEM *NotifyWorkItem = NotifyWorkItem0;
|
||||
PDEVICE_OBJECT FsvolDeviceObject = NotifyWorkItem->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;
|
||||
ULONG NotifyInfoSize;
|
||||
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)
|
||||
{
|
||||
/* !!!: we should wait until all pending notify work is done! */
|
||||
if (1 == InterlockedCompareExchange(&FsvolDeviceExtension->VolumeNotifyLock, 0, 1))
|
||||
FspFsvolDeviceFileRenameReleaseOwner(FsvolDeviceObject, FsvolDeviceObject);
|
||||
break;
|
||||
@ -1257,7 +1247,7 @@ static VOID FspVolumeNotifyWork(PVOID NotifyWorkItem0)
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
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"\\");
|
||||
}
|
||||
if (NT_SUCCESS(Result))
|
||||
@ -1273,7 +1263,6 @@ static VOID FspVolumeNotifyWork(PVOID NotifyWorkItem0)
|
||||
if (0 != FullFileName.Buffer)
|
||||
FspFree(FullFileName.Buffer);
|
||||
|
||||
FspFree(NotifyWorkItem->InputBuffer);
|
||||
FspFree(NotifyWorkItem);
|
||||
|
||||
FspDeviceDereference(FsvolDeviceObject);
|
||||
|
@ -151,6 +151,109 @@ void notify_timeout_test(void)
|
||||
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)
|
||||
{
|
||||
if (!OptExternal)
|
||||
@ -158,5 +261,6 @@ void notify_tests(void)
|
||||
TEST(notify_abandon_test);
|
||||
TEST(notify_abandon_rename_test);
|
||||
TEST(notify_timeout_test);
|
||||
TEST(notify_change_test);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user