diff --git a/build/VStudio/testing/mirror.vcxproj b/build/VStudio/testing/mirror.vcxproj
index 62a93367..e3cbb944 100644
--- a/build/VStudio/testing/mirror.vcxproj
+++ b/build/VStudio/testing/mirror.vcxproj
@@ -165,9 +165,6 @@
true
-
-
-
{4a7c0b21-9e10-4c81-92de-1493efcf24eb}
diff --git a/build/VStudio/testing/mirror.vcxproj.filters b/build/VStudio/testing/mirror.vcxproj.filters
index 80ecc54c..ee7c46c8 100644
--- a/build/VStudio/testing/mirror.vcxproj.filters
+++ b/build/VStudio/testing/mirror.vcxproj.filters
@@ -6,9 +6,4 @@
cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
- Source
-
-
\ No newline at end of file
diff --git a/build/VStudio/testing/winfsp-tests.vcxproj b/build/VStudio/testing/winfsp-tests.vcxproj
index 3447dde0..733437ce 100644
--- a/build/VStudio/testing/winfsp-tests.vcxproj
+++ b/build/VStudio/testing/winfsp-tests.vcxproj
@@ -176,9 +176,6 @@
TurnOffAllWarnings
TurnOffAllWarnings
-
-
-
diff --git a/build/VStudio/testing/winfsp-tests.vcxproj.filters b/build/VStudio/testing/winfsp-tests.vcxproj.filters
index c56a1e40..93e79dc7 100644
--- a/build/VStudio/testing/winfsp-tests.vcxproj.filters
+++ b/build/VStudio/testing/winfsp-tests.vcxproj.filters
@@ -10,18 +10,9 @@
-
- Source
-
-
- Source
-
Source\tlib
-
- Source
-
diff --git a/build/VStudio/winfsp_dll.vcxproj b/build/VStudio/winfsp_dll.vcxproj
index cc2cec8a..06bcac75 100644
--- a/build/VStudio/winfsp_dll.vcxproj
+++ b/build/VStudio/winfsp_dll.vcxproj
@@ -178,18 +178,6 @@
$(OutDir)$(TargetFileName).map
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/build/VStudio/winfsp_dll.vcxproj.filters b/build/VStudio/winfsp_dll.vcxproj.filters
index 76348406..1b8d3f22 100644
--- a/build/VStudio/winfsp_dll.vcxproj.filters
+++ b/build/VStudio/winfsp_dll.vcxproj.filters
@@ -13,32 +13,4 @@
{1d6501f4-cebd-4a00-a774-deb782b59fb5}
-
-
- Source
-
-
- Source
-
-
- Source
-
-
- Source
-
-
- Source
-
-
-
-
- Include\winfsp
-
-
- Include\winfsp
-
-
- Source
-
-
\ No newline at end of file
diff --git a/build/VStudio/winfsp_sys.vcxproj b/build/VStudio/winfsp_sys.vcxproj
index 856c099a..0bbf7bee 100644
--- a/build/VStudio/winfsp_sys.vcxproj
+++ b/build/VStudio/winfsp_sys.vcxproj
@@ -157,24 +157,20 @@
-
-
-
-
+
-
diff --git a/build/VStudio/winfsp_sys.vcxproj.filters b/build/VStudio/winfsp_sys.vcxproj.filters
index cab112ad..eff809c7 100644
--- a/build/VStudio/winfsp_sys.vcxproj.filters
+++ b/build/VStudio/winfsp_sys.vcxproj.filters
@@ -14,16 +14,28 @@
-
+
Source
-
+
+ Source
+
+
+ Source
+
+
+ Source
+
+
Source
Source
-
+
+ Source
+
+
Source
@@ -32,33 +44,21 @@
Source
-
- Source
-
Source
-
- Source
-
Source
Source
-
- Source
-
Source
Source
-
- Source
-
Source
@@ -71,22 +71,13 @@
Source
-
+
Source
-
+
Source
-
- Source
-
-
- Source
-
-
- Source
-
-
+
Source
@@ -97,8 +88,5 @@
Include\winfsp
-
- Include\winfsp
-
\ No newline at end of file
diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h
index bdc204e2..74eba980 100644
--- a/inc/winfsp/fsctl.h
+++ b/inc/winfsp/fsctl.h
@@ -28,18 +28,11 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
/* fsctl device codes */
#define FSP_FSCTL_CREATE \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'C', METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-/* fsvrt device codes */
-#define FSP_FSCTL_DELETE \
- CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'D', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_TRANSACT \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'T', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_CREATE_BUFFER_SIZEMIN 128
#define FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMIN 16384 /* checked by driver! */
-#define FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMIN 16384 /* not checked by driver! */
-
-#define FSP_FSCTL_VOLUME_PARAMS_SIZE FSP_FSCTL_DEFAULT_ALIGN_UP(sizeof(FSP_FSCTL_VOLUME_PARAMS))
#define FSP_FSCTL_TRANSACT_REQ_SIZEMAX (4096 - 64) /* 64: size for internal request header */
#define FSP_FSCTL_TRANSACT_RSP_SIZEMAX (4096 - 64) /* symmetry! */
@@ -50,7 +43,6 @@ enum
{
FspFsctlTransactUnknownKind = 0,
FspFsctlTransactCreateKind,
- FspFsctlTransactCreateCleanupCloseKind,
FspFsctlTransactCloseKind,
FspFsctlTransactReadKind,
FspFsctlTransactWriteKind,
@@ -90,7 +82,6 @@ typedef struct
UINT32 IrpTimeout; /* milliseconds; values between 1 min and 10 min */
UINT32 EaSupported:1; /* supports extended attributes (unimplemented; set to 0) */
UINT32 FileNameRequired:1; /* FileName required for all operations (not just Create) */
- UINT32 NoSystemAccessCheck:1; /* if set the user-mode flie system performs access checks */
} FSP_FSCTL_VOLUME_PARAMS;
typedef struct
{
@@ -155,8 +146,6 @@ typedef struct
{
UINT64 UserContext; /* open file user context (unique file id) */
UINT64 UserContext2; /* kernel file object user context (only low 32 bits valid) */
- UINT32 FileAttributes; /* FILE_ATTRIBUTE_{NORMAL,DIRECTORY,etc.} */
- FSP_FSCTL_TRANSACT_BUF SecurityDescriptor; /* security descriptor */
} Opened;
/* IoStatus.Status == STATUS_REPARSE */
struct
@@ -210,15 +199,6 @@ static inline FSP_FSCTL_TRANSACT_RSP *FspFsctlTransactConsumeResponse(
}
#if !defined(WINFSP_SYS_INTERNAL)
-FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
- const FSP_FSCTL_VOLUME_PARAMS *Params, PSECURITY_DESCRIPTOR SecurityDescriptor,
- PWCHAR VolumePathBuf, SIZE_T VolumePathSize);
-FSP_API NTSTATUS FspFsctlOpenVolume(PWSTR VolumePath,
- PHANDLE PVolumeHandle);
-FSP_API NTSTATUS FspFsctlDeleteVolume(HANDLE VolumeHandle);
-FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
- PVOID ResponseBuf, SIZE_T ResponseBufSize,
- PVOID RequestBuf, SIZE_T *PRequestBufSize);
#endif
#endif
diff --git a/src/sys/cleanup.c b/src/sys/cleanup.c
index 4aea9e75..3ff58fb4 100644
--- a/src/sys/cleanup.c
+++ b/src/sys/cleanup.c
@@ -23,14 +23,18 @@ FSP_DRIVER_DISPATCH FspCleanup;
#pragma alloc_text(PAGE, FspCleanup)
#endif
+VOID FspFsctlDeleteVolume(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+
static NTSTATUS FspFsctlCleanup(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
PAGED_CODE();
- NTSTATUS Result = STATUS_SUCCESS;
+ FspFsctlDeleteVolume(DeviceObject, Irp, IrpSp);
+
Irp->IoStatus.Information = 0;
- return Result;
+ return STATUS_SUCCESS;
}
static NTSTATUS FspFsvrtCleanup(
@@ -38,9 +42,8 @@ static NTSTATUS FspFsvrtCleanup(
{
PAGED_CODE();
- NTSTATUS Result = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
- return Result;
+ return STATUS_SUCCESS;
}
static NTSTATUS FspFsvolCleanup(
@@ -48,101 +51,7 @@ static NTSTATUS FspFsvolCleanup(
{
PAGED_CODE();
- /* is this a valid FileObject? */
- if (!FspFileContextIsValid(IrpSp->FileObject->FsContext))
- return STATUS_SUCCESS;
-
- NTSTATUS Result;
- FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
- PFILE_OBJECT FileObject = IrpSp->FileObject;
- FSP_FILE_CONTEXT *FsContext = FileObject->FsContext;
- UINT64 UserContext = FsContext->UserContext;
- UINT64 UserContext2 = (UINT_PTR)FileObject->FsContext2;
- BOOLEAN DeletePending;
- LONG OpenCount;
-
- /* lock the FsContext */
- ExAcquireResourceExclusiveLite(FsContext->Header.Resource, TRUE);
-
- /* propagate the FsContext DeleteOnClose to DeletePending */
- if (FsContext->DeleteOnClose)
- FsContext->DeletePending = TRUE;
- DeletePending = FsContext->DeletePending;
-
- /* all handles on this FileObject are gone; decrement its FsContext->OpenCount */
- OpenCount = FspFileContextClose(FsContext);
-
- /* unlock the FsContext */
- ExReleaseResourceLite(FsContext->Header.Resource);
-
- /* is the FsContext going away as well? */
- if (0 == OpenCount)
- {
- /*
- * The following must be done under the file system volume device Resource,
- * because we are manipulating its GenericTable.
- */
- ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->Base.Resource, TRUE);
- try
- {
- /* remove the FsContext from the file system volume device generic table */
- FspFsvolDeviceDeleteContext(DeviceObject, FsContext->UserContext, 0);
- }
- finally
- {
- ExReleaseResourceLite(&FsvolDeviceExtension->Base.Resource);
- }
- }
-
- PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
- if (!FspDeviceRetain(FsvrtDeviceObject))
- /* IRP_MJ_CLEANUP cannot really fail :-\ */
- return STATUS_SUCCESS;
-
- try
- {
- FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
- BOOLEAN FileNameRequired = 0 != FsvrtDeviceExtension->VolumeParams.FileNameRequired;
- FSP_FSCTL_TRANSACT_REQ *Request;
-
- /* create the user-mode file system request */
- Result = FspIopCreateRequest(Irp, FileNameRequired ? &FsContext->FileName : 0, 0, &Request);
- if (!NT_SUCCESS(Result))
- goto leak_exit;
-
- /*
- * The new request is associated with our IRP and will be deleted during its completion.
- */
-
- /* populate the Cleanup request */
- Request->Kind = FspFsctlTransactCleanupKind;
- Request->Req.Cleanup.UserContext = UserContext;
- Request->Req.Cleanup.UserContext2 = UserContext2;
- Request->Req.Cleanup.Delete = DeletePending && 0 == OpenCount;
-
- Result = STATUS_PENDING;
-
- goto exit;
-
- leak_exit:;
-#if DBG
- DEBUGLOG("FileObject=%p[%p:\"%wZ\"], UserContext=%llx, UserContext2=%llx: "
- "error: the user-mode file system handle will be leaked!",
- IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName,
- UserContext, UserContext2);
-#endif
-
- /* IRP_MJ_CLEANUP cannot really fail :-\ */
- Result = STATUS_SUCCESS;
-
- exit:;
- }
- finally
- {
- FspDeviceRelease(FsvrtDeviceObject);
- }
-
- return Result;
+ return STATUS_INVALID_DEVICE_REQUEST;
}
VOID FspFsvolCleanupComplete(
@@ -158,8 +67,6 @@ NTSTATUS FspCleanup(
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_CLEANUP == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
diff --git a/src/sys/close.c b/src/sys/close.c
index 1b912117..384534b2 100644
--- a/src/sys/close.c
+++ b/src/sys/close.c
@@ -28,9 +28,8 @@ static NTSTATUS FspFsctlClose(
{
PAGED_CODE();
- NTSTATUS Result = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
- return Result;
+ return STATUS_SUCCESS;
}
static NTSTATUS FspFsvrtClose(
@@ -38,9 +37,8 @@ static NTSTATUS FspFsvrtClose(
{
PAGED_CODE();
- NTSTATUS Result = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
- return Result;
+ return STATUS_SUCCESS;
}
static NTSTATUS FspFsvolClose(
@@ -48,73 +46,7 @@ static NTSTATUS FspFsvolClose(
{
PAGED_CODE();
- /* is this a valid FileObject? */
- if (!FspFileContextIsValid(IrpSp->FileObject->FsContext))
- return STATUS_SUCCESS;
-
- NTSTATUS Result;
- FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
- PFILE_OBJECT FileObject = IrpSp->FileObject;
- FSP_FILE_CONTEXT *FsContext = FileObject->FsContext;
- UINT64 UserContext = FsContext->UserContext;
- UINT64 UserContext2 = (UINT_PTR)FileObject->FsContext2;
-
- /* dereference the FsContext (and delete if no more references) */
- FspFileContextRelease(FsContext);
-
- PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
- if (!FspDeviceRetain(FsvrtDeviceObject))
- /* IRP_MJ_CLOSE cannot really fail :-\ */
- return STATUS_SUCCESS;
-
- try
- {
- FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
- BOOLEAN FileNameRequired = 0 != FsvrtDeviceExtension->VolumeParams.FileNameRequired;
- FSP_FSCTL_TRANSACT_REQ *Request;
-
- /* create the user-mode file system request */
- Result = FspIopCreateRequest(0, FileNameRequired ? &FsContext->FileName : 0, 0, &Request);
- if (!NT_SUCCESS(Result))
- goto leak_exit;
-
- /*
- * The new request is associated with our IRP and will be deleted during its completion.
- */
-
- /* populate the Close request */
- Request->Kind = FspFsctlTransactCloseKind;
- Request->Req.Close.UserContext = UserContext;
- Request->Req.Close.UserContext2 = UserContext2;
-
- /* post as a work request; this allows us to complete our own IRP and return immediately! */
- if (!FspIopPostWorkRequest(DeviceObject, Request))
- /* no need to delete the request here as FspIopPostWorkRequest() will do so in all cases */
- goto leak_exit;
-
- Result = STATUS_SUCCESS;
-
- goto exit;
-
- leak_exit:;
-#if DBG
- DEBUGLOG("FileObject=%p[%p:\"%wZ\"], UserContext=%llx, UserContext2=%llx: "
- "error: the user-mode file system handle will be leaked!",
- IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName,
- UserContext, UserContext2);
-#endif
-
- /* IRP_MJ_CLOSE cannot really fail :-\ */
- Result = STATUS_SUCCESS;
-
- exit:;
- }
- finally
- {
- FspDeviceRelease(FsvrtDeviceObject);
- }
-
- return Result;
+ return STATUS_INVALID_DEVICE_REQUEST;
}
VOID FspFsvolCloseComplete(
@@ -130,8 +62,6 @@ NTSTATUS FspClose(
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_CLOSE == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
diff --git a/src/sys/create.c b/src/sys/create.c
index 052558fe..fc1fdfbd 100644
--- a/src/sys/create.c
+++ b/src/sys/create.c
@@ -14,9 +14,7 @@ static NTSTATUS FspFsvolCreate(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
FSP_IOPREP_DISPATCH FspFsvolCreatePrepare;
FSP_IOCMPL_DISPATCH FspFsvolCreateComplete;
-static VOID FspFsvolCreateCleanupClose(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response);
-FSP_IOP_REQUEST_FINI FspFsvolCreateRequestFini;
+static FSP_IOP_REQUEST_FINI FspFsvolCreateRequestFini;
FSP_DRIVER_DISPATCH FspCreate;
#ifdef ALLOC_PRAGMA
@@ -25,25 +23,17 @@ FSP_DRIVER_DISPATCH FspCreate;
#pragma alloc_text(PAGE, FspFsvolCreate)
#pragma alloc_text(PAGE, FspFsvolCreatePrepare)
#pragma alloc_text(PAGE, FspFsvolCreateComplete)
-#pragma alloc_text(PAGE, FspFsvolCreateCleanupClose)
#pragma alloc_text(PAGE, FspFsvolCreateRequestFini)
#pragma alloc_text(PAGE, FspCreate)
#endif
-enum
-{
- RequestFsContext = 0,
- RequestAccessToken,
-};
-
static NTSTATUS FspFsctlCreate(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
PAGED_CODE();
- NTSTATUS Result = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
- return Result;
+ return STATUS_SUCCESS;
}
static NTSTATUS FspFsvrtCreate(
@@ -51,9 +41,8 @@ static NTSTATUS FspFsvrtCreate(
{
PAGED_CODE();
- NTSTATUS Result = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
- return Result;
+ return STATUS_SUCCESS;
}
static NTSTATUS FspFsvolCreate(
@@ -61,280 +50,7 @@ static NTSTATUS FspFsvolCreate(
{
PAGED_CODE();
- /* open the volume object? */
- if (0 == IrpSp->FileObject->FileName.Length &&
- (0 == IrpSp->FileObject->RelatedFileObject ||
- 0 == IrpSp->FileObject->RelatedFileObject->FsContext))
- {
- FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
- PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
-
- IrpSp->FileObject->Vpb = FsvrtDeviceObject->Vpb;
- Irp->IoStatus.Information = FILE_OPENED;
- return STATUS_SUCCESS;
- }
-
- NTSTATUS Result;
- FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
-
- PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
- if (!FspDeviceRetain(FsvrtDeviceObject))
- return STATUS_CANCELLED;
-
- try
- {
- FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
- PFILE_OBJECT FileObject = IrpSp->FileObject;
- PFILE_OBJECT RelatedFileObject = FileObject->RelatedFileObject;
- UNICODE_STRING FileName = FileObject->FileName;
- PACCESS_STATE AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
- ULONG CreateOptions = IrpSp->Parameters.Create.Options;
- USHORT FileAttributes = IrpSp->Parameters.Create.FileAttributes;
- PSECURITY_DESCRIPTOR SecurityDescriptor = AccessState->SecurityDescriptor;
- ULONG SecurityDescriptorSize = 0;
- LARGE_INTEGER AllocationSize = Irp->Overlay.AllocationSize;
- ACCESS_MASK DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
- USHORT ShareAccess = IrpSp->Parameters.Create.ShareAccess;
- PFILE_FULL_EA_INFORMATION EaBuffer = Irp->AssociatedIrp.SystemBuffer;
- //ULONG EaLength = IrpSp->Parameters.Create.EaLength;
- ULONG Flags = IrpSp->Flags;
- KPROCESSOR_MODE RequestorMode =
- FlagOn(Flags, SL_FORCE_ACCESS_CHECK) ? UserMode : Irp->RequestorMode;
- BOOLEAN HasTraversePrivilege =
- BooleanFlagOn(AccessState->Flags, TOKEN_HAS_TRAVERSE_PRIVILEGE);
- BOOLEAN IsAbsoluteSecurityDescriptor = FALSE;
- BOOLEAN IsSelfRelativeSecurityDescriptor = FALSE;
- BOOLEAN HasTrailingBackslash = FALSE;
- FSP_FILE_CONTEXT *FsContext = 0;
- FSP_FSCTL_TRANSACT_REQ *Request;
-
- /* cannot open a paging file */
- if (FlagOn(Flags, SL_OPEN_PAGING_FILE))
- {
- Result = STATUS_ACCESS_DENIED;
- goto exit;
- }
-
- /* cannot open files by fileid */
- if (FlagOn(CreateOptions, FILE_OPEN_BY_FILE_ID))
- {
- Result = STATUS_NOT_IMPLEMENTED;
- goto exit;
- }
-
- /* do we support EA? */
- if (0 != EaBuffer && !FsvrtDeviceExtension->VolumeParams.EaSupported)
- {
- Result = STATUS_EAS_NOT_SUPPORTED;
- goto exit;
- }
-
- /* check create options */
- if (FlagOn(CreateOptions, FILE_NON_DIRECTORY_FILE) &&
- FlagOn(CreateOptions, FILE_DIRECTORY_FILE))
- {
- Result = STATUS_INVALID_PARAMETER;
- goto exit;
- }
-
- /* check security descriptor validity */
- if (0 != SecurityDescriptor)
- {
- IsAbsoluteSecurityDescriptor = RtlValidSecurityDescriptor(SecurityDescriptor);
- if (IsAbsoluteSecurityDescriptor)
- {
- Result = RtlAbsoluteToSelfRelativeSD(SecurityDescriptor, 0, &SecurityDescriptorSize);
- if (STATUS_BUFFER_TOO_SMALL != Result)
- {
- Result = STATUS_INVALID_PARAMETER;
- goto exit;
- }
- }
- else
- {
- SecurityDescriptorSize = RtlLengthSecurityDescriptor(SecurityDescriptor);
- IsSelfRelativeSecurityDescriptor = RtlValidRelativeSecurityDescriptor(
- SecurityDescriptor, SecurityDescriptorSize, 0);
- if (!IsSelfRelativeSecurityDescriptor)
- {
- Result = STATUS_INVALID_PARAMETER;
- goto exit;
- }
- }
- }
-
- /* according to fastfat, filenames that begin with two backslashes are ok */
- if (sizeof(WCHAR) * 2 <= FileName.Length &&
- L'\\' == FileName.Buffer[1] && L'\\' == FileName.Buffer[0])
- {
- FileName.Length -= sizeof(WCHAR);
- FileName.MaximumLength -= sizeof(WCHAR);
- FileName.Buffer++;
-
- if (sizeof(WCHAR) * 2 <= FileName.Length &&
- L'\\' == FileName.Buffer[1] && L'\\' == FileName.Buffer[0])
- {
- Result = STATUS_OBJECT_NAME_INVALID;
- goto exit;
- }
- }
-
- /* check for trailing backslash */
- if (sizeof(WCHAR) * 2/* not empty or root */ <= FileName.Length &&
- L'\\' == FileName.Buffer[FileName.Length / 2 - 1])
- {
- FileName.Length -= sizeof(WCHAR);
- HasTrailingBackslash = TRUE;
-
- if (sizeof(WCHAR) * 2 <= FileName.Length && L'\\' == FileName.Buffer[FileName.Length / 2 - 1])
- {
- Result = STATUS_OBJECT_NAME_INVALID;
- goto exit;
- }
- }
- if (HasTrailingBackslash && !FlagOn(CreateOptions, FILE_DIRECTORY_FILE))
- {
- Result = STATUS_OBJECT_NAME_INVALID;
- goto exit;
- }
-
- /* is this a relative or absolute open? */
- if (0 != RelatedFileObject)
- {
- FSP_FILE_CONTEXT *RelatedFsContext = RelatedFileObject->FsContext;
-
- /* is this a valid RelatedFileObject? */
- if (!FspFileContextIsValid(RelatedFsContext))
- {
- Result = STATUS_OBJECT_PATH_NOT_FOUND;
- goto exit;
- }
-
- /* must be a relative path */
- if (sizeof(WCHAR) <= FileName.Length && L'\\' == FileName.Buffer[0])
- {
- Result = STATUS_OBJECT_NAME_INVALID;
- goto exit;
- }
-
- /* cannot FILE_DELETE_ON_CLOSE on the root directory */
- if (sizeof(WCHAR) == RelatedFsContext->FileName.Length &&
- 0 == FileName.Length &&
- FlagOn(CreateOptions, FILE_DELETE_ON_CLOSE))
- {
- Result = STATUS_CANNOT_DELETE;
- goto exit;
- }
-
- /*
- * There is no need to lock our accesses of RelatedFileObject->FsContext->FileName,
- * because RelatedFileObject->FsContext->Filename is read-only (after creation) and
- * because RelatedFileObject->FsContext is guaranteed to exist while RelatedFileObject
- * exists.
- */
- BOOLEAN AppendBackslash =
- sizeof(WCHAR) * 2/* not empty or root */ <= RelatedFsContext->FileName.Length &&
- sizeof(WCHAR) <= FileName.Length && L':' != FileName.Buffer[0];
- Result = FspFileContextCreate(DeviceObject,
- RelatedFsContext->FileName.Length + AppendBackslash * sizeof(WCHAR) + FileName.Length,
- &FsContext);
- if (!NT_SUCCESS(Result))
- goto exit;
-
- Result = RtlAppendUnicodeStringToString(&FsContext->FileName, &RelatedFsContext->FileName);
- ASSERT(NT_SUCCESS(Result));
- if (AppendBackslash)
- {
- Result = RtlAppendUnicodeToString(&FsContext->FileName, L"\\");
- ASSERT(NT_SUCCESS(Result));
- }
- }
- else
- {
- /* must be an absolute path */
- if (sizeof(WCHAR) <= FileName.Length && L'\\' != FileName.Buffer[0])
- {
- Result = STATUS_OBJECT_NAME_INVALID;
- goto exit;
- }
-
- /* cannot FILE_DELETE_ON_CLOSE on the root directory */
- if (sizeof(WCHAR) == FileName.Length &&
- FlagOn(CreateOptions, FILE_DELETE_ON_CLOSE))
- {
- Result = STATUS_CANNOT_DELETE;
- goto exit;
- }
-
- Result = FspFileContextCreate(DeviceObject,
- FileName.Length,
- &FsContext);
- if (!NT_SUCCESS(Result))
- goto exit;
- }
-
- Result = RtlAppendUnicodeStringToString(&FsContext->FileName, &FileName);
- ASSERT(NT_SUCCESS(Result));
-
- /* create the user-mode file system request */
- Result = FspIopCreateRequestEx(Irp, &FsContext->FileName, SecurityDescriptorSize,
- FspFsvolCreateRequestFini, &Request);
- if (!NT_SUCCESS(Result))
- {
- FspFileContextRelease(FsContext);
- goto exit;
- }
-
- /*
- * The new request is associated with our IRP and will be deleted during its completion.
- * Go ahead and associate our FsContext with the Request as well.
- */
- FspIopRequestContext(Request, RequestFsContext) = FsContext;
-
- /* populate the Create request */
- Request->Kind = FspFsctlTransactCreateKind;
- Request->Req.Create.CreateOptions = CreateOptions;
- Request->Req.Create.FileAttributes = FileAttributes;
- Request->Req.Create.SecurityDescriptor.Offset = 0 == SecurityDescriptorSize ? 0 :
- FSP_FSCTL_DEFAULT_ALIGN_UP(Request->FileName.Size);
- Request->Req.Create.SecurityDescriptor.Size = (UINT16)SecurityDescriptorSize;
- Request->Req.Create.AllocationSize = AllocationSize.QuadPart;
- Request->Req.Create.AccessToken = 0;
- Request->Req.Create.DesiredAccess = DesiredAccess;
- Request->Req.Create.ShareAccess = ShareAccess;
- Request->Req.Create.Ea.Offset = 0;
- Request->Req.Create.Ea.Size = 0;
- Request->Req.Create.UserMode = UserMode == RequestorMode;
- Request->Req.Create.HasTraversePrivilege = HasTraversePrivilege;
- Request->Req.Create.OpenTargetDirectory = BooleanFlagOn(Flags, SL_OPEN_TARGET_DIRECTORY);
- Request->Req.Create.CaseSensitive = BooleanFlagOn(Flags, SL_CASE_SENSITIVE);
-
- /* copy the security descriptor into the request */
- if (IsAbsoluteSecurityDescriptor)
- {
- Result = RtlAbsoluteToSelfRelativeSD(SecurityDescriptor,
- Request->Buffer + Request->Req.Create.SecurityDescriptor.Offset, &SecurityDescriptorSize);
- if (!NT_SUCCESS(Result))
- {
- if (STATUS_BAD_DESCRIPTOR_FORMAT == Result || STATUS_BUFFER_TOO_SMALL == Result)
- Result = STATUS_INVALID_PARAMETER; /* should not happen */
- goto exit;
- }
- }
- else if (IsSelfRelativeSecurityDescriptor)
- RtlCopyMemory(Request->Buffer + Request->Req.Create.SecurityDescriptor.Offset,
- SecurityDescriptor, SecurityDescriptorSize);
-
- Result = STATUS_PENDING;
-
- exit:;
- }
- finally
- {
- FspDeviceRelease(FsvrtDeviceObject);
- }
-
- return Result;
+ return STATUS_INVALID_DEVICE_REQUEST;
}
NTSTATUS FspFsvolCreatePrepare(
@@ -342,30 +58,6 @@ NTSTATUS FspFsvolCreatePrepare(
{
FSP_ENTER_IOP(PAGED_CODE());
- PDEVICE_OBJECT DeviceObject = IrpSp->DeviceObject;
- FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
- FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension =
- FspFsvrtDeviceExtension(FsvolDeviceExtension->FsvrtDeviceObject);
-
- /* is the user-mode file system doing access checks? */
- if (!FsvrtDeviceExtension->VolumeParams.NoSystemAccessCheck)
- {
- ASSERT(0 == Request->Req.Create.AccessToken);
- FSP_RETURN(Result = STATUS_SUCCESS);
- }
-
- /* get a user-mode handle to the access token */
- PACCESS_STATE AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
- HANDLE UserModeAccessToken;
- Result = ObOpenObjectByPointer(SeQuerySubjectContextToken(&AccessState->SubjectSecurityContext),
- 0, 0, TOKEN_QUERY, *SeTokenObjectType, UserMode, &UserModeAccessToken);
- if (!NT_SUCCESS(Result))
- FSP_RETURN();
-
- /* send the user-mode handle to the user-mode file system */
- FspIopRequestContext(Request, RequestAccessToken) = UserModeAccessToken;
- Request->Req.Create.AccessToken = (UINT_PTR)UserModeAccessToken;
-
FSP_LEAVE_IOP();
}
@@ -374,358 +66,14 @@ VOID FspFsvolCreateComplete(
{
FSP_ENTER_IOC(PAGED_CODE());
- /*
- * NOTE:
- * In the following we may have to close the just opened file object. But we must
- * never close a file we just created, because this will leave an orphan file on
- * the disk.
- *
- * Files may have to be closed if a security access or share access check fails. In
- * both those cases we were opening an existing file and so it is safe to close it.
- *
- * Because of how IRP_MJ_CREATE works in Windows, it is difficult to improve on this
- * scheme without introducing a 2-phase Create protocol, which is undesirable as it
- * means two trips into user-mode for a single Create request.
- */
-
- PDEVICE_OBJECT DeviceObject = IrpSp->DeviceObject;
- FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
- PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
- FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
- FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
- PFILE_OBJECT FileObject = IrpSp->FileObject;
- PACCESS_STATE AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
- ULONG CreateOptions = IrpSp->Parameters.Create.Options;
- BOOLEAN FileCreated = FILE_CREATED == Response->IoStatus.Information;
- UINT32 ResponseFileAttributes = Response->Rsp.Create.Opened.FileAttributes;
- PSECURITY_DESCRIPTOR SecurityDescriptor;
- ULONG SecurityDescriptorSize;
- UNICODE_STRING ReparseFileName;
- ACCESS_MASK DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
- PPRIVILEGE_SET Privileges = 0;
- USHORT ShareAccess = IrpSp->Parameters.Create.ShareAccess;
- ULONG Flags = IrpSp->Flags;
- KPROCESSOR_MODE RequestorMode =
- FlagOn(Flags, SL_FORCE_ACCESS_CHECK) ? UserMode : Irp->RequestorMode;
- FSP_FILE_CONTEXT *FsContext = FspIopRequestContext(Request, RequestFsContext);
- ACCESS_MASK GrantedAccess;
- BOOLEAN Inserted = FALSE;
-
- /* did the user-mode file system sent us a failure code? */
- if (!NT_SUCCESS(Response->IoStatus.Status))
- {
- Irp->IoStatus.Information = Response->IoStatus.Information;
- Result = Response->IoStatus.Status;
- FSP_RETURN();
- }
-
- /* special case STATUS_REPARSE */
- if (STATUS_REPARSE == Result)
- {
- ReparseFileName.Buffer =
- (PVOID)(Response->Buffer + Response->Rsp.Create.Reparse.FileName.Offset);
- ReparseFileName.Length = ReparseFileName.MaximumLength =
- Response->Rsp.Create.Reparse.FileName.Size;
-
- Result = STATUS_ACCESS_DENIED;
- if (IO_REPARSE == Response->IoStatus.Information)
- {
- if (0 == ReparseFileName.Length ||
- (PUINT8)ReparseFileName.Buffer + ReparseFileName.Length >
- (PUINT8)Response + Response->Size)
- FSP_RETURN();
-
- if (ReparseFileName.Length > FileObject->FileName.MaximumLength)
- {
- PVOID Buffer = FspAllocExternal(ReparseFileName.Length);
- if (0 == Buffer)
- FSP_RETURN(Result = STATUS_INSUFFICIENT_RESOURCES);
- FspFreeExternal(FileObject->FileName.Buffer);
- FileObject->FileName.MaximumLength = ReparseFileName.Length;
- FileObject->FileName.Buffer = Buffer;
- }
- FileObject->FileName.Length = 0;
- RtlCopyUnicodeString(&FileObject->FileName, &ReparseFileName);
- }
- else
- if (IO_REMOUNT == Response->IoStatus.Information)
- {
- if (0 != ReparseFileName.Length)
- FSP_RETURN();
- }
- else
- FSP_RETURN();
-
- Irp->IoStatus.Information = Response->IoStatus.Information;
- Result = Response->IoStatus.Status;
- FSP_RETURN();
- }
-
- /* are we doing access checks? */
- if (!FsvrtDeviceExtension->VolumeParams.NoSystemAccessCheck)
- {
- /* read-only attribute check */
- if (!FileCreated && FlagOn(ResponseFileAttributes, FILE_ATTRIBUTE_READONLY))
- {
- /* from fastfat: allowed accesses when read-only */
- ACCESS_MASK Allowed =
- DELETE | READ_CONTROL | WRITE_OWNER | WRITE_DAC |
- SYNCHRONIZE | ACCESS_SYSTEM_SECURITY |
- FILE_READ_DATA | FILE_READ_EA | FILE_WRITE_EA |
- FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES |
- FILE_EXECUTE | FILE_TRAVERSE | FILE_LIST_DIRECTORY |
- FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE | FILE_DELETE_CHILD;
-
- if (FlagOn(DesiredAccess, ~Allowed))
- {
- FspFsvolCreateCleanupClose(Irp, Response);
- FSP_RETURN(Result = STATUS_ACCESS_DENIED);
- }
- else
- if (!FlagOn(ResponseFileAttributes, FILE_ATTRIBUTE_DIRECTORY) &&
- FlagOn(CreateOptions, FILE_DELETE_ON_CLOSE))
- {
- FspFsvolCreateCleanupClose(Irp, Response);
- FSP_RETURN(Result = STATUS_CANNOT_DELETE);
- }
- }
-
- /* security descriptor check */
- SecurityDescriptor =
- (PVOID)(Response->Buffer + Response->Rsp.Create.Opened.SecurityDescriptor.Offset);
- SecurityDescriptorSize = Response->Rsp.Create.Opened.SecurityDescriptor.Size;
- if (0 != SecurityDescriptorSize)
- {
- if ((PUINT8)SecurityDescriptor + SecurityDescriptorSize >
- (PUINT8)Response + Response->Size ||
- !FspValidRelativeSecurityDescriptor(SecurityDescriptor, SecurityDescriptorSize, 0))
- {
- FspFsvolCreateCleanupClose(Irp, Response);
- FSP_RETURN(Result = STATUS_ACCESS_DENIED);
- }
-
- /* access check */
- if (!SeAccessCheck(SecurityDescriptor,
- &AccessState->SubjectSecurityContext,
- FALSE,
- DesiredAccess,
- AccessState->PreviouslyGrantedAccess,
- &Privileges,
- IoGetFileObjectGenericMapping(),
- RequestorMode,
- &GrantedAccess,
- &Result))
- {
- FspFsvolCreateCleanupClose(Irp, Response);
- FSP_RETURN();
- }
-
- if (0 != Privileges)
- {
- Result = SeAppendPrivileges(AccessState, Privileges);
- SeFreePrivileges(Privileges);
- if (!NT_SUCCESS(Result))
- {
- FspFsvolCreateCleanupClose(Irp, Response);
- FSP_RETURN();
- }
- }
-
- SetFlag(AccessState->PreviouslyGrantedAccess, GrantedAccess);
- ClearFlag(AccessState->RemainingDesiredAccess, GrantedAccess);
- }
- }
-
- /* were we asked to open a directory or non-directory? */
- if (FlagOn(CreateOptions, FILE_DIRECTORY_FILE) &&
- !FileCreated && !FlagOn(ResponseFileAttributes, FILE_ATTRIBUTE_DIRECTORY))
- {
- FspFsvolCreateCleanupClose(Irp, Response);
- FSP_RETURN(Result = STATUS_NOT_A_DIRECTORY);
- }
- if (FlagOn(CreateOptions, FILE_NON_DIRECTORY_FILE) &&
- !FileCreated && FlagOn(ResponseFileAttributes, FILE_ATTRIBUTE_DIRECTORY))
- {
- FspFsvolCreateCleanupClose(Irp, Response);
- FSP_RETURN(Result = STATUS_FILE_IS_A_DIRECTORY);
- }
-
- /*
- * The following must be done under the file system volume device Resource,
- * because we are manipulating its GenericTable and accessing foreign FsContext's.
- */
- ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->Base.Resource, TRUE);
- try
- {
- /* insert the newly created FsContext into our generic table */
- FsContext = FspFsvolDeviceInsertContext(DeviceObject,
- FsContext->UserContext, FsContext, &FsContext->ElementStorage, &Inserted);
- ASSERT(0 != FsContext);
-
- /* share access check */
- if (Inserted)
- {
- /*
- * This is a newly created FsContext. Set its share access and
- * increment its open count. There is no need to acquire the
- * FsContext's Resource (because it is newly created).
- */
- IoSetShareAccess(AccessState->PreviouslyGrantedAccess,
- ShareAccess, FileObject, &FsContext->ShareAccess);
- FspFileContextOpen(FsContext);
- if (FlagOn(CreateOptions, FILE_DELETE_ON_CLOSE))
- FsContext->DeleteOnClose = TRUE;
- Result = STATUS_SUCCESS;
- }
- else
- {
- /*
- * This is an existing FsContext. We must acquire its Resource and
- * check if there is a delete pending and the share access. Only if
- * both tests succeed we increment the open count and report success.
- */
- ExAcquireResourceExclusiveLite(FsContext->Header.Resource, TRUE);
- if (FsContext->DeletePending)
- Result = STATUS_DELETE_PENDING;
- else
- Result = IoCheckShareAccess(AccessState->PreviouslyGrantedAccess,
- ShareAccess, FileObject, &FsContext->ShareAccess, TRUE);
- if (NT_SUCCESS(Result))
- {
- FspFileContextRetain(FsContext);
- FspFileContextOpen(FsContext);
- if (FlagOn(CreateOptions, FILE_DELETE_ON_CLOSE))
- FsContext->DeleteOnClose = TRUE;
- }
- ExReleaseResourceLite(FsContext->Header.Resource);
- }
- }
- finally
- {
- ExReleaseResourceLite(&FsvolDeviceExtension->Base.Resource);
- }
-
- /* did we fail our share access checks? */
- if (!NT_SUCCESS(Result))
- {
- ASSERT(!Inserted);
- FspFsvolCreateCleanupClose(Irp, Response);
- FSP_RETURN();
- }
-
- /*
- * Looks like SUCCESS!
- */
-
- /* did an FsContext with the same UserContext already exist? */
- if (!Inserted)
- /* delete the newly created FsContext as it is not being used */
- FspFileContextRelease(FspIopRequestContext(Request, RequestFsContext));
-
- /* disassociate our FsContext from the Request */
- FspIopRequestContext(Request, RequestFsContext) = 0;
-
- /* record the user-mode file system contexts */
- FsContext->UserContext = Response->Rsp.Create.Opened.UserContext;
- FileObject->FsContext = FsContext;
- FileObject->FsContext2 = (PVOID)(UINT_PTR)Response->Rsp.Create.Opened.UserContext2;
-
- /* finish seting up the FileObject */
- FileObject->Vpb = FsvrtDeviceObject->Vpb;
-
- /* SUCCESS! */
- Irp->IoStatus.Information = Response->IoStatus.Information;
- Result = Response->IoStatus.Status;
-
FSP_LEAVE_IOC(
"FileObject=%p[%p:\"%wZ\"]",
IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName);
}
-static VOID FspFsvolCreateCleanupClose(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+static VOID FspFsvolCreateRequestFini(PVOID Context[3])
{
PAGED_CODE();
-
- /*
- * This routine handles the case where we must close an open file,
- * because of a failure during Create completion. We simply create
- * a CreateClose request and we post it as a work item.
- *
- * Ideally there would be no failure modes for this routine. Reality is
- * different.
- *
- * The more serious (but perhaps non-existent in practice) failure is a
- * memory allocation failure. In this case we will leak the user-mode
- * file system handle!
- *
- * This routine may also fail if we cannot post a work item, which means that
- * the virtual volume device and the file system volume device are being
- * deleted. Because it is assumed that only the user-mode file system would
- * initiate a device deletion, this case is more benign (presumably the file
- * system knows to close off all its handles when tearing down its devices).
- */
-
- NTSTATUS Result;
- PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
- PDEVICE_OBJECT DeviceObject = IrpSp->DeviceObject;
- FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
- FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension =
- FspFsvrtDeviceExtension(FsvolDeviceExtension->FsvrtDeviceObject);
- FSP_FSCTL_TRANSACT_REQ *OriginalRequest = FspIrpRequest(Irp);
- FSP_FILE_CONTEXT *FsContext = FspIopRequestContext(OriginalRequest, RequestFsContext);
- UINT64 UserContext = Response->Rsp.Create.Opened.UserContext;
- UINT64 UserContext2 = Response->Rsp.Create.Opened.UserContext2;
- BOOLEAN FileNameRequired = 0 != FsvrtDeviceExtension->VolumeParams.FileNameRequired;
- FSP_FSCTL_TRANSACT_REQ *Request;
-
- /* create the user-mode file system request */
- Result = FspIopCreateRequest(0, FileNameRequired ? &FsContext->FileName : 0, 0, &Request);
- if (!NT_SUCCESS(Result))
- goto leak_exit;
-
- /* populate the CreateCleanupClose request */
- Request->Kind = FspFsctlTransactCreateCleanupCloseKind;
- Request->Req.Cleanup.UserContext = UserContext;
- Request->Req.Cleanup.UserContext2 = UserContext2;
- Request->Req.Cleanup.Delete = FILE_CREATED == Response->IoStatus.Information;
-
- /* post as a work request */
- if (!FspIopPostWorkRequest(DeviceObject, Request))
- /* no need to delete the request here as FspIopPostWorkRequest() will do so in all cases */
- goto leak_exit;
-
- goto exit;
-
-leak_exit:;
-#if DBG
- DEBUGLOG("FileObject=%p[%p:\"%wZ\"], UserContext=%llx, UserContext2=%llx: "
- "error: the user-mode file system handle will be leaked!",
- IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName,
- UserContext, UserContext2);
-#endif
-
-exit:;
-}
-
-VOID FspFsvolCreateRequestFini(PVOID Context[3])
-{
- PAGED_CODE();
-
- if (0 != Context[RequestFsContext])
- FspFileContextRelease(Context[RequestFsContext]);
-
- if (0 != Context[RequestAccessToken])
- {
-#if DBG
- NTSTATUS Result0;
- Result0 = ObCloseHandle(Context[RequestAccessToken], KernelMode);
- if (!NT_SUCCESS(Result0))
- DEBUGLOG("ObCloseHandle() = %s", NtStatusSym(Result0));
-#else
- ObCloseHandle(Context[RequestAccessToken], KernelMode);
-#endif
- }
}
NTSTATUS FspCreate(
@@ -733,8 +81,6 @@ NTSTATUS FspCreate(
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_CREATE == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
diff --git a/src/sys/debug.c b/src/sys/debug.c
index 2e5e4dff..583a2730 100644
--- a/src/sys/debug.c
+++ b/src/sys/debug.c
@@ -166,7 +166,6 @@ const char *IoctlCodeSym(ULONG ControlCode)
switch (ControlCode)
{
SYM(FSP_FSCTL_CREATE)
- SYM(FSP_FSCTL_DELETE)
SYM(FSP_FSCTL_TRANSACT)
SYM(FSP_FSCTL_WORK)
default:
diff --git a/src/sys/devctl.c b/src/sys/devctl.c
index 9b892362..56214417 100644
--- a/src/sys/devctl.c
+++ b/src/sys/devctl.c
@@ -8,13 +8,13 @@
static NTSTATUS FspFsvolDeviceControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOCMPL_DISPATCH FspFsvolDeviceControlComplete;
FSP_DRIVER_DISPATCH FspDeviceControl;
-FSP_IOCMPL_DISPATCH FspDeviceControlComplete;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFsvolDeviceControl)
+#pragma alloc_text(PAGE, FspFsvolDeviceControlComplete)
#pragma alloc_text(PAGE, FspDeviceControl)
-#pragma alloc_text(PAGE, FspDeviceControlComplete)
#endif
static NTSTATUS FspFsvolDeviceControl(
@@ -25,13 +25,19 @@ static NTSTATUS FspFsvolDeviceControl(
return STATUS_INVALID_DEVICE_REQUEST;
}
+VOID FspFsvolDeviceControlComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC("%s", "");
+}
+
NTSTATUS FspDeviceControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_DEVICE_CONTROL == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
@@ -42,11 +48,3 @@ NTSTATUS FspDeviceControl(
FSP_LEAVE_MJ("%s", "");
}
-
-VOID FspDeviceControlComplete(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
-{
- FSP_ENTER_IOC(PAGED_CODE());
-
- FSP_LEAVE_IOC("%s", "");
-}
diff --git a/src/sys/device.c b/src/sys/device.c
index 62205799..e4339bb4 100644
--- a/src/sys/device.c
+++ b/src/sys/device.c
@@ -15,29 +15,21 @@ NTSTATUS FspDeviceCreate(UINT32 Kind, ULONG ExtraSize,
PDEVICE_OBJECT *PDeviceObject);
VOID FspDeviceInitComplete(PDEVICE_OBJECT DeviceObject);
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject);
-static NTSTATUS FspFsctlDeviceInit(PDEVICE_OBJECT DeviceObject);
-static VOID FspFsctlDeviceInitComplete(PDEVICE_OBJECT DeviceObject);
-static VOID FspFsctlDeviceFini(PDEVICE_OBJECT DeviceObject);
-static NTSTATUS FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject);
-static VOID FspFsvrtDeviceInitComplete(PDEVICE_OBJECT DeviceObject);
-static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject);
+BOOLEAN FspDeviceRetain(PDEVICE_OBJECT DeviceObject);
+VOID FspDeviceRelease(PDEVICE_OBJECT DeviceObject);
+PVOID FspDeviceLookupContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier);
+PVOID FspDeviceInsertContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, PVOID Context,
+ FSP_DEVICE_GENERIC_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted);
+VOID FspDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier,
+ PBOOLEAN PDeleted);
+static RTL_AVL_COMPARE_ROUTINE FspDeviceCompareElement;
+static RTL_AVL_ALLOCATE_ROUTINE FspDeviceAllocateElement;
+static RTL_AVL_FREE_ROUTINE FspDeviceFreeElement;
static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject);
static VOID FspFsvolDeviceInitComplete(PDEVICE_OBJECT DeviceObject);
static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject);
-BOOLEAN FspDeviceRetain(PDEVICE_OBJECT DeviceObject);
-VOID FspDeviceRelease(PDEVICE_OBJECT DeviceObject);
-VOID FspFsctlDeviceVolumeCreated(PDEVICE_OBJECT DeviceObject);
-VOID FspFsctlDeviceVolumeDeleted(PDEVICE_OBJECT DeviceObject);
-static IO_TIMER_ROUTINE FspFsvrtDeviceTimerRoutine;
-static WORKER_THREAD_ROUTINE FspFsvrtDeviceExpirationRoutine;
-PVOID FspFsvolDeviceLookupContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier);
-PVOID FspFsvolDeviceInsertContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, PVOID Context,
- FSP_DEVICE_GENERIC_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted);
-VOID FspFsvolDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier,
- PBOOLEAN PDeleted);
-static RTL_AVL_COMPARE_ROUTINE FspFsvolDeviceCompareElement;
-static RTL_AVL_ALLOCATE_ROUTINE FspFsvolDeviceAllocateElement;
-static RTL_AVL_FREE_ROUTINE FspFsvolDeviceFreeElement;
+static IO_TIMER_ROUTINE FspFsvolDeviceTimerRoutine;
+static WORKER_THREAD_ROUTINE FspFsvolDeviceExpirationRoutine;
NTSTATUS FspDeviceCopyList(
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount);
VOID FspDeviceDeleteList(
@@ -49,23 +41,15 @@ VOID FspDeviceDeleteAll(VOID);
#pragma alloc_text(PAGE, FspDeviceCreate)
#pragma alloc_text(PAGE, FspDeviceInitComplete)
#pragma alloc_text(PAGE, FspDeviceDelete)
-#pragma alloc_text(PAGE, FspFsctlDeviceInit)
-#pragma alloc_text(PAGE, FspFsctlDeviceInitComplete)
-#pragma alloc_text(PAGE, FspFsctlDeviceFini)
-#pragma alloc_text(PAGE, FspFsvrtDeviceInit)
-#pragma alloc_text(PAGE, FspFsvrtDeviceInitComplete)
-#pragma alloc_text(PAGE, FspFsvrtDeviceFini)
+#pragma alloc_text(PAGE, FspDeviceLookupContext)
+#pragma alloc_text(PAGE, FspDeviceInsertContext)
+#pragma alloc_text(PAGE, FspDeviceDeleteContext)
+#pragma alloc_text(PAGE, FspDeviceCompareElement)
+#pragma alloc_text(PAGE, FspDeviceAllocateElement)
+#pragma alloc_text(PAGE, FspDeviceFreeElement)
#pragma alloc_text(PAGE, FspFsvolDeviceInit)
#pragma alloc_text(PAGE, FspFsvolDeviceInitComplete)
#pragma alloc_text(PAGE, FspFsvolDeviceFini)
-#pragma alloc_text(PAGE, FspFsctlDeviceVolumeCreated)
-#pragma alloc_text(PAGE, FspFsctlDeviceVolumeDeleted)
-#pragma alloc_text(PAGE, FspFsvolDeviceLookupContext)
-#pragma alloc_text(PAGE, FspFsvolDeviceInsertContext)
-#pragma alloc_text(PAGE, FspFsvolDeviceDeleteContext)
-#pragma alloc_text(PAGE, FspFsvolDeviceCompareElement)
-#pragma alloc_text(PAGE, FspFsvolDeviceAllocateElement)
-#pragma alloc_text(PAGE, FspFsvolDeviceFreeElement)
#pragma alloc_text(PAGE, FspDeviceCopyList)
#pragma alloc_text(PAGE, FspDeviceDeleteList)
#pragma alloc_text(PAGE, FspDeviceDeleteAll)
@@ -89,10 +73,10 @@ NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
DeviceExtensionSize = sizeof(FSP_FSVOL_DEVICE_EXTENSION);
break;
case FspFsvrtDeviceExtensionKind:
- DeviceExtensionSize = sizeof(FSP_FSVRT_DEVICE_EXTENSION);
+ DeviceExtensionSize = 0;
break;
case FspFsctlDeviceExtensionKind:
- DeviceExtensionSize = sizeof(FSP_FSCTL_DEVICE_EXTENSION);
+ DeviceExtensionSize = 0;
break;
default:
ASSERT(0);
@@ -117,6 +101,8 @@ NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
KeInitializeSpinLock(&DeviceExtension->SpinLock);
DeviceExtension->RefCount = 1;
ExInitializeResourceLite(&DeviceExtension->Resource);
+ RtlInitializeGenericTableAvl(&DeviceExtension->GenericTable,
+ FspDeviceCompareElement, FspDeviceAllocateElement, FspDeviceFreeElement, 0);
DeviceExtension->Kind = Kind;
switch (Kind)
@@ -125,15 +111,24 @@ NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
Result = FspFsvolDeviceInit(DeviceObject);
break;
case FspFsvrtDeviceExtensionKind:
- Result = FspFsvrtDeviceInit(DeviceObject);
break;
case FspFsctlDeviceExtensionKind:
- Result = FspFsctlDeviceInit(DeviceObject);
break;
}
if (!NT_SUCCESS(Result))
{
+#if 0
+ /* FspDeviceFreeElement is now a no-op, so this is no longer necessary */
+ /*
+ * Enumerate and delete all entries in the GenericTable.
+ * There is no need to protect accesses to the table as we are in the device destructor.
+ */
+ FSP_DEVICE_GENERIC_TABLE_ELEMENT_DATA *Element;
+ while (0 != (Element = RtlGetElementGenericTableAvl(&DeviceExtension->GenericTable, 0)))
+ RtlDeleteElementGenericTableAvl(&DeviceExtension->GenericTable, &Element->Identifier);
+#endif
+
ExDeleteResourceLite(&DeviceExtension->Resource);
IoDeleteDevice(DeviceObject);
}
@@ -164,10 +159,8 @@ VOID FspDeviceInitComplete(PDEVICE_OBJECT DeviceObject)
FspFsvolDeviceInitComplete(DeviceObject);
break;
case FspFsvrtDeviceExtensionKind:
- FspFsvrtDeviceInitComplete(DeviceObject);
break;
case FspFsctlDeviceExtensionKind:
- FspFsctlDeviceInitComplete(DeviceObject);
break;
default:
ASSERT(0);
@@ -189,128 +182,27 @@ VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject)
FspFsvolDeviceFini(DeviceObject);
break;
case FspFsvrtDeviceExtensionKind:
- FspFsvrtDeviceFini(DeviceObject);
break;
case FspFsctlDeviceExtensionKind:
- FspFsctlDeviceFini(DeviceObject);
break;
default:
ASSERT(0);
return;
}
- ExDeleteResourceLite(&DeviceExtension->Resource);
-
- IoDeleteDevice(DeviceObject);
-}
-
-static NTSTATUS FspFsctlDeviceInit(PDEVICE_OBJECT DeviceObject)
-{
- PAGED_CODE();
-
- return STATUS_SUCCESS;
-}
-
-static VOID FspFsctlDeviceInitComplete(PDEVICE_OBJECT DeviceObject)
-{
- PAGED_CODE();
-}
-
-static VOID FspFsctlDeviceFini(PDEVICE_OBJECT DeviceObject)
-{
- PAGED_CODE();
-}
-
-static NTSTATUS FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject)
-{
- PAGED_CODE();
-
- NTSTATUS Result;
- FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
-
- /* initialize our timer routine */
- Result = IoInitializeTimer(DeviceObject, FspFsvrtDeviceTimerRoutine, 0);
- if (!NT_SUCCESS(Result))
- return Result;
-
- FspIoqInitialize(&FsvrtDeviceExtension->Ioq);
- KeInitializeSpinLock(&FsvrtDeviceExtension->ExpirationLock);
- ExInitializeWorkItem(&FsvrtDeviceExtension->ExpirationWorkItem,
- FspFsvrtDeviceExpirationRoutine, DeviceObject);
-
- FsvrtDeviceExtension->SwapVpb = FspAllocNonPagedExternal(sizeof *FsvrtDeviceExtension->SwapVpb);
- if (0 == FsvrtDeviceExtension->SwapVpb)
- return STATUS_INSUFFICIENT_RESOURCES;
- RtlZeroMemory(FsvrtDeviceExtension->SwapVpb, sizeof *FsvrtDeviceExtension->SwapVpb);
-
- return STATUS_SUCCESS;
-}
-
-static VOID FspFsvrtDeviceInitComplete(PDEVICE_OBJECT DeviceObject)
-{
- PAGED_CODE();
-
- IoStartTimer(DeviceObject);
-}
-
-static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject)
-{
- PAGED_CODE();
-
- FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
-
- /*
- * First things first: stop our timer.
- *
- * Our IoTimer routine will NOT be called again after IoStopTimer() returns.
- * However a work item may be in flight. For this reason our IoTimer routine
- * does an ObReferenceObject() on our DeviceObject before queueing work items.
- */
- IoStopTimer(DeviceObject);
-
- if (0 != FsvrtDeviceExtension->SwapVpb)
- FspFreeExternal(FsvrtDeviceExtension->SwapVpb);
-}
-
-static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
-{
- PAGED_CODE();
-
- FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
-
- RtlInitializeGenericTableAvl(&FsvolDeviceExtension->GenericTable,
- FspFsvolDeviceCompareElement, FspFsvolDeviceAllocateElement, FspFsvolDeviceFreeElement, 0);
-
- return STATUS_SUCCESS;
-}
-
-static VOID FspFsvolDeviceInitComplete(PDEVICE_OBJECT DeviceObject)
-{
- PAGED_CODE();
-}
-
-static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject)
-{
- PAGED_CODE();
-
- FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
-
#if 0
- /* FspFsvolDeviceFreeElement is now a no-op, so this is no longer necessary */
+ /* FspDeviceFreeElement is now a no-op, so this is no longer necessary */
/*
* Enumerate and delete all entries in the GenericTable.
* There is no need to protect accesses to the table as we are in the device destructor.
*/
FSP_DEVICE_GENERIC_TABLE_ELEMENT_DATA *Element;
- while (0 != (Element = RtlGetElementGenericTableAvl(&FsvolDeviceExtension->GenericTable, 0)))
- RtlDeleteElementGenericTableAvl(&FsvolDeviceExtension->GenericTable, &Element->Identifier);
+ while (0 != (Element = RtlGetElementGenericTableAvl(&DeviceExtension->GenericTable, 0)))
+ RtlDeleteElementGenericTableAvl(&DeviceExtension->GenericTable, &Element->Identifier);
#endif
- /*
- * Dereference the virtual volume device so that it can now go away.
- */
- if (0 != FsvolDeviceExtension->FsvrtDeviceObject)
- ObDereferenceObject(FsvolDeviceExtension->FsvrtDeviceObject);
+ ExDeleteResourceLite(&DeviceExtension->Resource);
+ IoDeleteDevice(DeviceObject);
}
BOOLEAN FspDeviceRetain(PDEVICE_OBJECT DeviceObject)
@@ -352,144 +244,60 @@ VOID FspDeviceRelease(PDEVICE_OBJECT DeviceObject)
FspDeviceDelete(DeviceObject);
}
-VOID FspFsctlDeviceVolumeCreated(PDEVICE_OBJECT DeviceObject)
+PVOID FspDeviceLookupContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier)
{
PAGED_CODE();
- ASSERT(FspFsctlDeviceExtensionKind == FspDeviceExtension(DeviceObject)->Kind);
- ASSERT(ExIsResourceAcquiredExclusiveLite(&FspDeviceExtension(DeviceObject)->Resource));
-
-#if 1
- FspFsctlDeviceExtension(DeviceObject)->FsvrtDeviceObjectCount++;
-#else
- ULONG FsvrtDeviceObjectCount = FspFsctlDeviceExtension(DeviceObject)->FsvrtDeviceObjectCount++;
- if (0 == FsvrtDeviceObjectCount)
- IoRegisterFileSystem(DeviceObject);
-#endif
-}
-
-VOID FspFsctlDeviceVolumeDeleted(PDEVICE_OBJECT DeviceObject)
-{
- PAGED_CODE();
-
- ASSERT(FspFsctlDeviceExtensionKind == FspDeviceExtension(DeviceObject)->Kind);
- ASSERT(ExIsResourceAcquiredExclusiveLite(&FspDeviceExtension(DeviceObject)->Resource));
-
-#if 1
- --FspFsctlDeviceExtension(DeviceObject)->FsvrtDeviceObjectCount;
-#else
- ULONG FsvrtDeviceObjectCount = --FspFsctlDeviceExtension(DeviceObject)->FsvrtDeviceObjectCount;
- if (0 == FsvrtDeviceObjectCount)
- IoUnregisterFileSystem(DeviceObject);
-#endif
-}
-
-static VOID FspFsvrtDeviceTimerRoutine(PDEVICE_OBJECT DeviceObject, PVOID Context)
-{
- // !PAGED_CODE();
-
- /*
- * This routine runs at DPC level. Reference our DeviceObject and queue a work item
- * so that we can do our processing at Passive level. Only do so if the work item
- * is not already in flight (otherwise we could requeue the same work item).
- */
-
- ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
-
- FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
-
- KeAcquireSpinLockAtDpcLevel(&FsvrtDeviceExtension->ExpirationLock);
- if (!FsvrtDeviceExtension->ExpirationInProgress)
- {
- FsvrtDeviceExtension->ExpirationInProgress = TRUE;
- ObReferenceObject(DeviceObject);
- ExQueueWorkItem(&FsvrtDeviceExtension->ExpirationWorkItem, DelayedWorkQueue);
- }
- KeReleaseSpinLockFromDpcLevel(&FsvrtDeviceExtension->ExpirationLock);
-}
-
-static VOID FspFsvrtDeviceExpirationRoutine(PVOID Context)
-{
- // !PAGED_CODE();
-
- PDEVICE_OBJECT DeviceObject = Context;
- if (FspDeviceRetain(DeviceObject))
- try
- {
- FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
- LARGE_INTEGER Timeout;
- KIRQL Irql;
-
- Timeout.QuadPart = FsvrtDeviceExtension->VolumeParams.IrpTimeout * 10000;
- /* convert millis to nanos */
- FspIoqRemoveExpired(&FsvrtDeviceExtension->Ioq, &Timeout);
-
- KeAcquireSpinLock(&FsvrtDeviceExtension->ExpirationLock, &Irql);
- FsvrtDeviceExtension->ExpirationInProgress = FALSE;
- KeReleaseSpinLock(&FsvrtDeviceExtension->ExpirationLock, Irql);
- }
- finally
- {
- FspDeviceRelease(DeviceObject);
- }
-
- ObDereferenceObject(DeviceObject);
-}
-
-PVOID FspFsvolDeviceLookupContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier)
-{
- PAGED_CODE();
-
- FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
- ASSERT(FspFsvolDeviceExtensionKind == FsvolDeviceExtension->Base.Kind);
- ASSERT(ExIsResourceAcquiredExclusiveLite(&FsvolDeviceExtension->Base.Resource));
+ FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject);
+ ASSERT(ExIsResourceAcquiredExclusiveLite(&DeviceExtension->Resource));
FSP_DEVICE_GENERIC_TABLE_ELEMENT_DATA *Result;
- Result = RtlLookupElementGenericTableAvl(&FsvolDeviceExtension->GenericTable, &Identifier);
+ Result = RtlLookupElementGenericTableAvl(&DeviceExtension->GenericTable, &Identifier);
return 0 != Result ? Result->Context : 0;
}
-PVOID FspFsvolDeviceInsertContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, PVOID Context,
+PVOID FspDeviceInsertContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, PVOID Context,
FSP_DEVICE_GENERIC_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted)
{
PAGED_CODE();
- FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
- ASSERT(FspFsvolDeviceExtensionKind == FsvolDeviceExtension->Base.Kind);
- ASSERT(ExIsResourceAcquiredExclusiveLite(&FsvolDeviceExtension->Base.Resource));
+ FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject);
+ ASSERT(ExIsResourceAcquiredExclusiveLite(&DeviceExtension->Resource));
+ ASSERT(0 != ElementStorage);
FSP_DEVICE_GENERIC_TABLE_ELEMENT_DATA *Result, Element = { 0 };
Element.Identifier = Identifier;
Element.Context = Context;
- FsvolDeviceExtension->GenericTableElementStorage = ElementStorage;
- Result = RtlInsertElementGenericTableAvl(&FsvolDeviceExtension->GenericTable,
+ DeviceExtension->GenericTableElementStorage = ElementStorage;
+ Result = RtlInsertElementGenericTableAvl(&DeviceExtension->GenericTable,
&Element, sizeof Element, PInserted);
- FsvolDeviceExtension->GenericTableElementStorage = 0;
+ DeviceExtension->GenericTableElementStorage = 0;
- return 0 != Result ? Result->Context : 0;
+ ASSERT(0 != Result);
+
+ return Result->Context;
}
-VOID FspFsvolDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier,
+VOID FspDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier,
PBOOLEAN PDeleted)
{
PAGED_CODE();
- FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
- ASSERT(FspFsvolDeviceExtensionKind == FsvolDeviceExtension->Base.Kind);
- ASSERT(ExIsResourceAcquiredExclusiveLite(&FsvolDeviceExtension->Base.Resource));
+ FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject);
+ ASSERT(ExIsResourceAcquiredExclusiveLite(&DeviceExtension->Resource));
BOOLEAN Deleted;
- Deleted = RtlDeleteElementGenericTableAvl(&FsvolDeviceExtension->GenericTable, &Identifier);
+ Deleted = RtlDeleteElementGenericTableAvl(&DeviceExtension->GenericTable, &Identifier);
if (0 != PDeleted)
*PDeleted = Deleted;
}
-static RTL_GENERIC_COMPARE_RESULTS NTAPI FspFsvolDeviceCompareElement(
+static RTL_GENERIC_COMPARE_RESULTS NTAPI FspDeviceCompareElement(
PRTL_AVL_TABLE Table, PVOID FirstElement, PVOID SecondElement)
{
PAGED_CODE();
@@ -503,25 +311,149 @@ static RTL_GENERIC_COMPARE_RESULTS NTAPI FspFsvolDeviceCompareElement(
return GenericEqual;
}
-static PVOID NTAPI FspFsvolDeviceAllocateElement(
+static PVOID NTAPI FspDeviceAllocateElement(
PRTL_AVL_TABLE Table, CLONG ByteSize)
{
PAGED_CODE();
- FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
- CONTAINING_RECORD(Table, FSP_FSVOL_DEVICE_EXTENSION, GenericTable);
+ FSP_DEVICE_EXTENSION *DeviceExtension =
+ CONTAINING_RECORD(Table, FSP_DEVICE_EXTENSION, GenericTable);
ASSERT(sizeof(FSP_DEVICE_GENERIC_TABLE_ELEMENT) == ByteSize);
- return FsvolDeviceExtension->GenericTableElementStorage;
+ return DeviceExtension->GenericTableElementStorage;
}
-static VOID NTAPI FspFsvolDeviceFreeElement(
+static VOID NTAPI FspDeviceFreeElement(
PRTL_AVL_TABLE Table, PVOID Buffer)
{
PAGED_CODE();
}
+static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
+{
+ PAGED_CODE();
+
+ NTSTATUS Result;
+ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
+
+ /* allocate a spare VPB in case we are mounted on an fsvrt */
+ if (FILE_DEVICE_DISK_FILE_SYSTEM == DeviceObject->DeviceType)
+ {
+ FsvolDeviceExtension->SwapVpb = FspAllocNonPagedExternal(sizeof *FsvolDeviceExtension->SwapVpb);
+ if (0 == FsvolDeviceExtension->SwapVpb)
+ return STATUS_INSUFFICIENT_RESOURCES;
+ RtlZeroMemory(FsvolDeviceExtension->SwapVpb, sizeof *FsvolDeviceExtension->SwapVpb);
+ }
+
+ /* setup our Ioq and expiration fields */
+ FspIoqInitialize(&FsvolDeviceExtension->Ioq, FspIopCompleteCanceledIrp);
+ KeInitializeSpinLock(&FsvolDeviceExtension->ExpirationLock);
+ ExInitializeWorkItem(&FsvolDeviceExtension->ExpirationWorkItem,
+ FspFsvolDeviceExpirationRoutine, DeviceObject);
+
+ /* initialize our timer routine */
+ Result = IoInitializeTimer(DeviceObject, FspFsvolDeviceTimerRoutine, 0);
+ if (!NT_SUCCESS(Result))
+ return Result;
+
+ return STATUS_SUCCESS;
+}
+
+static VOID FspFsvolDeviceInitComplete(PDEVICE_OBJECT DeviceObject)
+{
+ PAGED_CODE();
+
+ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
+
+ /*
+ * Reference the virtual volume device so that it will not go away while we are using it.
+ */
+ if (0 != FsvolDeviceExtension->FsvrtDeviceObject)
+ ObReferenceObject(FsvolDeviceExtension->FsvrtDeviceObject);
+
+ /* start our expiration timer */
+ IoStartTimer(DeviceObject);
+}
+
+static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject)
+{
+ PAGED_CODE();
+
+ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
+
+ /*
+ * First things first: stop our timer.
+ *
+ * Our IoTimer routine will NOT be called again after IoStopTimer() returns.
+ * However a work item may be in flight. For this reason our IoTimer routine
+ * does an ObReferenceObject() on our DeviceObject before queueing work items.
+ */
+ IoStopTimer(DeviceObject);
+
+ /*
+ * Dereference the virtual volume device so that it can now go away.
+ */
+ if (0 != FsvolDeviceExtension->FsvrtDeviceObject)
+ ObDereferenceObject(FsvolDeviceExtension->FsvrtDeviceObject);
+
+ /* free the spare VPB if we still have it */
+ if (0 != FsvolDeviceExtension->SwapVpb)
+ FspFreeExternal(FsvolDeviceExtension->SwapVpb);
+}
+
+static VOID FspFsvolDeviceTimerRoutine(PDEVICE_OBJECT DeviceObject, PVOID Context)
+{
+ // !PAGED_CODE();
+
+ /*
+ * This routine runs at DPC level. Reference our DeviceObject and queue a work item
+ * so that we can do our processing at Passive level. Only do so if the work item
+ * is not already in flight (otherwise we could requeue the same work item).
+ */
+
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
+
+ KeAcquireSpinLockAtDpcLevel(&FsvolDeviceExtension->ExpirationLock);
+ if (!FsvolDeviceExtension->ExpirationInProgress)
+ {
+ FsvolDeviceExtension->ExpirationInProgress = TRUE;
+ ObReferenceObject(DeviceObject);
+ ExQueueWorkItem(&FsvolDeviceExtension->ExpirationWorkItem, DelayedWorkQueue);
+ }
+ KeReleaseSpinLockFromDpcLevel(&FsvolDeviceExtension->ExpirationLock);
+}
+
+static VOID FspFsvolDeviceExpirationRoutine(PVOID Context)
+{
+ // !PAGED_CODE();
+
+ PDEVICE_OBJECT DeviceObject = Context;
+ if (FspDeviceRetain(DeviceObject))
+ try
+ {
+ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
+ LARGE_INTEGER Timeout;
+ KIRQL Irql;
+
+ Timeout.QuadPart = FsvolDeviceExtension->VolumeParams.IrpTimeout * 10000;
+ /* convert millis to nanos */
+ FspIoqRemoveExpired(&FsvolDeviceExtension->Ioq, &Timeout);
+
+ KeAcquireSpinLock(&FsvolDeviceExtension->ExpirationLock, &Irql);
+ FsvolDeviceExtension->ExpirationInProgress = FALSE;
+ KeReleaseSpinLock(&FsvolDeviceExtension->ExpirationLock, Irql);
+ }
+ finally
+ {
+ FspDeviceRelease(DeviceObject);
+ }
+
+ ObDereferenceObject(DeviceObject);
+}
+
NTSTATUS FspDeviceCopyList(
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount)
{
diff --git a/src/sys/dirctl.c b/src/sys/dirctl.c
index c0e7772c..43f281e6 100644
--- a/src/sys/dirctl.c
+++ b/src/sys/dirctl.c
@@ -8,13 +8,13 @@
static NTSTATUS FspFsvolDirectoryControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOCMPL_DISPATCH FspFsvolDirectoryControlComplete;
FSP_DRIVER_DISPATCH FspDirectoryControl;
-FSP_IOCMPL_DISPATCH FspDirectoryControlComplete;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFsvolDirectoryControl)
+#pragma alloc_text(PAGE, FspFsvolDirectoryControlComplete)
#pragma alloc_text(PAGE, FspDirectoryControl)
-#pragma alloc_text(PAGE, FspDirectoryControlComplete)
#endif
static NTSTATUS FspFsvolDirectoryControl(
@@ -25,13 +25,19 @@ static NTSTATUS FspFsvolDirectoryControl(
return STATUS_INVALID_DEVICE_REQUEST;
}
+VOID FspFsvolDirectoryControlComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC("%s", "");
+}
+
NTSTATUS FspDirectoryControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_DIRECTORY_CONTROL == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
@@ -42,11 +48,3 @@ NTSTATUS FspDirectoryControl(
FSP_LEAVE_MJ("%s", "");
}
-
-VOID FspDirectoryControlComplete(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
-{
- FSP_ENTER_IOC(PAGED_CODE());
-
- FSP_LEAVE_IOC("%s", "");
-}
diff --git a/src/sys/driver.c b/src/sys/driver.c
index cb7a0e7f..ce382ba9 100644
--- a/src/sys/driver.c
+++ b/src/sys/driver.c
@@ -58,7 +58,6 @@ NTSTATUS DriverEntry(
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = FspDirectoryControl;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FspFileSystemControl;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FspDeviceControl;
- DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = FspInternalDeviceControl;
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = FspShutdown;
DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = FspLockControl;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FspCleanup;
@@ -71,24 +70,23 @@ NTSTATUS DriverEntry(
/* setup the I/O completion functions */
FspIopCompleteFunction[IRP_MJ_CREATE] = FspFsvolCreateComplete;
FspIopCompleteFunction[IRP_MJ_CLOSE] = FspFsvolCloseComplete;
- FspIopCompleteFunction[IRP_MJ_READ] = FspReadComplete;
- FspIopCompleteFunction[IRP_MJ_WRITE] = FspWriteComplete;
- FspIopCompleteFunction[IRP_MJ_QUERY_INFORMATION] = FspQueryInformationComplete;
- FspIopCompleteFunction[IRP_MJ_SET_INFORMATION] = FspSetInformationComplete;
- FspIopCompleteFunction[IRP_MJ_QUERY_EA] = FspQueryEaComplete;
- FspIopCompleteFunction[IRP_MJ_SET_EA] = FspSetEaComplete;
- FspIopCompleteFunction[IRP_MJ_FLUSH_BUFFERS] = FspFlushBuffersComplete;
- FspIopCompleteFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = FspQueryVolumeInformationComplete;
- FspIopCompleteFunction[IRP_MJ_SET_VOLUME_INFORMATION] = FspSetVolumeInformationComplete;
- FspIopCompleteFunction[IRP_MJ_DIRECTORY_CONTROL] = FspDirectoryControlComplete;
- FspIopCompleteFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FspFileSystemControlComplete;
- FspIopCompleteFunction[IRP_MJ_DEVICE_CONTROL] = FspDeviceControlComplete;
- FspIopCompleteFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = FspFsvolInternalDeviceControlComplete;
- FspIopCompleteFunction[IRP_MJ_SHUTDOWN] = FspShutdownComplete;
- FspIopCompleteFunction[IRP_MJ_LOCK_CONTROL] = FspLockControlComplete;
+ FspIopCompleteFunction[IRP_MJ_READ] = FspFsvolReadComplete;
+ FspIopCompleteFunction[IRP_MJ_WRITE] = FspFsvolWriteComplete;
+ FspIopCompleteFunction[IRP_MJ_QUERY_INFORMATION] = FspFsvolQueryInformationComplete;
+ FspIopCompleteFunction[IRP_MJ_SET_INFORMATION] = FspFsvolSetInformationComplete;
+ FspIopCompleteFunction[IRP_MJ_QUERY_EA] = FspFsvolQueryEaComplete;
+ FspIopCompleteFunction[IRP_MJ_SET_EA] = FspFsvolSetEaComplete;
+ FspIopCompleteFunction[IRP_MJ_FLUSH_BUFFERS] = FspFsvolFlushBuffersComplete;
+ FspIopCompleteFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = FspFsvolQueryVolumeInformationComplete;
+ FspIopCompleteFunction[IRP_MJ_SET_VOLUME_INFORMATION] = FspFsvolSetVolumeInformationComplete;
+ FspIopCompleteFunction[IRP_MJ_DIRECTORY_CONTROL] = FspFsvolDirectoryControlComplete;
+ FspIopCompleteFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FspFsvolFileSystemControlComplete;
+ FspIopCompleteFunction[IRP_MJ_DEVICE_CONTROL] = FspFsvolDeviceControlComplete;
+ FspIopCompleteFunction[IRP_MJ_SHUTDOWN] = FspFsvolShutdownComplete;
+ FspIopCompleteFunction[IRP_MJ_LOCK_CONTROL] = FspFsvolLockControlComplete;
FspIopCompleteFunction[IRP_MJ_CLEANUP] = FspFsvolCleanupComplete;
- FspIopCompleteFunction[IRP_MJ_QUERY_SECURITY] = FspQuerySecurityComplete;
- FspIopCompleteFunction[IRP_MJ_SET_SECURITY] = FspSetSecurityComplete;
+ FspIopCompleteFunction[IRP_MJ_QUERY_SECURITY] = FspFsvolQuerySecurityComplete;
+ FspIopCompleteFunction[IRP_MJ_SET_SECURITY] = FspFsvolSetSecurityComplete;
/* setup fast I/O and resource acquisition */
static FAST_IO_DISPATCH FspFastIoDispatch = { 0 };
@@ -124,18 +122,15 @@ NTSTATUS DriverEntry(
DriverObject->FastIoDispatch = &FspFastIoDispatch;
/*
- * Register our devices as file systems. We do this here to simplify file system
- * registration/unregistration, although this makes our driver unloadable from the
- * get go.
+ * Register our "disk" device as a file system. We do not register our "net" device
+ * as a file system, but we register with the MUP instead at a later time.
*
- * Unfortunately a call to IoRegisterFileSystem(), even if followed by a call to
- * IoUnregistreFileSystem(), makes the driver unloadable. We attempted to move
- * the register/unregister calls to FspFsctlDeviceVolume{Created,Deleted}, but it
- * did not make any difference with regards to making the driver unloadable. Hence
- * we stick to the simpler scheme of doing registration here.
+ * Please note that the call below makes our driver unloadable. In fact the driver
+ * remains unloadable even if we issue an IoUnregisterFileSystem() call immediately
+ * after our IoRegisterFileSystem() call! Some system component appears to keep an
+ * extra reference to our device somewhere.
*/
IoRegisterFileSystem(FspFsctlDiskDeviceObject);
- IoRegisterFileSystem(FspFsctlNetDeviceObject);
#pragma prefast(suppress:28175, "We are in DriverEntry: ok to access DriverName")
FSP_LEAVE("DriverName=\"%wZ\", RegistryPath=\"%wZ\"",
diff --git a/src/sys/driver.h b/src/sys/driver.h
index 0b9df793..9184a8de 100644
--- a/src/sys/driver.h
+++ b/src/sys/driver.h
@@ -13,6 +13,10 @@
#include
#include
+/* disable warnings */
+#pragma warning(disable:4100) /* unreferenced formal parameter */
+#pragma warning(disable:4200) /* zero-sized array in struct/union */
+
#define DRIVER_NAME "WinFsp"
/* IoCreateDeviceSecure default SDDL's */
@@ -21,6 +25,11 @@
#define FSP_FSVRT_DEVICE_SDDL "D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GR;;;WD)"
/* System:GENERIC_ALL, Administrators:GENERIC_ALL, World:GENERIC_READ */
+/* misc macros */
+#define FSP_ALLOC_INTERNAL_TAG 'IpsF'
+#define FSP_ALLOC_EXTERNAL_TAG 'XpsF'
+#define FSP_IO_INCREMENT IO_NETWORK_INCREMENT
+
/* DEBUGLOG */
#if DBG
#define DEBUGLOG(fmt, ...) \
@@ -111,15 +120,12 @@
if (0 == (IrpSp->Control & SL_PENDING_RETURNED))\
{ \
/* if the IRP has not been marked pending already */\
- ASSERT(FspFsvolDeviceExtensionKind == FspDeviceExtension(DeviceObject)->Kind);\
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =\
FspFsvolDeviceExtension(DeviceObject);\
- FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension =\
- FspFsvrtDeviceExtension(FsvolDeviceExtension->FsvrtDeviceObject);\
- if (!FspIoqPostIrp(&FsvrtDeviceExtension->Ioq, Irp))\
+ if (!FspIoqPostIrp(&FsvolDeviceExtension->Ioq, Irp))\
{ \
/* this can only happen if the Ioq was stopped */\
- ASSERT(FspIoqStopped(&FsvrtDeviceExtension->Ioq));\
+ ASSERT(FspIoqStopped(&FsvolDeviceExtension->Ioq));\
FspIopCompleteIrp(Irp, Result = STATUS_CANCELLED);\
} \
} \
@@ -166,15 +172,6 @@
goto fsp_leave_label; \
} while (0,0)
-/* misc macros */
-#define FSP_ALLOC_INTERNAL_TAG 'IpsF'
-#define FSP_ALLOC_EXTERNAL_TAG 'XpsF'
-#define FSP_IO_INCREMENT IO_NETWORK_INCREMENT
-
-/* disable warnings */
-#pragma warning(disable:4100) /* unreferenced formal parameter */
-#pragma warning(disable:4200) /* zero-sized array in struct/union */
-
/* driver major functions */
_Function_class_(DRIVER_DISPATCH)
_IRQL_requires_max_(APC_LEVEL)
@@ -189,7 +186,6 @@ _Dispatch_type_(IRP_MJ_DEVICE_CONTROL) FSP_DRIVER_DISPATCH FspDeviceControl;
_Dispatch_type_(IRP_MJ_DIRECTORY_CONTROL) FSP_DRIVER_DISPATCH FspDirectoryControl;
_Dispatch_type_(IRP_MJ_FILE_SYSTEM_CONTROL) FSP_DRIVER_DISPATCH FspFileSystemControl;
_Dispatch_type_(IRP_MJ_FLUSH_BUFFERS) FSP_DRIVER_DISPATCH FspFlushBuffers;
-_Dispatch_type_(IRP_MJ_INTERNAL_DEVICE_CONTROL) FSP_DRIVER_DISPATCH FspInternalDeviceControl;
_Dispatch_type_(IRP_MJ_LOCK_CONTROL) FSP_DRIVER_DISPATCH FspLockControl;
_Dispatch_type_(IRP_MJ_QUERY_EA) FSP_DRIVER_DISPATCH FspQueryEa;
_Dispatch_type_(IRP_MJ_QUERY_INFORMATION) FSP_DRIVER_DISPATCH FspQueryInformation;
@@ -216,28 +212,25 @@ FSP_IOPREP_DISPATCH FspFsvolCreatePrepare;
FSP_IOCMPL_DISPATCH FspFsvolCleanupComplete;
FSP_IOCMPL_DISPATCH FspFsvolCloseComplete;
FSP_IOCMPL_DISPATCH FspFsvolCreateComplete;
-FSP_IOCMPL_DISPATCH FspDeviceControlComplete;
-FSP_IOCMPL_DISPATCH FspDirectoryControlComplete;
-FSP_IOCMPL_DISPATCH FspFileSystemControlComplete;
-FSP_IOCMPL_DISPATCH FspFlushBuffersComplete;
-FSP_IOCMPL_DISPATCH FspFsvolInternalDeviceControlComplete;
-FSP_IOCMPL_DISPATCH FspLockControlComplete;
-FSP_IOCMPL_DISPATCH FspQueryEaComplete;
-FSP_IOCMPL_DISPATCH FspQueryInformationComplete;
-FSP_IOCMPL_DISPATCH FspQuerySecurityComplete;
-FSP_IOCMPL_DISPATCH FspQueryVolumeInformationComplete;
-FSP_IOCMPL_DISPATCH FspReadComplete;
-FSP_IOCMPL_DISPATCH FspSetEaComplete;
-FSP_IOCMPL_DISPATCH FspSetInformationComplete;
-FSP_IOCMPL_DISPATCH FspSetSecurityComplete;
-FSP_IOCMPL_DISPATCH FspSetVolumeInformationComplete;
-FSP_IOCMPL_DISPATCH FspShutdownComplete;
-FSP_IOCMPL_DISPATCH FspWriteComplete;
+FSP_IOCMPL_DISPATCH FspFsvolDeviceControlComplete;
+FSP_IOCMPL_DISPATCH FspFsvolDirectoryControlComplete;
+FSP_IOCMPL_DISPATCH FspFsvolFileSystemControlComplete;
+FSP_IOCMPL_DISPATCH FspFsvolFlushBuffersComplete;
+FSP_IOCMPL_DISPATCH FspFsvolLockControlComplete;
+FSP_IOCMPL_DISPATCH FspFsvolQueryEaComplete;
+FSP_IOCMPL_DISPATCH FspFsvolQueryInformationComplete;
+FSP_IOCMPL_DISPATCH FspFsvolQuerySecurityComplete;
+FSP_IOCMPL_DISPATCH FspFsvolQueryVolumeInformationComplete;
+FSP_IOCMPL_DISPATCH FspFsvolReadComplete;
+FSP_IOCMPL_DISPATCH FspFsvolSetEaComplete;
+FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete;
+FSP_IOCMPL_DISPATCH FspFsvolSetSecurityComplete;
+FSP_IOCMPL_DISPATCH FspFsvolSetVolumeInformationComplete;
+FSP_IOCMPL_DISPATCH FspFsvolShutdownComplete;
+FSP_IOCMPL_DISPATCH FspFsvolWriteComplete;
-/* fast I/O */
+/* fast I/O and resource acquisition */
FAST_IO_CHECK_IF_POSSIBLE FspFastIoCheckIfPossible;
-
-/* resource acquisition */
FAST_IO_ACQUIRE_FILE FspAcquireFileForNtCreateSection;
FAST_IO_RELEASE_FILE FspReleaseFileForNtCreateSection;
FAST_IO_ACQUIRE_FOR_MOD_WRITE FspAcquireForModWrite;
@@ -245,6 +238,52 @@ FAST_IO_RELEASE_FOR_MOD_WRITE FspReleaseForModWrite;
FAST_IO_ACQUIRE_FOR_CCFLUSH FspAcquireForCcFlush;
FAST_IO_RELEASE_FOR_CCFLUSH FspReleaseForCcFlush;
+/* memory allocation */
+static inline
+PVOID FspAlloc(SIZE_T Size)
+{
+ return ExAllocatePoolWithTag(PagedPool, Size, FSP_ALLOC_INTERNAL_TAG);
+}
+static inline
+PVOID FspAllocNonPaged(SIZE_T Size)
+{
+ return ExAllocatePoolWithTag(NonPagedPool, Size, FSP_ALLOC_INTERNAL_TAG);
+}
+static inline
+VOID FspFree(PVOID Pointer)
+{
+ ExFreePoolWithTag(Pointer, FSP_ALLOC_INTERNAL_TAG);
+}
+static inline
+PVOID FspAllocExternal(SIZE_T Size)
+{
+ return ExAllocatePoolWithTag(PagedPool, Size, FSP_ALLOC_EXTERNAL_TAG);
+}
+static inline
+PVOID FspAllocNonPagedExternal(SIZE_T Size)
+{
+ return ExAllocatePoolWithTag(NonPagedPool, Size, FSP_ALLOC_EXTERNAL_TAG);
+}
+static inline
+VOID FspFreeExternal(PVOID Pointer)
+{
+ ExFreePool(Pointer);
+}
+
+/* utility: GUIDs */
+NTSTATUS FspCreateGuid(GUID *Guid);
+
+/* utility: delayed work queue */
+typedef struct
+{
+ KTIMER Timer;
+ KDPC Dpc;
+ WORK_QUEUE_ITEM WorkQueueItem;
+} FSP_WORK_ITEM_WITH_DELAY;
+VOID FspInitializeWorkItemWithDelay(FSP_WORK_ITEM_WITH_DELAY *WorkItem,
+ PWORKER_THREAD_ROUTINE Routine, PVOID Context);
+VOID FspQueueWorkItemWithDelay(FSP_WORK_ITEM_WITH_DELAY *WorkItem, LARGE_INTEGER Timeout);
+
/* IRP context */
#define FspIrpTimestamp(Irp) \
(*(ULONGLONG *)&(Irp)->Tail.Overlay.DriverContext[0])
@@ -261,8 +300,9 @@ typedef struct
KEVENT PendingIrpEvent;
LIST_ENTRY PendingIrpList, ProcessIrpList;
IO_CSQ PendingIoCsq, ProcessIoCsq;
+ VOID (*CompleteCanceledIrp)(PIRP Irp);
} FSP_IOQ;
-VOID FspIoqInitialize(FSP_IOQ *Ioq);
+VOID FspIoqInitialize(FSP_IOQ *Ioq, VOID (*CompleteCanceledIrp)(PIRP Irp));
VOID FspIoqStop(FSP_IOQ *Ioq);
BOOLEAN FspIoqStopped(FSP_IOQ *Ioq);
VOID FspIoqRemoveExpired(FSP_IOQ *Ioq, PLARGE_INTEGER Timeout);
@@ -289,10 +329,21 @@ VOID FspIopCompleteIrp(PIRP Irp, NTSTATUS Result)
{
FspIopCompleteIrpEx(Irp, Result, TRUE);
}
+VOID FspIopCompleteCanceledIrp(PIRP Irp);
NTSTATUS FspIopDispatchPrepare(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request);
VOID FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response);
/* device management */
+typedef struct
+{
+ UINT64 Identifier;
+ PVOID Context;
+} FSP_DEVICE_GENERIC_TABLE_ELEMENT_DATA;
+typedef struct
+{
+ RTL_BALANCED_LINKS Header;
+ FSP_DEVICE_GENERIC_TABLE_ELEMENT_DATA Data;
+} FSP_DEVICE_GENERIC_TABLE_ELEMENT;
enum
{
FspFsctlDeviceExtensionKind = '\0ltC', /* file system control device (e.g. \Device\WinFsp.Disk) */
@@ -304,62 +355,32 @@ typedef struct
KSPIN_LOCK SpinLock;
LONG RefCount;
ERESOURCE Resource;
+ RTL_AVL_TABLE GenericTable;
+ PVOID GenericTableElementStorage;
UINT32 Kind;
} FSP_DEVICE_EXTENSION;
typedef struct
-{
- FSP_DEVICE_EXTENSION Base;
- ULONG FsvrtDeviceObjectCount;
-} FSP_FSCTL_DEVICE_EXTENSION;
-typedef struct
{
FSP_DEVICE_EXTENSION Base;
PDEVICE_OBJECT FsctlDeviceObject;
- PDEVICE_OBJECT FsvolDeviceObject;
+ PDEVICE_OBJECT FsvrtDeviceObject;
+ HANDLE MupHandle;
+ BOOLEAN DeletePending;
+ FSP_WORK_ITEM_WITH_DELAY DeleteVolumeWorkItem;
+ FSP_DEVICE_GENERIC_TABLE_ELEMENT ElementStorage;
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
+ PVPB SwapVpb;
FSP_IOQ Ioq;
KSPIN_LOCK ExpirationLock;
WORK_QUEUE_ITEM ExpirationWorkItem;
BOOLEAN ExpirationInProgress;
- PVPB SwapVpb;
- BOOLEAN Deleted;
- FSP_FSCTL_DECLSPEC_ALIGN UINT8 SecurityDescriptorBuf[];
-} FSP_FSVRT_DEVICE_EXTENSION;
-typedef struct
-{
- FSP_DEVICE_EXTENSION Base;
- PDEVICE_OBJECT FsvrtDeviceObject;
- RTL_AVL_TABLE GenericTable;
- PVOID GenericTableElementStorage;
} FSP_FSVOL_DEVICE_EXTENSION;
-typedef struct
-{
- UINT64 Identifier;
- PVOID Context;
-} FSP_DEVICE_GENERIC_TABLE_ELEMENT_DATA;
-typedef struct
-{
- RTL_BALANCED_LINKS Header;
- FSP_DEVICE_GENERIC_TABLE_ELEMENT_DATA Data;
-} FSP_DEVICE_GENERIC_TABLE_ELEMENT;
static inline
FSP_DEVICE_EXTENSION *FspDeviceExtension(PDEVICE_OBJECT DeviceObject)
{
return DeviceObject->DeviceExtension;
}
static inline
-FSP_FSCTL_DEVICE_EXTENSION *FspFsctlDeviceExtension(PDEVICE_OBJECT DeviceObject)
-{
- ASSERT(FspFsctlDeviceExtensionKind == ((FSP_DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->Kind);
- return DeviceObject->DeviceExtension;
-}
-static inline
-FSP_FSVRT_DEVICE_EXTENSION *FspFsvrtDeviceExtension(PDEVICE_OBJECT DeviceObject)
-{
- ASSERT(FspFsvrtDeviceExtensionKind == ((FSP_DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->Kind);
- return DeviceObject->DeviceExtension;
-}
-static inline
FSP_FSVOL_DEVICE_EXTENSION *FspFsvolDeviceExtension(PDEVICE_OBJECT DeviceObject)
{
ASSERT(FspFsvolDeviceExtensionKind == ((FSP_DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->Kind);
@@ -376,12 +397,10 @@ VOID FspDeviceInitComplete(PDEVICE_OBJECT DeviceObject);
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject);
BOOLEAN FspDeviceRetain(PDEVICE_OBJECT DeviceObject);
VOID FspDeviceRelease(PDEVICE_OBJECT DeviceObject);
-VOID FspFsctlDeviceVolumeCreated(PDEVICE_OBJECT DeviceObject);
-VOID FspFsctlDeviceVolumeDeleted(PDEVICE_OBJECT DeviceObject);
-PVOID FspFsvolDeviceLookupContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier);
-PVOID FspFsvolDeviceInsertContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, PVOID Context,
+PVOID FspDeviceLookupContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier);
+PVOID FspDeviceInsertContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, PVOID Context,
FSP_DEVICE_GENERIC_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted);
-VOID FspFsvolDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier,
+VOID FspDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier,
PBOOLEAN PDeleted);
NTSTATUS FspDeviceCopyList(
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount);
@@ -389,6 +408,23 @@ VOID FspDeviceDeleteList(
PDEVICE_OBJECT *DeviceObjects, ULONG DeviceObjectCount);
VOID FspDeviceDeleteAll(VOID);
+/* debug */
+#if DBG
+BOOLEAN HasDbgBreakPoint(const char *Function);
+const char *NtStatusSym(NTSTATUS Status);
+const char *IrpMajorFunctionSym(UCHAR MajorFunction);
+const char *IrpMinorFunctionSym(UCHAR MajorFunction, UCHAR MinorFunction);
+const char *IoctlCodeSym(ULONG ControlCode);
+#endif
+
+/* extern */
+extern PDRIVER_OBJECT FspDriverObject;
+extern PDEVICE_OBJECT FspFsctlDiskDeviceObject;
+extern PDEVICE_OBJECT FspFsctlNetDeviceObject;
+extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[];
+extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[];
+
+#if 0
/* file objects */
#define FspFileContextKind(FsContext) \
(((FSP_FILE_CONTEXT *)FsContext)->Header.NodeTypeCode)
@@ -451,69 +487,6 @@ VOID FspFileContextRelease(FSP_FILE_CONTEXT *Context)
FspFileContextDelete(Context);
}
-/* misc */
-static inline
-PVOID FspAlloc(SIZE_T Size)
-{
- return ExAllocatePoolWithTag(PagedPool, Size, FSP_ALLOC_INTERNAL_TAG);
-}
-static inline
-PVOID FspAllocNonPaged(SIZE_T Size)
-{
- return ExAllocatePoolWithTag(NonPagedPool, Size, FSP_ALLOC_INTERNAL_TAG);
-}
-static inline
-VOID FspFree(PVOID Pointer)
-{
- ExFreePoolWithTag(Pointer, FSP_ALLOC_INTERNAL_TAG);
-}
-static inline
-PVOID FspAllocExternal(SIZE_T Size)
-{
- return ExAllocatePoolWithTag(PagedPool, Size, FSP_ALLOC_EXTERNAL_TAG);
-}
-static inline
-PVOID FspAllocNonPagedExternal(SIZE_T Size)
-{
- return ExAllocatePoolWithTag(NonPagedPool, Size, FSP_ALLOC_EXTERNAL_TAG);
-}
-static inline
-VOID FspFreeExternal(PVOID Pointer)
-{
- ExFreePool(Pointer);
-}
-NTSTATUS FspCreateGuid(GUID *Guid);
-BOOLEAN FspValidRelativeSecurityDescriptor(
- PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG SecurityDescriptorLength,
- SECURITY_INFORMATION RequiredInformation);
-NTSTATUS FspSecuritySubjectContextAccessCheck(
- PSECURITY_DESCRIPTOR SecurityDescriptor, ACCESS_MASK DesiredAccess, KPROCESSOR_MODE AccessMode);
-
-/* delayed work queue */
-typedef struct
-{
- KTIMER Timer;
- KDPC Dpc;
- WORK_QUEUE_ITEM WorkQueueItem;
-} FSP_WORK_ITEM_WITH_DELAY;
-VOID FspInitializeWorkItemWithDelay(FSP_WORK_ITEM_WITH_DELAY *WorkItem,
- PWORKER_THREAD_ROUTINE Routine, PVOID Context);
-VOID FspQueueWorkItemWithDelay(FSP_WORK_ITEM_WITH_DELAY *WorkItem, LARGE_INTEGER Timeout);
-
-/* debug */
-#if DBG
-BOOLEAN HasDbgBreakPoint(const char *Function);
-const char *NtStatusSym(NTSTATUS Status);
-const char *IrpMajorFunctionSym(UCHAR MajorFunction);
-const char *IrpMinorFunctionSym(UCHAR MajorFunction, UCHAR MinorFunction);
-const char *IoctlCodeSym(ULONG ControlCode);
#endif
-/* extern */
-extern PDRIVER_OBJECT FspDriverObject;
-extern PDEVICE_OBJECT FspFsctlDiskDeviceObject;
-extern PDEVICE_OBJECT FspFsctlNetDeviceObject;
-extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[];
-extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[];
-
#endif
diff --git a/src/sys/ea.c b/src/sys/ea.c
index d1511cc0..4c65d9c3 100644
--- a/src/sys/ea.c
+++ b/src/sys/ea.c
@@ -8,20 +8,20 @@
static NTSTATUS FspFsvolQueryEa(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOCMPL_DISPATCH FspFsvolQueryEaComplete;
static NTSTATUS FspFsvolSetEa(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOCMPL_DISPATCH FspFsvolSetEaComplete;
FSP_DRIVER_DISPATCH FspQueryEa;
FSP_DRIVER_DISPATCH FspSetEa;
-FSP_IOCMPL_DISPATCH FspQueryEaComplete;
-FSP_IOCMPL_DISPATCH FspSetEaComplete;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFsvolQueryEa)
+#pragma alloc_text(PAGE, FspFsvolQueryEaComplete)
#pragma alloc_text(PAGE, FspFsvolSetEa)
+#pragma alloc_text(PAGE, FspFsvolSetEaComplete)
#pragma alloc_text(PAGE, FspQueryEa)
#pragma alloc_text(PAGE, FspSetEa)
-#pragma alloc_text(PAGE, FspQueryEaComplete)
-#pragma alloc_text(PAGE, FspSetEaComplete)
#endif
static NTSTATUS FspFsvolQueryEa(
@@ -32,6 +32,14 @@ static NTSTATUS FspFsvolQueryEa(
return STATUS_INVALID_DEVICE_REQUEST;
}
+VOID FspFsvolQueryEaComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC("%s", "");
+}
+
static NTSTATUS FspFsvolSetEa(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
@@ -40,13 +48,19 @@ static NTSTATUS FspFsvolSetEa(
return STATUS_INVALID_DEVICE_REQUEST;
}
+VOID FspFsvolSetEaComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC("%s", "");
+}
+
NTSTATUS FspQueryEa(
PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_QUERY_EA == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
@@ -63,8 +77,6 @@ NTSTATUS FspSetEa(
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_SET_EA == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
@@ -75,19 +87,3 @@ NTSTATUS FspSetEa(
FSP_LEAVE_MJ("%s", "");
}
-
-VOID FspQueryEaComplete(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
-{
- FSP_ENTER_IOC(PAGED_CODE());
-
- FSP_LEAVE_IOC("%s", "");
-}
-
-VOID FspSetEaComplete(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
-{
- FSP_ENTER_IOC(PAGED_CODE());
-
- FSP_LEAVE_IOC("%s", "");
-}
diff --git a/src/sys/fastio.c b/src/sys/fastio.c
index a32bf2dd..a46821e4 100644
--- a/src/sys/fastio.c
+++ b/src/sys/fastio.c
@@ -7,9 +7,21 @@
#include
FAST_IO_CHECK_IF_POSSIBLE FspFastIoCheckIfPossible;
+FAST_IO_ACQUIRE_FILE FspAcquireFileForNtCreateSection;
+FAST_IO_RELEASE_FILE FspReleaseFileForNtCreateSection;
+FAST_IO_ACQUIRE_FOR_MOD_WRITE FspAcquireForModWrite;
+FAST_IO_RELEASE_FOR_MOD_WRITE FspReleaseForModWrite;
+FAST_IO_ACQUIRE_FOR_CCFLUSH FspAcquireForCcFlush;
+FAST_IO_RELEASE_FOR_CCFLUSH FspReleaseForCcFlush;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFastIoCheckIfPossible)
+#pragma alloc_text(PAGE, FspAcquireFileForNtCreateSection)
+#pragma alloc_text(PAGE, FspReleaseFileForNtCreateSection)
+#pragma alloc_text(PAGE, FspAcquireForModWrite)
+#pragma alloc_text(PAGE, FspReleaseForModWrite)
+#pragma alloc_text(PAGE, FspAcquireForCcFlush)
+#pragma alloc_text(PAGE, FspReleaseForCcFlush)
#endif
BOOLEAN FspFastIoCheckIfPossible(
@@ -28,3 +40,66 @@ BOOLEAN FspFastIoCheckIfPossible(
FSP_LEAVE_BOOL("%s", "");
}
+
+VOID FspAcquireFileForNtCreateSection(
+ PFILE_OBJECT FileObject)
+{
+ FSP_ENTER_VOID(PAGED_CODE());
+
+ FSP_LEAVE_VOID("%s", "");
+}
+
+VOID FspReleaseFileForNtCreateSection(
+ PFILE_OBJECT FileObject)
+{
+ FSP_ENTER_VOID(PAGED_CODE());
+
+ FSP_LEAVE_VOID("%s", "");
+}
+
+NTSTATUS FspAcquireForModWrite(
+ PFILE_OBJECT FileObject,
+ PLARGE_INTEGER EndingOffset,
+ PERESOURCE *ResourceToRelease,
+ PDEVICE_OBJECT DeviceObject)
+{
+ FSP_ENTER(PAGED_CODE());
+
+ Result = STATUS_NOT_IMPLEMENTED;
+
+ FSP_LEAVE("%s", "");
+}
+
+NTSTATUS FspReleaseForModWrite(
+ PFILE_OBJECT FileObject,
+ PERESOURCE ResourceToRelease,
+ PDEVICE_OBJECT DeviceObject)
+{
+ FSP_ENTER(PAGED_CODE());
+
+ Result = STATUS_NOT_IMPLEMENTED;
+
+ FSP_LEAVE("%s", "");
+}
+
+NTSTATUS FspAcquireForCcFlush(
+ PFILE_OBJECT FileObject,
+ PDEVICE_OBJECT DeviceObject)
+{
+ FSP_ENTER(PAGED_CODE());
+
+ Result = STATUS_NOT_IMPLEMENTED;
+
+ FSP_LEAVE("%s", "");
+}
+
+NTSTATUS FspReleaseForCcFlush(
+ PFILE_OBJECT FileObject,
+ PDEVICE_OBJECT DeviceObject)
+{
+ FSP_ENTER(PAGED_CODE());
+
+ Result = STATUS_NOT_IMPLEMENTED;
+
+ FSP_LEAVE("%s", "");
+}
diff --git a/src/sys/fileinfo.c b/src/sys/fileinfo.c
index 72d0385d..01242977 100644
--- a/src/sys/fileinfo.c
+++ b/src/sys/fileinfo.c
@@ -8,20 +8,20 @@
static NTSTATUS FspFsvolQueryInformation(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOCMPL_DISPATCH FspFsvolQueryInformationComplete;
static NTSTATUS FspFsvolSetInformation(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete;
FSP_DRIVER_DISPATCH FspQueryInformation;
FSP_DRIVER_DISPATCH FspSetInformation;
-FSP_IOCMPL_DISPATCH FspQueryInformationComplete;
-FSP_IOCMPL_DISPATCH FspSetInformationComplete;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFsvolQueryInformation)
+#pragma alloc_text(PAGE, FspFsvolQueryInformationComplete)
#pragma alloc_text(PAGE, FspFsvolSetInformation)
+#pragma alloc_text(PAGE, FspFsvolSetInformationComplete)
#pragma alloc_text(PAGE, FspQueryInformation)
#pragma alloc_text(PAGE, FspSetInformation)
-#pragma alloc_text(PAGE, FspQueryInformationComplete)
-#pragma alloc_text(PAGE, FspSetInformationComplete)
#endif
static NTSTATUS FspFsvolQueryInformation(
@@ -32,6 +32,14 @@ static NTSTATUS FspFsvolQueryInformation(
return STATUS_INVALID_DEVICE_REQUEST;
}
+VOID FspFsvolQueryInformationComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC("%s", "");
+}
+
static NTSTATUS FspFsvolSetInformation(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
@@ -40,13 +48,19 @@ static NTSTATUS FspFsvolSetInformation(
return STATUS_INVALID_DEVICE_REQUEST;
}
+VOID FspFsvolSetInformationComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC("%s", "");
+}
+
NTSTATUS FspQueryInformation(
PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_QUERY_INFORMATION == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
@@ -63,8 +77,6 @@ NTSTATUS FspSetInformation(
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_SET_INFORMATION == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
@@ -75,19 +87,3 @@ NTSTATUS FspSetInformation(
FSP_LEAVE_MJ("%s", "");
}
-
-VOID FspQueryInformationComplete(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
-{
- FSP_ENTER_IOC(PAGED_CODE());
-
- FSP_LEAVE_IOC("%s", "");
-}
-
-VOID FspSetInformationComplete(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
-{
- FSP_ENTER_IOC(PAGED_CODE());
-
- FSP_LEAVE_IOC("%s", "");
-}
diff --git a/src/sys/flush.c b/src/sys/flush.c
index 181b7153..72e60658 100644
--- a/src/sys/flush.c
+++ b/src/sys/flush.c
@@ -8,13 +8,13 @@
static NTSTATUS FspFsvolFlushBuffers(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOCMPL_DISPATCH FspFsvolFlushBuffersComplete;
FSP_DRIVER_DISPATCH FspFlushBuffers;
-FSP_IOCMPL_DISPATCH FspFlushBuffersComplete;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFsvolFlushBuffers)
+#pragma alloc_text(PAGE, FspFsvolFlushBuffersComplete)
#pragma alloc_text(PAGE, FspFlushBuffers)
-#pragma alloc_text(PAGE, FspFlushBuffersComplete)
#endif
static NTSTATUS FspFsvolFlushBuffers(
@@ -25,13 +25,19 @@ static NTSTATUS FspFsvolFlushBuffers(
return STATUS_INVALID_DEVICE_REQUEST;
}
+VOID FspFsvolFlushBuffersComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC("%s", "");
+}
+
NTSTATUS FspFlushBuffers(
PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_FLUSH_BUFFERS == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
@@ -42,11 +48,3 @@ NTSTATUS FspFlushBuffers(
FSP_LEAVE_MJ("%s", "");
}
-
-VOID FspFlushBuffersComplete(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
-{
- FSP_ENTER_IOC(PAGED_CODE());
-
- FSP_LEAVE_IOC("%s", "");
-}
diff --git a/src/sys/fsctl.c b/src/sys/fsctl.c
index 9b97c926..b77c6a19 100644
--- a/src/sys/fsctl.c
+++ b/src/sys/fsctl.c
@@ -6,99 +6,64 @@
#include
-/*
- * Overview
- *
- * The fsctl module provides the IOCTL interface to interact with the
- * user-mode file system. The user-mode file system can use the IOCTL's
- * to create new volumes, delete them (while they are live!) and transact
- * with them.
- *
- *
- * Volume Creation
- *
- * The creation of a new volume is performed using an FSP_FSCTL_CREATE
- * IOCTL code. Creation is simple: a new device \Device\Volume{GUID} is
- * created and its path is returned to the user-mode file system. The
- * user-mode file system also passes a security descriptor to associate
- * with the new virtual volume device so that only the creating user-mode
- * file system can control the new volume.
- *
- *
- * Volume Deletion
- *
- * Deletion of an existing volume is performed using FSP_FSCTL_DELETE and
- * is quite a bit more involved. We must protect against the following two
- * eventualities: (1) that the volume is currently in use and cannot simply
- * go away, and (2) that a simultaneous mount operation is taking place
- * while we are deleting the volume.
- *
- * To protect against the first eventuality we maintain a reference count
- * on all our device extensions. Every time an MJ function is entered,
- * the reference count is incremented (FspDeviceRetain). Every time
- * an IRP is completed, the reference count is decremented (FspDeviceRelease).
- * When the reference count reaches 0 the device is deleted using
- * IoDeleteDevice. This ensures that a device will not go away while an
- * IRP is being pending/processed.
- *
- * To protect against the second eventuality we use the lock (ERESOURCE)
- * on the root Fsctl device to wrap volume deletion and attempts from the
- * system to mount the same volume. We also mark the virtual volume device
- * as Deleted in case we attempt to delete it (FspDeviceRelease) but we
- * cannot because it is currently in use.
- *
- * A sticky point is our use of the Windows VPB. It is not well documented
- * how one should handle this structure during forcible dismount. The fastfat
- * and cdfs samples use a technique where they keep a spare VPB and they swap
- * it with the volume one during forcible dismount. We do something similar.
- * The issue is what to do with the old VPB, because we can delete a volume
- * that is not currently being used. We check the VPB's ReferenceCount and
- * we free the VPB in this case.
- *
- *
- * Volume Transact
- *
- * The user-mode file system's primary interaction with the kernel-mode driver
- * is by using the FSP_FSCTL_TRANSACT IOCTL code. Every virtual volume device
- * maintains an FSP_IOQ (refer to ioq.c for more). When an FSP_FSCTL_TRANSACT
- * arrives it first processes any responses (FSP_FSCTL_TRANSACT_RSP) that the
- * user-mode file system has sent to handle requests sent to it using a prior
- * FSP_FSCTL_TRANSACT. It then proceeds to handle any pending IRP requests by
- * sending the corresponding requests (FSP_FSCTL_TRANSACT_REQ) to the user-
- * mode file system.
- */
-
+static NTSTATUS FspFsctlFileSystemControl(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static NTSTATUS FspFsctlCreateVolume(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static NTSTATUS FspFsctlMountVolume(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
-static NTSTATUS FspFsvrtDeleteVolume(
+VOID FspFsctlDeleteVolume(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
-static WORKER_THREAD_ROUTINE FspFsvrtDeleteVolumeDelayed;
-static NTSTATUS FspFsvrtTransact(
- PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
-static NTSTATUS FspFsctlFileSystemControl(
- PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
-static NTSTATUS FspFsvrtFileSystemControl(
+static WORKER_THREAD_ROUTINE FspFsctlDeleteVolumeDelayed;
+static NTSTATUS FspFsctlTransact(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static NTSTATUS FspFsvolFileSystemControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOCMPL_DISPATCH FspFsvolFileSystemControlComplete;
FSP_DRIVER_DISPATCH FspFileSystemControl;
-FSP_IOCMPL_DISPATCH FspFileSystemControlComplete;
#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FspFsctlFileSystemControl)
#pragma alloc_text(PAGE, FspFsctlCreateVolume)
#pragma alloc_text(PAGE, FspFsctlMountVolume)
-#pragma alloc_text(PAGE, FspFsvrtDeleteVolume)
-#pragma alloc_text(PAGE, FspFsvrtDeleteVolumeDelayed)
-#pragma alloc_text(PAGE, FspFsvrtTransact)
-#pragma alloc_text(PAGE, FspFsctlFileSystemControl)
-#pragma alloc_text(PAGE, FspFsvrtFileSystemControl)
+#pragma alloc_text(PAGE, FspFsctlDeleteVolume)
+#pragma alloc_text(PAGE, FspFsctlDeleteVolumeDelayed)
+#pragma alloc_text(PAGE, FspFsctlTransact)
#pragma alloc_text(PAGE, FspFsvolFileSystemControl)
+#pragma alloc_text(PAGE, FspFsvolFileSystemControlComplete)
#pragma alloc_text(PAGE, FspFileSystemControl)
-#pragma alloc_text(PAGE, FspFileSystemControlComplete)
#endif
+static NTSTATUS FspFsctlFileSystemControl(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PAGED_CODE();
+
+ NTSTATUS Result = STATUS_INVALID_DEVICE_REQUEST;
+ switch (IrpSp->MinorFunction)
+ {
+ case IRP_MN_USER_FS_REQUEST:
+ switch (IrpSp->Parameters.FileSystemControl.FsControlCode)
+ {
+ case FSP_FSCTL_CREATE:
+ Result = FspFsctlCreateVolume(DeviceObject, Irp, IrpSp);
+ break;
+ case FSP_FSCTL_TRANSACT:
+ Result = FspFsctlTransact(DeviceObject, Irp, IrpSp);
+ break;
+ }
+ break;
+ case IRP_MN_MOUNT_VOLUME:
+ Result = FspFsctlMountVolume(DeviceObject, Irp, IrpSp);
+ break;
+#if 0
+ case IRP_MN_VERIFY_VOLUME:
+ break;
+#endif
+ }
+ return Result;
+}
+
static NTSTATUS FspFsctlCreateVolume(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
@@ -108,29 +73,24 @@ static NTSTATUS FspFsctlCreateVolume(
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
PVOID SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
- PSECURITY_DESCRIPTOR SecurityDescriptor =
- (PVOID)((PUINT8)SystemBuffer + FSP_FSCTL_VOLUME_PARAMS_SIZE);
- DWORD SecurityDescriptorSize = InputBufferLength - FSP_FSCTL_VOLUME_PARAMS_SIZE;
- if (FSP_FSCTL_VOLUME_PARAMS_SIZE >= InputBufferLength || 0 == SystemBuffer ||
- !FspValidRelativeSecurityDescriptor(SecurityDescriptor, SecurityDescriptorSize,
- DACL_SECURITY_INFORMATION))
+ if (sizeof(FSP_FSCTL_VOLUME_PARAMS) > InputBufferLength || 0 == SystemBuffer)
return STATUS_INVALID_PARAMETER;
if (FSP_FSCTL_CREATE_BUFFER_SIZEMIN > OutputBufferLength)
return STATUS_BUFFER_TOO_SMALL;
NTSTATUS Result;
FSP_FSCTL_VOLUME_PARAMS VolumeParams = *(FSP_FSCTL_VOLUME_PARAMS *)SystemBuffer;
- PVOID SecurityDescriptorBuf = 0;
- FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension;
/* check the passed in VolumeParams */
if (FspFsctlIrpTimeoutMinimum > VolumeParams.IrpTimeout ||
VolumeParams.IrpTimeout > FspFsctlIrpTimeoutMaximum)
+ {
#if DBG
/* allow the debug timeout value on debug builds */
if (FspFsctlIrpTimeoutDebug != VolumeParams.IrpTimeout)
#endif
VolumeParams.IrpTimeout = FspFsctlIrpTimeoutDefault;
+ }
if (FspFsctlTransactTimeoutMinimum > VolumeParams.TransactTimeout ||
VolumeParams.TransactTimeout > FspFsctlTransactTimeoutMaximum)
VolumeParams.TransactTimeout = FspFsctlTransactTimeoutDefault;
@@ -141,14 +101,7 @@ static NTSTATUS FspFsctlCreateVolume(
if (!NT_SUCCESS(Result))
return Result;
- /* copy the security descriptor from the system buffer to a temporary one */
- SecurityDescriptorBuf = FspAlloc(SecurityDescriptorSize);
- if (0 == SecurityDescriptorBuf)
- return STATUS_INSUFFICIENT_RESOURCES;
- RtlCopyMemory(SecurityDescriptorBuf, SecurityDescriptor, SecurityDescriptorSize);
-
/* prepare the device name and SDDL */
- PDEVICE_OBJECT FsvrtDeviceObject;
UNICODE_STRING DeviceSddl;
UNICODE_STRING DeviceName;
RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSVRT_DEVICE_SDDL);
@@ -160,38 +113,81 @@ static NTSTATUS FspFsctlCreateVolume(
Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]);
ASSERT(NT_SUCCESS(Result));
- /* create the virtual volume device */
- FSP_FSCTL_DEVICE_EXTENSION *FsctlDeviceExtension = FspFsctlDeviceExtension(DeviceObject);
- ExAcquireResourceExclusiveLite(&FsctlDeviceExtension->Base.Resource, TRUE);
+ FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject);
+ ExAcquireResourceExclusiveLite(&DeviceExtension->Resource, TRUE);
try
{
- Result = FspDeviceCreateSecure(FspFsvrtDeviceExtensionKind, SecurityDescriptorSize,
- &DeviceName, FILE_DEVICE_VIRTUAL_DISK,
- &DeviceSddl, &FspFsvrtDeviceClassGuid,
- &FsvrtDeviceObject);
- if (NT_SUCCESS(Result))
+ HANDLE MupHandle = 0;
+ PDEVICE_OBJECT FsvrtDeviceObject = 0;
+ PDEVICE_OBJECT FsvolDeviceObject;
+ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension;
+ BOOLEAN Inserted;
+
+ /* quick check to see if we already have a volume */
+ FsvolDeviceObject = FspDeviceLookupContext(DeviceObject, (UINT_PTR)IrpSp->FileObject);
+ if (0 != FsvolDeviceObject)
{
+ Result = STATUS_ACCESS_DENIED;
+ goto exit;
+ }
+
+ /* create the volume (and virtual disk) device(s) */
+ Result = FspDeviceCreate(FspFsvolDeviceExtensionKind, 0,
+ DeviceObject->DeviceType,
+ &FsvolDeviceObject);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+ if (FILE_DEVICE_DISK_FILE_SYSTEM == DeviceObject->DeviceType)
+ {
+ Result = FspDeviceCreateSecure(FspFsvrtDeviceExtensionKind, 0,
+ &DeviceName, FILE_DEVICE_VIRTUAL_DISK,
+ &DeviceSddl, &FspFsvrtDeviceClassGuid,
+ &FsvrtDeviceObject);
+ if (!NT_SUCCESS(Result))
+ {
+ FspDeviceRelease(FsvolDeviceObject);
+ goto exit;
+ }
#pragma prefast(suppress:28175, "We are a filesystem: ok to access SectorSize")
FsvrtDeviceObject->SectorSize = VolumeParams.SectorSize;
- FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
- FsvrtDeviceExtension->FsctlDeviceObject = DeviceObject;
- FsvrtDeviceExtension->VolumeParams = VolumeParams;
- RtlCopyMemory(FsvrtDeviceExtension->SecurityDescriptorBuf,
- SecurityDescriptorBuf, SecurityDescriptorSize);
- FspDeviceInitComplete(FsvrtDeviceObject);
- Irp->IoStatus.Information = DeviceName.Length + sizeof(WCHAR);
- FspFsctlDeviceVolumeCreated(DeviceObject);
}
+#pragma prefast(suppress:28175, "We are a filesystem: ok to access SectorSize")
+ FsvolDeviceObject->SectorSize = VolumeParams.SectorSize;
+ FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
+ FsvolDeviceExtension->FsctlDeviceObject = DeviceObject;
+ FsvolDeviceExtension->FsvrtDeviceObject = FsvrtDeviceObject;
+ FsvolDeviceExtension->MupHandle = MupHandle;
+ FsvolDeviceExtension->VolumeParams = VolumeParams;
+ if (0 != FsvrtDeviceObject)
+ FspDeviceInitComplete(FsvrtDeviceObject);
+ FspDeviceInitComplete(FsvolDeviceObject);
+
+ /* do we need to register with MUP? */
+ if (0 == FsvrtDeviceObject)
+ {
+ Result = FsRtlRegisterUncProviderEx(&MupHandle, &DeviceName, FsvolDeviceObject, 0);
+ if (!NT_SUCCESS(Result))
+ {
+ FspDeviceRelease(FsvolDeviceObject);
+ goto exit;
+ }
+ }
+
+ /* associate the new volume device with our file object */
+ FspDeviceInsertContext(DeviceObject, (UINT_PTR)IrpSp->FileObject, FsvolDeviceObject,
+ &FsvolDeviceExtension->ElementStorage, &Inserted);
+ ASSERT(Inserted);
+
+ Irp->IoStatus.Information = DeviceName.Length + sizeof(WCHAR);
+ Result = STATUS_SUCCESS;
+
+ exit:;
}
finally
{
- ExReleaseResourceLite(&FsctlDeviceExtension->Base.Resource);
+ ExReleaseResourceLite(&DeviceExtension->Resource);
}
- /* free the temporary security descriptor */
- if (0 != SecurityDescriptorBuf)
- FspFree(SecurityDescriptorBuf);
-
return Result;
}
@@ -201,222 +197,182 @@ static NTSTATUS FspFsctlMountVolume(
PAGED_CODE();
NTSTATUS Result;
- FSP_FSCTL_DEVICE_EXTENSION *FsctlDeviceExtension = FspFsctlDeviceExtension(DeviceObject);
- ExAcquireResourceExclusiveLite(&FsctlDeviceExtension->Base.Resource, TRUE);
+ FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject);
+ ExAcquireResourceExclusiveLite(&DeviceExtension->Resource, TRUE);
try
{
- PDEVICE_OBJECT *DeviceObjects = 0;
- ULONG DeviceObjectCount = 0;
PVPB Vpb = IrpSp->Parameters.MountVolume.Vpb;
PDEVICE_OBJECT FsvrtDeviceObject = IrpSp->Parameters.MountVolume.DeviceObject;
PDEVICE_OBJECT FsvolDeviceObject;
- FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension =
- FspFsvrtDeviceExtension(FsvrtDeviceObject);
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension;
- /* check the passed in volume object; it must be one of our own and not marked Deleted */
- Result = FspDeviceCopyList(&DeviceObjects, &DeviceObjectCount);
- if (NT_SUCCESS(Result))
+ /* quick check to see if we already have a volume */
+ FsvolDeviceObject = FspDeviceLookupContext(DeviceObject, (UINT_PTR)IrpSp->FileObject);
+ if (0 != FsvolDeviceObject)
{
Result = STATUS_UNRECOGNIZED_VOLUME;
- for (ULONG i = 0; DeviceObjectCount > i; i++)
- if (DeviceObjects[i] == FsvrtDeviceObject)
- {
- if (FspDeviceRetain(FsvrtDeviceObject))
- {
- if (!FsvrtDeviceExtension->Deleted &&
- FILE_DEVICE_VIRTUAL_DISK == FsvrtDeviceObject->DeviceType)
- Result = STATUS_SUCCESS;
- else
- FspDeviceRelease(FsvrtDeviceObject);
- }
- break;
- }
- FspDeviceDeleteList(DeviceObjects, DeviceObjectCount);
- }
- if (!NT_SUCCESS(Result))
goto exit;
-
- /* create the file system device object */
- Result = FspDeviceCreate(FspFsvolDeviceExtensionKind, 0,
- DeviceObject->DeviceType,
- &FsvolDeviceObject);
- if (NT_SUCCESS(Result))
- {
- /*
- * Reference the virtual volume device so that it will not go away while the
- * file system device object is alive!
- */
- ObReferenceObject(FsvrtDeviceObject);
-
-#pragma prefast(suppress:28175, "We are a filesystem: ok to access SectorSize")
- FsvolDeviceObject->SectorSize = FsvrtDeviceExtension->VolumeParams.SectorSize;
- FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
- FsvolDeviceExtension->FsvrtDeviceObject = FsvrtDeviceObject;
- FsvrtDeviceExtension->FsvolDeviceObject = FsvolDeviceObject;
- FspDeviceInitComplete(FsvolDeviceObject);
- Vpb->DeviceObject = FsvolDeviceObject;
- Vpb->SerialNumber = FsvrtDeviceExtension->VolumeParams.SerialNumber;
- Irp->IoStatus.Information = 0;
}
- FspDeviceRelease(FsvrtDeviceObject);
+ FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
+ if (FsvolDeviceExtension->DeletePending ||
+ FsvolDeviceExtension->FsvrtDeviceObject != FsvrtDeviceObject)
+ {
+ Result = STATUS_UNRECOGNIZED_VOLUME;
+ goto exit;
+ }
+
+ Vpb->DeviceObject = FsvolDeviceObject;
+ Vpb->SerialNumber = FsvolDeviceExtension->VolumeParams.SerialNumber;
+
+ Irp->IoStatus.Information = 0;
+ Result = STATUS_SUCCESS;
exit:;
}
finally
{
- ExReleaseResourceLite(&FsctlDeviceExtension->Base.Resource);
+ ExReleaseResourceLite(&DeviceExtension->Resource);
}
return Result;
}
-typedef struct
-{
- PDEVICE_OBJECT FsvolDeviceObject;
- PVPB OldVpb;
- FSP_WORK_ITEM_WITH_DELAY WorkItemWithDelay;
-} FSP_FSVRT_DELETE_VOLUME_WORK_ITEM;
-
-static NTSTATUS FspFsvrtDeleteVolume(
+VOID FspFsctlDeleteVolume(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
+ /* performed during IRP_MJ_CLEANUP! */
PAGED_CODE();
- NTSTATUS Result;
- FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
- FSP_FSCTL_DEVICE_EXTENSION *FsctlDeviceExtension =
- FspFsctlDeviceExtension(FsvrtDeviceExtension->FsctlDeviceObject);
+ PDEVICE_OBJECT FsvolDeviceObject = 0;
- ExAcquireResourceExclusiveLite(&FsctlDeviceExtension->Base.Resource, TRUE);
+ FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject);
+ ExAcquireResourceExclusiveLite(&DeviceExtension->Resource, TRUE);
try
{
- PDEVICE_OBJECT FsctlDeviceObject = FsvrtDeviceExtension->FsctlDeviceObject;
- PDEVICE_OBJECT FsvolDeviceObject = FsvrtDeviceExtension->FsvolDeviceObject;
- PVPB OldVpb;
- BOOLEAN DeleteVpb = FALSE;
- BOOLEAN DeleteDelayed = FALSE;
- LARGE_INTEGER DelayTimeout;
- FSP_FSVRT_DELETE_VOLUME_WORK_ITEM *WorkItem = 0;
- KIRQL Irql;
-
- /* access check */
- Result = FspSecuritySubjectContextAccessCheck(
- FsvrtDeviceExtension->SecurityDescriptorBuf, FILE_WRITE_DATA, Irp->RequestorMode);
- if (!NT_SUCCESS(Result))
- goto exit;
-
- /* pre-allocate a work item in case we need it for delayed delete */
- WorkItem = FspAllocNonPaged(sizeof *WorkItem);
- if (0 == WorkItem)
- {
- Result = STATUS_INSUFFICIENT_RESOURCES;
- goto exit;
- }
-
- /* mark the virtual volume device as deleted */
- FsvrtDeviceExtension->Deleted = TRUE;
-
- /* stop the I/O queue */
- FspIoqStop(&FsvrtDeviceExtension->Ioq);
-
- /* swap the preallocated VPB */
-#pragma prefast(push)
-#pragma prefast(disable:28175, "We are a filesystem: ok to access Vpb")
- IoAcquireVpbSpinLock(&Irql);
- OldVpb = DeviceObject->Vpb;
- if (0 != OldVpb && 0 != FsvrtDeviceExtension->SwapVpb)
- {
- DeviceObject->Vpb = FsvrtDeviceExtension->SwapVpb;
- DeviceObject->Vpb->Size = sizeof *DeviceObject->Vpb;
- DeviceObject->Vpb->Type = IO_TYPE_VPB;
- DeviceObject->Vpb->Flags = FlagOn(OldVpb->Flags, VPB_REMOVE_PENDING);
- DeviceObject->Vpb->RealDevice = OldVpb->RealDevice;
- DeviceObject->Vpb->RealDevice->Vpb = DeviceObject->Vpb;
- FsvrtDeviceExtension->SwapVpb = 0;
- DeleteVpb = 0 == OldVpb->ReferenceCount;
- DeleteDelayed = !DeleteVpb && 0 != FsvolDeviceObject;
- if (DeleteDelayed)
- /* keep VPB around for delayed delete */
- OldVpb->ReferenceCount++;
- }
- IoReleaseVpbSpinLock(Irql);
- if (DeleteDelayed)
- /* keep fsvol around for delayed delete */
- FspDeviceRetain(FsvolDeviceObject);
- else if (DeleteVpb)
- FspFreeExternal(OldVpb);
-#pragma prefast(pop)
-
- /* release the file system device and virtual volume objects */
- FsvrtDeviceExtension->FsvolDeviceObject = 0;
+ FsvolDeviceObject = FspDeviceLookupContext(DeviceObject, (UINT_PTR)IrpSp->FileObject);
if (0 != FsvolDeviceObject)
- FspDeviceRelease(FsvolDeviceObject);
- FspDeviceRelease(DeviceObject);
-
- FspFsctlDeviceVolumeDeleted(FsctlDeviceObject);
-
- /* are we doing delayed delete of VPB and fsvol? */
- if (DeleteDelayed)
- {
- DelayTimeout.QuadPart = 300/*ms*/ * -10000;
- WorkItem->FsvolDeviceObject = FsvolDeviceObject;
- WorkItem->OldVpb = OldVpb;
- FspInitializeWorkItemWithDelay(&WorkItem->WorkItemWithDelay,
- FspFsvrtDeleteVolumeDelayed, WorkItem);
- FspQueueWorkItemWithDelay(&WorkItem->WorkItemWithDelay, DelayTimeout);
- WorkItem = 0;
- }
-
- Result = STATUS_SUCCESS;
-
- exit:
- if (0 != WorkItem)
- FspFree(WorkItem);
+ FspDeviceDeleteContext(DeviceObject, (UINT_PTR)IrpSp->FileObject, 0);
}
finally
{
- ExReleaseResourceLite(&FsctlDeviceExtension->Base.Resource);
+ ExReleaseResourceLite(&DeviceExtension->Resource);
}
- return Result;
+ if (0 != FsvolDeviceObject)
+ {
+ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
+
+ /* mark the volume device as pending delete */
+ FsvolDeviceExtension->DeletePending = TRUE;
+
+ /* stop the I/O queue */
+ FspIoqStop(&FsvolDeviceExtension->Ioq);
+
+ /* do we have a virtual disk device or a MUP handle? */
+ if (0 != FsvolDeviceExtension->FsvrtDeviceObject)
+ {
+ PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
+ PVPB OldVpb;
+ KIRQL Irql;
+ BOOLEAN DeleteVpb = FALSE;
+ BOOLEAN DeleteDelayed = FALSE;
+ LARGE_INTEGER DelayTimeout;
+
+ /* swap the virtual disk device VPB with the preallocated one */
+#pragma prefast(push)
+#pragma prefast(disable:28175, "We are a filesystem: ok to access Vpb")
+ IoAcquireVpbSpinLock(&Irql);
+ OldVpb = FsvrtDeviceObject->Vpb;
+ if (0 != OldVpb)
+ {
+ FsvrtDeviceObject->Vpb = FsvolDeviceExtension->SwapVpb;
+ FsvrtDeviceObject->Vpb->Size = sizeof *FsvrtDeviceObject->Vpb;
+ FsvrtDeviceObject->Vpb->Type = IO_TYPE_VPB;
+ FsvrtDeviceObject->Vpb->Flags = FlagOn(OldVpb->Flags, VPB_REMOVE_PENDING);
+ FsvrtDeviceObject->Vpb->RealDevice = OldVpb->RealDevice;
+ FsvrtDeviceObject->Vpb->RealDevice->Vpb = FsvrtDeviceObject->Vpb;
+ DeleteVpb = 0 == OldVpb->ReferenceCount;
+ DeleteDelayed = !DeleteVpb;
+ if (DeleteDelayed)
+ {
+ /* keep VPB around for delayed delete */
+ OldVpb->ReferenceCount++;
+ FsvolDeviceExtension->SwapVpb = OldVpb;
+ }
+ else
+ FsvolDeviceExtension->SwapVpb = 0;
+ }
+ IoReleaseVpbSpinLock(Irql);
+ if (DeleteDelayed)
+ /* keep volume device object around for delayed delete */
+ FspDeviceRetain(FsvolDeviceObject);
+ else if (DeleteVpb)
+ /* no more references to the old VPB; delete now! */
+ FspFreeExternal(OldVpb);
+#pragma prefast(pop)
+
+ /* release the virtual disk and volume device objects */
+ FspDeviceRelease(FsvrtDeviceObject);
+ FspDeviceRelease(FsvolDeviceObject);
+
+ /* are we doing delayed delete of VPB and volume device object? */
+ if (DeleteDelayed)
+ {
+ DelayTimeout.QuadPart = 300/*ms*/ * -10000;
+ FspInitializeWorkItemWithDelay(&FsvolDeviceExtension->DeleteVolumeWorkItem,
+ FspFsctlDeleteVolumeDelayed, FsvolDeviceObject);
+ FspQueueWorkItemWithDelay(&FsvolDeviceExtension->DeleteVolumeWorkItem, DelayTimeout);
+ }
+ }
+ else if (0 != FsvolDeviceExtension->MupHandle)
+ {
+ HANDLE MupHandle = FsvolDeviceExtension->MupHandle;
+
+ FsRtlDeregisterUncProvider(MupHandle);
+
+ /* release the volume device object */
+ FspDeviceRelease(FsvolDeviceObject);
+ }
+ }
}
-static VOID FspFsvrtDeleteVolumeDelayed(PVOID Context)
+static VOID FspFsctlDeleteVolumeDelayed(PVOID Context)
{
PAGED_CODE();
- FSP_FSVRT_DELETE_VOLUME_WORK_ITEM *WorkItem = Context;
+ PDEVICE_OBJECT FsvolDeviceObject = Context;
+ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
+ KIRQL Irql;
BOOLEAN DeleteVpb = FALSE;
LARGE_INTEGER DelayTimeout;
- KIRQL Irql;
IoAcquireVpbSpinLock(&Irql);
- ASSERT(0 != WorkItem->OldVpb->ReferenceCount);
- DeleteVpb = 1 == WorkItem->OldVpb->ReferenceCount;
+ ASSERT(0 != FsvolDeviceExtension->SwapVpb->ReferenceCount);
+ DeleteVpb = 1 == FsvolDeviceExtension->SwapVpb->ReferenceCount;
if (DeleteVpb)
- WorkItem->OldVpb->ReferenceCount = 0;
+ FsvolDeviceExtension->SwapVpb->ReferenceCount = 0;
IoReleaseVpbSpinLock(Irql);
if (DeleteVpb)
{
- FspFreeExternal(WorkItem->OldVpb);
- FspDeviceRelease(WorkItem->FsvolDeviceObject);
- FspFree(WorkItem);
+ FspFreeExternal(FsvolDeviceExtension->SwapVpb);
+ FsvolDeviceExtension->SwapVpb = 0;
+ FspDeviceRelease(FsvolDeviceObject);
}
else
{
DelayTimeout.QuadPart = 300/*ms*/ * -10000;
- FspQueueWorkItemWithDelay(&WorkItem->WorkItemWithDelay, DelayTimeout);
+ FspQueueWorkItemWithDelay(&FsvolDeviceExtension->DeleteVolumeWorkItem, DelayTimeout);
}
}
-static NTSTATUS FspFsvrtTransact(
+static NTSTATUS FspFsctlTransact(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
PAGED_CODE();
+#if 0
/* check parameters */
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
@@ -518,56 +474,10 @@ static NTSTATUS FspFsvrtTransact(
Irp->IoStatus.Information = (PUINT8)Request - (PUINT8)SystemBuffer;
return STATUS_SUCCESS;
-}
-static NTSTATUS FspFsctlFileSystemControl(
- PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
-{
- PAGED_CODE();
-
- NTSTATUS Result = STATUS_INVALID_DEVICE_REQUEST;
- switch (IrpSp->MinorFunction)
- {
- case IRP_MN_USER_FS_REQUEST:
- switch (IrpSp->Parameters.FileSystemControl.FsControlCode)
- {
- case FSP_FSCTL_CREATE:
- Result = FspFsctlCreateVolume(DeviceObject, Irp, IrpSp);
- break;
- }
- break;
- case IRP_MN_MOUNT_VOLUME:
- Result = FspFsctlMountVolume(DeviceObject, Irp, IrpSp);
- break;
-#if 0
- case IRP_MN_VERIFY_VOLUME:
- break;
+#else
+ return STATUS_INVALID_DEVICE_REQUEST;
#endif
- }
- return Result;
-}
-
-static NTSTATUS FspFsvrtFileSystemControl(
- PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
-{
- PAGED_CODE();
-
- NTSTATUS Result = STATUS_INVALID_DEVICE_REQUEST;
- switch (IrpSp->MinorFunction)
- {
- case IRP_MN_USER_FS_REQUEST:
- switch (IrpSp->Parameters.FileSystemControl.FsControlCode)
- {
- case FSP_FSCTL_DELETE:
- Result = FspFsvrtDeleteVolume(DeviceObject, Irp, IrpSp);
- break;
- case FSP_FSCTL_TRANSACT:
- Result = FspFsvrtTransact(DeviceObject, Irp, IrpSp);
- break;
- }
- break;
- }
- return Result;
}
static NTSTATUS FspFsvolFileSystemControl(
@@ -584,19 +494,28 @@ static NTSTATUS FspFsvolFileSystemControl(
return Result;
}
+VOID FspFsvolFileSystemControlComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC(
+ "FileObject=%p%s%s",
+ IrpSp->FileObject,
+ IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction ? ", " : "",
+ IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction ?
+ IoctlCodeSym(IrpSp->Parameters.FileSystemControl.FsControlCode) : "");
+}
+
NTSTATUS FspFileSystemControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_FILE_SYSTEM_CONTROL == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
FSP_RETURN(Result = FspFsvolFileSystemControl(DeviceObject, Irp, IrpSp));
- case FspFsvrtDeviceExtensionKind:
- FSP_RETURN(Result = FspFsvrtFileSystemControl(DeviceObject, Irp, IrpSp));
case FspFsctlDeviceExtensionKind:
FSP_RETURN(Result = FspFsctlFileSystemControl(DeviceObject, Irp, IrpSp));
default:
@@ -610,16 +529,3 @@ NTSTATUS FspFileSystemControl(
IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction ?
IoctlCodeSym(IrpSp->Parameters.FileSystemControl.FsControlCode) : "");
}
-
-VOID FspFileSystemControlComplete(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
-{
- FSP_ENTER_IOC(PAGED_CODE());
-
- FSP_LEAVE_IOC(
- "FileObject=%p%s%s",
- IrpSp->FileObject,
- IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction ? ", " : "",
- IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction ?
- IoctlCodeSym(IrpSp->Parameters.FileSystemControl.FsControlCode) : "");
-}
diff --git a/src/sys/iop.c b/src/sys/iop.c
index bd9f691c..3776e27b 100644
--- a/src/sys/iop.c
+++ b/src/sys/iop.c
@@ -113,10 +113,12 @@ NTSTATUS FspIopPostWorkRequest(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_TRANSACT_R
}
PIO_STACK_LOCATION IrpSp = IoGetNextIrpStackLocation(Irp);
- IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
- IrpSp->Parameters.DeviceIoControl.IoControlCode = FSP_FSCTL_WORK;
- IrpSp->Parameters.DeviceIoControl.InputBufferLength = Request->Size;
- IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = Request;
+ Irp->RequestorMode = KernelMode;
+ IrpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
+ IrpSp->MinorFunction = IRP_MN_USER_FS_REQUEST;
+ IrpSp->Parameters.FileSystemControl.FsControlCode = FSP_FSCTL_WORK;
+ IrpSp->Parameters.FileSystemControl.InputBufferLength = Request->Size;
+ IrpSp->Parameters.FileSystemControl.Type3InputBuffer = Request;
ASSERT(METHOD_NEITHER == (IrpSp->Parameters.DeviceIoControl.IoControlCode & 3));
@@ -170,6 +172,11 @@ VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceRelease)
FspDeviceRelease(DeviceObject);
}
+VOID FspIopCompleteCanceledIrp(PIRP Irp)
+{
+ FspIopCompleteIrpEx(Irp, STATUS_CANCELLED, TRUE);
+}
+
NTSTATUS FspIopDispatchPrepare(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request)
{
PAGED_CODE();
diff --git a/src/sys/ioq.c b/src/sys/ioq.c
index b0a5ad6b..cc527e86 100644
--- a/src/sys/ioq.c
+++ b/src/sys/ioq.c
@@ -120,7 +120,8 @@ static VOID FspIoqPendingReleaseLock(PIO_CSQ IoCsq, _IRQL_restores_ KIRQL Irql)
static VOID FspIoqPendingCompleteCanceledIrp(PIO_CSQ IoCsq, PIRP Irp)
{
- FspIopCompleteIrp(Irp, STATUS_CANCELLED);
+ FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq);
+ Ioq->CompleteCanceledIrp(Irp);
}
static NTSTATUS FspIoqProcessInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext)
@@ -183,11 +184,14 @@ static VOID FspIoqProcessReleaseLock(PIO_CSQ IoCsq, _IRQL_restores_ KIRQL Irql)
static VOID FspIoqProcessCompleteCanceledIrp(PIO_CSQ IoCsq, PIRP Irp)
{
- FspIopCompleteIrp(Irp, STATUS_CANCELLED);
+ FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, ProcessIoCsq);
+ Ioq->CompleteCanceledIrp(Irp);
}
-VOID FspIoqInitialize(FSP_IOQ *Ioq)
+VOID FspIoqInitialize(FSP_IOQ *Ioq, VOID (*CompleteCanceledIrp)(PIRP Irp))
{
+ ASSERT(0 != CompleteCanceledIrp);
+
RtlZeroMemory(Ioq, sizeof *Ioq);
KeInitializeSpinLock(&Ioq->SpinLock);
KeInitializeEvent(&Ioq->PendingIrpEvent, NotificationEvent, FALSE);
@@ -207,6 +211,7 @@ VOID FspIoqInitialize(FSP_IOQ *Ioq)
FspIoqProcessAcquireLock,
FspIoqProcessReleaseLock,
FspIoqProcessCompleteCanceledIrp);
+ Ioq->CompleteCanceledIrp = CompleteCanceledIrp;
}
VOID FspIoqStop(FSP_IOQ *Ioq)
@@ -219,9 +224,9 @@ VOID FspIoqStop(FSP_IOQ *Ioq)
KeReleaseSpinLock(&Ioq->SpinLock, Irql);
PIRP Irp;
while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, 0)))
- FspIoqPendingCompleteCanceledIrp(&Ioq->PendingIoCsq, Irp);
+ Ioq->CompleteCanceledIrp(Irp);
while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->ProcessIoCsq, 0)))
- FspIoqProcessCompleteCanceledIrp(&Ioq->ProcessIoCsq, Irp);
+ Ioq->CompleteCanceledIrp(Irp);
}
BOOLEAN FspIoqStopped(FSP_IOQ *Ioq)
@@ -245,9 +250,9 @@ VOID FspIoqRemoveExpired(FSP_IOQ *Ioq, PLARGE_INTEGER Timeout)
PeekContext.ExpirationTime = 0;
PIRP Irp;
while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, &PeekContext)))
- FspIoqPendingCompleteCanceledIrp(&Ioq->PendingIoCsq, Irp);
+ Ioq->CompleteCanceledIrp(Irp);
while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->ProcessIoCsq, &PeekContext)))
- FspIoqProcessCompleteCanceledIrp(&Ioq->ProcessIoCsq, Irp);
+ Ioq->CompleteCanceledIrp(Irp);
}
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp)
diff --git a/src/sys/lockctl.c b/src/sys/lockctl.c
index bf1f03b9..8da709bf 100644
--- a/src/sys/lockctl.c
+++ b/src/sys/lockctl.c
@@ -8,13 +8,13 @@
static NTSTATUS FspFsvolLockControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOCMPL_DISPATCH FspFsvolLockControlComplete;
FSP_DRIVER_DISPATCH FspLockControl;
-FSP_IOCMPL_DISPATCH FspLockControlComplete;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFsvolLockControl)
+#pragma alloc_text(PAGE, FspFsvolLockControlComplete)
#pragma alloc_text(PAGE, FspLockControl)
-#pragma alloc_text(PAGE, FspLockControlComplete)
#endif
static NTSTATUS FspFsvolLockControl(
@@ -25,13 +25,19 @@ static NTSTATUS FspFsvolLockControl(
return STATUS_INVALID_DEVICE_REQUEST;
}
+VOID FspFsvolLockControlComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC("%s", "");
+}
+
NTSTATUS FspLockControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_LOCK_CONTROL == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
@@ -42,11 +48,3 @@ NTSTATUS FspLockControl(
FSP_LEAVE_MJ("%s", "");
}
-
-VOID FspLockControlComplete(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
-{
- FSP_ENTER_IOC(PAGED_CODE());
-
- FSP_LEAVE_IOC("%s", "");
-}
diff --git a/src/sys/read.c b/src/sys/read.c
index f6bc6976..cd42b7e6 100644
--- a/src/sys/read.c
+++ b/src/sys/read.c
@@ -8,13 +8,13 @@
static NTSTATUS FspFsvolRead(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOCMPL_DISPATCH FspFsvolReadComplete;
FSP_DRIVER_DISPATCH FspRead;
-FSP_IOCMPL_DISPATCH FspReadComplete;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFsvolRead)
+#pragma alloc_text(PAGE, FspFsvolReadComplete)
#pragma alloc_text(PAGE, FspRead)
-#pragma alloc_text(PAGE, FspReadComplete)
#endif
static NTSTATUS FspFsvolRead(
@@ -25,13 +25,19 @@ static NTSTATUS FspFsvolRead(
return STATUS_INVALID_DEVICE_REQUEST;
}
+VOID FspFsvolReadComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC("%s", "");
+}
+
NTSTATUS FspRead(
PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_READ == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
@@ -42,11 +48,3 @@ NTSTATUS FspRead(
FSP_LEAVE_MJ("%s", "");
}
-
-VOID FspReadComplete(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
-{
- FSP_ENTER_IOC(PAGED_CODE());
-
- FSP_LEAVE_IOC("%s", "");
-}
diff --git a/src/sys/resource.c b/src/sys/resource.c
deleted file mode 100644
index 638af5c1..00000000
--- a/src/sys/resource.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * @file sys/resource.c
- *
- * @copyright 2015 Bill Zissimopoulos
- */
-
-#include
-
-FAST_IO_ACQUIRE_FILE FspAcquireFileForNtCreateSection;
-FAST_IO_RELEASE_FILE FspReleaseFileForNtCreateSection;
-FAST_IO_ACQUIRE_FOR_MOD_WRITE FspAcquireForModWrite;
-FAST_IO_RELEASE_FOR_MOD_WRITE FspReleaseForModWrite;
-FAST_IO_ACQUIRE_FOR_CCFLUSH FspAcquireForCcFlush;
-FAST_IO_RELEASE_FOR_CCFLUSH FspReleaseForCcFlush;
-
-#ifdef ALLOC_PRAGMA
-#pragma alloc_text(PAGE, FspAcquireFileForNtCreateSection)
-#pragma alloc_text(PAGE, FspReleaseFileForNtCreateSection)
-#pragma alloc_text(PAGE, FspAcquireForModWrite)
-#pragma alloc_text(PAGE, FspReleaseForModWrite)
-#pragma alloc_text(PAGE, FspAcquireForCcFlush)
-#pragma alloc_text(PAGE, FspReleaseForCcFlush)
-#endif
-
-VOID FspAcquireFileForNtCreateSection(
- PFILE_OBJECT FileObject)
-{
- FSP_ENTER_VOID(PAGED_CODE());
-
- FSP_LEAVE_VOID("%s", "");
-}
-
-VOID FspReleaseFileForNtCreateSection(
- PFILE_OBJECT FileObject)
-{
- FSP_ENTER_VOID(PAGED_CODE());
-
- FSP_LEAVE_VOID("%s", "");
-}
-
-NTSTATUS FspAcquireForModWrite(
- PFILE_OBJECT FileObject,
- PLARGE_INTEGER EndingOffset,
- PERESOURCE *ResourceToRelease,
- PDEVICE_OBJECT DeviceObject)
-{
- FSP_ENTER(PAGED_CODE());
-
- Result = STATUS_NOT_IMPLEMENTED;
-
- FSP_LEAVE("%s", "");
-}
-
-NTSTATUS FspReleaseForModWrite(
- PFILE_OBJECT FileObject,
- PERESOURCE ResourceToRelease,
- PDEVICE_OBJECT DeviceObject)
-{
- FSP_ENTER(PAGED_CODE());
-
- Result = STATUS_NOT_IMPLEMENTED;
-
- FSP_LEAVE("%s", "");
-}
-
-NTSTATUS FspAcquireForCcFlush(
- PFILE_OBJECT FileObject,
- PDEVICE_OBJECT DeviceObject)
-{
- FSP_ENTER(PAGED_CODE());
-
- Result = STATUS_NOT_IMPLEMENTED;
-
- FSP_LEAVE("%s", "");
-}
-
-NTSTATUS FspReleaseForCcFlush(
- PFILE_OBJECT FileObject,
- PDEVICE_OBJECT DeviceObject)
-{
- FSP_ENTER(PAGED_CODE());
-
- Result = STATUS_NOT_IMPLEMENTED;
-
- FSP_LEAVE("%s", "");
-}
diff --git a/src/sys/security.c b/src/sys/security.c
index 117e1f7c..f9920818 100644
--- a/src/sys/security.c
+++ b/src/sys/security.c
@@ -8,20 +8,20 @@
static NTSTATUS FspFsvolQuerySecurity(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOCMPL_DISPATCH FspFsvolQuerySecurityComplete;
static NTSTATUS FspFsvolSetSecurity(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOCMPL_DISPATCH FspFsvolSetSecurityComplete;
FSP_DRIVER_DISPATCH FspQuerySecurity;
FSP_DRIVER_DISPATCH FspSetSecurity;
-FSP_IOCMPL_DISPATCH FspQuerySecurityComplete;
-FSP_IOCMPL_DISPATCH FspSetSecurityComplete;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFsvolQuerySecurity)
+#pragma alloc_text(PAGE, FspFsvolQuerySecurityComplete)
#pragma alloc_text(PAGE, FspFsvolSetSecurity)
+#pragma alloc_text(PAGE, FspFsvolSetSecurityComplete)
#pragma alloc_text(PAGE, FspQuerySecurity)
#pragma alloc_text(PAGE, FspSetSecurity)
-#pragma alloc_text(PAGE, FspQuerySecurityComplete)
-#pragma alloc_text(PAGE, FspSetSecurityComplete)
#endif
static NTSTATUS FspFsvolQuerySecurity(
@@ -32,6 +32,14 @@ static NTSTATUS FspFsvolQuerySecurity(
return STATUS_INVALID_DEVICE_REQUEST;
}
+VOID FspFsvolQuerySecurityComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC("%s", "");
+}
+
static NTSTATUS FspFsvolSetSecurity(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
@@ -40,13 +48,19 @@ static NTSTATUS FspFsvolSetSecurity(
return STATUS_INVALID_DEVICE_REQUEST;
}
+VOID FspFsvolSetSecurityComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC("%s", "");
+}
+
NTSTATUS FspQuerySecurity(
PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_QUERY_SECURITY == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
@@ -63,8 +77,6 @@ NTSTATUS FspSetSecurity(
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_SET_SECURITY == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
@@ -75,19 +87,3 @@ NTSTATUS FspSetSecurity(
FSP_LEAVE_MJ("%s", "");
}
-
-VOID FspQuerySecurityComplete(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
-{
- FSP_ENTER_IOC(PAGED_CODE());
-
- FSP_LEAVE_IOC("%s", "");
-}
-
-VOID FspSetSecurityComplete(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
-{
- FSP_ENTER_IOC(PAGED_CODE());
-
- FSP_LEAVE_IOC("%s", "");
-}
diff --git a/src/sys/shutdown.c b/src/sys/shutdown.c
index c9d117dd..57e33f8f 100644
--- a/src/sys/shutdown.c
+++ b/src/sys/shutdown.c
@@ -9,12 +9,12 @@
static NTSTATUS FspFsvolShutdown(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
FSP_DRIVER_DISPATCH FspShutdown;
-FSP_IOCMPL_DISPATCH FspShutdownComplete;
+FSP_IOCMPL_DISPATCH FspFsvolShutdownComplete;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFsvolShutdown)
+#pragma alloc_text(PAGE, FspFsvolShutdownComplete)
#pragma alloc_text(PAGE, FspShutdown)
-#pragma alloc_text(PAGE, FspShutdownComplete)
#endif
static NTSTATUS FspFsvolShutdown(
@@ -25,13 +25,19 @@ static NTSTATUS FspFsvolShutdown(
return STATUS_INVALID_DEVICE_REQUEST;
}
+VOID FspFsvolShutdownComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC("%s", "");
+}
+
NTSTATUS FspShutdown(
PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_SHUTDOWN == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
@@ -42,11 +48,3 @@ NTSTATUS FspShutdown(
FSP_LEAVE_MJ("%s", "");
}
-
-VOID FspShutdownComplete(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
-{
- FSP_ENTER_IOC(PAGED_CODE());
-
- FSP_LEAVE_IOC("%s", "");
-}
diff --git a/src/sys/util.c b/src/sys/util.c
new file mode 100644
index 00000000..2fd7b922
--- /dev/null
+++ b/src/sys/util.c
@@ -0,0 +1,61 @@
+/**
+ * @file sys/util.c
+ *
+ * @copyright 2015 Bill Zissimopoulos
+ */
+
+#include
+
+NTSTATUS FspCreateGuid(GUID *Guid);
+VOID FspInitializeWorkItemWithDelay(FSP_WORK_ITEM_WITH_DELAY *WorkItem,
+ PWORKER_THREAD_ROUTINE Routine, PVOID Context);
+VOID FspQueueWorkItemWithDelay(FSP_WORK_ITEM_WITH_DELAY *WorkItem, LARGE_INTEGER Timeout);
+static KDEFERRED_ROUTINE FspQueueWorkItemWithDelayDPC;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FspCreateGuid)
+#pragma alloc_text(PAGE, FspInitializeWorkItemWithDelay)
+#pragma alloc_text(PAGE, FspQueueWorkItemWithDelay)
+#endif
+
+NTSTATUS FspCreateGuid(GUID *Guid)
+{
+ PAGED_CODE();
+
+ NTSTATUS Result;
+
+ int Retries = 3;
+ do
+ {
+ Result = ExUuidCreate(Guid);
+ } while (!NT_SUCCESS(Result) && 0 < --Retries);
+
+ return Result;
+}
+
+VOID FspInitializeWorkItemWithDelay(FSP_WORK_ITEM_WITH_DELAY *WorkItem,
+ PWORKER_THREAD_ROUTINE Routine, PVOID Context)
+{
+ PAGED_CODE();
+
+ KeInitializeTimer(&WorkItem->Timer);
+ KeInitializeDpc(&WorkItem->Dpc, FspQueueWorkItemWithDelayDPC, WorkItem);
+ ExInitializeWorkItem(&WorkItem->WorkQueueItem, Routine, Context);
+}
+
+VOID FspQueueWorkItemWithDelay(FSP_WORK_ITEM_WITH_DELAY *WorkItem, LARGE_INTEGER Timeout)
+{
+ PAGED_CODE();
+
+ KeSetTimer(&WorkItem->Timer, Timeout, &WorkItem->Dpc);
+}
+
+static VOID FspQueueWorkItemWithDelayDPC(PKDPC Dpc,
+ PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
+{
+ // !PAGED_CODE();
+
+ FSP_WORK_ITEM_WITH_DELAY *WorkItem = DeferredContext;
+
+ ExQueueWorkItem(&WorkItem->WorkQueueItem, DelayedWorkQueue);
+}
diff --git a/src/sys/volinfo.c b/src/sys/volinfo.c
index 2f0e2b7c..89da6a51 100644
--- a/src/sys/volinfo.c
+++ b/src/sys/volinfo.c
@@ -8,20 +8,20 @@
static NTSTATUS FspFsvolQueryVolumeInformation(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOCMPL_DISPATCH FspFsvolQueryVolumeInformationComplete;
static NTSTATUS FspFsvolSetVolumeInformation(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOCMPL_DISPATCH FspFsvolSetVolumeInformationComplete;
FSP_DRIVER_DISPATCH FspQueryVolumeInformation;
FSP_DRIVER_DISPATCH FspSetVolumeInformation;
-FSP_IOCMPL_DISPATCH FspQueryVolumeInformationComplete;
-FSP_IOCMPL_DISPATCH FspSetVolumeInformationComplete;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFsvolQueryVolumeInformation)
+#pragma alloc_text(PAGE, FspFsvolQueryVolumeInformationComplete)
#pragma alloc_text(PAGE, FspFsvolSetVolumeInformation)
+#pragma alloc_text(PAGE, FspFsvolSetVolumeInformationComplete)
#pragma alloc_text(PAGE, FspQueryVolumeInformation)
#pragma alloc_text(PAGE, FspSetVolumeInformation)
-#pragma alloc_text(PAGE, FspQueryVolumeInformationComplete)
-#pragma alloc_text(PAGE, FspSetVolumeInformationComplete)
#endif
static NTSTATUS FspFsvolQueryVolumeInformation(
@@ -32,6 +32,14 @@ static NTSTATUS FspFsvolQueryVolumeInformation(
return STATUS_INVALID_DEVICE_REQUEST;
}
+VOID FspFsvolQueryVolumeInformationComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC("%s", "");
+}
+
static NTSTATUS FspFsvolSetVolumeInformation(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
@@ -40,13 +48,19 @@ static NTSTATUS FspFsvolSetVolumeInformation(
return STATUS_INVALID_DEVICE_REQUEST;
}
+VOID FspFsvolSetVolumeInformationComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC("%s", "");
+}
+
NTSTATUS FspQueryVolumeInformation(
PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_QUERY_VOLUME_INFORMATION == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
@@ -63,8 +77,6 @@ NTSTATUS FspSetVolumeInformation(
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_SET_VOLUME_INFORMATION == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
@@ -75,19 +87,3 @@ NTSTATUS FspSetVolumeInformation(
FSP_LEAVE_MJ("%s", "");
}
-
-VOID FspQueryVolumeInformationComplete(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
-{
- FSP_ENTER_IOC(PAGED_CODE());
-
- FSP_LEAVE_IOC("%s", "");
-}
-
-VOID FspSetVolumeInformationComplete(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
-{
- FSP_ENTER_IOC(PAGED_CODE());
-
- FSP_LEAVE_IOC("%s", "");
-}
diff --git a/src/sys/write.c b/src/sys/write.c
index 947247ce..6fb5a942 100644
--- a/src/sys/write.c
+++ b/src/sys/write.c
@@ -8,13 +8,13 @@
static NTSTATUS FspFsvolWrite(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOCMPL_DISPATCH FspFsvolWriteComplete;
FSP_DRIVER_DISPATCH FspWrite;
-FSP_IOCMPL_DISPATCH FspWriteComplete;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFsvolWrite)
+#pragma alloc_text(PAGE, FspFsvolWriteComplete)
#pragma alloc_text(PAGE, FspWrite)
-#pragma alloc_text(PAGE, FspWriteComplete)
#endif
static NTSTATUS FspFsvolWrite(
@@ -25,13 +25,19 @@ static NTSTATUS FspFsvolWrite(
return STATUS_INVALID_DEVICE_REQUEST;
}
+VOID FspFsvolWriteComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC("%s", "");
+}
+
NTSTATUS FspWrite(
PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
FSP_ENTER_MJ(PAGED_CODE());
- ASSERT(IRP_MJ_WRITE == IrpSp->MajorFunction);
-
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
@@ -42,11 +48,3 @@ NTSTATUS FspWrite(
FSP_LEAVE_MJ("%s", "");
}
-
-VOID FspWriteComplete(
- PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
-{
- FSP_ENTER_IOC(PAGED_CODE());
-
- FSP_LEAVE_IOC("%s", "");
-}
diff --git a/src/dll/debug.c b/src0/dll/debug.c
similarity index 100%
rename from src/dll/debug.c
rename to src0/dll/debug.c
diff --git a/src/dll/fsctl.c b/src0/dll/fsctl.c
similarity index 100%
rename from src/dll/fsctl.c
rename to src0/dll/fsctl.c
diff --git a/src/dll/library.c b/src0/dll/library.c
similarity index 100%
rename from src/dll/library.c
rename to src0/dll/library.c
diff --git a/src/dll/library.h b/src0/dll/library.h
similarity index 100%
rename from src/dll/library.h
rename to src0/dll/library.h
diff --git a/src/dll/loop.c b/src0/dll/loop.c
similarity index 100%
rename from src/dll/loop.c
rename to src0/dll/loop.c
diff --git a/src/dll/ntstatus.c b/src0/dll/ntstatus.c
similarity index 100%
rename from src/dll/ntstatus.c
rename to src0/dll/ntstatus.c
diff --git a/src/dll/ntstatus.i b/src0/dll/ntstatus.i
similarity index 100%
rename from src/dll/ntstatus.i
rename to src0/dll/ntstatus.i
diff --git a/src0/sys/cleanup.c b/src0/sys/cleanup.c
new file mode 100644
index 00000000..4aea9e75
--- /dev/null
+++ b/src0/sys/cleanup.c
@@ -0,0 +1,176 @@
+/**
+ * @file sys/cleanup.c
+ *
+ * @copyright 2015 Bill Zissimopoulos
+ */
+
+#include
+
+static NTSTATUS FspFsctlCleanup(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+static NTSTATUS FspFsvrtCleanup(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+static NTSTATUS FspFsvolCleanup(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOCMPL_DISPATCH FspFsvolCleanupComplete;
+FSP_DRIVER_DISPATCH FspCleanup;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FspFsctlCleanup)
+#pragma alloc_text(PAGE, FspFsvrtCleanup)
+#pragma alloc_text(PAGE, FspFsvolCleanup)
+#pragma alloc_text(PAGE, FspFsvolCleanupComplete)
+#pragma alloc_text(PAGE, FspCleanup)
+#endif
+
+static NTSTATUS FspFsctlCleanup(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PAGED_CODE();
+
+ NTSTATUS Result = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ return Result;
+}
+
+static NTSTATUS FspFsvrtCleanup(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PAGED_CODE();
+
+ NTSTATUS Result = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ return Result;
+}
+
+static NTSTATUS FspFsvolCleanup(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PAGED_CODE();
+
+ /* is this a valid FileObject? */
+ if (!FspFileContextIsValid(IrpSp->FileObject->FsContext))
+ return STATUS_SUCCESS;
+
+ NTSTATUS Result;
+ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
+ PFILE_OBJECT FileObject = IrpSp->FileObject;
+ FSP_FILE_CONTEXT *FsContext = FileObject->FsContext;
+ UINT64 UserContext = FsContext->UserContext;
+ UINT64 UserContext2 = (UINT_PTR)FileObject->FsContext2;
+ BOOLEAN DeletePending;
+ LONG OpenCount;
+
+ /* lock the FsContext */
+ ExAcquireResourceExclusiveLite(FsContext->Header.Resource, TRUE);
+
+ /* propagate the FsContext DeleteOnClose to DeletePending */
+ if (FsContext->DeleteOnClose)
+ FsContext->DeletePending = TRUE;
+ DeletePending = FsContext->DeletePending;
+
+ /* all handles on this FileObject are gone; decrement its FsContext->OpenCount */
+ OpenCount = FspFileContextClose(FsContext);
+
+ /* unlock the FsContext */
+ ExReleaseResourceLite(FsContext->Header.Resource);
+
+ /* is the FsContext going away as well? */
+ if (0 == OpenCount)
+ {
+ /*
+ * The following must be done under the file system volume device Resource,
+ * because we are manipulating its GenericTable.
+ */
+ ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->Base.Resource, TRUE);
+ try
+ {
+ /* remove the FsContext from the file system volume device generic table */
+ FspFsvolDeviceDeleteContext(DeviceObject, FsContext->UserContext, 0);
+ }
+ finally
+ {
+ ExReleaseResourceLite(&FsvolDeviceExtension->Base.Resource);
+ }
+ }
+
+ PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
+ if (!FspDeviceRetain(FsvrtDeviceObject))
+ /* IRP_MJ_CLEANUP cannot really fail :-\ */
+ return STATUS_SUCCESS;
+
+ try
+ {
+ FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
+ BOOLEAN FileNameRequired = 0 != FsvrtDeviceExtension->VolumeParams.FileNameRequired;
+ FSP_FSCTL_TRANSACT_REQ *Request;
+
+ /* create the user-mode file system request */
+ Result = FspIopCreateRequest(Irp, FileNameRequired ? &FsContext->FileName : 0, 0, &Request);
+ if (!NT_SUCCESS(Result))
+ goto leak_exit;
+
+ /*
+ * The new request is associated with our IRP and will be deleted during its completion.
+ */
+
+ /* populate the Cleanup request */
+ Request->Kind = FspFsctlTransactCleanupKind;
+ Request->Req.Cleanup.UserContext = UserContext;
+ Request->Req.Cleanup.UserContext2 = UserContext2;
+ Request->Req.Cleanup.Delete = DeletePending && 0 == OpenCount;
+
+ Result = STATUS_PENDING;
+
+ goto exit;
+
+ leak_exit:;
+#if DBG
+ DEBUGLOG("FileObject=%p[%p:\"%wZ\"], UserContext=%llx, UserContext2=%llx: "
+ "error: the user-mode file system handle will be leaked!",
+ IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName,
+ UserContext, UserContext2);
+#endif
+
+ /* IRP_MJ_CLEANUP cannot really fail :-\ */
+ Result = STATUS_SUCCESS;
+
+ exit:;
+ }
+ finally
+ {
+ FspDeviceRelease(FsvrtDeviceObject);
+ }
+
+ return Result;
+}
+
+VOID FspFsvolCleanupComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC("FileObject=%p", IrpSp->FileObject);
+}
+
+NTSTATUS FspCleanup(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+ FSP_ENTER_MJ(PAGED_CODE());
+
+ ASSERT(IRP_MJ_CLEANUP == IrpSp->MajorFunction);
+
+ switch (FspDeviceExtension(DeviceObject)->Kind)
+ {
+ case FspFsvolDeviceExtensionKind:
+ FSP_RETURN(Result = FspFsvolCleanup(DeviceObject, Irp, IrpSp));
+ case FspFsvrtDeviceExtensionKind:
+ FSP_RETURN(Result = FspFsvrtCleanup(DeviceObject, Irp, IrpSp));
+ case FspFsctlDeviceExtensionKind:
+ FSP_RETURN(Result = FspFsctlCleanup(DeviceObject, Irp, IrpSp));
+ default:
+ FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST);
+ }
+
+ FSP_LEAVE_MJ("FileObject=%p", IrpSp->FileObject);
+}
diff --git a/src0/sys/close.c b/src0/sys/close.c
new file mode 100644
index 00000000..1b912117
--- /dev/null
+++ b/src0/sys/close.c
@@ -0,0 +1,148 @@
+/**
+ * @file sys/close.c
+ *
+ * @copyright 2015 Bill Zissimopoulos
+ */
+
+#include
+
+static NTSTATUS FspFsctlClose(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+static NTSTATUS FspFsvrtClose(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+static NTSTATUS FspFsvolClose(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOCMPL_DISPATCH FspFsvolCloseComplete;
+FSP_DRIVER_DISPATCH FspClose;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FspFsctlClose)
+#pragma alloc_text(PAGE, FspFsvrtClose)
+#pragma alloc_text(PAGE, FspFsvolClose)
+#pragma alloc_text(PAGE, FspFsvolCloseComplete)
+#pragma alloc_text(PAGE, FspClose)
+#endif
+
+static NTSTATUS FspFsctlClose(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PAGED_CODE();
+
+ NTSTATUS Result = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ return Result;
+}
+
+static NTSTATUS FspFsvrtClose(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PAGED_CODE();
+
+ NTSTATUS Result = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ return Result;
+}
+
+static NTSTATUS FspFsvolClose(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PAGED_CODE();
+
+ /* is this a valid FileObject? */
+ if (!FspFileContextIsValid(IrpSp->FileObject->FsContext))
+ return STATUS_SUCCESS;
+
+ NTSTATUS Result;
+ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
+ PFILE_OBJECT FileObject = IrpSp->FileObject;
+ FSP_FILE_CONTEXT *FsContext = FileObject->FsContext;
+ UINT64 UserContext = FsContext->UserContext;
+ UINT64 UserContext2 = (UINT_PTR)FileObject->FsContext2;
+
+ /* dereference the FsContext (and delete if no more references) */
+ FspFileContextRelease(FsContext);
+
+ PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
+ if (!FspDeviceRetain(FsvrtDeviceObject))
+ /* IRP_MJ_CLOSE cannot really fail :-\ */
+ return STATUS_SUCCESS;
+
+ try
+ {
+ FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
+ BOOLEAN FileNameRequired = 0 != FsvrtDeviceExtension->VolumeParams.FileNameRequired;
+ FSP_FSCTL_TRANSACT_REQ *Request;
+
+ /* create the user-mode file system request */
+ Result = FspIopCreateRequest(0, FileNameRequired ? &FsContext->FileName : 0, 0, &Request);
+ if (!NT_SUCCESS(Result))
+ goto leak_exit;
+
+ /*
+ * The new request is associated with our IRP and will be deleted during its completion.
+ */
+
+ /* populate the Close request */
+ Request->Kind = FspFsctlTransactCloseKind;
+ Request->Req.Close.UserContext = UserContext;
+ Request->Req.Close.UserContext2 = UserContext2;
+
+ /* post as a work request; this allows us to complete our own IRP and return immediately! */
+ if (!FspIopPostWorkRequest(DeviceObject, Request))
+ /* no need to delete the request here as FspIopPostWorkRequest() will do so in all cases */
+ goto leak_exit;
+
+ Result = STATUS_SUCCESS;
+
+ goto exit;
+
+ leak_exit:;
+#if DBG
+ DEBUGLOG("FileObject=%p[%p:\"%wZ\"], UserContext=%llx, UserContext2=%llx: "
+ "error: the user-mode file system handle will be leaked!",
+ IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName,
+ UserContext, UserContext2);
+#endif
+
+ /* IRP_MJ_CLOSE cannot really fail :-\ */
+ Result = STATUS_SUCCESS;
+
+ exit:;
+ }
+ finally
+ {
+ FspDeviceRelease(FsvrtDeviceObject);
+ }
+
+ return Result;
+}
+
+VOID FspFsvolCloseComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC("FileObject=%p", IrpSp->FileObject);
+}
+
+NTSTATUS FspClose(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+ FSP_ENTER_MJ(PAGED_CODE());
+
+ ASSERT(IRP_MJ_CLOSE == IrpSp->MajorFunction);
+
+ switch (FspDeviceExtension(DeviceObject)->Kind)
+ {
+ case FspFsvolDeviceExtensionKind:
+ FSP_RETURN(Result = FspFsvolClose(DeviceObject, Irp, IrpSp));
+ case FspFsvrtDeviceExtensionKind:
+ FSP_RETURN(Result = FspFsvrtClose(DeviceObject, Irp, IrpSp));
+ case FspFsctlDeviceExtensionKind:
+ FSP_RETURN(Result = FspFsctlClose(DeviceObject, Irp, IrpSp));
+ default:
+ FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST);
+ }
+
+ FSP_LEAVE_MJ("FileObject=%p", IrpSp->FileObject);
+}
diff --git a/src0/sys/create.c b/src0/sys/create.c
new file mode 100644
index 00000000..052558fe
--- /dev/null
+++ b/src0/sys/create.c
@@ -0,0 +1,767 @@
+/**
+ * @file sys/create.c
+ *
+ * @copyright 2015 Bill Zissimopoulos
+ */
+
+#include
+
+static NTSTATUS FspFsctlCreate(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+static NTSTATUS FspFsvrtCreate(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+static NTSTATUS FspFsvolCreate(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_IOPREP_DISPATCH FspFsvolCreatePrepare;
+FSP_IOCMPL_DISPATCH FspFsvolCreateComplete;
+static VOID FspFsvolCreateCleanupClose(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response);
+FSP_IOP_REQUEST_FINI FspFsvolCreateRequestFini;
+FSP_DRIVER_DISPATCH FspCreate;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FspFsctlCreate)
+#pragma alloc_text(PAGE, FspFsvrtCreate)
+#pragma alloc_text(PAGE, FspFsvolCreate)
+#pragma alloc_text(PAGE, FspFsvolCreatePrepare)
+#pragma alloc_text(PAGE, FspFsvolCreateComplete)
+#pragma alloc_text(PAGE, FspFsvolCreateCleanupClose)
+#pragma alloc_text(PAGE, FspFsvolCreateRequestFini)
+#pragma alloc_text(PAGE, FspCreate)
+#endif
+
+enum
+{
+ RequestFsContext = 0,
+ RequestAccessToken,
+};
+
+static NTSTATUS FspFsctlCreate(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PAGED_CODE();
+
+ NTSTATUS Result = STATUS_SUCCESS;
+ Irp->IoStatus.Information = FILE_OPENED;
+ return Result;
+}
+
+static NTSTATUS FspFsvrtCreate(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PAGED_CODE();
+
+ NTSTATUS Result = STATUS_SUCCESS;
+ Irp->IoStatus.Information = FILE_OPENED;
+ return Result;
+}
+
+static NTSTATUS FspFsvolCreate(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PAGED_CODE();
+
+ /* open the volume object? */
+ if (0 == IrpSp->FileObject->FileName.Length &&
+ (0 == IrpSp->FileObject->RelatedFileObject ||
+ 0 == IrpSp->FileObject->RelatedFileObject->FsContext))
+ {
+ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
+ PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
+
+ IrpSp->FileObject->Vpb = FsvrtDeviceObject->Vpb;
+ Irp->IoStatus.Information = FILE_OPENED;
+ return STATUS_SUCCESS;
+ }
+
+ NTSTATUS Result;
+ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
+
+ PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
+ if (!FspDeviceRetain(FsvrtDeviceObject))
+ return STATUS_CANCELLED;
+
+ try
+ {
+ FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
+ PFILE_OBJECT FileObject = IrpSp->FileObject;
+ PFILE_OBJECT RelatedFileObject = FileObject->RelatedFileObject;
+ UNICODE_STRING FileName = FileObject->FileName;
+ PACCESS_STATE AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
+ ULONG CreateOptions = IrpSp->Parameters.Create.Options;
+ USHORT FileAttributes = IrpSp->Parameters.Create.FileAttributes;
+ PSECURITY_DESCRIPTOR SecurityDescriptor = AccessState->SecurityDescriptor;
+ ULONG SecurityDescriptorSize = 0;
+ LARGE_INTEGER AllocationSize = Irp->Overlay.AllocationSize;
+ ACCESS_MASK DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
+ USHORT ShareAccess = IrpSp->Parameters.Create.ShareAccess;
+ PFILE_FULL_EA_INFORMATION EaBuffer = Irp->AssociatedIrp.SystemBuffer;
+ //ULONG EaLength = IrpSp->Parameters.Create.EaLength;
+ ULONG Flags = IrpSp->Flags;
+ KPROCESSOR_MODE RequestorMode =
+ FlagOn(Flags, SL_FORCE_ACCESS_CHECK) ? UserMode : Irp->RequestorMode;
+ BOOLEAN HasTraversePrivilege =
+ BooleanFlagOn(AccessState->Flags, TOKEN_HAS_TRAVERSE_PRIVILEGE);
+ BOOLEAN IsAbsoluteSecurityDescriptor = FALSE;
+ BOOLEAN IsSelfRelativeSecurityDescriptor = FALSE;
+ BOOLEAN HasTrailingBackslash = FALSE;
+ FSP_FILE_CONTEXT *FsContext = 0;
+ FSP_FSCTL_TRANSACT_REQ *Request;
+
+ /* cannot open a paging file */
+ if (FlagOn(Flags, SL_OPEN_PAGING_FILE))
+ {
+ Result = STATUS_ACCESS_DENIED;
+ goto exit;
+ }
+
+ /* cannot open files by fileid */
+ if (FlagOn(CreateOptions, FILE_OPEN_BY_FILE_ID))
+ {
+ Result = STATUS_NOT_IMPLEMENTED;
+ goto exit;
+ }
+
+ /* do we support EA? */
+ if (0 != EaBuffer && !FsvrtDeviceExtension->VolumeParams.EaSupported)
+ {
+ Result = STATUS_EAS_NOT_SUPPORTED;
+ goto exit;
+ }
+
+ /* check create options */
+ if (FlagOn(CreateOptions, FILE_NON_DIRECTORY_FILE) &&
+ FlagOn(CreateOptions, FILE_DIRECTORY_FILE))
+ {
+ Result = STATUS_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ /* check security descriptor validity */
+ if (0 != SecurityDescriptor)
+ {
+ IsAbsoluteSecurityDescriptor = RtlValidSecurityDescriptor(SecurityDescriptor);
+ if (IsAbsoluteSecurityDescriptor)
+ {
+ Result = RtlAbsoluteToSelfRelativeSD(SecurityDescriptor, 0, &SecurityDescriptorSize);
+ if (STATUS_BUFFER_TOO_SMALL != Result)
+ {
+ Result = STATUS_INVALID_PARAMETER;
+ goto exit;
+ }
+ }
+ else
+ {
+ SecurityDescriptorSize = RtlLengthSecurityDescriptor(SecurityDescriptor);
+ IsSelfRelativeSecurityDescriptor = RtlValidRelativeSecurityDescriptor(
+ SecurityDescriptor, SecurityDescriptorSize, 0);
+ if (!IsSelfRelativeSecurityDescriptor)
+ {
+ Result = STATUS_INVALID_PARAMETER;
+ goto exit;
+ }
+ }
+ }
+
+ /* according to fastfat, filenames that begin with two backslashes are ok */
+ if (sizeof(WCHAR) * 2 <= FileName.Length &&
+ L'\\' == FileName.Buffer[1] && L'\\' == FileName.Buffer[0])
+ {
+ FileName.Length -= sizeof(WCHAR);
+ FileName.MaximumLength -= sizeof(WCHAR);
+ FileName.Buffer++;
+
+ if (sizeof(WCHAR) * 2 <= FileName.Length &&
+ L'\\' == FileName.Buffer[1] && L'\\' == FileName.Buffer[0])
+ {
+ Result = STATUS_OBJECT_NAME_INVALID;
+ goto exit;
+ }
+ }
+
+ /* check for trailing backslash */
+ if (sizeof(WCHAR) * 2/* not empty or root */ <= FileName.Length &&
+ L'\\' == FileName.Buffer[FileName.Length / 2 - 1])
+ {
+ FileName.Length -= sizeof(WCHAR);
+ HasTrailingBackslash = TRUE;
+
+ if (sizeof(WCHAR) * 2 <= FileName.Length && L'\\' == FileName.Buffer[FileName.Length / 2 - 1])
+ {
+ Result = STATUS_OBJECT_NAME_INVALID;
+ goto exit;
+ }
+ }
+ if (HasTrailingBackslash && !FlagOn(CreateOptions, FILE_DIRECTORY_FILE))
+ {
+ Result = STATUS_OBJECT_NAME_INVALID;
+ goto exit;
+ }
+
+ /* is this a relative or absolute open? */
+ if (0 != RelatedFileObject)
+ {
+ FSP_FILE_CONTEXT *RelatedFsContext = RelatedFileObject->FsContext;
+
+ /* is this a valid RelatedFileObject? */
+ if (!FspFileContextIsValid(RelatedFsContext))
+ {
+ Result = STATUS_OBJECT_PATH_NOT_FOUND;
+ goto exit;
+ }
+
+ /* must be a relative path */
+ if (sizeof(WCHAR) <= FileName.Length && L'\\' == FileName.Buffer[0])
+ {
+ Result = STATUS_OBJECT_NAME_INVALID;
+ goto exit;
+ }
+
+ /* cannot FILE_DELETE_ON_CLOSE on the root directory */
+ if (sizeof(WCHAR) == RelatedFsContext->FileName.Length &&
+ 0 == FileName.Length &&
+ FlagOn(CreateOptions, FILE_DELETE_ON_CLOSE))
+ {
+ Result = STATUS_CANNOT_DELETE;
+ goto exit;
+ }
+
+ /*
+ * There is no need to lock our accesses of RelatedFileObject->FsContext->FileName,
+ * because RelatedFileObject->FsContext->Filename is read-only (after creation) and
+ * because RelatedFileObject->FsContext is guaranteed to exist while RelatedFileObject
+ * exists.
+ */
+ BOOLEAN AppendBackslash =
+ sizeof(WCHAR) * 2/* not empty or root */ <= RelatedFsContext->FileName.Length &&
+ sizeof(WCHAR) <= FileName.Length && L':' != FileName.Buffer[0];
+ Result = FspFileContextCreate(DeviceObject,
+ RelatedFsContext->FileName.Length + AppendBackslash * sizeof(WCHAR) + FileName.Length,
+ &FsContext);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ Result = RtlAppendUnicodeStringToString(&FsContext->FileName, &RelatedFsContext->FileName);
+ ASSERT(NT_SUCCESS(Result));
+ if (AppendBackslash)
+ {
+ Result = RtlAppendUnicodeToString(&FsContext->FileName, L"\\");
+ ASSERT(NT_SUCCESS(Result));
+ }
+ }
+ else
+ {
+ /* must be an absolute path */
+ if (sizeof(WCHAR) <= FileName.Length && L'\\' != FileName.Buffer[0])
+ {
+ Result = STATUS_OBJECT_NAME_INVALID;
+ goto exit;
+ }
+
+ /* cannot FILE_DELETE_ON_CLOSE on the root directory */
+ if (sizeof(WCHAR) == FileName.Length &&
+ FlagOn(CreateOptions, FILE_DELETE_ON_CLOSE))
+ {
+ Result = STATUS_CANNOT_DELETE;
+ goto exit;
+ }
+
+ Result = FspFileContextCreate(DeviceObject,
+ FileName.Length,
+ &FsContext);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+ }
+
+ Result = RtlAppendUnicodeStringToString(&FsContext->FileName, &FileName);
+ ASSERT(NT_SUCCESS(Result));
+
+ /* create the user-mode file system request */
+ Result = FspIopCreateRequestEx(Irp, &FsContext->FileName, SecurityDescriptorSize,
+ FspFsvolCreateRequestFini, &Request);
+ if (!NT_SUCCESS(Result))
+ {
+ FspFileContextRelease(FsContext);
+ goto exit;
+ }
+
+ /*
+ * The new request is associated with our IRP and will be deleted during its completion.
+ * Go ahead and associate our FsContext with the Request as well.
+ */
+ FspIopRequestContext(Request, RequestFsContext) = FsContext;
+
+ /* populate the Create request */
+ Request->Kind = FspFsctlTransactCreateKind;
+ Request->Req.Create.CreateOptions = CreateOptions;
+ Request->Req.Create.FileAttributes = FileAttributes;
+ Request->Req.Create.SecurityDescriptor.Offset = 0 == SecurityDescriptorSize ? 0 :
+ FSP_FSCTL_DEFAULT_ALIGN_UP(Request->FileName.Size);
+ Request->Req.Create.SecurityDescriptor.Size = (UINT16)SecurityDescriptorSize;
+ Request->Req.Create.AllocationSize = AllocationSize.QuadPart;
+ Request->Req.Create.AccessToken = 0;
+ Request->Req.Create.DesiredAccess = DesiredAccess;
+ Request->Req.Create.ShareAccess = ShareAccess;
+ Request->Req.Create.Ea.Offset = 0;
+ Request->Req.Create.Ea.Size = 0;
+ Request->Req.Create.UserMode = UserMode == RequestorMode;
+ Request->Req.Create.HasTraversePrivilege = HasTraversePrivilege;
+ Request->Req.Create.OpenTargetDirectory = BooleanFlagOn(Flags, SL_OPEN_TARGET_DIRECTORY);
+ Request->Req.Create.CaseSensitive = BooleanFlagOn(Flags, SL_CASE_SENSITIVE);
+
+ /* copy the security descriptor into the request */
+ if (IsAbsoluteSecurityDescriptor)
+ {
+ Result = RtlAbsoluteToSelfRelativeSD(SecurityDescriptor,
+ Request->Buffer + Request->Req.Create.SecurityDescriptor.Offset, &SecurityDescriptorSize);
+ if (!NT_SUCCESS(Result))
+ {
+ if (STATUS_BAD_DESCRIPTOR_FORMAT == Result || STATUS_BUFFER_TOO_SMALL == Result)
+ Result = STATUS_INVALID_PARAMETER; /* should not happen */
+ goto exit;
+ }
+ }
+ else if (IsSelfRelativeSecurityDescriptor)
+ RtlCopyMemory(Request->Buffer + Request->Req.Create.SecurityDescriptor.Offset,
+ SecurityDescriptor, SecurityDescriptorSize);
+
+ Result = STATUS_PENDING;
+
+ exit:;
+ }
+ finally
+ {
+ FspDeviceRelease(FsvrtDeviceObject);
+ }
+
+ return Result;
+}
+
+NTSTATUS FspFsvolCreatePrepare(
+ PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request)
+{
+ FSP_ENTER_IOP(PAGED_CODE());
+
+ PDEVICE_OBJECT DeviceObject = IrpSp->DeviceObject;
+ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
+ FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension =
+ FspFsvrtDeviceExtension(FsvolDeviceExtension->FsvrtDeviceObject);
+
+ /* is the user-mode file system doing access checks? */
+ if (!FsvrtDeviceExtension->VolumeParams.NoSystemAccessCheck)
+ {
+ ASSERT(0 == Request->Req.Create.AccessToken);
+ FSP_RETURN(Result = STATUS_SUCCESS);
+ }
+
+ /* get a user-mode handle to the access token */
+ PACCESS_STATE AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
+ HANDLE UserModeAccessToken;
+ Result = ObOpenObjectByPointer(SeQuerySubjectContextToken(&AccessState->SubjectSecurityContext),
+ 0, 0, TOKEN_QUERY, *SeTokenObjectType, UserMode, &UserModeAccessToken);
+ if (!NT_SUCCESS(Result))
+ FSP_RETURN();
+
+ /* send the user-mode handle to the user-mode file system */
+ FspIopRequestContext(Request, RequestAccessToken) = UserModeAccessToken;
+ Request->Req.Create.AccessToken = (UINT_PTR)UserModeAccessToken;
+
+ FSP_LEAVE_IOP();
+}
+
+VOID FspFsvolCreateComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ /*
+ * NOTE:
+ * In the following we may have to close the just opened file object. But we must
+ * never close a file we just created, because this will leave an orphan file on
+ * the disk.
+ *
+ * Files may have to be closed if a security access or share access check fails. In
+ * both those cases we were opening an existing file and so it is safe to close it.
+ *
+ * Because of how IRP_MJ_CREATE works in Windows, it is difficult to improve on this
+ * scheme without introducing a 2-phase Create protocol, which is undesirable as it
+ * means two trips into user-mode for a single Create request.
+ */
+
+ PDEVICE_OBJECT DeviceObject = IrpSp->DeviceObject;
+ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
+ PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
+ FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
+ FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
+ PFILE_OBJECT FileObject = IrpSp->FileObject;
+ PACCESS_STATE AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
+ ULONG CreateOptions = IrpSp->Parameters.Create.Options;
+ BOOLEAN FileCreated = FILE_CREATED == Response->IoStatus.Information;
+ UINT32 ResponseFileAttributes = Response->Rsp.Create.Opened.FileAttributes;
+ PSECURITY_DESCRIPTOR SecurityDescriptor;
+ ULONG SecurityDescriptorSize;
+ UNICODE_STRING ReparseFileName;
+ ACCESS_MASK DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
+ PPRIVILEGE_SET Privileges = 0;
+ USHORT ShareAccess = IrpSp->Parameters.Create.ShareAccess;
+ ULONG Flags = IrpSp->Flags;
+ KPROCESSOR_MODE RequestorMode =
+ FlagOn(Flags, SL_FORCE_ACCESS_CHECK) ? UserMode : Irp->RequestorMode;
+ FSP_FILE_CONTEXT *FsContext = FspIopRequestContext(Request, RequestFsContext);
+ ACCESS_MASK GrantedAccess;
+ BOOLEAN Inserted = FALSE;
+
+ /* did the user-mode file system sent us a failure code? */
+ if (!NT_SUCCESS(Response->IoStatus.Status))
+ {
+ Irp->IoStatus.Information = Response->IoStatus.Information;
+ Result = Response->IoStatus.Status;
+ FSP_RETURN();
+ }
+
+ /* special case STATUS_REPARSE */
+ if (STATUS_REPARSE == Result)
+ {
+ ReparseFileName.Buffer =
+ (PVOID)(Response->Buffer + Response->Rsp.Create.Reparse.FileName.Offset);
+ ReparseFileName.Length = ReparseFileName.MaximumLength =
+ Response->Rsp.Create.Reparse.FileName.Size;
+
+ Result = STATUS_ACCESS_DENIED;
+ if (IO_REPARSE == Response->IoStatus.Information)
+ {
+ if (0 == ReparseFileName.Length ||
+ (PUINT8)ReparseFileName.Buffer + ReparseFileName.Length >
+ (PUINT8)Response + Response->Size)
+ FSP_RETURN();
+
+ if (ReparseFileName.Length > FileObject->FileName.MaximumLength)
+ {
+ PVOID Buffer = FspAllocExternal(ReparseFileName.Length);
+ if (0 == Buffer)
+ FSP_RETURN(Result = STATUS_INSUFFICIENT_RESOURCES);
+ FspFreeExternal(FileObject->FileName.Buffer);
+ FileObject->FileName.MaximumLength = ReparseFileName.Length;
+ FileObject->FileName.Buffer = Buffer;
+ }
+ FileObject->FileName.Length = 0;
+ RtlCopyUnicodeString(&FileObject->FileName, &ReparseFileName);
+ }
+ else
+ if (IO_REMOUNT == Response->IoStatus.Information)
+ {
+ if (0 != ReparseFileName.Length)
+ FSP_RETURN();
+ }
+ else
+ FSP_RETURN();
+
+ Irp->IoStatus.Information = Response->IoStatus.Information;
+ Result = Response->IoStatus.Status;
+ FSP_RETURN();
+ }
+
+ /* are we doing access checks? */
+ if (!FsvrtDeviceExtension->VolumeParams.NoSystemAccessCheck)
+ {
+ /* read-only attribute check */
+ if (!FileCreated && FlagOn(ResponseFileAttributes, FILE_ATTRIBUTE_READONLY))
+ {
+ /* from fastfat: allowed accesses when read-only */
+ ACCESS_MASK Allowed =
+ DELETE | READ_CONTROL | WRITE_OWNER | WRITE_DAC |
+ SYNCHRONIZE | ACCESS_SYSTEM_SECURITY |
+ FILE_READ_DATA | FILE_READ_EA | FILE_WRITE_EA |
+ FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES |
+ FILE_EXECUTE | FILE_TRAVERSE | FILE_LIST_DIRECTORY |
+ FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE | FILE_DELETE_CHILD;
+
+ if (FlagOn(DesiredAccess, ~Allowed))
+ {
+ FspFsvolCreateCleanupClose(Irp, Response);
+ FSP_RETURN(Result = STATUS_ACCESS_DENIED);
+ }
+ else
+ if (!FlagOn(ResponseFileAttributes, FILE_ATTRIBUTE_DIRECTORY) &&
+ FlagOn(CreateOptions, FILE_DELETE_ON_CLOSE))
+ {
+ FspFsvolCreateCleanupClose(Irp, Response);
+ FSP_RETURN(Result = STATUS_CANNOT_DELETE);
+ }
+ }
+
+ /* security descriptor check */
+ SecurityDescriptor =
+ (PVOID)(Response->Buffer + Response->Rsp.Create.Opened.SecurityDescriptor.Offset);
+ SecurityDescriptorSize = Response->Rsp.Create.Opened.SecurityDescriptor.Size;
+ if (0 != SecurityDescriptorSize)
+ {
+ if ((PUINT8)SecurityDescriptor + SecurityDescriptorSize >
+ (PUINT8)Response + Response->Size ||
+ !FspValidRelativeSecurityDescriptor(SecurityDescriptor, SecurityDescriptorSize, 0))
+ {
+ FspFsvolCreateCleanupClose(Irp, Response);
+ FSP_RETURN(Result = STATUS_ACCESS_DENIED);
+ }
+
+ /* access check */
+ if (!SeAccessCheck(SecurityDescriptor,
+ &AccessState->SubjectSecurityContext,
+ FALSE,
+ DesiredAccess,
+ AccessState->PreviouslyGrantedAccess,
+ &Privileges,
+ IoGetFileObjectGenericMapping(),
+ RequestorMode,
+ &GrantedAccess,
+ &Result))
+ {
+ FspFsvolCreateCleanupClose(Irp, Response);
+ FSP_RETURN();
+ }
+
+ if (0 != Privileges)
+ {
+ Result = SeAppendPrivileges(AccessState, Privileges);
+ SeFreePrivileges(Privileges);
+ if (!NT_SUCCESS(Result))
+ {
+ FspFsvolCreateCleanupClose(Irp, Response);
+ FSP_RETURN();
+ }
+ }
+
+ SetFlag(AccessState->PreviouslyGrantedAccess, GrantedAccess);
+ ClearFlag(AccessState->RemainingDesiredAccess, GrantedAccess);
+ }
+ }
+
+ /* were we asked to open a directory or non-directory? */
+ if (FlagOn(CreateOptions, FILE_DIRECTORY_FILE) &&
+ !FileCreated && !FlagOn(ResponseFileAttributes, FILE_ATTRIBUTE_DIRECTORY))
+ {
+ FspFsvolCreateCleanupClose(Irp, Response);
+ FSP_RETURN(Result = STATUS_NOT_A_DIRECTORY);
+ }
+ if (FlagOn(CreateOptions, FILE_NON_DIRECTORY_FILE) &&
+ !FileCreated && FlagOn(ResponseFileAttributes, FILE_ATTRIBUTE_DIRECTORY))
+ {
+ FspFsvolCreateCleanupClose(Irp, Response);
+ FSP_RETURN(Result = STATUS_FILE_IS_A_DIRECTORY);
+ }
+
+ /*
+ * The following must be done under the file system volume device Resource,
+ * because we are manipulating its GenericTable and accessing foreign FsContext's.
+ */
+ ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->Base.Resource, TRUE);
+ try
+ {
+ /* insert the newly created FsContext into our generic table */
+ FsContext = FspFsvolDeviceInsertContext(DeviceObject,
+ FsContext->UserContext, FsContext, &FsContext->ElementStorage, &Inserted);
+ ASSERT(0 != FsContext);
+
+ /* share access check */
+ if (Inserted)
+ {
+ /*
+ * This is a newly created FsContext. Set its share access and
+ * increment its open count. There is no need to acquire the
+ * FsContext's Resource (because it is newly created).
+ */
+ IoSetShareAccess(AccessState->PreviouslyGrantedAccess,
+ ShareAccess, FileObject, &FsContext->ShareAccess);
+ FspFileContextOpen(FsContext);
+ if (FlagOn(CreateOptions, FILE_DELETE_ON_CLOSE))
+ FsContext->DeleteOnClose = TRUE;
+ Result = STATUS_SUCCESS;
+ }
+ else
+ {
+ /*
+ * This is an existing FsContext. We must acquire its Resource and
+ * check if there is a delete pending and the share access. Only if
+ * both tests succeed we increment the open count and report success.
+ */
+ ExAcquireResourceExclusiveLite(FsContext->Header.Resource, TRUE);
+ if (FsContext->DeletePending)
+ Result = STATUS_DELETE_PENDING;
+ else
+ Result = IoCheckShareAccess(AccessState->PreviouslyGrantedAccess,
+ ShareAccess, FileObject, &FsContext->ShareAccess, TRUE);
+ if (NT_SUCCESS(Result))
+ {
+ FspFileContextRetain(FsContext);
+ FspFileContextOpen(FsContext);
+ if (FlagOn(CreateOptions, FILE_DELETE_ON_CLOSE))
+ FsContext->DeleteOnClose = TRUE;
+ }
+ ExReleaseResourceLite(FsContext->Header.Resource);
+ }
+ }
+ finally
+ {
+ ExReleaseResourceLite(&FsvolDeviceExtension->Base.Resource);
+ }
+
+ /* did we fail our share access checks? */
+ if (!NT_SUCCESS(Result))
+ {
+ ASSERT(!Inserted);
+ FspFsvolCreateCleanupClose(Irp, Response);
+ FSP_RETURN();
+ }
+
+ /*
+ * Looks like SUCCESS!
+ */
+
+ /* did an FsContext with the same UserContext already exist? */
+ if (!Inserted)
+ /* delete the newly created FsContext as it is not being used */
+ FspFileContextRelease(FspIopRequestContext(Request, RequestFsContext));
+
+ /* disassociate our FsContext from the Request */
+ FspIopRequestContext(Request, RequestFsContext) = 0;
+
+ /* record the user-mode file system contexts */
+ FsContext->UserContext = Response->Rsp.Create.Opened.UserContext;
+ FileObject->FsContext = FsContext;
+ FileObject->FsContext2 = (PVOID)(UINT_PTR)Response->Rsp.Create.Opened.UserContext2;
+
+ /* finish seting up the FileObject */
+ FileObject->Vpb = FsvrtDeviceObject->Vpb;
+
+ /* SUCCESS! */
+ Irp->IoStatus.Information = Response->IoStatus.Information;
+ Result = Response->IoStatus.Status;
+
+ FSP_LEAVE_IOC(
+ "FileObject=%p[%p:\"%wZ\"]",
+ IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName);
+}
+
+static VOID FspFsvolCreateCleanupClose(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ PAGED_CODE();
+
+ /*
+ * This routine handles the case where we must close an open file,
+ * because of a failure during Create completion. We simply create
+ * a CreateClose request and we post it as a work item.
+ *
+ * Ideally there would be no failure modes for this routine. Reality is
+ * different.
+ *
+ * The more serious (but perhaps non-existent in practice) failure is a
+ * memory allocation failure. In this case we will leak the user-mode
+ * file system handle!
+ *
+ * This routine may also fail if we cannot post a work item, which means that
+ * the virtual volume device and the file system volume device are being
+ * deleted. Because it is assumed that only the user-mode file system would
+ * initiate a device deletion, this case is more benign (presumably the file
+ * system knows to close off all its handles when tearing down its devices).
+ */
+
+ NTSTATUS Result;
+ PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ PDEVICE_OBJECT DeviceObject = IrpSp->DeviceObject;
+ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
+ FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension =
+ FspFsvrtDeviceExtension(FsvolDeviceExtension->FsvrtDeviceObject);
+ FSP_FSCTL_TRANSACT_REQ *OriginalRequest = FspIrpRequest(Irp);
+ FSP_FILE_CONTEXT *FsContext = FspIopRequestContext(OriginalRequest, RequestFsContext);
+ UINT64 UserContext = Response->Rsp.Create.Opened.UserContext;
+ UINT64 UserContext2 = Response->Rsp.Create.Opened.UserContext2;
+ BOOLEAN FileNameRequired = 0 != FsvrtDeviceExtension->VolumeParams.FileNameRequired;
+ FSP_FSCTL_TRANSACT_REQ *Request;
+
+ /* create the user-mode file system request */
+ Result = FspIopCreateRequest(0, FileNameRequired ? &FsContext->FileName : 0, 0, &Request);
+ if (!NT_SUCCESS(Result))
+ goto leak_exit;
+
+ /* populate the CreateCleanupClose request */
+ Request->Kind = FspFsctlTransactCreateCleanupCloseKind;
+ Request->Req.Cleanup.UserContext = UserContext;
+ Request->Req.Cleanup.UserContext2 = UserContext2;
+ Request->Req.Cleanup.Delete = FILE_CREATED == Response->IoStatus.Information;
+
+ /* post as a work request */
+ if (!FspIopPostWorkRequest(DeviceObject, Request))
+ /* no need to delete the request here as FspIopPostWorkRequest() will do so in all cases */
+ goto leak_exit;
+
+ goto exit;
+
+leak_exit:;
+#if DBG
+ DEBUGLOG("FileObject=%p[%p:\"%wZ\"], UserContext=%llx, UserContext2=%llx: "
+ "error: the user-mode file system handle will be leaked!",
+ IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName,
+ UserContext, UserContext2);
+#endif
+
+exit:;
+}
+
+VOID FspFsvolCreateRequestFini(PVOID Context[3])
+{
+ PAGED_CODE();
+
+ if (0 != Context[RequestFsContext])
+ FspFileContextRelease(Context[RequestFsContext]);
+
+ if (0 != Context[RequestAccessToken])
+ {
+#if DBG
+ NTSTATUS Result0;
+ Result0 = ObCloseHandle(Context[RequestAccessToken], KernelMode);
+ if (!NT_SUCCESS(Result0))
+ DEBUGLOG("ObCloseHandle() = %s", NtStatusSym(Result0));
+#else
+ ObCloseHandle(Context[RequestAccessToken], KernelMode);
+#endif
+ }
+}
+
+NTSTATUS FspCreate(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+ FSP_ENTER_MJ(PAGED_CODE());
+
+ ASSERT(IRP_MJ_CREATE == IrpSp->MajorFunction);
+
+ switch (FspDeviceExtension(DeviceObject)->Kind)
+ {
+ case FspFsvolDeviceExtensionKind:
+ FSP_RETURN(Result = FspFsvolCreate(DeviceObject, Irp, IrpSp));
+ case FspFsvrtDeviceExtensionKind:
+ FSP_RETURN(Result = FspFsvrtCreate(DeviceObject, Irp, IrpSp));
+ case FspFsctlDeviceExtensionKind:
+ FSP_RETURN(Result = FspFsctlCreate(DeviceObject, Irp, IrpSp));
+ default:
+ FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST);
+ }
+
+ FSP_LEAVE_MJ(
+ "FileObject=%p[%p:\"%wZ\"], "
+ "Flags=%x, "
+ "DesiredAccess=%#lx, "
+ "ShareAccess=%#x, "
+ "Options=%#lx, "
+ "FileAttributes=%#x, "
+ "AllocationSize=%#lx:%#lx, "
+ "Ea=%p, EaLength=%ld",
+ IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName,
+ IrpSp->Flags,
+ IrpSp->Parameters.Create.SecurityContext->DesiredAccess,
+ IrpSp->Parameters.Create.ShareAccess,
+ IrpSp->Parameters.Create.Options,
+ IrpSp->Parameters.Create.FileAttributes,
+ Irp->Overlay.AllocationSize.HighPart, Irp->Overlay.AllocationSize.LowPart,
+ Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.Create.EaLength);
+}
diff --git a/src/sys/fileobj.c b/src0/sys/fileobj.c
similarity index 100%
rename from src/sys/fileobj.c
rename to src0/sys/fileobj.c
diff --git a/src0/sys/fsctl.c b/src0/sys/fsctl.c
new file mode 100644
index 00000000..9b97c926
--- /dev/null
+++ b/src0/sys/fsctl.c
@@ -0,0 +1,625 @@
+/**
+ * @file sys/fsctl.c
+ *
+ * @copyright 2015 Bill Zissimopoulos
+ */
+
+#include
+
+/*
+ * Overview
+ *
+ * The fsctl module provides the IOCTL interface to interact with the
+ * user-mode file system. The user-mode file system can use the IOCTL's
+ * to create new volumes, delete them (while they are live!) and transact
+ * with them.
+ *
+ *
+ * Volume Creation
+ *
+ * The creation of a new volume is performed using an FSP_FSCTL_CREATE
+ * IOCTL code. Creation is simple: a new device \Device\Volume{GUID} is
+ * created and its path is returned to the user-mode file system. The
+ * user-mode file system also passes a security descriptor to associate
+ * with the new virtual volume device so that only the creating user-mode
+ * file system can control the new volume.
+ *
+ *
+ * Volume Deletion
+ *
+ * Deletion of an existing volume is performed using FSP_FSCTL_DELETE and
+ * is quite a bit more involved. We must protect against the following two
+ * eventualities: (1) that the volume is currently in use and cannot simply
+ * go away, and (2) that a simultaneous mount operation is taking place
+ * while we are deleting the volume.
+ *
+ * To protect against the first eventuality we maintain a reference count
+ * on all our device extensions. Every time an MJ function is entered,
+ * the reference count is incremented (FspDeviceRetain). Every time
+ * an IRP is completed, the reference count is decremented (FspDeviceRelease).
+ * When the reference count reaches 0 the device is deleted using
+ * IoDeleteDevice. This ensures that a device will not go away while an
+ * IRP is being pending/processed.
+ *
+ * To protect against the second eventuality we use the lock (ERESOURCE)
+ * on the root Fsctl device to wrap volume deletion and attempts from the
+ * system to mount the same volume. We also mark the virtual volume device
+ * as Deleted in case we attempt to delete it (FspDeviceRelease) but we
+ * cannot because it is currently in use.
+ *
+ * A sticky point is our use of the Windows VPB. It is not well documented
+ * how one should handle this structure during forcible dismount. The fastfat
+ * and cdfs samples use a technique where they keep a spare VPB and they swap
+ * it with the volume one during forcible dismount. We do something similar.
+ * The issue is what to do with the old VPB, because we can delete a volume
+ * that is not currently being used. We check the VPB's ReferenceCount and
+ * we free the VPB in this case.
+ *
+ *
+ * Volume Transact
+ *
+ * The user-mode file system's primary interaction with the kernel-mode driver
+ * is by using the FSP_FSCTL_TRANSACT IOCTL code. Every virtual volume device
+ * maintains an FSP_IOQ (refer to ioq.c for more). When an FSP_FSCTL_TRANSACT
+ * arrives it first processes any responses (FSP_FSCTL_TRANSACT_RSP) that the
+ * user-mode file system has sent to handle requests sent to it using a prior
+ * FSP_FSCTL_TRANSACT. It then proceeds to handle any pending IRP requests by
+ * sending the corresponding requests (FSP_FSCTL_TRANSACT_REQ) to the user-
+ * mode file system.
+ */
+
+static NTSTATUS FspFsctlCreateVolume(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+static NTSTATUS FspFsctlMountVolume(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+static NTSTATUS FspFsvrtDeleteVolume(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+static WORKER_THREAD_ROUTINE FspFsvrtDeleteVolumeDelayed;
+static NTSTATUS FspFsvrtTransact(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+static NTSTATUS FspFsctlFileSystemControl(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+static NTSTATUS FspFsvrtFileSystemControl(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+static NTSTATUS FspFsvolFileSystemControl(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+FSP_DRIVER_DISPATCH FspFileSystemControl;
+FSP_IOCMPL_DISPATCH FspFileSystemControlComplete;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FspFsctlCreateVolume)
+#pragma alloc_text(PAGE, FspFsctlMountVolume)
+#pragma alloc_text(PAGE, FspFsvrtDeleteVolume)
+#pragma alloc_text(PAGE, FspFsvrtDeleteVolumeDelayed)
+#pragma alloc_text(PAGE, FspFsvrtTransact)
+#pragma alloc_text(PAGE, FspFsctlFileSystemControl)
+#pragma alloc_text(PAGE, FspFsvrtFileSystemControl)
+#pragma alloc_text(PAGE, FspFsvolFileSystemControl)
+#pragma alloc_text(PAGE, FspFileSystemControl)
+#pragma alloc_text(PAGE, FspFileSystemControlComplete)
+#endif
+
+static NTSTATUS FspFsctlCreateVolume(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PAGED_CODE();
+
+ /* check parameters */
+ ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
+ ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
+ PVOID SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
+ PSECURITY_DESCRIPTOR SecurityDescriptor =
+ (PVOID)((PUINT8)SystemBuffer + FSP_FSCTL_VOLUME_PARAMS_SIZE);
+ DWORD SecurityDescriptorSize = InputBufferLength - FSP_FSCTL_VOLUME_PARAMS_SIZE;
+ if (FSP_FSCTL_VOLUME_PARAMS_SIZE >= InputBufferLength || 0 == SystemBuffer ||
+ !FspValidRelativeSecurityDescriptor(SecurityDescriptor, SecurityDescriptorSize,
+ DACL_SECURITY_INFORMATION))
+ return STATUS_INVALID_PARAMETER;
+ if (FSP_FSCTL_CREATE_BUFFER_SIZEMIN > OutputBufferLength)
+ return STATUS_BUFFER_TOO_SMALL;
+
+ NTSTATUS Result;
+ FSP_FSCTL_VOLUME_PARAMS VolumeParams = *(FSP_FSCTL_VOLUME_PARAMS *)SystemBuffer;
+ PVOID SecurityDescriptorBuf = 0;
+ FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension;
+
+ /* check the passed in VolumeParams */
+ if (FspFsctlIrpTimeoutMinimum > VolumeParams.IrpTimeout ||
+ VolumeParams.IrpTimeout > FspFsctlIrpTimeoutMaximum)
+#if DBG
+ /* allow the debug timeout value on debug builds */
+ if (FspFsctlIrpTimeoutDebug != VolumeParams.IrpTimeout)
+#endif
+ VolumeParams.IrpTimeout = FspFsctlIrpTimeoutDefault;
+ if (FspFsctlTransactTimeoutMinimum > VolumeParams.TransactTimeout ||
+ VolumeParams.TransactTimeout > FspFsctlTransactTimeoutMaximum)
+ VolumeParams.TransactTimeout = FspFsctlTransactTimeoutDefault;
+
+ /* create volume guid */
+ GUID Guid;
+ Result = FspCreateGuid(&Guid);
+ if (!NT_SUCCESS(Result))
+ return Result;
+
+ /* copy the security descriptor from the system buffer to a temporary one */
+ SecurityDescriptorBuf = FspAlloc(SecurityDescriptorSize);
+ if (0 == SecurityDescriptorBuf)
+ return STATUS_INSUFFICIENT_RESOURCES;
+ RtlCopyMemory(SecurityDescriptorBuf, SecurityDescriptor, SecurityDescriptorSize);
+
+ /* prepare the device name and SDDL */
+ PDEVICE_OBJECT FsvrtDeviceObject;
+ UNICODE_STRING DeviceSddl;
+ UNICODE_STRING DeviceName;
+ RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSVRT_DEVICE_SDDL);
+ RtlInitEmptyUnicodeString(&DeviceName, SystemBuffer, FSP_FSCTL_CREATE_BUFFER_SIZEMIN);
+ Result = RtlUnicodeStringPrintf(&DeviceName,
+ L"\\Device\\Volume{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+ Guid.Data1, Guid.Data2, Guid.Data3,
+ Guid.Data4[0], Guid.Data4[1], Guid.Data4[2], Guid.Data4[3],
+ Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]);
+ ASSERT(NT_SUCCESS(Result));
+
+ /* create the virtual volume device */
+ FSP_FSCTL_DEVICE_EXTENSION *FsctlDeviceExtension = FspFsctlDeviceExtension(DeviceObject);
+ ExAcquireResourceExclusiveLite(&FsctlDeviceExtension->Base.Resource, TRUE);
+ try
+ {
+ Result = FspDeviceCreateSecure(FspFsvrtDeviceExtensionKind, SecurityDescriptorSize,
+ &DeviceName, FILE_DEVICE_VIRTUAL_DISK,
+ &DeviceSddl, &FspFsvrtDeviceClassGuid,
+ &FsvrtDeviceObject);
+ if (NT_SUCCESS(Result))
+ {
+#pragma prefast(suppress:28175, "We are a filesystem: ok to access SectorSize")
+ FsvrtDeviceObject->SectorSize = VolumeParams.SectorSize;
+ FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
+ FsvrtDeviceExtension->FsctlDeviceObject = DeviceObject;
+ FsvrtDeviceExtension->VolumeParams = VolumeParams;
+ RtlCopyMemory(FsvrtDeviceExtension->SecurityDescriptorBuf,
+ SecurityDescriptorBuf, SecurityDescriptorSize);
+ FspDeviceInitComplete(FsvrtDeviceObject);
+ Irp->IoStatus.Information = DeviceName.Length + sizeof(WCHAR);
+ FspFsctlDeviceVolumeCreated(DeviceObject);
+ }
+ }
+ finally
+ {
+ ExReleaseResourceLite(&FsctlDeviceExtension->Base.Resource);
+ }
+
+ /* free the temporary security descriptor */
+ if (0 != SecurityDescriptorBuf)
+ FspFree(SecurityDescriptorBuf);
+
+ return Result;
+}
+
+static NTSTATUS FspFsctlMountVolume(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PAGED_CODE();
+
+ NTSTATUS Result;
+ FSP_FSCTL_DEVICE_EXTENSION *FsctlDeviceExtension = FspFsctlDeviceExtension(DeviceObject);
+
+ ExAcquireResourceExclusiveLite(&FsctlDeviceExtension->Base.Resource, TRUE);
+ try
+ {
+ PDEVICE_OBJECT *DeviceObjects = 0;
+ ULONG DeviceObjectCount = 0;
+ PVPB Vpb = IrpSp->Parameters.MountVolume.Vpb;
+ PDEVICE_OBJECT FsvrtDeviceObject = IrpSp->Parameters.MountVolume.DeviceObject;
+ PDEVICE_OBJECT FsvolDeviceObject;
+ FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension =
+ FspFsvrtDeviceExtension(FsvrtDeviceObject);
+ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension;
+
+ /* check the passed in volume object; it must be one of our own and not marked Deleted */
+ Result = FspDeviceCopyList(&DeviceObjects, &DeviceObjectCount);
+ if (NT_SUCCESS(Result))
+ {
+ Result = STATUS_UNRECOGNIZED_VOLUME;
+ for (ULONG i = 0; DeviceObjectCount > i; i++)
+ if (DeviceObjects[i] == FsvrtDeviceObject)
+ {
+ if (FspDeviceRetain(FsvrtDeviceObject))
+ {
+ if (!FsvrtDeviceExtension->Deleted &&
+ FILE_DEVICE_VIRTUAL_DISK == FsvrtDeviceObject->DeviceType)
+ Result = STATUS_SUCCESS;
+ else
+ FspDeviceRelease(FsvrtDeviceObject);
+ }
+ break;
+ }
+ FspDeviceDeleteList(DeviceObjects, DeviceObjectCount);
+ }
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ /* create the file system device object */
+ Result = FspDeviceCreate(FspFsvolDeviceExtensionKind, 0,
+ DeviceObject->DeviceType,
+ &FsvolDeviceObject);
+ if (NT_SUCCESS(Result))
+ {
+ /*
+ * Reference the virtual volume device so that it will not go away while the
+ * file system device object is alive!
+ */
+ ObReferenceObject(FsvrtDeviceObject);
+
+#pragma prefast(suppress:28175, "We are a filesystem: ok to access SectorSize")
+ FsvolDeviceObject->SectorSize = FsvrtDeviceExtension->VolumeParams.SectorSize;
+ FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
+ FsvolDeviceExtension->FsvrtDeviceObject = FsvrtDeviceObject;
+ FsvrtDeviceExtension->FsvolDeviceObject = FsvolDeviceObject;
+ FspDeviceInitComplete(FsvolDeviceObject);
+ Vpb->DeviceObject = FsvolDeviceObject;
+ Vpb->SerialNumber = FsvrtDeviceExtension->VolumeParams.SerialNumber;
+ Irp->IoStatus.Information = 0;
+ }
+
+ FspDeviceRelease(FsvrtDeviceObject);
+
+ exit:;
+ }
+ finally
+ {
+ ExReleaseResourceLite(&FsctlDeviceExtension->Base.Resource);
+ }
+
+ return Result;
+}
+
+typedef struct
+{
+ PDEVICE_OBJECT FsvolDeviceObject;
+ PVPB OldVpb;
+ FSP_WORK_ITEM_WITH_DELAY WorkItemWithDelay;
+} FSP_FSVRT_DELETE_VOLUME_WORK_ITEM;
+
+static NTSTATUS FspFsvrtDeleteVolume(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PAGED_CODE();
+
+ NTSTATUS Result;
+ FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
+ FSP_FSCTL_DEVICE_EXTENSION *FsctlDeviceExtension =
+ FspFsctlDeviceExtension(FsvrtDeviceExtension->FsctlDeviceObject);
+
+ ExAcquireResourceExclusiveLite(&FsctlDeviceExtension->Base.Resource, TRUE);
+ try
+ {
+ PDEVICE_OBJECT FsctlDeviceObject = FsvrtDeviceExtension->FsctlDeviceObject;
+ PDEVICE_OBJECT FsvolDeviceObject = FsvrtDeviceExtension->FsvolDeviceObject;
+ PVPB OldVpb;
+ BOOLEAN DeleteVpb = FALSE;
+ BOOLEAN DeleteDelayed = FALSE;
+ LARGE_INTEGER DelayTimeout;
+ FSP_FSVRT_DELETE_VOLUME_WORK_ITEM *WorkItem = 0;
+ KIRQL Irql;
+
+ /* access check */
+ Result = FspSecuritySubjectContextAccessCheck(
+ FsvrtDeviceExtension->SecurityDescriptorBuf, FILE_WRITE_DATA, Irp->RequestorMode);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ /* pre-allocate a work item in case we need it for delayed delete */
+ WorkItem = FspAllocNonPaged(sizeof *WorkItem);
+ if (0 == WorkItem)
+ {
+ Result = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit;
+ }
+
+ /* mark the virtual volume device as deleted */
+ FsvrtDeviceExtension->Deleted = TRUE;
+
+ /* stop the I/O queue */
+ FspIoqStop(&FsvrtDeviceExtension->Ioq);
+
+ /* swap the preallocated VPB */
+#pragma prefast(push)
+#pragma prefast(disable:28175, "We are a filesystem: ok to access Vpb")
+ IoAcquireVpbSpinLock(&Irql);
+ OldVpb = DeviceObject->Vpb;
+ if (0 != OldVpb && 0 != FsvrtDeviceExtension->SwapVpb)
+ {
+ DeviceObject->Vpb = FsvrtDeviceExtension->SwapVpb;
+ DeviceObject->Vpb->Size = sizeof *DeviceObject->Vpb;
+ DeviceObject->Vpb->Type = IO_TYPE_VPB;
+ DeviceObject->Vpb->Flags = FlagOn(OldVpb->Flags, VPB_REMOVE_PENDING);
+ DeviceObject->Vpb->RealDevice = OldVpb->RealDevice;
+ DeviceObject->Vpb->RealDevice->Vpb = DeviceObject->Vpb;
+ FsvrtDeviceExtension->SwapVpb = 0;
+ DeleteVpb = 0 == OldVpb->ReferenceCount;
+ DeleteDelayed = !DeleteVpb && 0 != FsvolDeviceObject;
+ if (DeleteDelayed)
+ /* keep VPB around for delayed delete */
+ OldVpb->ReferenceCount++;
+ }
+ IoReleaseVpbSpinLock(Irql);
+ if (DeleteDelayed)
+ /* keep fsvol around for delayed delete */
+ FspDeviceRetain(FsvolDeviceObject);
+ else if (DeleteVpb)
+ FspFreeExternal(OldVpb);
+#pragma prefast(pop)
+
+ /* release the file system device and virtual volume objects */
+ FsvrtDeviceExtension->FsvolDeviceObject = 0;
+ if (0 != FsvolDeviceObject)
+ FspDeviceRelease(FsvolDeviceObject);
+ FspDeviceRelease(DeviceObject);
+
+ FspFsctlDeviceVolumeDeleted(FsctlDeviceObject);
+
+ /* are we doing delayed delete of VPB and fsvol? */
+ if (DeleteDelayed)
+ {
+ DelayTimeout.QuadPart = 300/*ms*/ * -10000;
+ WorkItem->FsvolDeviceObject = FsvolDeviceObject;
+ WorkItem->OldVpb = OldVpb;
+ FspInitializeWorkItemWithDelay(&WorkItem->WorkItemWithDelay,
+ FspFsvrtDeleteVolumeDelayed, WorkItem);
+ FspQueueWorkItemWithDelay(&WorkItem->WorkItemWithDelay, DelayTimeout);
+ WorkItem = 0;
+ }
+
+ Result = STATUS_SUCCESS;
+
+ exit:
+ if (0 != WorkItem)
+ FspFree(WorkItem);
+ }
+ finally
+ {
+ ExReleaseResourceLite(&FsctlDeviceExtension->Base.Resource);
+ }
+
+ return Result;
+}
+
+static VOID FspFsvrtDeleteVolumeDelayed(PVOID Context)
+{
+ PAGED_CODE();
+
+ FSP_FSVRT_DELETE_VOLUME_WORK_ITEM *WorkItem = Context;
+ BOOLEAN DeleteVpb = FALSE;
+ LARGE_INTEGER DelayTimeout;
+ KIRQL Irql;
+
+ IoAcquireVpbSpinLock(&Irql);
+ ASSERT(0 != WorkItem->OldVpb->ReferenceCount);
+ DeleteVpb = 1 == WorkItem->OldVpb->ReferenceCount;
+ if (DeleteVpb)
+ WorkItem->OldVpb->ReferenceCount = 0;
+ IoReleaseVpbSpinLock(Irql);
+ if (DeleteVpb)
+ {
+ FspFreeExternal(WorkItem->OldVpb);
+ FspDeviceRelease(WorkItem->FsvolDeviceObject);
+ FspFree(WorkItem);
+ }
+ else
+ {
+ DelayTimeout.QuadPart = 300/*ms*/ * -10000;
+ FspQueueWorkItemWithDelay(&WorkItem->WorkItemWithDelay, DelayTimeout);
+ }
+}
+
+static NTSTATUS FspFsvrtTransact(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PAGED_CODE();
+
+ /* check parameters */
+ ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
+ ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
+ PVOID SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
+ if (0 == SystemBuffer ||
+ (0 != InputBufferLength &&
+ FSP_FSCTL_DEFAULT_ALIGN_UP(sizeof(FSP_FSCTL_TRANSACT_RSP)) > InputBufferLength))
+ return STATUS_INVALID_PARAMETER;
+ if (FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMIN > OutputBufferLength)
+ return STATUS_BUFFER_TOO_SMALL;
+
+ NTSTATUS Result;
+ FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
+ PUINT8 SystemBufferEnd;
+ FSP_FSCTL_TRANSACT_RSP *Response, *NextResponse;
+ FSP_FSCTL_TRANSACT_REQ *Request, *PendingIrpRequest;
+ PIRP ProcessIrp, PendingIrp;
+ LARGE_INTEGER Timeout;
+
+ /* access check */
+ Result = FspSecuritySubjectContextAccessCheck(
+ FsvrtDeviceExtension->SecurityDescriptorBuf, FILE_WRITE_DATA, Irp->RequestorMode);
+ if (!NT_SUCCESS(Result))
+ return Result;
+
+ /* process any user-mode file system responses */
+ Response = SystemBuffer;
+ SystemBufferEnd = (PUINT8)SystemBuffer + InputBufferLength;
+ for (;;)
+ {
+ NextResponse = FspFsctlTransactConsumeResponse(Response, SystemBufferEnd);
+ if (0 == NextResponse)
+ break;
+
+ ProcessIrp = FspIoqEndProcessingIrp(&FsvrtDeviceExtension->Ioq, (UINT_PTR)Response->Hint);
+ if (0 == ProcessIrp)
+ /* either IRP was canceled or a bogus Hint was provided */
+ continue;
+
+ FspIopDispatchComplete(ProcessIrp, Response);
+
+ Response = NextResponse;
+ }
+
+ /* wait for an IRP to arrive */
+ KeQuerySystemTime(&Timeout);
+ Timeout.QuadPart += FsvrtDeviceExtension->VolumeParams.TransactTimeout * 10000;
+ /* convert millis to nanos and add to absolute time */
+ while (0 == (PendingIrp = FspIoqNextPendingIrp(&FsvrtDeviceExtension->Ioq, &Timeout)))
+ {
+ if (FspIoqStopped(&FsvrtDeviceExtension->Ioq))
+ return STATUS_CANCELLED;
+ }
+ if (FspIoqTimeout == PendingIrp)
+ {
+ Irp->IoStatus.Information = 0;
+ return STATUS_SUCCESS;
+ }
+
+ /* send any pending IRP's to the user-mode file system */
+ Request = SystemBuffer;
+ SystemBufferEnd = (PUINT8)SystemBuffer + OutputBufferLength;
+ ASSERT(FspFsctlTransactCanProduceRequest(Request, SystemBufferEnd));
+ for (;;)
+ {
+ PendingIrpRequest = FspIrpRequest(PendingIrp);
+
+ Result = FspIopDispatchPrepare(PendingIrp, PendingIrpRequest);
+ if (!NT_SUCCESS(Result))
+ FspIopCompleteIrp(PendingIrp, Result);
+ else
+ {
+ RtlCopyMemory(Request, PendingIrpRequest, PendingIrpRequest->Size);
+ Request = FspFsctlTransactProduceRequest(Request, PendingIrpRequest->Size);
+
+ if (!FspIoqStartProcessingIrp(&FsvrtDeviceExtension->Ioq, PendingIrp))
+ {
+ /*
+ * This can only happen if the Ioq was stopped. Abandon everything
+ * and return STATUS_CANCELLED. Any IRP's in the Pending and Process
+ * queues of the Ioq will be cancelled during FspIoqStop(). We must
+ * also cancel the PendingIrp we have in our hands.
+ */
+ ASSERT(FspIoqStopped(&FsvrtDeviceExtension->Ioq));
+ FspIopCompleteIrp(PendingIrp, STATUS_CANCELLED);
+ return STATUS_CANCELLED;
+ }
+
+ /* check that we have enough space before pulling the next pending IRP off the queue */
+ if (!FspFsctlTransactCanProduceRequest(Request, SystemBufferEnd))
+ break;
+ }
+
+ PendingIrp = FspIoqNextPendingIrp(&FsvrtDeviceExtension->Ioq, 0);
+ if (0 == PendingIrp)
+ break;
+
+ }
+ Irp->IoStatus.Information = (PUINT8)Request - (PUINT8)SystemBuffer;
+
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS FspFsctlFileSystemControl(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PAGED_CODE();
+
+ NTSTATUS Result = STATUS_INVALID_DEVICE_REQUEST;
+ switch (IrpSp->MinorFunction)
+ {
+ case IRP_MN_USER_FS_REQUEST:
+ switch (IrpSp->Parameters.FileSystemControl.FsControlCode)
+ {
+ case FSP_FSCTL_CREATE:
+ Result = FspFsctlCreateVolume(DeviceObject, Irp, IrpSp);
+ break;
+ }
+ break;
+ case IRP_MN_MOUNT_VOLUME:
+ Result = FspFsctlMountVolume(DeviceObject, Irp, IrpSp);
+ break;
+#if 0
+ case IRP_MN_VERIFY_VOLUME:
+ break;
+#endif
+ }
+ return Result;
+}
+
+static NTSTATUS FspFsvrtFileSystemControl(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PAGED_CODE();
+
+ NTSTATUS Result = STATUS_INVALID_DEVICE_REQUEST;
+ switch (IrpSp->MinorFunction)
+ {
+ case IRP_MN_USER_FS_REQUEST:
+ switch (IrpSp->Parameters.FileSystemControl.FsControlCode)
+ {
+ case FSP_FSCTL_DELETE:
+ Result = FspFsvrtDeleteVolume(DeviceObject, Irp, IrpSp);
+ break;
+ case FSP_FSCTL_TRANSACT:
+ Result = FspFsvrtTransact(DeviceObject, Irp, IrpSp);
+ break;
+ }
+ break;
+ }
+ return Result;
+}
+
+static NTSTATUS FspFsvolFileSystemControl(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PAGED_CODE();
+
+ NTSTATUS Result = STATUS_INVALID_DEVICE_REQUEST;
+ switch (IrpSp->MinorFunction)
+ {
+ case IRP_MN_USER_FS_REQUEST:
+ break;
+ }
+ return Result;
+}
+
+NTSTATUS FspFileSystemControl(
+ PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+ FSP_ENTER_MJ(PAGED_CODE());
+
+ ASSERT(IRP_MJ_FILE_SYSTEM_CONTROL == IrpSp->MajorFunction);
+
+ switch (FspDeviceExtension(DeviceObject)->Kind)
+ {
+ case FspFsvolDeviceExtensionKind:
+ FSP_RETURN(Result = FspFsvolFileSystemControl(DeviceObject, Irp, IrpSp));
+ case FspFsvrtDeviceExtensionKind:
+ FSP_RETURN(Result = FspFsvrtFileSystemControl(DeviceObject, Irp, IrpSp));
+ case FspFsctlDeviceExtensionKind:
+ FSP_RETURN(Result = FspFsctlFileSystemControl(DeviceObject, Irp, IrpSp));
+ default:
+ FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST);
+ }
+
+ FSP_LEAVE_MJ(
+ "FileObject=%p%s%s",
+ IrpSp->FileObject,
+ IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction ? ", " : "",
+ IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction ?
+ IoctlCodeSym(IrpSp->Parameters.FileSystemControl.FsControlCode) : "");
+}
+
+VOID FspFileSystemControlComplete(
+ PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
+{
+ FSP_ENTER_IOC(PAGED_CODE());
+
+ FSP_LEAVE_IOC(
+ "FileObject=%p%s%s",
+ IrpSp->FileObject,
+ IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction ? ", " : "",
+ IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction ?
+ IoctlCodeSym(IrpSp->Parameters.FileSystemControl.FsControlCode) : "");
+}
diff --git a/src/sys/idevctl.c b/src0/sys/idevctl.c
similarity index 100%
rename from src/sys/idevctl.c
rename to src0/sys/idevctl.c
diff --git a/src/sys/misc.c b/src0/sys/misc.c
similarity index 100%
rename from src/sys/misc.c
rename to src0/sys/misc.c