本文是一篇譯文,主要以實例形式講述了C++中DeviceIoCteatol的用法。分享給大家供大家參考。具體方法如下:
應用程序代碼如下:
DWORD dwBytesReturned = 0;  
    BYTE bytBuffer_1[512];  
    BYTE bytBuffer_2[512];  
    CHAR string[2048];  
    HANDLE hDevice, hDriver;  
    BOOL bRet;  
bRet = DeviceIoControl(hDriver, IOCTL_WRITE, (LPVOID)bytBuffer_1, 512,  
                            NULL, 0, &dwBytesReturned, NULL);  
    if(bRet == FALSE)  
    {  
        printf("/nFailed - DeviceIoControl - IOCTL_WRITE./n");  
        return 0;  
    }  
      
    printf("/nWrite MBR using I/O port operations.../n");  
  
    bRet = ReadFile(hDevice, (LPVOID)bytBuffer_1, 512, &dwBytesReturned, NULL);  
  
    if(bRet == FALSE)  
    {  
        printf("/nFailed - ReadFile - the second one./n");  
        return 0;  
    }  
      
    printf("/nRead MBR using the ReadFile function.../n");  
    printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - -");  
  
    sprintf(string, "/n");  
  
    for(DWORD n = 0; n < 512; n++)  
    {  
        sprintf(string, "%s %02X", string, bytBuffer_1[n]);  
  
        if(((n + 1) % 16) == 0)  
            sprintf(string, "%s/n", string);  
  
        if(((n + 1) % 16) == 8)  
            sprintf(string, "%s -", string);  
    }  
  
    printf("%s", string);  
  
    printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - -");  
  
    bRet = DeviceIoControl(hDriver, IOCTL_READ, NULL, 0, (LPVOID)bytBuffer_2, 512,  
                                    &dwBytesReturned, NULL);  
    if(bRet == FALSE)  
    {  
        printf("/nFailed - DeviceIoControl - IOCTL_READ - the second one./n");  
        return 0;  
    }  
  
    printf("/nRead MBR using I/O port operations.../n");  
    printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - -");  
  
    sprintf(string, "/n");  
  
    for(DWORD t = 0; t < 512; t++)  
    {  
        sprintf(string, "%s %02X", string, bytBuffer_2[t]);  
  
        if(((t + 1) % 16) == 0)  
            sprintf(string, "%s/n", string);  
  
        if(((t + 1) % 16) == 8)  
            sprintf(string, "%s -", string);  
    }  
  
    printf("%s", string);  
  
    printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - -");  
  
    printf("/nSucceed - Kill HDDGMon./n");  
    return 1;  
}
驅動代碼如下:
#include <ntddk.h>  
  
#define DEVICE_NAME L"http://Device//KillHDDGMon"  
#define LINK_NAME   L"http://DosDevices//KillHDDGMon"  
  
#define IOCTL_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)  
#define IOCTL_READ  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)  
  
VOID Unload(  
    __in  struct _DRIVER_OBJECT *DriverObject  
    )  
{  
    UNICODE_STRING ustrLinkName;  
  
    DbgPrint("Driver Unload.....");  
  
    RtlInitUnicodeString(&ustrLinkName, LINK_NAME);  
    IoDeleteSymbolicLink(&ustrLinkName);  
  
    IoDeleteDevice(DriverObject->DeviceObject);  
}  
  
NTSTATUS DispatchCreateClose(  
    __inout  struct _DEVICE_OBJECT *DeviceObject,  
    __inout  struct _IRP *Irp  
    )  
{  
    NTSTATUS status = STATUS_SUCCESS;  
    KdPrint(("Dispatch CreateClose..."));  
  
    Irp->IoStatus.Status = status;  
    IoCompleteRequest(Irp, IO_NO_INCREMENT);  
  
    return status;  
}  
  
