mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2025-11-11 11:08:02 -06:00
Windows Driver: Fix strange crashes caused by probably by APC queue issues from calls to IoBuildDeviceIoControlRequest and ZwCreate (cf https://www.osr.com/blog/2018/02/14/beware-iobuilddeviceiocontrolrequest/)
This commit is contained in:
@@ -142,6 +142,7 @@ static BOOL RamEncryptionActivated = FALSE;
|
|||||||
static KeSaveExtendedProcessorStateFn KeSaveExtendedProcessorStatePtr = NULL;
|
static KeSaveExtendedProcessorStateFn KeSaveExtendedProcessorStatePtr = NULL;
|
||||||
static KeRestoreExtendedProcessorStateFn KeRestoreExtendedProcessorStatePtr = NULL;
|
static KeRestoreExtendedProcessorStateFn KeRestoreExtendedProcessorStatePtr = NULL;
|
||||||
static ExGetFirmwareEnvironmentVariableFn ExGetFirmwareEnvironmentVariablePtr = NULL;
|
static ExGetFirmwareEnvironmentVariableFn ExGetFirmwareEnvironmentVariablePtr = NULL;
|
||||||
|
static KeAreAllApcsDisabledFn KeAreAllApcsDisabledPtr = NULL;
|
||||||
|
|
||||||
POOL_TYPE ExDefaultNonPagedPoolType = NonPagedPool;
|
POOL_TYPE ExDefaultNonPagedPoolType = NonPagedPool;
|
||||||
ULONG ExDefaultMdlProtection = 0;
|
ULONG ExDefaultMdlProtection = 0;
|
||||||
@@ -272,6 +273,15 @@ NTSTATUS DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
|||||||
ExDefaultMdlProtection = MdlMappingNoExecute;
|
ExDefaultMdlProtection = MdlMappingNoExecute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KeAreAllApcsDisabled is available starting from Windows Server 2003
|
||||||
|
if ((OsMajorVersion > 5) || (OsMajorVersion == 5 && OsMinorVersion >= 2))
|
||||||
|
{
|
||||||
|
UNICODE_STRING KeAreAllApcsDisabledFuncName;
|
||||||
|
RtlInitUnicodeString(&KeAreAllApcsDisabledFuncName, L"KeAreAllApcsDisabled");
|
||||||
|
|
||||||
|
KeAreAllApcsDisabledPtr = (KeAreAllApcsDisabledFn) MmGetSystemRoutineAddress(&KeAreAllApcsDisabledFuncName);
|
||||||
|
}
|
||||||
|
|
||||||
// KeSaveExtendedProcessorState/KeRestoreExtendedProcessorState are available starting from Windows 7
|
// KeSaveExtendedProcessorState/KeRestoreExtendedProcessorState are available starting from Windows 7
|
||||||
if ((OsMajorVersion > 6) || (OsMajorVersion == 6 && OsMinorVersion >= 1))
|
if ((OsMajorVersion > 6) || (OsMajorVersion == 6 && OsMinorVersion >= 1))
|
||||||
{
|
{
|
||||||
@@ -3457,6 +3467,18 @@ void OnShutdownPending ()
|
|||||||
while (SendDeviceIoControlRequest (RootDeviceObject, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0) == STATUS_INSUFFICIENT_RESOURCES);
|
while (SendDeviceIoControlRequest (RootDeviceObject, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0) == STATUS_INSUFFICIENT_RESOURCES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PWSTR deviceName; ULONG IoControlCode; void *InputBuffer; ULONG InputBufferSize; void *OutputBuffer; ULONG OutputBufferSize;
|
||||||
|
NTSTATUS Status;
|
||||||
|
KEVENT WorkItemCompletedEvent;
|
||||||
|
} TCDeviceIoControlWorkItemArgs;
|
||||||
|
|
||||||
|
static VOID TCDeviceIoControlWorkItemRoutine (PDEVICE_OBJECT rootDeviceObject, TCDeviceIoControlWorkItemArgs *arg)
|
||||||
|
{
|
||||||
|
arg->Status = TCDeviceIoControl (arg->deviceName, arg->IoControlCode, arg->InputBuffer, arg->InputBufferSize, arg->OutputBuffer, arg->OutputBufferSize);
|
||||||
|
KeSetEvent (&arg->WorkItemCompletedEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS TCDeviceIoControl (PWSTR deviceName, ULONG IoControlCode, void *InputBuffer, ULONG InputBufferSize, void *OutputBuffer, ULONG OutputBufferSize)
|
NTSTATUS TCDeviceIoControl (PWSTR deviceName, ULONG IoControlCode, void *InputBuffer, ULONG InputBufferSize, void *OutputBuffer, ULONG OutputBufferSize)
|
||||||
{
|
{
|
||||||
@@ -3468,6 +3490,30 @@ NTSTATUS TCDeviceIoControl (PWSTR deviceName, ULONG IoControlCode, void *InputBu
|
|||||||
KEVENT event;
|
KEVENT event;
|
||||||
UNICODE_STRING name;
|
UNICODE_STRING name;
|
||||||
|
|
||||||
|
if ((KeGetCurrentIrql() >= APC_LEVEL) || VC_KeAreAllApcsDisabled())
|
||||||
|
{
|
||||||
|
TCDeviceIoControlWorkItemArgs args;
|
||||||
|
|
||||||
|
PIO_WORKITEM workItem = IoAllocateWorkItem (RootDeviceObject);
|
||||||
|
if (!workItem)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
args.deviceName = deviceName;
|
||||||
|
args.IoControlCode = IoControlCode;
|
||||||
|
args.InputBuffer = InputBuffer;
|
||||||
|
args.InputBufferSize = InputBufferSize;
|
||||||
|
args.OutputBuffer = OutputBuffer;
|
||||||
|
args.OutputBufferSize = OutputBufferSize;
|
||||||
|
|
||||||
|
KeInitializeEvent (&args.WorkItemCompletedEvent, SynchronizationEvent, FALSE);
|
||||||
|
IoQueueWorkItem (workItem, TCDeviceIoControlWorkItemRoutine, DelayedWorkQueue, &args);
|
||||||
|
|
||||||
|
KeWaitForSingleObject (&args.WorkItemCompletedEvent, Executive, KernelMode, FALSE, NULL);
|
||||||
|
IoFreeWorkItem (workItem);
|
||||||
|
|
||||||
|
return args.Status;
|
||||||
|
}
|
||||||
|
|
||||||
RtlInitUnicodeString(&name, deviceName);
|
RtlInitUnicodeString(&name, deviceName);
|
||||||
ntStatus = IoGetDeviceObjectPointer (&name, FILE_READ_ATTRIBUTES, &fileObject, &deviceObject);
|
ntStatus = IoGetDeviceObjectPointer (&name, FILE_READ_ATTRIBUTES, &fileObject, &deviceObject);
|
||||||
|
|
||||||
@@ -3528,7 +3574,7 @@ NTSTATUS SendDeviceIoControlRequest (PDEVICE_OBJECT deviceObject, ULONG ioContro
|
|||||||
PIRP irp;
|
PIRP irp;
|
||||||
KEVENT event;
|
KEVENT event;
|
||||||
|
|
||||||
if (KeGetCurrentIrql() > APC_LEVEL)
|
if ((KeGetCurrentIrql() >= APC_LEVEL) || VC_KeAreAllApcsDisabled())
|
||||||
{
|
{
|
||||||
SendDeviceIoControlRequestWorkItemArgs args;
|
SendDeviceIoControlRequestWorkItemArgs args;
|
||||||
|
|
||||||
@@ -3844,6 +3890,136 @@ NTSTATUS MountManagerUnmount (int nDosDriveNo)
|
|||||||
return ntStatus;
|
return ntStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
MOUNT_STRUCT* mount; PEXTENSION NewExtension;
|
||||||
|
NTSTATUS Status;
|
||||||
|
KEVENT WorkItemCompletedEvent;
|
||||||
|
} UpdateFsVolumeInformationWorkItemArgs;
|
||||||
|
|
||||||
|
static NTSTATUS UpdateFsVolumeInformation (MOUNT_STRUCT* mount, PEXTENSION NewExtension);
|
||||||
|
|
||||||
|
static VOID UpdateFsVolumeInformationWorkItemRoutine (PDEVICE_OBJECT rootDeviceObject, UpdateFsVolumeInformationWorkItemArgs *arg)
|
||||||
|
{
|
||||||
|
arg->Status = UpdateFsVolumeInformation (arg->mount, arg->NewExtension);
|
||||||
|
KeSetEvent (&arg->WorkItemCompletedEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS UpdateFsVolumeInformation (MOUNT_STRUCT* mount, PEXTENSION NewExtension)
|
||||||
|
{
|
||||||
|
HANDLE volumeHandle;
|
||||||
|
PFILE_OBJECT volumeFileObject;
|
||||||
|
ULONG labelLen = (ULONG) wcslen (mount->wszLabel);
|
||||||
|
BOOL bIsNTFS = FALSE;
|
||||||
|
ULONG labelMaxLen, labelEffectiveLen;
|
||||||
|
|
||||||
|
if ((KeGetCurrentIrql() >= APC_LEVEL) || VC_KeAreAllApcsDisabled())
|
||||||
|
{
|
||||||
|
UpdateFsVolumeInformationWorkItemArgs args;
|
||||||
|
|
||||||
|
PIO_WORKITEM workItem = IoAllocateWorkItem (RootDeviceObject);
|
||||||
|
if (!workItem)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
args.mount = mount;
|
||||||
|
args.NewExtension = NewExtension;
|
||||||
|
|
||||||
|
KeInitializeEvent (&args.WorkItemCompletedEvent, SynchronizationEvent, FALSE);
|
||||||
|
IoQueueWorkItem (workItem, UpdateFsVolumeInformationWorkItemRoutine, DelayedWorkQueue, &args);
|
||||||
|
|
||||||
|
KeWaitForSingleObject (&args.WorkItemCompletedEvent, Executive, KernelMode, FALSE, NULL);
|
||||||
|
IoFreeWorkItem (workItem);
|
||||||
|
|
||||||
|
return args.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
if (NT_SUCCESS (TCOpenFsVolume (NewExtension, &volumeHandle, &volumeFileObject)))
|
||||||
|
{
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
ULONG fsStatus;
|
||||||
|
|
||||||
|
if (NT_SUCCESS (TCFsctlCall (volumeFileObject, FSCTL_IS_VOLUME_DIRTY, NULL, 0, &fsStatus, sizeof (fsStatus)))
|
||||||
|
&& (fsStatus & VOLUME_IS_DIRTY))
|
||||||
|
{
|
||||||
|
mount->FilesystemDirty = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
mount->FilesystemDirty = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// detect if the filesystem is NTFS or FAT
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
NTFS_VOLUME_DATA_BUFFER ntfsData;
|
||||||
|
if (NT_SUCCESS (TCFsctlCall (volumeFileObject, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &ntfsData, sizeof (ntfsData))))
|
||||||
|
{
|
||||||
|
bIsNTFS = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
bIsNTFS = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NewExtension->bIsNTFS = bIsNTFS;
|
||||||
|
mount->bIsNTFS = bIsNTFS;
|
||||||
|
|
||||||
|
if (labelLen > 0)
|
||||||
|
{
|
||||||
|
if (bIsNTFS)
|
||||||
|
labelMaxLen = 32; // NTFS maximum label length
|
||||||
|
else
|
||||||
|
labelMaxLen = 11; // FAT maximum label length
|
||||||
|
|
||||||
|
// calculate label effective length
|
||||||
|
labelEffectiveLen = labelLen > labelMaxLen? labelMaxLen : labelLen;
|
||||||
|
|
||||||
|
// correct the label in the device
|
||||||
|
memset (&NewExtension->wszLabel[labelEffectiveLen], 0, 33 - labelEffectiveLen);
|
||||||
|
memcpy (mount->wszLabel, NewExtension->wszLabel, 33);
|
||||||
|
|
||||||
|
// set the volume label
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
IO_STATUS_BLOCK ioblock;
|
||||||
|
ULONG labelInfoSize = sizeof(FILE_FS_LABEL_INFORMATION) + (labelEffectiveLen * sizeof(WCHAR));
|
||||||
|
FILE_FS_LABEL_INFORMATION* labelInfo = (FILE_FS_LABEL_INFORMATION*) TCalloc (labelInfoSize);
|
||||||
|
if (labelInfo)
|
||||||
|
{
|
||||||
|
labelInfo->VolumeLabelLength = labelEffectiveLen * sizeof(WCHAR);
|
||||||
|
memcpy (labelInfo->VolumeLabel, mount->wszLabel, labelInfo->VolumeLabelLength);
|
||||||
|
|
||||||
|
if (STATUS_SUCCESS == ZwSetVolumeInformationFile (volumeHandle, &ioblock, labelInfo, labelInfoSize, FileFsLabelInformation))
|
||||||
|
{
|
||||||
|
mount->bDriverSetLabel = TRUE;
|
||||||
|
NewExtension->bDriverSetLabel = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
TCfree(labelInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TCCloseFsVolume (volumeHandle, volumeFileObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS MountDevice (PDEVICE_OBJECT DeviceObject, MOUNT_STRUCT *mount)
|
NTSTATUS MountDevice (PDEVICE_OBJECT DeviceObject, MOUNT_STRUCT *mount)
|
||||||
{
|
{
|
||||||
@@ -3931,12 +4107,6 @@ NTSTATUS MountDevice (PDEVICE_OBJECT DeviceObject, MOUNT_STRUCT *mount)
|
|||||||
{
|
{
|
||||||
if (mount->nReturnCode == 0)
|
if (mount->nReturnCode == 0)
|
||||||
{
|
{
|
||||||
HANDLE volumeHandle;
|
|
||||||
PFILE_OBJECT volumeFileObject;
|
|
||||||
ULONG labelLen = (ULONG) wcslen (mount->wszLabel);
|
|
||||||
BOOL bIsNTFS = FALSE;
|
|
||||||
ULONG labelMaxLen, labelEffectiveLen;
|
|
||||||
|
|
||||||
Dump ("Mount SUCCESS TC code = 0x%08x READ-ONLY = %d\n", mount->nReturnCode, NewExtension->bReadOnly);
|
Dump ("Mount SUCCESS TC code = 0x%08x READ-ONLY = %d\n", mount->nReturnCode, NewExtension->bReadOnly);
|
||||||
|
|
||||||
if (NewExtension->bReadOnly)
|
if (NewExtension->bReadOnly)
|
||||||
@@ -3968,81 +4138,13 @@ NTSTATUS MountDevice (PDEVICE_OBJECT DeviceObject, MOUNT_STRUCT *mount)
|
|||||||
|
|
||||||
mount->FilesystemDirty = FALSE;
|
mount->FilesystemDirty = FALSE;
|
||||||
|
|
||||||
if (mount->bMountManager && NT_SUCCESS (TCOpenFsVolume (NewExtension, &volumeHandle, &volumeFileObject)))
|
if (mount->bMountManager)
|
||||||
{
|
{
|
||||||
__try
|
NTSTATUS updateStatus = UpdateFsVolumeInformation (mount, NewExtension);
|
||||||
|
if (!NT_SUCCESS (updateStatus))
|
||||||
{
|
{
|
||||||
ULONG fsStatus;
|
Dump ("MountDevice: UpdateFsVolumeInformation failed with status 0x%08x\n", updateStatus);
|
||||||
|
|
||||||
if (NT_SUCCESS (TCFsctlCall (volumeFileObject, FSCTL_IS_VOLUME_DIRTY, NULL, 0, &fsStatus, sizeof (fsStatus)))
|
|
||||||
&& (fsStatus & VOLUME_IS_DIRTY))
|
|
||||||
{
|
|
||||||
mount->FilesystemDirty = TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
||||||
{
|
|
||||||
mount->FilesystemDirty = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// detect if the filesystem is NTFS or FAT
|
|
||||||
__try
|
|
||||||
{
|
|
||||||
NTFS_VOLUME_DATA_BUFFER ntfsData;
|
|
||||||
if (NT_SUCCESS (TCFsctlCall (volumeFileObject, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &ntfsData, sizeof (ntfsData))))
|
|
||||||
{
|
|
||||||
bIsNTFS = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
||||||
{
|
|
||||||
bIsNTFS = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
NewExtension->bIsNTFS = bIsNTFS;
|
|
||||||
mount->bIsNTFS = bIsNTFS;
|
|
||||||
|
|
||||||
if (labelLen > 0)
|
|
||||||
{
|
|
||||||
if (bIsNTFS)
|
|
||||||
labelMaxLen = 32; // NTFS maximum label length
|
|
||||||
else
|
|
||||||
labelMaxLen = 11; // FAT maximum label length
|
|
||||||
|
|
||||||
// calculate label effective length
|
|
||||||
labelEffectiveLen = labelLen > labelMaxLen? labelMaxLen : labelLen;
|
|
||||||
|
|
||||||
// correct the label in the device
|
|
||||||
memset (&NewExtension->wszLabel[labelEffectiveLen], 0, 33 - labelEffectiveLen);
|
|
||||||
memcpy (mount->wszLabel, NewExtension->wszLabel, 33);
|
|
||||||
|
|
||||||
// set the volume label
|
|
||||||
__try
|
|
||||||
{
|
|
||||||
IO_STATUS_BLOCK ioblock;
|
|
||||||
ULONG labelInfoSize = sizeof(FILE_FS_LABEL_INFORMATION) + (labelEffectiveLen * sizeof(WCHAR));
|
|
||||||
FILE_FS_LABEL_INFORMATION* labelInfo = (FILE_FS_LABEL_INFORMATION*) TCalloc (labelInfoSize);
|
|
||||||
if (labelInfo)
|
|
||||||
{
|
|
||||||
labelInfo->VolumeLabelLength = labelEffectiveLen * sizeof(WCHAR);
|
|
||||||
memcpy (labelInfo->VolumeLabel, mount->wszLabel, labelInfo->VolumeLabelLength);
|
|
||||||
|
|
||||||
if (STATUS_SUCCESS == ZwSetVolumeInformationFile (volumeHandle, &ioblock, labelInfo, labelInfoSize, FileFsLabelInformation))
|
|
||||||
{
|
|
||||||
mount->bDriverSetLabel = TRUE;
|
|
||||||
NewExtension->bDriverSetLabel = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
TCfree(labelInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TCCloseFsVolume (volumeHandle, volumeFileObject);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -4056,6 +4158,20 @@ NTSTATUS MountDevice (PDEVICE_OBJECT DeviceObject, MOUNT_STRUCT *mount)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UNMOUNT_STRUCT *unmountRequest; PDEVICE_OBJECT deviceObject; BOOL ignoreOpenFiles;
|
||||||
|
NTSTATUS Status;
|
||||||
|
KEVENT WorkItemCompletedEvent;
|
||||||
|
} UnmountDeviceWorkItemArgs;
|
||||||
|
|
||||||
|
|
||||||
|
static VOID UnmountDeviceWorkItemRoutine (PDEVICE_OBJECT rootDeviceObject, UnmountDeviceWorkItemArgs *arg)
|
||||||
|
{
|
||||||
|
arg->Status = UnmountDevice (arg->unmountRequest, arg->deviceObject, arg->ignoreOpenFiles);
|
||||||
|
KeSetEvent (&arg->WorkItemCompletedEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS UnmountDevice (UNMOUNT_STRUCT *unmountRequest, PDEVICE_OBJECT deviceObject, BOOL ignoreOpenFiles)
|
NTSTATUS UnmountDevice (UNMOUNT_STRUCT *unmountRequest, PDEVICE_OBJECT deviceObject, BOOL ignoreOpenFiles)
|
||||||
{
|
{
|
||||||
PEXTENSION extension = deviceObject->DeviceExtension;
|
PEXTENSION extension = deviceObject->DeviceExtension;
|
||||||
@@ -4063,6 +4179,27 @@ NTSTATUS UnmountDevice (UNMOUNT_STRUCT *unmountRequest, PDEVICE_OBJECT deviceObj
|
|||||||
HANDLE volumeHandle;
|
HANDLE volumeHandle;
|
||||||
PFILE_OBJECT volumeFileObject;
|
PFILE_OBJECT volumeFileObject;
|
||||||
|
|
||||||
|
if ((KeGetCurrentIrql() >= APC_LEVEL) || VC_KeAreAllApcsDisabled())
|
||||||
|
{
|
||||||
|
UnmountDeviceWorkItemArgs args;
|
||||||
|
|
||||||
|
PIO_WORKITEM workItem = IoAllocateWorkItem (RootDeviceObject);
|
||||||
|
if (!workItem)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
args.deviceObject = deviceObject;
|
||||||
|
args.unmountRequest = unmountRequest;
|
||||||
|
args.ignoreOpenFiles = ignoreOpenFiles;
|
||||||
|
|
||||||
|
KeInitializeEvent (&args.WorkItemCompletedEvent, SynchronizationEvent, FALSE);
|
||||||
|
IoQueueWorkItem (workItem, UnmountDeviceWorkItemRoutine, DelayedWorkQueue, &args);
|
||||||
|
|
||||||
|
KeWaitForSingleObject (&args.WorkItemCompletedEvent, Executive, KernelMode, FALSE, NULL);
|
||||||
|
IoFreeWorkItem (workItem);
|
||||||
|
|
||||||
|
return args.Status;
|
||||||
|
}
|
||||||
|
|
||||||
Dump ("UnmountDevice %d\n", extension->nDosDriveNo);
|
Dump ("UnmountDevice %d\n", extension->nDosDriveNo);
|
||||||
|
|
||||||
ntStatus = TCOpenFsVolume (extension, &volumeHandle, &volumeFileObject);
|
ntStatus = TCOpenFsVolume (extension, &volumeHandle, &volumeFileObject);
|
||||||
@@ -4760,3 +4897,11 @@ VOID NTAPI KeRestoreExtendedProcessorState (
|
|||||||
(KeRestoreExtendedProcessorStatePtr) (XStateSave);
|
(KeRestoreExtendedProcessorStatePtr) (XStateSave);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN VC_KeAreAllApcsDisabled (VOID)
|
||||||
|
{
|
||||||
|
if (KeAreAllApcsDisabledPtr)
|
||||||
|
return (KeAreAllApcsDisabledPtr) ();
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|||||||
@@ -886,6 +886,18 @@ void TCCloseVolume (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PDEVICE_OBJECT deviceObject; PEXTENSION Extension; ULONG ioControlCode; void *inputBuffer; int inputBufferSize; void *outputBuffer; int outputBufferSize;
|
||||||
|
NTSTATUS Status;
|
||||||
|
KEVENT WorkItemCompletedEvent;
|
||||||
|
} TCSendHostDeviceIoControlRequestExWorkItemArgs;
|
||||||
|
|
||||||
|
static VOID TCSendHostDeviceIoControlRequestExWorkItemRoutine (PDEVICE_OBJECT rootDeviceObject, TCSendHostDeviceIoControlRequestExWorkItemArgs *arg)
|
||||||
|
{
|
||||||
|
arg->Status = TCSendHostDeviceIoControlRequestEx (arg->deviceObject, arg->Extension, arg->ioControlCode, arg->inputBuffer, arg->inputBufferSize, arg->outputBuffer, arg->outputBufferSize);
|
||||||
|
KeSetEvent (&arg->WorkItemCompletedEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS TCSendHostDeviceIoControlRequestEx (PDEVICE_OBJECT DeviceObject,
|
NTSTATUS TCSendHostDeviceIoControlRequestEx (PDEVICE_OBJECT DeviceObject,
|
||||||
PEXTENSION Extension,
|
PEXTENSION Extension,
|
||||||
@@ -901,6 +913,31 @@ NTSTATUS TCSendHostDeviceIoControlRequestEx (PDEVICE_OBJECT DeviceObject,
|
|||||||
|
|
||||||
UNREFERENCED_PARAMETER(DeviceObject); /* Remove compiler warning */
|
UNREFERENCED_PARAMETER(DeviceObject); /* Remove compiler warning */
|
||||||
|
|
||||||
|
if ((KeGetCurrentIrql() >= APC_LEVEL) || VC_KeAreAllApcsDisabled())
|
||||||
|
{
|
||||||
|
TCSendHostDeviceIoControlRequestExWorkItemArgs args;
|
||||||
|
|
||||||
|
PIO_WORKITEM workItem = IoAllocateWorkItem (RootDeviceObject);
|
||||||
|
if (!workItem)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
args.deviceObject = DeviceObject;
|
||||||
|
args.Extension = Extension;
|
||||||
|
args.ioControlCode = IoControlCode;
|
||||||
|
args.inputBuffer = InputBuffer;
|
||||||
|
args.inputBufferSize = InputBufferSize;
|
||||||
|
args.outputBuffer = OutputBuffer;
|
||||||
|
args.outputBufferSize = OutputBufferSize;
|
||||||
|
|
||||||
|
KeInitializeEvent (&args.WorkItemCompletedEvent, SynchronizationEvent, FALSE);
|
||||||
|
IoQueueWorkItem (workItem, TCSendHostDeviceIoControlRequestExWorkItemRoutine, DelayedWorkQueue, &args);
|
||||||
|
|
||||||
|
KeWaitForSingleObject (&args.WorkItemCompletedEvent, Executive, KernelMode, FALSE, NULL);
|
||||||
|
IoFreeWorkItem (workItem);
|
||||||
|
|
||||||
|
return args.Status;
|
||||||
|
}
|
||||||
|
|
||||||
KeClearEvent (&Extension->keVolumeEvent);
|
KeClearEvent (&Extension->keVolumeEvent);
|
||||||
|
|
||||||
Irp = IoBuildDeviceIoControlRequest (IoControlCode,
|
Irp = IoBuildDeviceIoControlRequest (IoControlCode,
|
||||||
|
|||||||
Reference in New Issue
Block a user