freeotfehashdriver.c
来自「文件驱动加密,功能强大,可产生加密分区,支持AES,MD2,MD4,MD5MD2」· C语言 代码 · 共 1,396 行 · 第 1/4 页
C
1,396 行
{
DEBUGOUTHASHDRV(DEBUGLEV_ERROR, ("outBuffer size wrong size (expect min: %d; got: %d)\n",
sizeof(DIOC_HASH_DATA_OUT)-sizeof(DIOCBufferOut->Hash),
irpSp->Parameters.DeviceIoControl.OutputBufferLength
));
status = STATUS_INVALID_BUFFER_SIZE;
return status;
}
// Request valid so far, process...
// We have to allocate a buffer to hold the output, before it can be copied
// out to the output buffer; otherwise, the input buffer gets garbled as
// data is written to the output buffer
// Match the user's buffer; if it's too small, the operation will kick
// it out
// This calculates the size of the variable part of the struct
// Yes, this should be correct: The total size of the user's output buffer,
// less the size of the struct - but then plus the size of
// the variable parts reserved within the buffer
userBufferSizeBytes = (irpSp->Parameters.DeviceIoControl.OutputBufferLength) -
sizeof(DIOCBufferOut) +
sizeof(DIOCBufferOut->Hash);
tmpOutput = ExAllocatePool(
NonPagedPool,
userBufferSizeBytes
);
// The size of the buffer in bits; the algorithm will read this value, then
// overwrite it with the actual size of the output (in bits)
tmpLengthBits = (userBufferSizeBytes * 8);
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("Input buffer length is: %d bits\n", DIOCBufferIn->DataLength));
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("Allocated output buffer for: %d bits\n", tmpLengthBits));
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("About to process...\n"));
status = ImpHashHashData(
&DIOCBufferIn->HashGUID,
DIOCBufferIn->DataLength, // In bits
(char*)&DIOCBufferIn->Data,
&tmpLengthBits, // In bits
(char*)tmpOutput
);
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("Done with status: %d (want status: %d)\n", status, STATUS_SUCCESS));
if (NT_SUCCESS(status))
{
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("tmp buffer was: %d bits, output was %d bits\n", (userBufferSizeBytes * 8), tmpLengthBits));
// Actual check...
// Ensure output DIOC butter is large enough to store the output
// Note that we can't carry out this check until we've created the
// output value, in case the algorithm used produces variable length
// output
if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(DIOC_HASH_DATA_OUT)+(tmpLengthBits/8)-sizeof(DIOCBufferOut->Hash))
{
DEBUGOUTHASHDRV(DEBUGLEV_ERROR, ("outBuffer size wrong size (expect actual: %d; got: %d)\n",
sizeof(DIOC_HASH_DATA_OUT)+(tmpLengthBits/8)-sizeof(DIOCBufferOut->Hash),
irpSp->Parameters.DeviceIoControl.OutputBufferLength
));
status = STATUS_INVALID_BUFFER_SIZE;
}
else
{
RtlCopyMemory(&DIOCBufferOut->Hash, tmpOutput, (tmpLengthBits / 8));
DIOCBufferOut->HashLength = tmpLengthBits;
Irp->IoStatus.Information = sizeof(DIOC_HASH_DATA_OUT)+(tmpLengthBits/8)-sizeof(DIOCBufferOut->Hash);
}
}
else
{
DEBUGOUTHASHDRV(DEBUGLEV_ERROR, ("FAILED"));
}
SecZeroMemory(tmpOutput, userBufferSizeBytes);
ExFreePool(tmpOutput);
DEBUGOUTHASHDRV(DEBUGLEV_EXIT, ("IOCTL_FreeOTFEHashIOCTL_Hash\n"));
return status;
}
// =========================================================================
// Create the main device object; the one which user code will normally
// talk to when creating new devices, carrying out general driver
// queries, etc
// DeviceObject will be set to the newly created device object
NTSTATUS
CreateDevice (
IN PDRIVER_OBJECT DriverObject,
OUT PDEVICE_OBJECT *DeviceObject
)
{
NTSTATUS status;
UNICODE_STRING devName;
PDEVICE_EXTENSION devExtension;
HANDLE threadHandle;
PDEVICE_OBJECT devObj;
ANSI_STRING tmpANSIName;
GUID driverGUID;
HASH_DRIVER_INFO tmpDevExt;
DEBUGOUTHASHDRV(DEBUGLEV_ENTER, ("CreateDevice\n"));
ASSERT(DriverObject != NULL);
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("Building device name...\n"));
// We subtrace a sizeof(WCHAR) to discount the #NULL - required
// since although the UNICODE_STRING string doesn't require it, swprintf
// adds one on anyway
// This is a bit of a hack to get the driver's GUID
ImpHashDriverExtDetailsInit(&tmpDevExt);
driverGUID = tmpDevExt.DriverGUID;
ImpHashDriverExtDetailsCleardown(&tmpDevExt);
devName.MaximumLength = sizeof(DEVICE_HASH_DIR_NAME)
// ^^ dir name
+ sizeof(WCHAR)
// ^^ slash
+ GUID_STRING_REP_UNICODE_BYTE_LENGTH
// ^^ GUID length
+ sizeof(WCHAR);
// ^^ terminating NULL
devName.Buffer = ExAllocatePool(
NonPagedPool,
devName.MaximumLength
);
RtlZeroMemory(devName.Buffer, devName.MaximumLength);
// Note the "/" in the format string
devName.Length = (USHORT)swprintf(devName.Buffer, L"%s\\", DEVICE_HASH_DIR_NAME);
// swprintf returns the number of WCHARs, not the length in bytes
devName.Length = devName.Length * sizeof(WCHAR);
status = AppendGUIDToUnicodeString(driverGUID, &devName);
if (!NT_SUCCESS(status))
{
DEBUGOUTHASHDRV(DEBUGLEV_ERROR, ("AppendGUIDToUnicodeString NOT OK\n"));
return status;
}
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("xdevNameLength: %d\n",
devName.Length));
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("xdevNameMaximumLength: %d\n",
devName.MaximumLength));
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("About to create device: %ls\n", devName.Buffer));
// Hmmm... I'd prefer to use FILE_DEVICE_UNKNOWN, but since
// IOCTL control codes pass through the device type, and we just
// pass then through...
// (See other call to IoCreateDevice in this file for details why we don't
// use FILE_DEVICE_VIRTUAL_DISK)
status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),
&devName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&devObj
);
if (!NT_SUCCESS(status))
{
DEBUGOUTHASHDRV(DEBUGLEV_ERROR, ("Status NOT OK\n"));
return status;
}
devExtension = (PDEVICE_EXTENSION)devObj->DeviceExtension;
devExtension->zzDeviceName = devName;
devExtension->ThreadObject = NULL;
devExtension->zzSymbolicLinkName.Buffer = NULL;
status = ImpHashDriverExtDetailsInit(&(devExtension->DriverInfo));
if (!NT_SUCCESS(status))
{
DEBUGOUTHASHDRV(DEBUGLEV_ERROR, ("Failed to ImpHashDriverExtDetailsInit.\n"));
DestroyDevice(devObj);
return status;
}
// Create symlink; his allows user applications to CreateFile with
// "SymbolicName"
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("Building symlink name...\n"));
// We add on sizeof(WCHAR) to include the terminating #NULL - required
// since although the UNICODE_STRING string doesn't require it, swprintf
// adds one on anyway
devExtension->zzSymbolicLinkName.MaximumLength = sizeof(DEVICE_HASH_SYMLINK_PREFIX)
// ^^ dir name
+ sizeof(WCHAR)
// ^^ slash
+ GUID_STRING_REP_UNICODE_BYTE_LENGTH
// ^^ GUID length
+ sizeof(WCHAR);
// ^^ terminating NULL
devExtension->zzSymbolicLinkName.Buffer = ExAllocatePool(
NonPagedPool,
devExtension->zzSymbolicLinkName.MaximumLength
);
RtlZeroMemory(devExtension->zzSymbolicLinkName.Buffer, devExtension->zzSymbolicLinkName.MaximumLength);
devExtension->zzSymbolicLinkName.Length = (USHORT)swprintf(
devExtension->zzSymbolicLinkName.Buffer,
L"%s",
DEVICE_HASH_SYMLINK_PREFIX
);
// swprintf returns the number of WCHARs, not the length in bytes
devExtension->zzSymbolicLinkName.Length = devExtension->zzSymbolicLinkName.Length * sizeof(WCHAR);
status = AppendGUIDToUnicodeString(driverGUID, &devExtension->zzSymbolicLinkName);
if (!NT_SUCCESS(status))
{
DEBUGOUTHASHDRV(DEBUGLEV_ERROR, ("AppendGUIDToUnicodeString NOT OK\n"));
DestroyDevice(devObj);
return status;
}
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("Unicoded symlink name: %ls\n",
devExtension->zzSymbolicLinkName.Buffer));
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("Length: %d\n",
devExtension->zzSymbolicLinkName.Length));
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("MaximumLength: %d\n",
devExtension->zzSymbolicLinkName.MaximumLength));
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("About to create dosdevice symlink: %ls -> %ls\n", devExtension->zzSymbolicLinkName.Buffer, devExtension->zzDeviceName.Buffer));
status = IoCreateSymbolicLink(&devExtension->zzSymbolicLinkName, &devExtension->zzDeviceName);
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("Done, checking status...\n"));
if (!NT_SUCCESS(status))
{
DEBUGOUTHASHDRV(DEBUGLEV_ERROR, ("Status NOT OK\n"));
DestroyDevice(devObj);
return status;
}
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("OK\n"));
devObj->Flags |= DO_DIRECT_IO;
devObj->Characteristics |= FILE_READ_ONLY_DEVICE;
// (Some of the bits following are taken from the DDK src/general/cancel example)
// This is used to serailize access to the queue.
KeInitializeSpinLock(&devExtension->IRPQueueLock);
KeInitializeSemaphore(&devExtension->IRPQueueSemaphore, 0, MAXLONG );
// Initialize the pending Irp devicequeue
InitializeListHead(&devExtension->PendingIRPQueue);
// Initialize the cancel safe queue
IoCsqInitialize(&devExtension->CancelSafeQueue,
CSQInsertIrp,
CSQRemoveIrp,
CSQPeekNextIrp,
CSQAcquireLock,
CSQReleaseLock,
CSQCompleteCanceledIrp);
// Create a thread for the device object
devExtension->TerminateThread = FALSE;
status = PsCreateSystemThread(
&threadHandle,
(ACCESS_MASK)0,
NULL,
(HANDLE)0L, // )0L because it's a
// driver-created thread
NULL,
FreeOTFEThread,
devObj
);
if (!NT_SUCCESS(status))
{
DEBUGOUTHASHDRV(DEBUGLEV_ERROR, ("Create thread FAILED.\n"));
DestroyDevice(devObj);
return status;
}
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("OK\n"));
// Convert the Thread object handle into a pointer to the Thread object
// itself. Then close the handle.
status = ObReferenceObjectByHandle(
threadHandle,
THREAD_ALL_ACCESS,
NULL,
KernelMode,
&devExtension->ThreadObject,
NULL
);
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("Done processing thread; checking status.\n"));
if (!NT_SUCCESS(status))
{
DEBUGOUTHASHDRV(DEBUGLEV_ERROR, ("Status FAILED.\n"));
ZwClose(threadHandle);
DestroyDevice(devObj);
return status;
}
DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("OK\n"));
// Close the thread handle
ZwClose(threadHandle);
// This is an easy thing to overlook - we do *not* have to unset the
// device's DO_DEVICE_INITIALIZING "Flags" as this function is carried out
// undef DriverEntry, and not something like AddDevice
*DeviceObject = devObj;
DEBUGOUTHASHDRV(DEBUGLEV_EXIT, ("CreateDevice\n"));
return STATUS_SUCCESS;
}
// =========================================================================
// Cancel all IRPs currently on the queue
void
CancelAllQueuedIRPs(
IN PDEVICE_OBJECT DeviceObject
)
{
PIRP pendingIrp;
PDEVICE_EXTENSION devExt;
DEBUGOUTMAINDRV(DEBUGLEV_ENTER, ("CancelAllQueuedIRPs\n"));
devExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
// We only check one member of the struct; this will tell us if the CancelSafeQueue has
// been initialised or not
if (devExt->CancelSafeQueue.CsqRemoveIrp != NULL)
{
DEBUGOUTMAINDRV(DEBUGLEV_INFO, ("Cancelling all queued IRPs.\n"));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?