NTSTATUS DispatchIoctl(  
    __inout  struct _DEVICE_OBJECT *DeviceObject,  
    __inout  struct _IRP *Irp  
    )  
{  
    NTSTATUS status = STATUS_SUCCESS;  
    PIO_STACK_LOCATION pIrpStack;  
    ULONG outSize;  
    ULONG IoControlCode;  
    PVOID pIoBuffer;  
  
    KdPrint(("Dispatch Ioctl..."));  
  
    pIoBuffer = Irp->AssociatedIrp.SystemBuffer;  
    pIrpStack = IoGetCurrentIrpStackLocation(Irp);  
    outSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;  
    IoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;  
  
    switch (IoControlCode)  
    {  
    case IOCTL_WRITE:  
        __asm  
        {  
            push eax  
            push edx  
            //---------------------------------------------------  
            // 以下代碼用I/O端口來寫主引導區  
  
            mov dx,1f6h // 要讀入的磁盤號及磁頭號  
            mov al,0a0h // 磁盤0,磁頭0  
            out dx,al  
  
            mov dx,1f2h // 要寫的扇區數量  
            mov al,1    // 寫一個扇區  
            out dx,al  
  
            mov dx,1f3h // 要寫的扇區號  
            mov al,1    // 寫到1扇區  
            out dx,al  
  
            mov dx,1f4h // 要寫的柱面的低8位  
            mov al,0    // 低8位為0  
            out dx,al  
  
            mov dx,1f5h // 要寫的柱面的高2位  
            mov al,0    // 高2位為0  
            out dx,al  
  
            mov dx,1f7h // 命令端口  
            mov al,30h  // 嘗試著寫扇區  
            out dx,al  
  
still_going_1:  
            in al,dx  
            test al,8   // 如果扇區緩沖沒有準備好的話則跳轉,直到準備好才向下執行  
            jz still_going_1  
  
            pop edx  
            pop eax  
        }  
        WRITE_PORT_BUFFER_USHORT((PUSHORT)0x1f0, (PUSHORT)pIoBuffer, 256);  
        status = STATUS_SUCCESS;  
        break;  
    case IOCTL_READ:  
        if (outSize >= 512)  
        {  
            __asm  
            {  
                push eax  
                push edx  
                //---------------------------------------------------  
                // 以下代碼用I/O端口來讀主引導區  
  
                mov dx,1f6h // 要讀入的磁盤號及磁頭號  
                mov al,0a0h // 磁盤0,磁頭0  
                out dx,al   
  
                mov dx,1f2h // 要讀入的扇區數量  
                mov al,1    // 讀一個扇區  
                out dx,al   
  
                mov dx,1f3h // 要讀的扇區號  
                mov al,1    // 扇區號為1  
                out dx,al   
  
                mov dx,1f4h // 要讀的柱面的低8位  
                mov al,0    // 柱面低8位為0  
                out dx,al   
  
                mov dx,1f5h // 柱面高2位  
                mov al,0    // 柱面高2位為0(通過1F4H和1F5H端口我們可以確定用來讀的柱面號是0)  
                out dx,al   
  
                mov dx,1f7h // 命令端口  
                mov al,20h  // 嘗試讀取扇區  
                out dx,al  
  
                still_going_2:   
                in al,dx    // 扇區緩沖是否準備好  
                test al,8   // 如果扇區緩沖沒有準備好的話則跳轉,直到準備好才向下執行。  
                jz still_going_2      
  
            /*  mov cx,512/2    // 設置循環次數(512/2次) 
                mov di,offset buffer 
                mov dx,1f0h // 將要傳輸的一個字節的數據 
                rep insw    // 傳輸數據     */  
  
                //---------------------------------------------------  
                pop edx  
                pop eax  
            }  
        READ_PORT_BUFFER_USHORT((PUSHORT)0x1f0, (PUSHORT)pIoBuffer, 256);  
        status = STATUS_SUCCESS;  
        }  
        else  
        {  
            Irp->IoStatus.Information = 0;  
            status = STATUS_BUFFER_TOO_SMALL;  
        }  
          
        break;  
    }  
    Irp->IoStatus.Status = status;  
    IoCompleteRequest(Irp, IO_NO_INCREMENT);  
  
    return status;  
}  
  
  
NTSTATUS DriverEntry(  
    __in  struct _DRIVER_OBJECT *DriverObject,  
    __in  PUNICODE_STRING RegistryPath  
    )  
{  
    NTSTATUS status = STATUS_SUCCESS;  
    UNICODE_STRING ustrDevName;  
    UNICODE_STRING ustrLinkName;  
    PDEVICE_OBJECT  pDevObj=NULL;  
  
    DriverObject->DriverUnload = Unload;  
    DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreateClose;  
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCreateClose;  
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;  
  
    RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);  
    status  = IoCreateDevice(DriverObject, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, 0,FALSE, &pDevObj);  
    if (!NT_SUCCESS(status))  
    {  
        return status;  
    }  
    RtlInitUnicodeString(&ustrLinkName, LINK_NAME);  
    status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);  
    if (!NT_SUCCESS(status))  
    {  
        IoDeleteSymbolicLink(&ustrLinkName);  
        return status;  
    }  
  
    return status;  
}
希望本文所述對大家的C++程序設計有所幫助。