sys,dll: DeviceControl operation

This commit is contained in:
Bill Zissimopoulos 2018-05-04 13:56:20 -07:00
parent 7aadf259d9
commit 894ae7b8f3
No known key found for this signature in database
GPG Key ID: 3D4F95D52C7B3EA3
10 changed files with 296 additions and 5 deletions

View File

@ -182,6 +182,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\..\..\tst\memfs\memfs.cpp" /> <ClCompile Include="..\..\..\tst\memfs\memfs.cpp" />
<ClCompile Include="..\..\..\tst\winfsp-tests\create-test.c" /> <ClCompile Include="..\..\..\tst\winfsp-tests\create-test.c" />
<ClCompile Include="..\..\..\tst\winfsp-tests\devctl-test.c" />
<ClCompile Include="..\..\..\tst\winfsp-tests\dirbuf-test.c" /> <ClCompile Include="..\..\..\tst\winfsp-tests\dirbuf-test.c" />
<ClCompile Include="..\..\..\tst\winfsp-tests\dirctl-test.c" /> <ClCompile Include="..\..\..\tst\winfsp-tests\dirctl-test.c" />
<ClCompile Include="..\..\..\tst\winfsp-tests\eventlog-test.c" /> <ClCompile Include="..\..\..\tst\winfsp-tests\eventlog-test.c" />

View File

@ -88,6 +88,9 @@
<ClCompile Include="..\..\..\tst\winfsp-tests\launch-test.c"> <ClCompile Include="..\..\..\tst\winfsp-tests\launch-test.c">
<Filter>Source</Filter> <Filter>Source</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\..\tst\winfsp-tests\devctl-test.c">
<Filter>Source</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\..\ext\tlib\testsuite.h"> <ClInclude Include="..\..\..\ext\tlib\testsuite.h">

View File

@ -82,6 +82,8 @@ FSP_FSCTL_STATIC_ASSERT(FSP_FSCTL_VOLUME_NAME_SIZEMAX <= 260 * sizeof(WCHAR),
#define FSP_FSCTL_TRANSACT_REQ_TOKEN_HANDLE(T) ((HANDLE)((T) & 0xffffffff)) #define FSP_FSCTL_TRANSACT_REQ_TOKEN_HANDLE(T) ((HANDLE)((T) & 0xffffffff))
#define FSP_FSCTL_TRANSACT_REQ_TOKEN_PID(T) ((UINT32)(((T) >> 32) & 0xffffffff)) #define FSP_FSCTL_TRANSACT_REQ_TOKEN_PID(T) ((UINT32)(((T) >> 32) & 0xffffffff))
#define FSP_FSCTL_DEVICECONTROL_SIZEMAX (4 * 1024) /* must be < FSP_FSCTL_TRANSACT_{REQ,RSP}_SIZEMAX */
/* marshalling */ /* marshalling */
#pragma warning(push) #pragma warning(push)
#pragma warning(disable:4200) /* zero-sized array in struct/union */ #pragma warning(disable:4200) /* zero-sized array in struct/union */
@ -154,11 +156,13 @@ enum
UINT32 AlwaysUseDoubleBuffering:1;\ UINT32 AlwaysUseDoubleBuffering:1;\
UINT32 PassQueryDirectoryFileName:1; /* pass FileName during QueryDirectory (GetDirInfoByName) */\ UINT32 PassQueryDirectoryFileName:1; /* pass FileName during QueryDirectory (GetDirInfoByName) */\
UINT32 FlushAndPurgeOnCleanup:1; /* keeps file off "standby" list */\ UINT32 FlushAndPurgeOnCleanup:1; /* keeps file off "standby" list */\
UINT32 KmReservedFlags:1;\ UINT32 DeviceControl:1; /* support user-mode ioctl handling */\
/* user-mode flags */\ /* user-mode flags */\
UINT32 UmFileContextIsUserContext2:1; /* user mode: FileContext parameter is UserContext2 */\ UINT32 UmFileContextIsUserContext2:1; /* user mode: FileContext parameter is UserContext2 */\
UINT32 UmFileContextIsFullContext:1; /* user mode: FileContext parameter is FullContext */\ UINT32 UmFileContextIsFullContext:1; /* user mode: FileContext parameter is FullContext */\
UINT32 UmReservedFlags:14;\ UINT32 UmReservedFlags:6;\
/* additional kernel-mode flags */\
UINT32 KmReservedFlags:8;\
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)];
#define FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN\ #define FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN\
@ -381,6 +385,14 @@ typedef struct
UINT16 TargetOnFileSystem; /* the target of the symbolic link is on this file system */ UINT16 TargetOnFileSystem; /* the target of the symbolic link is on this file system */
} FileSystemControl; } FileSystemControl;
struct struct
{
UINT64 UserContext;
UINT64 UserContext2;
UINT32 IoControlCode;
FSP_FSCTL_TRANSACT_BUF Buffer;
UINT32 OutputLength;
} DeviceControl;
struct
{ {
UINT64 UserContext; UINT64 UserContext;
UINT64 UserContext2; UINT64 UserContext2;
@ -466,6 +478,10 @@ typedef struct
FSP_FSCTL_TRANSACT_BUF Buffer; FSP_FSCTL_TRANSACT_BUF Buffer;
} FileSystemControl; } FileSystemControl;
struct struct
{
FSP_FSCTL_TRANSACT_BUF Buffer;
} DeviceControl;
struct
{ {
FSP_FSCTL_TRANSACT_BUF SecurityDescriptor; FSP_FSCTL_TRANSACT_BUF SecurityDescriptor;
} QuerySecurity; } QuerySecurity;

