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 + -
显示快捷键?