📄 ntdriver.c
字号:
return (LPWSTR) _T ("IOCTL_DISK_INTERNAL_CLEAR_VERIFY");
else if (ulCode == IOCTL_DISK_CHECK_VERIFY)
return (LPWSTR) _T ("IOCTL_DISK_CHECK_VERIFY");
else if (ulCode == IOCTL_DISK_MEDIA_REMOVAL)
return (LPWSTR) _T ("IOCTL_DISK_MEDIA_REMOVAL");
else if (ulCode == IOCTL_DISK_EJECT_MEDIA)
return (LPWSTR) _T ("IOCTL_DISK_EJECT_MEDIA");
else if (ulCode == IOCTL_DISK_LOAD_MEDIA)
return (LPWSTR) _T ("IOCTL_DISK_LOAD_MEDIA");
else if (ulCode == IOCTL_DISK_RESERVE)
return (LPWSTR) _T ("IOCTL_DISK_RESERVE");
else if (ulCode == IOCTL_DISK_RELEASE)
return (LPWSTR) _T ("IOCTL_DISK_RELEASE");
else if (ulCode == IOCTL_DISK_FIND_NEW_DEVICES)
return (LPWSTR) _T ("IOCTL_DISK_FIND_NEW_DEVICES");
else if (ulCode == IOCTL_DISK_GET_MEDIA_TYPES)
return (LPWSTR) _T ("IOCTL_DISK_GET_MEDIA_TYPES");
else if (ulCode == IOCTL_STORAGE_SET_HOTPLUG_INFO)
return (LPWSTR) _T ("IOCTL_STORAGE_SET_HOTPLUG_INFO");
else if (ulCode == IRP_MJ_READ)
return (LPWSTR) _T ("IRP_MJ_READ");
else if (ulCode == IRP_MJ_WRITE)
return (LPWSTR) _T ("IRP_MJ_WRITE");
else if (ulCode == IRP_MJ_CREATE)
return (LPWSTR) _T ("IRP_MJ_CREATE");
else if (ulCode == IRP_MJ_CLOSE)
return (LPWSTR) _T ("IRP_MJ_CLOSE");
else if (ulCode == IRP_MJ_CLEANUP)
return (LPWSTR) _T ("IRP_MJ_CLEANUP");
else if (ulCode == IRP_MJ_FLUSH_BUFFERS)
return (LPWSTR) _T ("IRP_MJ_FLUSH_BUFFERS");
else if (ulCode == IRP_MJ_SHUTDOWN)
return (LPWSTR) _T ("IRP_MJ_SHUTDOWN");
else if (ulCode == IRP_MJ_DEVICE_CONTROL)
return (LPWSTR) _T ("IRP_MJ_DEVICE_CONTROL");
else
{
return (LPWSTR) _T ("IOCTL");
}
}
#endif
PDEVICE_OBJECT
TCDeleteDeviceObject (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension)
{
PDEVICE_OBJECT OldDeviceObject = DeviceObject;
UNICODE_STRING Win32NameString;
NTSTATUS ntStatus;
Dump ("TCDeleteDeviceObject BEGIN\n");
if (Extension->bRootDevice)
{
RtlInitUnicodeString (&Win32NameString, (LPWSTR) DOS_ROOT_PREFIX);
ntStatus = IoDeleteSymbolicLink (&Win32NameString);
if (!NT_SUCCESS (ntStatus))
Dump ("IoDeleteSymbolicLink failed ntStatus = 0x%08x\n", ntStatus);
}
else
{
if (Extension->peThread != NULL)
TCStopVolumeThread (DeviceObject, Extension);
if (DeviceObject->ReferenceCount > 0)
ReferencedDeviceDeleted = TRUE;
// Forced dismount does not set reference count to zero even if all open handles are closed
Dump ("Deleting device with ref count %ld\n", DeviceObject->ReferenceCount);
DeviceObject->ReferenceCount = 0;
}
if (DeviceObject != NULL)
DeviceObject = DeviceObject->NextDevice;
IoDeleteDevice (OldDeviceObject);
Dump ("TCDeleteDeviceObject END\n");
return DeviceObject;
}
VOID
TCUnloadDriver (PDRIVER_OBJECT DriverObject)
{
PDEVICE_OBJECT DeviceObject = DriverObject->DeviceObject;
Dump ("TCUnloadDriver BEGIN\n");
UnmountAllDevices (DeviceObject, TRUE);
/* Now walk the list of driver objects and get rid of them */
while (DeviceObject != (PDEVICE_OBJECT) NULL)
{
DeviceObject = TCDeleteDeviceObject (DeviceObject,
(PEXTENSION) DeviceObject->DeviceExtension);
}
WipeCache ();
if (IsBootDriveMounted())
TC_BUG_CHECK (STATUS_INVALID_DEVICE_STATE);
Dump ("TCUnloadDriver END\n");
}
NTSTATUS
TCDeviceIoControl (PWSTR deviceName, ULONG IoControlCode,
void *InputBuffer, int InputBufferSize, void *OutputBuffer, int OutputBufferSize)
{
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS ntStatus;
PIRP irp;
PFILE_OBJECT fileObject;
PDEVICE_OBJECT deviceObject;
KEVENT event;
UNICODE_STRING name;
RtlInitUnicodeString(&name, deviceName);
ntStatus = IoGetDeviceObjectPointer (&name, FILE_READ_ATTRIBUTES, &fileObject, &deviceObject);
if (ntStatus != STATUS_SUCCESS)
return ntStatus;
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest (IoControlCode,
deviceObject,
InputBuffer, InputBufferSize,
OutputBuffer, OutputBufferSize,
FALSE,
&event,
&ioStatusBlock);
if (irp == NULL)
{
Dump ("IRP allocation failed\n");
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto ret;
}
ntStatus = IoCallDriver (deviceObject, irp);
if (ntStatus == STATUS_PENDING)
{
KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL);
ntStatus = ioStatusBlock.Status;
}
ret:
ObDereferenceObject (fileObject);
return ntStatus;
}
NTSTATUS SendDeviceIoControlRequest (PDEVICE_OBJECT deviceObject, ULONG ioControlCode, void *inputBuffer, int inputBufferSize, void *outputBuffer, int outputBufferSize)
{
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status;
PIRP irp;
KEVENT event;
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
KeInitializeEvent (&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest (ioControlCode, deviceObject, inputBuffer, inputBufferSize,
outputBuffer, outputBufferSize, FALSE, &event, &ioStatusBlock);
if (!irp)
return STATUS_INSUFFICIENT_RESOURCES;
ObReferenceObject (deviceObject);
status = IoCallDriver (deviceObject, irp);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL);
status = ioStatusBlock.Status;
}
ObDereferenceObject (deviceObject);
return status;
}
NTSTATUS ProbeRealDriveSize (PDEVICE_OBJECT driveDeviceObject, LARGE_INTEGER *driveSize)
{
NTSTATUS status;
LARGE_INTEGER sysLength;
LARGE_INTEGER offset;
byte *sectorBuffer = TCalloc (SECTOR_SIZE);
ULONGLONG startTime;
if (!sectorBuffer)
return STATUS_INSUFFICIENT_RESOURCES;
status = SendDeviceIoControlRequest (driveDeviceObject, IOCTL_DISK_GET_LENGTH_INFO,
NULL, 0, &sysLength, sizeof (sysLength));
if (!NT_SUCCESS (status))
{
Dump ("Failed to get drive size - error %x\n", status);
TCfree (sectorBuffer);
return status;
}
startTime = KeQueryInterruptTime ();
for (offset.QuadPart = sysLength.QuadPart; ; offset.QuadPart += SECTOR_SIZE)
{
status = TCReadDevice (driveDeviceObject, sectorBuffer, offset, SECTOR_SIZE);
if (!NT_SUCCESS (status))
{
driveSize->QuadPart = offset.QuadPart;
Dump ("Real drive size = %I64d\n", driveSize->QuadPart);
TCfree (sectorBuffer);
return STATUS_SUCCESS;
}
if (KeQueryInterruptTime() - startTime > 3ULL * 60 * 1000 * 1000 * 10)
{
// Abort if probing for more than 3 minutes
driveSize->QuadPart = sysLength.QuadPart;
TCfree (sectorBuffer);
return STATUS_TIMEOUT;
}
}
}
// Opens a mounted TC volume on filesystem level
NTSTATUS
TCOpenFsVolume (PEXTENSION Extension, PHANDLE volumeHandle, PFILE_OBJECT * fileObject)
{
NTSTATUS ntStatus;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING fullFileName;
IO_STATUS_BLOCK ioStatus;
WCHAR volumeName[TC_MAX_PATH];
TCGetDosNameFromNumber (volumeName, Extension->nDosDriveNo);
RtlInitUnicodeString (&fullFileName, volumeName);
InitializeObjectAttributes (&objectAttributes, &fullFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
ntStatus = ZwCreateFile (volumeHandle,
SYNCHRONIZE | GENERIC_READ,
&objectAttributes,
&ioStatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
Dump ("Volume %ls open NTSTATUS 0x%08x\n", volumeName, ntStatus);
if (!NT_SUCCESS (ntStatus))
return ntStatus;
ntStatus = ObReferenceObjectByHandle (*volumeHandle,
FILE_READ_DATA,
NULL,
KernelMode,
fileObject,
NULL);
Dump ("ObReferenceObjectByHandle NTSTATUS 0x%08x\n", ntStatus);
if (!NT_SUCCESS (ntStatus))
{
ZwClose(*volumeHandle);
return ntStatus;
}
return ntStatus;
}
void
TCCloseFsVolume (HANDLE volumeHandle, PFILE_OBJECT fileObject)
{
ObDereferenceObject (fileObject);
ZwClose (volumeHandle);
}
static NTSTATUS TCReadWriteDevice (BOOL write, PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length)
{
NTSTATUS status;
IO_STATUS_BLOCK ioStatusBlock;
PIRP irp;
KEVENT completionEvent;
ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
KeInitializeEvent (&completionEvent, NotificationEvent, FALSE);
irp = IoBuildSynchronousFsdRequest (write ? IRP_MJ_WRITE : IRP_MJ_READ, deviceObject, buffer, length, &offset, &completionEvent, &ioStatusBlock);
if (!irp)
return STATUS_INSUFFICIENT_RESOURCES;
ObReferenceObject (deviceObject);
status = IoCallDriver (deviceObject, irp);
if (status == STATUS_PENDING)
{
status = KeWaitForSingleObject (&completionEvent, Executive, KernelMode, FALSE, NULL);
if (NT_SUCCESS (status))
status = ioStatusBlock.Status;
}
ObDereferenceObject (deviceObject);
return status;
}
NTSTATUS TCReadDevice (PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length)
{
return TCReadWriteDevice (FALSE, deviceObject, buffer, offset, length);
}
NTSTATUS TCWriteDevice (PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length)
{
return TCReadWriteDevice (TRUE, deviceObject, buffer, offset, length);
}
NTSTATUS
TCFsctlCall (PFILE_OBJECT fileObject, LONG IoControlCode,
void *InputBuffer, int InputBufferSize, void *OutputBuffer, int OutputBufferSize)
{
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS ntStatus;
PIRP irp;
KEVENT event;
PIO_STACK_LOCATION stack;
PDEVICE_OBJECT deviceObject = IoGetRelatedDeviceObject (fileObject);
Dump ("IoGetRelatedDeviceObject = 0x%08x\n", deviceObject);
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest (IoControlCode,
deviceObject,
InputBuffer, InputBufferSize,
OutputBuffer, OutputBufferSize,
FALSE,
&event,
&ioStatusBlock);
if (irp == NULL)
{
Dump ("IRP allocation failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
stack = IoGetNextIrpStackLocation(irp);
stack->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
stack->MinorFunction = IRP_MN_USER_FS_REQUEST;
stack->FileObject = fileObject;
ntStatus = IoCallDriver (deviceObject, irp);
if (ntStatus == STATUS_PENDING)
{
KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL);
ntStatus = ioStatusBlock.Status;
}
return ntStatus;
}
NTSTATUS
CreateDriveLink (int nDosDriveNo)
{
WCHAR dev[256], link[256];
UNICODE_STRING deviceName, symLink;
NTSTATUS ntStatus;
TCGetNTNameFromNumber (dev, nDosDriveNo);
TCGetDosNameFromNumber (link, nDosDriveNo);
RtlInitUnicodeString (&deviceName, dev);
RtlInitUnicodeString (&symLink, link);
ntStatus = IoCreateSymbolicLink (&symLink, &deviceName);
Dump ("IoCreateSymbolicLink returned %X\n", ntStatus);
return ntStatus;
}
NTSTATUS
RemoveDriveLink (int nDosDriveNo)
{
WCHAR link[256];
UNICODE_STRING symLink;
NTSTATUS ntStatus;
TCGetDosNameFromNumber (link, nDosDriveNo);
RtlInitUnicodeString (&symLink, link);
ntStatus = IoDeleteSymbolicLink (&symLink);
Dump ("IoDeleteSymbolicLink returned %X\n", ntStatus);
return ntStatus;
}
NTSTATUS
MountManagerMount (MOUNT_STRUCT *mount)
{
NTSTATUS ntStatus;
WCHAR arrVolume[256];
char buf[200];
PMOUNTMGR_TARGET_NAME in = (PMOUNTMGR_TARGET_NAME) buf;
PMOUNTMGR_CREATE_POINT_INPUT point = (PMOUNTMGR_CREATE_POINT_INPUT) buf;
UNICODE_STRING symName, devName;
TCGetNTNameFromNumber (arrVolume, mount->nDosDriveNo);
in->DeviceNameLength = (USHORT) wcslen (arrVolume) * 2;
wcscpy(in->DeviceName, arrVolume);
ntStatus = TCDeviceIoControl (MOUNTMGR_DEVICE_NAME, IOCTL_MOUNTMGR_VOLUME_ARRI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -