📄 ntdriver.c
字号:
NTSTATUS ntStatus;
Dump ("TCDeleteDeviceObject BEGIN\n");
if (Extension->bRootDevice == TRUE)
{
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)
TCStopThread (DeviceObject, Extension);
}
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);
}
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");
return STATUS_INSUFFICIENT_RESOURCES;
}
ntStatus = IoCallDriver (deviceObject, irp);
if (ntStatus == STATUS_PENDING)
{
KeWaitForSingleObject (&event, UserRequest, UserMode, FALSE, NULL);
ntStatus = ioStatusBlock.Status;
}
return ntStatus;
}
// 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[64];
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);
}
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;
Dump("TCFsctlCall IoCallDriver\n");
ntStatus = IoCallDriver (deviceObject, irp);
if (ntStatus == STATUS_PENDING)
{
KeWaitForSingleObject (&event, UserRequest, UserMode, FALSE, NULL);
ntStatus = ioStatusBlock.Status;
}
return ntStatus;
}
NTSTATUS
CreateDriveLink (int nDosDriveNo)
{
WCHAR dev[64], link[64];
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[64];
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[64];
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_ARRIVAL_NOTIFICATION,
in, sizeof (in->DeviceNameLength) + wcslen (arrVolume) * 2, 0, 0);
memset (buf, 0, sizeof buf);
TCGetDosNameFromNumber ((PWSTR) &point[1], mount->nDosDriveNo);
point->SymbolicLinkNameOffset = sizeof (MOUNTMGR_CREATE_POINT_INPUT);
point->SymbolicLinkNameLength = (USHORT) wcslen ((PWSTR) &point[1]) * 2;
RtlInitUnicodeString(&symName, (PWSTR) (buf + point->SymbolicLinkNameOffset));
point->DeviceNameOffset = point->SymbolicLinkNameOffset + point->SymbolicLinkNameLength;
TCGetNTNameFromNumber ((PWSTR) (buf + point->DeviceNameOffset), mount->nDosDriveNo);
point->DeviceNameLength = (USHORT) wcslen ((PWSTR) (buf + point->DeviceNameOffset)) * 2;
RtlInitUnicodeString(&devName, (PWSTR) (buf + point->DeviceNameOffset));
ntStatus = TCDeviceIoControl (MOUNTMGR_DEVICE_NAME, IOCTL_MOUNTMGR_CREATE_POINT, point,
point->DeviceNameOffset + point->DeviceNameLength, 0, 0);
return ntStatus;
}
NTSTATUS
MountManagerUnmount (int nDosDriveNo)
{
NTSTATUS ntStatus;
WCHAR drive[] = {(WCHAR) nDosDriveNo + 'A', 0};
char buf[64], out[300];
PMOUNTMGR_MOUNT_POINT in = (PMOUNTMGR_MOUNT_POINT) buf;
memset (buf, 0, sizeof buf);
TCGetDosNameFromNumber ((PWSTR) &in[1], nDosDriveNo);
in->SymbolicLinkNameOffset = sizeof (MOUNTMGR_MOUNT_POINT);
in->SymbolicLinkNameLength = (USHORT) wcslen ((PWCHAR) &in[1]) * 2;
ntStatus = TCDeviceIoControl (MOUNTMGR_DEVICE_NAME, IOCTL_MOUNTMGR_DELETE_POINTS,
in, sizeof(MOUNTMGR_MOUNT_POINT) + in->SymbolicLinkNameLength, out, sizeof out);
Dump ("IOCTL_MOUNTMGR_DELETE_POINTS returned 0x%08x\n", ntStatus);
return ntStatus;
}
NTSTATUS
MountDevice (PDEVICE_OBJECT DeviceObject, MOUNT_STRUCT *mount)
{
PDEVICE_OBJECT NewDeviceObject;
NTSTATUS ntStatus;
/* Make sure the user is asking for a resonable
nDosDriveNo */
if (mount->nDosDriveNo >= 0 && mount->nDosDriveNo <= 25)
{
Dump ("Mount request looks valid\n");
}
else
{
Dump ("WARNING: MOUNT DRIVE LETTER INVALID\n");
return ERR_BAD_DRIVE_LETTER;
}
ntStatus = TCCreateDeviceObject (DeviceObject->DriverObject, &NewDeviceObject,
mount);
if (!NT_SUCCESS (ntStatus))
{
Dump ("Mount CREATE DEVICE ERROR, ntStatus = 0x%08x\n", ntStatus);
return ntStatus;
}
else
{
PEXTENSION NewExtension = (PEXTENSION) NewDeviceObject->DeviceExtension;
ntStatus = TCStartThread (NewDeviceObject, NewExtension, mount);
if (!NT_SUCCESS (ntStatus))
{
Dump ("Mount FAILURE NT ERROR, ntStatus = 0x%08x\n", ntStatus);
TCDeleteDeviceObject (NewDeviceObject, NewExtension);
return ntStatus;
}
else
{
if (mount->nReturnCode == 0)
{
Dump ("Mount SUCCESS TC code = 0x%08x READ-ONLY = %d\n", mount->nReturnCode,
NewExtension->bReadOnly);
if (NewExtension->bReadOnly == TRUE)
NewDeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE;
NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
if (mount->bMountManager)
MountManagerMount (mount);
NewExtension->bMountManager = mount->bMountManager;
// We create symbolic link even if mount manager is notified of
// arriving volume as it apparently sometimes fails to create the link
CreateDriveLink (mount->nDosDriveNo);
}
else
{
Dump ("Mount FAILURE TC code = 0x%08x\n", mount->nReturnCode);
TCDeleteDeviceObject (NewDeviceObject, NewExtension);
}
return STATUS_SUCCESS;
}
}
}
NTSTATUS
UnmountDevice (PDEVICE_OBJECT deviceObject, BOOL ignoreOpenFiles)
{
PEXTENSION extension = deviceObject->DeviceExtension;
NTSTATUS ntStatus;
HANDLE volumeHandle;
PFILE_OBJECT volumeFileObject;
ntStatus = TCOpenFsVolume (extension, &volumeHandle, &volumeFileObject);
if (!NT_SUCCESS (ntStatus))
{
// User may have deleted symbolic link
CreateDriveLink (extension->nDosDriveNo);
ntStatus = TCOpenFsVolume (extension, &volumeHandle, &volumeFileObject);
if (!NT_SUCCESS (ntStatus))
return ntStatus;
}
// Lock volume
ntStatus = TCFsctlCall (volumeFileObject, FSCTL_LOCK_VOLUME, 0, 0, 0, 0);
Dump ("FSCTL_LOCK_VOLUME returned %X\n", ntStatus);
if (!NT_SUCCESS (ntStatus) && !ignoreOpenFiles)
{
TCCloseFsVolume (volumeHandle, volumeFileObject);
return ERR_FILES_OPEN;
}
// Dismount volume
ntStatus = TCFsctlCall (volumeFileObject, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0);
Dump ("FSCTL_DISMOUNT_VOLUME returned %X\n", ntStatus);
extension->bShuttingDown = TRUE;
if (deviceObject->Vpb && deviceObject->Vpb->Flags & VPB_MOUNTED)
{
deviceObject->Flags |= DO_VERIFY_VOLUME;
}
if (extension->bMountManager)
MountManagerUnmount (extension->nDosDriveNo);
// We always remove symbolic link as mount manager might fail to do so
RemoveDriveLink (extension->nDosDriveNo);
TCCloseFsVolume (volumeHandle, volumeFileObject);
Dump ("Deleting DeviceObject with ref count %ld\n", deviceObject->ReferenceCount);
deviceObject->ReferenceCount = 0;
TCDeleteDeviceObject (deviceObject, (PEXTENSION) deviceObject->DeviceExtension);
return 0;
}
NTSTATUS
UnmountAllDevices (PDEVICE_OBJECT DeviceObject, BOOL ignoreOpenFiles)
{
NTSTATUS status = 0;
PDEVICE_OBJECT ListDevice;
Dump ("Unmounting all volumes\n");
DriverMutexWait ();
for (ListDevice = DeviceObject->DriverObject->DeviceObject;
ListDevice != (PDEVICE_OBJECT) NULL;
ListDevice = ListDevice->NextDevice)
{
PEXTENSION ListExtension = (PEXTENSION) ListDevice->DeviceExtension;
if (ListExtension->bRootDevice == FALSE && !ListExtension->bShuttingDown)
{
NTSTATUS ntStatus = UnmountDevice (ListDevice, ignoreOpenFiles);
status = ntStatus == 0 ? status : ntStatus;
}
}
DriverMutexRelease ();
return status;
}
// Resolves symbolic link name to its target name
NTSTATUS
SymbolicLinkToTarget (PWSTR symlinkName, PWSTR targetName, USHORT maxTargetNameLength)
{
NTSTATUS ntStatus;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING fullFileName;
HANDLE handle;
RtlInitUnicodeString (&fullFileName, symlinkName);
InitializeObjectAttributes (&objectAttributes, &fullFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
ntStatus = ZwOpenSymbolicLinkObject (&handle, GENERIC_READ, &objectAttributes);
if (NT_SUCCESS (ntStatus))
{
UNICODE_STRING target;
target.Buffer = targetName;
target.Length = 0;
target.MaximumLength = maxTargetNameLength;
memset (targetName, 0, maxTargetNameLength);
ntStatus = ZwQuerySymbolicLinkObject (handle, &target, NULL);
ZwClose (handle);
}
return ntStatus;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -