Merge pull request #181 from JohnOberschelp/master

Added DeviceIoControl to Airfs
This commit is contained in:
Bill Zissimopoulos 2018-08-01 19:35:03 -07:00 committed by GitHub
commit 999847d8db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -38,9 +38,13 @@ FSP_FSCTL_STATIC_ASSERT(AIRFS_MAX_PATH > MAX_PATH,
#define AIRFS_NAMED_STREAMS // Include alternate data streams support. #define AIRFS_NAMED_STREAMS // Include alternate data streams support.
#define AIRFS_DIRINFO_BY_NAME // Include GetDirInfoByName. #define AIRFS_DIRINFO_BY_NAME // Include GetDirInfoByName.
#define AIRFS_SLOWIO // Include delayed I/O response support. #define AIRFS_SLOWIO // Include delayed I/O response support.
#define AIRFS_CONTROL // Include DeviceIoControl support.
#define AIRFS_SECTOR_SIZE 512
#define AIRFS_SECTORS_PER_ALLOCATION_UNIT 1 #define SECTOR_SIZE 512
#define SECTORS_PER_ALLOCATION_UNIT 1
#define ALLOCATION_UNIT ( SECTOR_SIZE * SECTORS_PER_ALLOCATION_UNIT )
#define IN_ALLOCATION_UNITS(bytes) (((bytes) + ALLOCATION_UNIT - 1) / ALLOCATION_UNIT * ALLOCATION_UNIT)
enum enum
{ {
@ -660,10 +664,11 @@ NTSTATUS SetAllocSize(FSP_FILE_SYSTEM *FileSystem, NODE_ Node,
{ {
AIRFS_ Airfs = (AIRFS_) FileSystem->UserContext; AIRFS_ Airfs = (AIRFS_) FileSystem->UserContext;
RequestedAllocSize = IN_ALLOCATION_UNITS(RequestedAllocSize);
if (Node->FileInfo.AllocationSize != RequestedAllocSize) if (Node->FileInfo.AllocationSize != RequestedAllocSize)
{ {
if (RequestedAllocSize > Airfs->MaxFileSize) if (RequestedAllocSize > Airfs->MaxFileSize) return STATUS_DISK_FULL;
return STATUS_DISK_FULL;
// Reallocate only if the file is made smaller, or if it will not fit in the actual memory footprint. // Reallocate only if the file is made smaller, or if it will not fit in the actual memory footprint.
size_t ActualSize = AirfsHeapSize(Node->FileData); size_t ActualSize = AirfsHeapSize(Node->FileData);
@ -671,7 +676,7 @@ NTSTATUS SetAllocSize(FSP_FILE_SYSTEM *FileSystem, NODE_ Node,
{ {
// If the file grow request was modest, guess that it might happen again, and grow the file by 50%. // If the file grow request was modest, guess that it might happen again, and grow the file by 50%.
if (RequestedAllocSize > Node->FileInfo.AllocationSize && RequestedAllocSize <= ActualSize + ActualSize / 8) if (RequestedAllocSize > Node->FileInfo.AllocationSize && RequestedAllocSize <= ActualSize + ActualSize / 8)
RequestedAllocSize = (ActualSize + ActualSize / 2 + 7) ^ 7; RequestedAllocSize = IN_ALLOCATION_UNITS(ActualSize + ActualSize / 2);
PVOID FileData = AirfsHeapRealloc(Node->FileData, (size_t)RequestedAllocSize); PVOID FileData = AirfsHeapRealloc(Node->FileData, (size_t)RequestedAllocSize);
if (!FileData && RequestedAllocSize > 0) if (!FileData && RequestedAllocSize > 0)
@ -697,10 +702,7 @@ NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem, NODE_ Node,
{ {
if (Node->FileInfo.AllocationSize < RequestedFileSize) if (Node->FileInfo.AllocationSize < RequestedFileSize)
{ {
UINT64 AllocationUnit = AIRFS_SECTOR_SIZE * AIRFS_SECTORS_PER_ALLOCATION_UNIT; NTSTATUS Result = SetAllocSize(FileSystem, Node, RequestedFileSize);
UINT64 AllocationSize = (RequestedFileSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit;
NTSTATUS Result = SetAllocSize(FileSystem, Node, AllocationSize);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
return Result; return Result;
} }
@ -1054,11 +1056,7 @@ void ApiCleanup(FSP_FILE_SYSTEM *FileSystem, PVOID Node0, PWSTR Name, ULONG Flag
if (Flags & FspCleanupSetAllocationSize) if (Flags & FspCleanupSetAllocationSize)
{ {
UINT64 AllocationUnit = AIRFS_SECTOR_SIZE * AIRFS_SECTORS_PER_ALLOCATION_UNIT; SetAllocSize(FileSystem, Node, Node->FileInfo.FileSize);
UINT64 AllocationSize = (Node->FileInfo.FileSize + AllocationUnit - 1) /
AllocationUnit * AllocationUnit;
SetAllocSize(FileSystem, Node, AllocationSize);
} }
if ((Flags & FspCleanupDelete) && !NodeHasChildren(Node)) if ((Flags & FspCleanupDelete) && !NodeHasChildren(Node))
@ -1609,6 +1607,34 @@ NTSTATUS ApiGetStreamInfo(FSP_FILE_SYSTEM *FileSystem, PVOID Node0,
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
#endif
//////////////////////////////////////////////////////////////////////
#if defined(AIRFS_CONTROL)
NTSTATUS ApiControl(FSP_FILE_SYSTEM *FileSystem,
PVOID FileContext, UINT32 ControlCode,
PVOID InputBuffer, ULONG InputBufferLength,
PVOID OutputBuffer, ULONG OutputBufferLength, PULONG PBytesTransferred)
{
// Trivial example: Perform a ROT13 translation on alphas.
if (CTL_CODE(0x8000 + 'M', 'R', METHOD_BUFFERED, FILE_ANY_ACCESS) == ControlCode)
{
if (OutputBufferLength != InputBufferLength) return STATUS_INVALID_PARAMETER;
for (ULONG i = 0; i < InputBufferLength; i++)
{
char c = ((char*)InputBuffer)[i];
if (('A' <= c && c <= 'M') || ('a' <= c && c <= 'm')) c += 13;
else
if (('N' <= c && c <= 'Z') || ('n' <= c && c <= 'z')) c -= 13;
((char*)OutputBuffer)[i] = c;
}
*PBytesTransferred = InputBufferLength;
return STATUS_SUCCESS;
}
return STATUS_INVALID_DEVICE_REQUEST;
}
#endif #endif
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -1654,6 +1680,11 @@ FSP_FILE_SYSTEM_INTERFACE AirfsInterface =
#else #else
0, 0,
#endif #endif
#if defined(AIRFS_CONTROL)
ApiControl,
#else
0,
#endif
}; };
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -1711,7 +1742,6 @@ NTSTATUS AirfsCreate(
BOOLEAN FlushAndPurgeOnCleanup = !!(Flags & AirfsFlushAndPurgeOnCleanup); BOOLEAN FlushAndPurgeOnCleanup = !!(Flags & AirfsFlushAndPurgeOnCleanup);
PWSTR DevicePath = AirfsNet == (Flags & AirfsDeviceMask) ? PWSTR DevicePath = AirfsNet == (Flags & AirfsDeviceMask) ?
L"" FSP_FSCTL_NET_DEVICE_NAME : L"" FSP_FSCTL_DISK_DEVICE_NAME; L"" FSP_FSCTL_NET_DEVICE_NAME : L"" FSP_FSCTL_DISK_DEVICE_NAME;
UINT64 AllocationUnit;
AIRFS_ Airfs; AIRFS_ Airfs;
NODE_ RootNode; NODE_ RootNode;
PSECURITY_DESCRIPTOR RootSecurity; PSECURITY_DESCRIPTOR RootSecurity;
@ -1737,8 +1767,7 @@ NTSTATUS AirfsCreate(
memset(Airfs, 0, sizeof *Airfs); memset(Airfs, 0, sizeof *Airfs);
Airfs->MaxNodes = MaxNodes; Airfs->MaxNodes = MaxNodes;
AllocationUnit = AIRFS_SECTOR_SIZE * AIRFS_SECTORS_PER_ALLOCATION_UNIT; Airfs->MaxFileSize = IN_ALLOCATION_UNITS(MaxFileSize);
Airfs->MaxFileSize = (ULONG)((MaxFileSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit);
#ifdef AIRFS_SLOWIO #ifdef AIRFS_SLOWIO
Airfs->SlowioMaxDelay = SlowioMaxDelay; Airfs->SlowioMaxDelay = SlowioMaxDelay;
@ -1750,8 +1779,8 @@ NTSTATUS AirfsCreate(
memset(&VolumeParams, 0, sizeof VolumeParams); memset(&VolumeParams, 0, sizeof VolumeParams);
VolumeParams.Version = sizeof FSP_FSCTL_VOLUME_PARAMS; VolumeParams.Version = sizeof FSP_FSCTL_VOLUME_PARAMS;
VolumeParams.SectorSize = AIRFS_SECTOR_SIZE; VolumeParams.SectorSize = SECTOR_SIZE;
VolumeParams.SectorsPerAllocationUnit = AIRFS_SECTORS_PER_ALLOCATION_UNIT; VolumeParams.SectorsPerAllocationUnit = SECTORS_PER_ALLOCATION_UNIT;
VolumeParams.VolumeCreationTime = GetSystemTime(); VolumeParams.VolumeCreationTime = GetSystemTime();
VolumeParams.VolumeSerialNumber = (UINT32)(GetSystemTime() / (10000 * 1000)); VolumeParams.VolumeSerialNumber = (UINT32)(GetSystemTime() / (10000 * 1000));
VolumeParams.FileInfoTimeout = FileInfoTimeout; VolumeParams.FileInfoTimeout = FileInfoTimeout;
@ -1769,6 +1798,9 @@ NTSTATUS AirfsCreate(
VolumeParams.PassQueryDirectoryFileName = 1; VolumeParams.PassQueryDirectoryFileName = 1;
#endif #endif
VolumeParams.FlushAndPurgeOnCleanup = FlushAndPurgeOnCleanup; VolumeParams.FlushAndPurgeOnCleanup = FlushAndPurgeOnCleanup;
#if defined(AIRFS_CONTROL)
VolumeParams.DeviceControl = 1;
#endif
if (VolumePrefix) if (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),