View File

@ -822,12 +822,41 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
NTSTATUS (*GetDirInfoByName)(FSP_FILE_SYSTEM *FileSystem, NTSTATUS (*GetDirInfoByName)(FSP_FILE_SYSTEM *FileSystem,
PVOID FileContext, PWSTR FileName, PVOID FileContext, PWSTR FileName,
FSP_FSCTL_DIR_INFO *DirInfo); FSP_FSCTL_DIR_INFO *DirInfo);
/**
* Process control code.
*
* This function is called when a program uses the DeviceIoControl API.
*
* @param FileSystem
* The file system on which this request is posted.
* @param FileContext
* The file context of the file or directory to be controled.
* @param ControlCode
* The control code for the operation. This code must have a DeviceType with bit
* 0x8000 set and must have a TransferType of METHOD_BUFFERED.
* @param InputBuffer
* Pointer to a buffer that contains the input data.
* @param InputBufferLength
* Input data length.
* @param Buffer
* Pointer to a buffer that will receive the output data.
* @param Length
* Output data length.
* @param PBytesTransferred [out]
* Pointer to a memory location that will receive the actual number of bytes transferred.
* @return
* STATUS_SUCCESS or error code.
*/
NTSTATUS (*Control)(FSP_FILE_SYSTEM *FileSystem,
PVOID FileContext, UINT32 ControlCode,
PVOID InputBuffer, ULONG InputBufferLength,
PVOID OutputBuffer, ULONG OutputBufferLength, PULONG PBytesTransferred);
/* /*
* 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[39])(); NTSTATUS (*Reserved[38])();
} 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.");
@ -1141,6 +1170,8 @@ FSP_API NTSTATUS FspFileSystemOpQueryDirectory(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 FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem, FSP_API NTSTATUS FspFileSystemOpFileSystemControl(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 FspFileSystemOpDeviceControl(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
FSP_API NTSTATUS FspFileSystemOpQuerySecurity(FSP_FILE_SYSTEM *FileSystem, FSP_API NTSTATUS FspFileSystemOpQuerySecurity(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 FspFileSystemOpSetSecurity(FSP_FILE_SYSTEM *FileSystem, FSP_API NTSTATUS FspFileSystemOpSetSecurity(FSP_FILE_SYSTEM *FileSystem,

View File

@ -162,6 +162,7 @@ FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath,
FileSystem->Operations[FspFsctlTransactSetVolumeInformationKind] = FspFileSystemOpSetVolumeInformation; FileSystem->Operations[FspFsctlTransactSetVolumeInformationKind] = FspFileSystemOpSetVolumeInformation;
FileSystem->Operations[FspFsctlTransactQueryDirectoryKind] = FspFileSystemOpQueryDirectory; FileSystem->Operations[FspFsctlTransactQueryDirectoryKind] = FspFileSystemOpQueryDirectory;
FileSystem->Operations[FspFsctlTransactFileSystemControlKind] = FspFileSystemOpFileSystemControl; FileSystem->Operations[FspFsctlTransactFileSystemControlKind] = FspFileSystemOpFileSystemControl;
FileSystem->Operations[FspFsctlTransactDeviceControlKind] = FspFileSystemOpDeviceControl;
FileSystem->Operations[FspFsctlTransactQuerySecurityKind] = FspFileSystemOpQuerySecurity; FileSystem->Operations[FspFsctlTransactQuerySecurityKind] = FspFileSystemOpQuerySecurity;
FileSystem->Operations[FspFsctlTransactSetSecurityKind] = FspFileSystemOpSetSecurity; FileSystem->Operations[FspFsctlTransactSetSecurityKind] = FspFileSystemOpSetSecurity;
FileSystem->Operations[FspFsctlTransactQueryStreamInformationKind] = FspFileSystemOpQueryStreamInformation; FileSystem->Operations[FspFsctlTransactQueryStreamInformationKind] = FspFileSystemOpQueryStreamInformation;

View File

@ -1247,6 +1247,30 @@ FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
return Result; return Result;
} }
FSP_API NTSTATUS FspFileSystemOpDeviceControl(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
{
NTSTATUS Result;
ULONG BytesTransferred;
if (0 == FileSystem->Interface->Control)
return STATUS_INVALID_DEVICE_REQUEST;
Result = FileSystem->Interface->Control(FileSystem,
(PVOID)ValOfFileContext(Request->Req.DeviceControl),
Request->Req.DeviceControl.IoControlCode,
Request->Buffer, Request->Req.DeviceControl.Buffer.Size,
Response->Buffer, Request->Req.DeviceControl.OutputLength/* FSD guarantees correct size! */,
&BytesTransferred);
if (!NT_SUCCESS(Result))
return STATUS_BUFFER_OVERFLOW != Result ? Result : STATUS_BUFFER_TOO_SMALL;
Response->Size = (UINT16)(sizeof *Response + BytesTransferred);
Response->Rsp.DeviceControl.Buffer.Offset = 0;
Response->Rsp.DeviceControl.Buffer.Size = (UINT16)BytesTransferred;
return STATUS_SUCCESS;
}
FSP_API NTSTATUS FspFileSystemOpQuerySecurity(FSP_FILE_SYSTEM *FileSystem, FSP_API NTSTATUS FspFileSystemOpQuerySecurity(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
{ {

View File

@ -20,20 +20,81 @@
static NTSTATUS FspFsvolDeviceControl( static NTSTATUS FspFsvolDeviceControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
FSP_IOCMPL_DISPATCH FspFsvolDeviceControlComplete; FSP_IOCMPL_DISPATCH FspFsvolDeviceControlComplete;
static FSP_IOP_REQUEST_FINI FspFsvolDeviceControlRequestFini;
FSP_DRIVER_DISPATCH FspDeviceControl; FSP_DRIVER_DISPATCH FspDeviceControl;
#ifdef ALLOC_PRAGMA #ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFsvolDeviceControl) #pragma alloc_text(PAGE, FspFsvolDeviceControl)
#pragma alloc_text(PAGE, FspFsvolDeviceControlComplete) #pragma alloc_text(PAGE, FspFsvolDeviceControlComplete)
#pragma alloc_text(PAGE, FspFsvolDeviceControlRequestFini)
#pragma alloc_text(PAGE, FspDeviceControl) #pragma alloc_text(PAGE, FspDeviceControl)
#endif #endif
enum
{
RequestFileNode = 0,
};
static NTSTATUS FspFsvolDeviceControl( static NTSTATUS FspFsvolDeviceControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{ {
PAGED_CODE(); PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
PFILE_OBJECT FileObject = IrpSp->FileObject;
ULONG IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
/* do we support DeviceControl? */
if (!FsvolDeviceExtension->VolumeParams.DeviceControl)
return STATUS_INVALID_DEVICE_REQUEST; return STATUS_INVALID_DEVICE_REQUEST;
/* do not forward IRP's originating in the kernel! */
if (KernelMode == Irp->RequestorMode)
return STATUS_INVALID_DEVICE_REQUEST;
/* only allow custom devices and METHOD_BUFFERED */
if (0 == (DEVICE_TYPE_FROM_CTL_CODE(IoControlCode) & 0x8000) ||
METHOD_BUFFERED != METHOD_FROM_CTL_CODE(IoControlCode))
return STATUS_INVALID_DEVICE_REQUEST;
/* is this a valid FileObject? */
if (!FspFileNodeIsValid(FileObject->FsContext))
return STATUS_INVALID_PARAMETER;
NTSTATUS Result;
FSP_FILE_NODE *FileNode = FileObject->FsContext;
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
PVOID InputBuffer = Irp->AssociatedIrp.SystemBuffer;
ULONG InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
FSP_FSCTL_TRANSACT_REQ *Request;
ASSERT(FileNode == FileDesc->FileNode);
if (FSP_FSCTL_DEVICECONTROL_SIZEMAX < InputBufferLength ||
FSP_FSCTL_DEVICECONTROL_SIZEMAX < OutputBufferLength)
return STATUS_INVALID_BUFFER_SIZE;
Result = FspIopCreateRequestEx(Irp, 0, InputBufferLength,
FspFsvolDeviceControlRequestFini, &Request);
if (!NT_SUCCESS(Result))
return Result;
FspFileNodeAcquireShared(FileNode, Full);
Request->Kind = FspFsctlTransactDeviceControlKind;
Request->Req.DeviceControl.UserContext = FileNode->UserContext;
Request->Req.DeviceControl.UserContext2 = FileDesc->UserContext2;
Request->Req.DeviceControl.IoControlCode = IoControlCode;
Request->Req.DeviceControl.Buffer.Offset = 0;
Request->Req.DeviceControl.Buffer.Size = (UINT16)InputBufferLength;
Request->Req.DeviceControl.OutputLength = OutputBufferLength;
RtlCopyMemory(Request->Buffer, InputBuffer, InputBufferLength);
FspFileNodeSetOwner(FileNode, Full, Request);
FspIopRequestContext(Request, RequestFileNode) = FileNode;
return FSP_STATUS_IOQ_POST;
} }
NTSTATUS FspFsvolDeviceControlComplete( NTSTATUS FspFsvolDeviceControlComplete(
@ -41,12 +102,46 @@ NTSTATUS FspFsvolDeviceControlComplete(
{ {
FSP_ENTER_IOC(PAGED_CODE()); FSP_ENTER_IOC(PAGED_CODE());
if (!NT_SUCCESS(Response->IoStatus.Status))
{
Irp->IoStatus.Information = 0;
Result = Response->IoStatus.Status;
FSP_RETURN();
}
PVOID OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
if (Response->Buffer + Response->Rsp.DeviceControl.Buffer.Offset +
Response->Rsp.DeviceControl.Buffer.Size > (PUINT8)Response + Response->Size)
FSP_RETURN(Result = STATUS_INTERNAL_ERROR);
if (OutputBufferLength >= Response->Rsp.DeviceControl.Buffer.Size)
OutputBufferLength = Response->Rsp.DeviceControl.Buffer.Size;
else
Result = STATUS_BUFFER_OVERFLOW;
RtlCopyMemory(OutputBuffer, Response->Buffer + Response->Rsp.DeviceControl.Buffer.Offset,
OutputBufferLength);
Irp->IoStatus.Information = OutputBufferLength;
FSP_LEAVE_IOC( FSP_LEAVE_IOC(
"%s, FileObject=%p", "%s, FileObject=%p",
IoctlCodeSym(IrpSp->Parameters.DeviceIoControl.IoControlCode), IoctlCodeSym(IrpSp->Parameters.DeviceIoControl.IoControlCode),
IrpSp->FileObject); IrpSp->FileObject);
} }
static VOID FspFsvolDeviceControlRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4])
{
PAGED_CODE();
FSP_FILE_NODE *FileNode = Context[RequestFileNode];
if (0 != FileNode)
FspFileNodeReleaseOwner(FileNode, Full, Request);
}
NTSTATUS FspDeviceControl( NTSTATUS FspDeviceControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp) PDEVICE_OBJECT DeviceObject, PIRP Irp)
{ {

View File

@ -55,6 +55,11 @@ FSP_FSCTL_STATIC_ASSERT(MEMFS_MAX_PATH > MAX_PATH,
*/ */
#define MEMFS_SLOWIO #define MEMFS_SLOWIO
/*
* Define the MEMFS_CONTROL macro to include DeviceControl support.
*/
#define MEMFS_CONTROL
/* /*
* Define the DEBUG_BUFFER_CHECK macro on Windows 8 or above. This includes * Define the DEBUG_BUFFER_CHECK macro on Windows 8 or above. This includes
* a check for the Write buffer to ensure that it is read-only. * a check for the Write buffer to ensure that it is read-only.
@ -1895,6 +1900,38 @@ static NTSTATUS GetStreamInfo(FSP_FILE_SYSTEM *FileSystem,
} }
#endif #endif
#if defined(MEMFS_CONTROL)
static NTSTATUS Control(FSP_FILE_SYSTEM *FileSystem,
PVOID FileContext, UINT32 ControlCode,
PVOID InputBuffer, ULONG InputBufferLength,
PVOID OutputBuffer, ULONG OutputBufferLength, PULONG PBytesTransferred)
{
/* MEMFS also supports encryption! See below :) */
if (CTL_CODE(0x8000 + 'M', 'R', METHOD_BUFFERED, FILE_ANY_ACCESS) == ControlCode)
{
if (OutputBufferLength != InputBufferLength)
return STATUS_INVALID_PARAMETER;
for (PUINT8 P = (PUINT8)InputBuffer, Q = (PUINT8)OutputBuffer, EndP = P + InputBufferLength;
EndP > P; P++, Q++)
{
if (('A' <= *P && *P <= 'M') || ('a' <= *P && *P <= 'm'))
*Q = *P + 13;
else
if (('N' <= *P && *P <= 'Z') || ('n' <= *P && *P <= 'z'))
*Q = *P - 13;
else
*Q = *P;
}
*PBytesTransferred = InputBufferLength;
return STATUS_SUCCESS;
}
return STATUS_INVALID_DEVICE_REQUEST;
}
#endif
static FSP_FILE_SYSTEM_INTERFACE MemfsInterface = static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
{ {
GetVolumeInfo, GetVolumeInfo,
@ -1937,6 +1974,11 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
#else #else
0, 0,
#endif #endif
#if defined(MEMFS_CONTROL)
Control,
#else
0,
#endif
}; };
/* /*
@ -2028,6 +2070,9 @@ NTSTATUS MemfsCreateFunnel(
VolumeParams.PassQueryDirectoryFileName = 1; VolumeParams.PassQueryDirectoryFileName = 1;
#endif #endif
VolumeParams.FlushAndPurgeOnCleanup = FlushAndPurgeOnCleanup; VolumeParams.FlushAndPurgeOnCleanup = FlushAndPurgeOnCleanup;
#if defined(MEMFS_CONTROL)
VolumeParams.DeviceControl = 1;
#endif
if (0 != VolumePrefix) if (0 != VolumePrefix)
wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix); wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix);
wcscpy_s(VolumeParams.FileSystemName, sizeof VolumeParams.FileSystemName / sizeof(WCHAR), wcscpy_s(VolumeParams.FileSystemName, sizeof VolumeParams.FileSystemName / sizeof(WCHAR),

View File

@ -0,0 +1,74 @@
/**
* @file devctl-test.c
*
* @copyright 2015-2018 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this file in
* accordance with the commercial license agreement provided with the
* software.
*/
#include <winfsp/winfsp.h>
#include <tlib/testsuite.h>
#include <strsafe.h>
#include "memfs.h"
#include "winfsp-tests.h"
static void devctl_dotest(ULONG Flags, PWSTR Prefix, PWSTR Drive)
{
void *memfs = memfs_start(Flags);
WCHAR FilePath[1024];
HANDLE Handle;
BOOL Success;
CHAR Buffer[26];
DWORD BytesTransferred;
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\",
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
Handle = CreateFileW(FilePath,
GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, 0);
ASSERT(INVALID_HANDLE_VALUE != Handle);
Success = DeviceIoControl(Handle,
CTL_CODE(0x8000 + 'M', 'R', METHOD_BUFFERED, FILE_ANY_ACCESS),
"ABCDEFghijklmNOPQRStuvwxyz", 26,
Buffer, sizeof Buffer,
&BytesTransferred,
0);
ASSERT(Success);
ASSERT(26 == BytesTransferred);
ASSERT(0 == memcmp("NOPQRStuvwxyzABCDEFghijklm", Buffer, BytesTransferred));
Success = CloseHandle(Handle);
ASSERT(Success);
memfs_stop(memfs);
}
static void devctl_test(void)
{
if (WinFspDiskTests)
devctl_dotest(MemfsDisk, 0, 0);
if (WinFspNetTests)
devctl_dotest(MemfsNet, L"\\\\memfs\\share", L"\\\\memfs\\share");
}
void devctl_tests(void)
{
if (OptExternal)
return;
TEST(devctl_test);
}

View File

@ -199,6 +199,7 @@ int main(int argc, char *argv[])
TESTSUITE(lock_tests); TESTSUITE(lock_tests);
TESTSUITE(dirctl_tests); TESTSUITE(dirctl_tests);
TESTSUITE(exec_tests); TESTSUITE(exec_tests);
TESTSUITE(devctl_tests);
TESTSUITE(reparse_tests); TESTSUITE(reparse_tests);
TESTSUITE(stream_tests); TESTSUITE(stream_tests);
TESTSUITE(oplock_tests); TESTSUITE(oplock_tests);