📄 ntdriver.c
字号:
/* Setup the device extension */
Extension = (PEXTENSION) (*ppDeviceObject)->DeviceExtension;
memset (Extension, 0, sizeof (EXTENSION));
Extension->IsVolumeDevice = TRUE;
Extension->lMagicNumber = 0xabfeacde;
Extension->nDosDriveNo = mount->nDosDriveNo;
Extension->bRemovable = mount->bMountRemovable;
KeInitializeEvent (&Extension->keCreateEvent, SynchronizationEvent, FALSE);
KeInitializeSemaphore (&Extension->RequestSemaphore, 0L, MAXLONG);
KeInitializeSpinLock (&Extension->ListSpinLock);
InitializeListHead (&Extension->ListEntry);
Dump ("TCCreateDeviceObject STATUS_SUCCESS END\n");
return STATUS_SUCCESS;
}
void DriverMutexWait ()
{
KeWaitForMutexObject (&driverMutex, Executive, KernelMode, FALSE, NULL);
}
void DriverMutexRelease ()
{
KeReleaseMutex (&driverMutex, FALSE);
}
NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp)
{
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
if (!ValidateIOBufferSize (Irp, sizeof (MOUNTDEV_NAME), ValidateOutput))
{
Irp->IoStatus.Information = sizeof (MOUNTDEV_NAME);
Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
}
else
{
ULONG outLength;
UNICODE_STRING ntUnicodeString;
WCHAR ntName[256];
PMOUNTDEV_NAME outputBuffer = (PMOUNTDEV_NAME) Irp->AssociatedIrp.SystemBuffer;
TCGetNTNameFromNumber (ntName, Extension->nDosDriveNo);
RtlInitUnicodeString (&ntUnicodeString, ntName);
outputBuffer->NameLength = ntUnicodeString.Length;
outLength = ntUnicodeString.Length + sizeof(USHORT);
if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < outLength)
{
Irp->IoStatus.Information = sizeof (MOUNTDEV_NAME);
Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
break;
}
RtlCopyMemory ((PCHAR)outputBuffer->Name,ntUnicodeString.Buffer, ntUnicodeString.Length);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = outLength;
Dump ("name = %ls\n",ntName);
}
break;
case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:
if (!ValidateIOBufferSize (Irp, sizeof (MOUNTDEV_UNIQUE_ID), ValidateOutput))
{
Irp->IoStatus.Information = sizeof (MOUNTDEV_UNIQUE_ID);
Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
}
else
{
ULONG outLength;
UCHAR volId[128], tmp[] = { 0,0 };
PMOUNTDEV_UNIQUE_ID outputBuffer = (PMOUNTDEV_UNIQUE_ID) Irp->AssociatedIrp.SystemBuffer;
strcpy (volId, TC_UNIQUE_ID_PREFIX);
tmp[0] = 'A' + Extension->nDosDriveNo;
strcat (volId, tmp);
outputBuffer->UniqueIdLength = (USHORT) strlen (volId);
outLength = strlen (volId) + sizeof(USHORT);
if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < outLength)
{
Irp->IoStatus.Information = sizeof (MOUNTDEV_UNIQUE_ID);
Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
break;
}
RtlCopyMemory ((PCHAR)outputBuffer->UniqueId, volId, strlen (volId));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = outLength;
Dump ("id = %s\n",volId);
}
break;
case IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME:
{
ULONG outLength;
UNICODE_STRING ntUnicodeString;
WCHAR ntName[256];
PMOUNTDEV_SUGGESTED_LINK_NAME outputBuffer = (PMOUNTDEV_SUGGESTED_LINK_NAME) Irp->AssociatedIrp.SystemBuffer;
if (!ValidateIOBufferSize (Irp, sizeof (MOUNTDEV_SUGGESTED_LINK_NAME), ValidateOutput))
{
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
break;
}
TCGetDosNameFromNumber (ntName, Extension->nDosDriveNo);
RtlInitUnicodeString (&ntUnicodeString, ntName);
outLength = FIELD_OFFSET(MOUNTDEV_SUGGESTED_LINK_NAME,Name) + ntUnicodeString.Length;
outputBuffer->UseOnlyIfThereAreNoOtherLinks = FALSE;
outputBuffer->NameLength = ntUnicodeString.Length;
if(irpSp->Parameters.DeviceIoControl.OutputBufferLength < outLength)
{
Irp->IoStatus.Information = sizeof (MOUNTDEV_SUGGESTED_LINK_NAME);
Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
break;
}
RtlCopyMemory ((PCHAR)outputBuffer->Name,ntUnicodeString.Buffer, ntUnicodeString.Length);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = outLength;
Dump ("link = %ls\n",ntName);
}
break;
case IOCTL_DISK_GET_MEDIA_TYPES:
case IOCTL_DISK_GET_DRIVE_GEOMETRY:
/* Return the drive geometry for the disk. Note that we
return values which were made up to suit the disk size. */
if (ValidateIOBufferSize (Irp, sizeof (DISK_GEOMETRY), ValidateOutput))
{
PDISK_GEOMETRY outputBuffer = (PDISK_GEOMETRY)
Irp->AssociatedIrp.SystemBuffer;
outputBuffer->MediaType = Extension->bRemovable ? RemovableMedia : FixedMedia;
outputBuffer->Cylinders.QuadPart = Extension->NumberOfCylinders;
outputBuffer->TracksPerCylinder = Extension->TracksPerCylinder;
outputBuffer->SectorsPerTrack = Extension->SectorsPerTrack;
outputBuffer->BytesPerSector = Extension->BytesPerSector;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof (DISK_GEOMETRY);
}
break;
case IOCTL_DISK_GET_PARTITION_INFO:
if (ValidateIOBufferSize (Irp, sizeof (PARTITION_INFORMATION), ValidateOutput))
{
PPARTITION_INFORMATION outputBuffer = (PPARTITION_INFORMATION)
Irp->AssociatedIrp.SystemBuffer;
outputBuffer->PartitionType = Extension->PartitionType;
outputBuffer->BootIndicator = FALSE;
outputBuffer->RecognizedPartition = TRUE;
outputBuffer->RewritePartition = FALSE;
outputBuffer->StartingOffset.QuadPart = SECTOR_SIZE;
outputBuffer->PartitionLength.QuadPart= Extension->DiskLength;
outputBuffer->HiddenSectors = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof (PARTITION_INFORMATION);
}
break;
case IOCTL_DISK_GET_PARTITION_INFO_EX:
if (ValidateIOBufferSize (Irp, sizeof (PARTITION_INFORMATION_EX), ValidateOutput))
{
PPARTITION_INFORMATION_EX outputBuffer = (PPARTITION_INFORMATION_EX) Irp->AssociatedIrp.SystemBuffer;
outputBuffer->PartitionStyle = PARTITION_STYLE_MBR;
outputBuffer->RewritePartition = FALSE;
outputBuffer->StartingOffset.QuadPart = SECTOR_SIZE;
outputBuffer->PartitionLength.QuadPart= Extension->DiskLength;
outputBuffer->Mbr.PartitionType = Extension->PartitionType;
outputBuffer->Mbr.BootIndicator = FALSE;
outputBuffer->Mbr.RecognizedPartition = TRUE;
outputBuffer->Mbr.HiddenSectors = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof (PARTITION_INFORMATION_EX);
}
break;
case IOCTL_DISK_GET_DRIVE_LAYOUT:
if (ValidateIOBufferSize (Irp, sizeof (DRIVE_LAYOUT_INFORMATION), ValidateOutput))
{
PDRIVE_LAYOUT_INFORMATION outputBuffer = (PDRIVE_LAYOUT_INFORMATION)
Irp->AssociatedIrp.SystemBuffer;
outputBuffer->PartitionCount = 1;
outputBuffer->Signature = 0;
outputBuffer->PartitionEntry->PartitionType = Extension->PartitionType;
outputBuffer->PartitionEntry->BootIndicator = FALSE;
outputBuffer->PartitionEntry->RecognizedPartition = TRUE;
outputBuffer->PartitionEntry->RewritePartition = FALSE;
outputBuffer->PartitionEntry->StartingOffset.QuadPart = SECTOR_SIZE;
outputBuffer->PartitionEntry->PartitionLength.QuadPart = Extension->DiskLength;
outputBuffer->PartitionEntry->HiddenSectors = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof (PARTITION_INFORMATION);
}
break;
case IOCTL_DISK_GET_LENGTH_INFO:
if (!ValidateIOBufferSize (Irp, sizeof (GET_LENGTH_INFORMATION), ValidateOutput))
{
Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
Irp->IoStatus.Information = sizeof (GET_LENGTH_INFORMATION);
}
else
{
PGET_LENGTH_INFORMATION outputBuffer = (PGET_LENGTH_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
outputBuffer->Length.QuadPart = Extension->DiskLength;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof (GET_LENGTH_INFORMATION);
}
break;
case IOCTL_DISK_VERIFY:
if (ValidateIOBufferSize (Irp, sizeof (VERIFY_INFORMATION), ValidateInput))
{
PVERIFY_INFORMATION pVerifyInformation;
pVerifyInformation = (PVERIFY_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
if (pVerifyInformation->StartingOffset.QuadPart + pVerifyInformation->Length > Extension->DiskLength)
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
else
{
IO_STATUS_BLOCK ioStatus;
PVOID buffer = TCalloc (max (pVerifyInformation->Length, PAGE_SIZE));
if (!buffer)
{
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
LARGE_INTEGER offset = pVerifyInformation->StartingOffset;
offset.QuadPart += Extension->cryptoInfo->hiddenVolume ? Extension->cryptoInfo->hiddenVolumeOffset : Extension->cryptoInfo->volDataAreaOffset;
Irp->IoStatus.Status = ZwReadFile (Extension->hDeviceFile, NULL, NULL, NULL, &ioStatus, buffer, pVerifyInformation->Length, &offset, NULL);
TCfree (buffer);
if (NT_SUCCESS (Irp->IoStatus.Status) && ioStatus.Information != pVerifyInformation->Length)
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
}
Irp->IoStatus.Information = 0;
}
break;
case IOCTL_DISK_CHECK_VERIFY:
case IOCTL_STORAGE_CHECK_VERIFY:
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
if (irpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof (ULONG))
{
*((ULONG *) Irp->AssociatedIrp.SystemBuffer) = 0;
Irp->IoStatus.Information = sizeof (ULONG);
}
}
break;
case IOCTL_DISK_IS_WRITABLE:
{
if (Extension->bReadOnly)
Irp->IoStatus.Status = STATUS_MEDIA_WRITE_PROTECTED;
else
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
}
break;
case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:
// Vista's filesystem defragmenter fails if IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS does not succeed.
if (OsMajorVersion < 6)
{
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Information = 0;
}
else if (ValidateIOBufferSize (Irp, sizeof (VOLUME_DISK_EXTENTS), ValidateOutput))
{
VOLUME_DISK_EXTENTS *extents = (VOLUME_DISK_EXTENTS *) Irp->AssociatedIrp.SystemBuffer;
// No extent data can be returned as this is not a physical drive.
memset (extents, 0, sizeof (*extents));
extents->NumberOfDiskExtents = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof (*extents);
}
break;
default:
return TCCompleteIrp (Irp, STATUS_INVALID_DEVICE_REQUEST, 0);
}
#ifdef DEBUG
if (!NT_SUCCESS (Irp->IoStatus.Status))
{
Dump ("IOCTL error 0x%08x (0x%x %d)\n",
Irp->IoStatus.Status,
(int) (irpSp->Parameters.DeviceIoControl.IoControlCode >> 16),
(int) ((irpSp->Parameters.DeviceIoControl.IoControlCode & 0x1FFF) >> 2));
}
#endif
return TCCompleteDiskIrp (Irp, Irp->IoStatus.Status, Irp->IoStatus.Information);
}
NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp)
{
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
NTSTATUS ntStatus;
switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
{
case TC_IOCTL_GET_DRIVER_VERSION:
case TC_IOCTL_LEGACY_GET_DRIVER_VERSION:
if (ValidateIOBufferSize (Irp, sizeof (LONG), ValidateOutput))
{
LONG tmp = VERSION_NUM;
memcpy (Irp->AssociatedIrp.SystemBuffer, &tmp, 4);
Irp->IoStatus.Information = sizeof (LONG);
Irp->IoStatus.Status = STATUS_SUCCESS;
}
break;
case TC_IOCTL_GET_DEVICE_REFCOUNT:
if (ValidateIOBufferSize (Irp, sizeof (int), ValidateOutput))
{
*(int *) Irp->AssociatedIrp.SystemBuffer = DeviceObject->ReferenceCount;
Irp->IoStatus.Information = sizeof (int);
Irp->IoStatus.Status = STATUS_SUCCESS;
}
break;
case TC_IOCTL_WAS_REFERENCED_DEVICE_DELETED:
if (ValidateIOBufferSize (Irp, sizeof (int), ValidateOutput))
{
*(int *) Irp->AssociatedIrp.SystemBuffer = ReferencedDeviceDeleted;
Irp->IoStatus.Information = sizeof (int);
Irp->IoStatus.Status = STATUS_SUCCESS;
}
break;
case TC_IOCTL_IS_ANY_VOLUME_MOUNTED:
if (ValidateIOBufferSize (Irp, sizeof (int), ValidateOutput))
{
PDEVICE_OBJECT ListDevice;
*(int *) Irp->AssociatedIrp.SystemBuffer = 0;
DriverMutexWait ();
for (ListDevice = DeviceObject->DriverObject->DeviceObject;
ListDevice != (PDEVICE_OBJECT) NULL; ListDevice = ListDevice->NextDevice)
{
PEXTENSION ListExtension = (PEXTENSION) ListDevice->DeviceExtension;
if (!ListExtension->bRootDevice
&& ListExtension->IsVolumeDevice
&& ListExtension->lMagicNumber == 0xabfeacde)
{
*(int *) Irp->AssociatedIrp.SystemBuffer = 1;
break;
}
}
DriverMutexRelease ();
if (IsBootDriveMounted())
*(int *) Irp->AssociatedIrp.SystemBuffer = 1;
Irp->IoStatus.Information = sizeof (int);
Irp->IoStatus.Status = STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -