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_DIRINFO_BY_NAME // Include GetDirInfoByName.
#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
{
@ -660,10 +664,11 @@ NTSTATUS SetAllocSize(FSP_FILE_SYSTEM *FileSystem, NODE_ Node,
{
AIRFS_ Airfs = (AIRFS_) FileSystem->UserContext;
RequestedAllocSize = IN_ALLOCATION_UNITS(RequestedAllocSize);
if (Node->FileInfo.AllocationSize != RequestedAllocSize)
{
if (RequestedAllocSize > Airfs->MaxFileSize)
return STATUS_DISK_FULL;
if (RequestedAllocSize > Airfs->MaxFileSize) return STATUS_DISK_FULL;
// 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);
@ -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 (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);
if (!FileData && RequestedAllocSize > 0)
@ -697,10 +702,7 @@ NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem, NODE_ Node,
{
if (Node->FileInfo.AllocationSize < RequestedFileSize)
{
UINT64 AllocationUnit = AIRFS_SECTOR_SIZE * AIRFS_SECTORS_PER_ALLOCATION_UNIT;
UINT64 AllocationSize = (RequestedFileSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit;
NTSTATUS Result = SetAllocSize(FileSystem, Node, AllocationSize);
NTSTATUS Result = SetAllocSize(FileSystem, Node, RequestedFileSize);
if (!NT_SUCCESS(Result))
return Result;
}
@ -1054,11 +1056,7 @@ void ApiCleanup(FSP_FILE_SYSTEM *FileSystem, PVOID Node0, PWSTR Name, ULONG Flag
if (Flags & FspCleanupSetAllocationSize)
{
UINT64 AllocationUnit = AIRFS_SECTOR_SIZE * AIRFS_SECTORS_PER_ALLOCATION_UNIT;
UINT64 AllocationSize = (Node->FileInfo.FileSize + AllocationUnit - 1) /
AllocationUnit * AllocationUnit;
SetAllocSize(FileSystem, Node, AllocationSize);
SetAllocSize(FileSystem, Node, Node->FileInfo.FileSize);
}
if ((Flags & FspCleanupDelete) && !NodeHasChildren(Node))
@ -1609,6 +1607,34 @@ NTSTATUS ApiGetStreamInfo(FSP_FILE_SYSTEM *FileSystem, PVOID Node0,
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
//////////////////////////////////////////////////////////////////////
@ -1654,6 +1680,11 @@ FSP_FILE_SYSTEM_INTERFACE AirfsInterface =
#else
0,
#endif
#if defined(AIRFS_CONTROL)
ApiControl,
#else
0,
#endif
};
//////////////////////////////////////////////////////////////////////
@ -1711,7 +1742,6 @@ NTSTATUS AirfsCreate(
BOOLEAN FlushAndPurgeOnCleanup = !!(Flags & AirfsFlushAndPurgeOnCleanup);
PWSTR DevicePath = AirfsNet == (Flags & AirfsDeviceMask) ?
L"" FSP_FSCTL_NET_DEVICE_NAME : L"" FSP_FSCTL_DISK_DEVICE_NAME;
UINT64 AllocationUnit;
AIRFS_ Airfs;
NODE_ RootNode;
PSECURITY_DESCRIPTOR RootSecurity;
@ -1737,8 +1767,7 @@ NTSTATUS AirfsCreate(
memset(Airfs, 0, sizeof *Airfs);
Airfs->MaxNodes = MaxNodes;
AllocationUnit = AIRFS_SECTOR_SIZE * AIRFS_SECTORS_PER_ALLOCATION_UNIT;
Airfs->MaxFileSize = (ULONG)((MaxFileSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit);
Airfs->MaxFileSize = IN_ALLOCATION_UNITS(MaxFileSize);
#ifdef AIRFS_SLOWIO
Airfs->SlowioMaxDelay = SlowioMaxDelay;
@ -1750,8 +1779,8 @@ NTSTATUS AirfsCreate(
memset(&VolumeParams, 0, sizeof VolumeParams);
VolumeParams.Version = sizeof FSP_FSCTL_VOLUME_PARAMS;
VolumeParams.SectorSize = AIRFS_SECTOR_SIZE;
VolumeParams.SectorsPerAllocationUnit = AIRFS_SECTORS_PER_ALLOCATION_UNIT;
VolumeParams.SectorSize = SECTOR_SIZE;
VolumeParams.SectorsPerAllocationUnit = SECTORS_PER_ALLOCATION_UNIT;
VolumeParams.VolumeCreationTime = GetSystemTime();
VolumeParams.VolumeSerialNumber = (UINT32)(GetSystemTime() / (10000 * 1000));
VolumeParams.FileInfoTimeout = FileInfoTimeout;
@ -1769,6 +1798,9 @@ NTSTATUS AirfsCreate(
VolumeParams.PassQueryDirectoryFileName = 1;
#endif
VolumeParams.FlushAndPurgeOnCleanup = FlushAndPurgeOnCleanup;
#if defined(AIRFS_CONTROL)
VolumeParams.DeviceControl = 1;
#endif
if (VolumePrefix)
wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix);
wcscpy_s(VolumeParams.FileSystemName, sizeof VolumeParams.FileSystemName / sizeof(WCHAR),