wdshm
驱动牛犊
驱动牛犊
  • 注册日期2006-02-21
  • 最后登录2009-04-01
  • 粉丝0
  • 关注0
  • 积分7分
  • 威望32点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
阅读:3961回复:1

为什么我程序里的DeviceIoControl总是返回错误码87?

楼主#
更多 发布于:2008-10-21 20:09
最近开始学习编写驱动,刚输入了一个示例,在DriverMonitor中成功加载并正确产生一个符号链接,但是我用一个exe文件调用驱动时,总是有提示说DeviceIoControl执行出错,错误代码是87,表示传输给此函数的参数有问题,但是我一直不知道是什么参数有问题呢?请各路高手赐教呀。感激!!

/////驱动代码
#include <ntddk.h>


#define DEVICE_HELLO_INDEX 0x860
#define START_HELLOWORLD (ULONG) CTL_CODE(FILE_DEVICE_UNKNOWN, DEVICE_HELLO_INDEX, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define STOP_HELLOWORLD  (ULONG) CTL_CODE(FILE_DEVICE_UNKNOWN, DEVICE_HELLO_INDEX + 1, METHOD_BUFFERED, FILE_ANY_ACCESS)

const WCHAR ntDeviceName[] = L"\\Device\\HelloWorld";
const WCHAR dosDeviceName[] = L"\\DosDevices\\HelloWorld";

NTSTATUS HelloWorldDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp);
VOID HelloWorldUnload(IN PDRIVER_OBJECT DriverObject);

PDEVICE_OBJECT IpDeviceObject = NULL; //全局变量


//驱动入口
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    UNICODE_STRING DeviceNameString;
    UNICODE_STRING DeviceLinkString;

    DbgPrint("Hi,Starting DriverEntry()\n");

    RtlInitUnicodeString(&DeviceNameString, ntDeviceName);
    RtlInitUnicodeString(&DeviceLinkString, dosDeviceName);
    ntStatus = IoCreateDevice(DriverObject, 0, &DeviceNameString, FILE_DEVICE_UNKNOWN, 0, TRUE, &IpDeviceObject);

    if (!NT_SUCCESS(ntStatus))
    {
        DbgPrint("Hi, Error IoCreateDevice()\n");
        return STATUS_UNSUCCESSFUL;
    }
    ntStatus = IoCreateSymbolicLink(&DeviceLinkString, &DeviceNameString);
    if (!NT_SUCCESS(ntStatus))
    {
        DbgPrint("Hi, Error IoCreateDevice()\n");
        return STATUS_UNSUCCESSFUL;
    }

    DriverObject->MajorFunction[IRP_MJ_CREATE] = HelloWorldDispatch;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloWorldDispatch;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HelloWorldDispatch;
    DriverObject->DriverUnload = HelloWorldUnload;

    DbgPrint("Hi, DriverEntry() finished.\n");

    return ntStatus;
}


NTSTATUS HelloWorldDispatch(IN PDEVICE_OBJECT DeviceObjet, IN PIRP pIrp)
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    ULONG IoControlCodes = 0;
    PIO_STACK_LOCATION IrpStack = NULL;

    pIrp->IoStatus.Status = STATUS_SUCCESS;
    pIrp->IoStatus.Information = 0;

    DbgPrint("Hi, starting HelleWorldDispatch()\n");

    IrpStack = IoGetCurrentIrpStackLocation(pIrp);
    switch(IrpStack->MajorFunction)
    {
    case IRP_MJ_CREATE:
        DbgPrint("hi, IRP_MJ_CREATE\n");
        break;
    case IRP_MJ_CLOSE:
        DbgPrint("hi, IRP_MJ_CLOSE\n");
        break;
    case IRP_MJ_DEVICE_CONTROL:
        DbgPrint("hi, IRP_MJ_DEVICE_CONTROL\n");

        switch(IoControlCodes)
        {
        case START_HELLOWORLD:
            DbgPrint("hi, Starting \"Hello World\"\n");
            break;
        case STOP_HELLOWORLD:
            DbgPrint("hi, Stoping \"Hello World\"\n");
            break;
        default:
            pIrp->IoStatus.Status = STATUS_INVALID_PARAMETER;
            break;
        }
        break;
    default:
        break;
    }

    ntStatus = pIrp->IoStatus.Status;
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    return ntStatus;
}


VOID HelloWorldUnload(IN PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING DeviceLinkString;
    PDEVICE_OBJECT DeviceObjectTemp1 = NULL;
    PDEVICE_OBJECT DeviceObjectTemp2 = NULL;

    DbgPrint("hi, Starting HelloWorldUnload()\n");

    RtlInitUnicodeString(&DeviceLinkString, dosDeviceName);
    IoDeleteSymbolicLink(&DeviceLinkString);

    if (DriverObject)
    {
        DeviceObjectTemp1 = DriverObject->DeviceObject;
        while (DeviceObjectTemp1)
        {
            DeviceObjectTemp2 = DeviceObjectTemp1;
            DeviceObjectTemp1 = DeviceObjectTemp1->NextDevice;
            IoDeleteDevice(DeviceObjectTemp2);
        }
    }
}



/////测试代码
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>

#define DEVICE_HELLO_INDEX 0x860
#define START_HELLOWORLD (ULONG) CTL_CODE(FILE_DEVICE_UNKNOWN, DEVICE_HELLO_INDEX, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define STOP_HELLOWORLD  (ULONG) CTL_CODE(FILE_DEVICE_UNKNOWN, DEVICE_HELLO_INDEX + 1, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define erron GetLastError()

#define MY_DEVICE_NAME "\\\\.\\HelloWorld"
#define MY_DEVICE_START "-start"
#define MY_DEVICE_STOP "-stop"


BOOL DriverControl(TCHAR* Maik);
VOID Usage(TCHAR* Parameter);

DWORD BLACK = 0;

int main(int argc, TCHAR* argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        return 0;
    }

    if (strcmp(argv[1], MY_DEVICE_START) == 0
        || strcmp(argv[1], MY_DEVICE_STOP) == 0)
    {
        DriverControl(argv[1]);
    }
    else {
        Usage(argv[0]);
        return 0;
    }
    return 0;
}


BOOL DriverControl(TCHAR * Maik)
{
    HANDLE hDevice = NULL;
    DWORD RetBytes = 0;

    hDevice = CreateFile(MY_DEVICE_NAME,
                        GENERIC_READ | GENERIC_WRITE,
                        0,
                        NULL,
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL);
    if (hDevice == INVALID_HANDLE_VALUE)
    {
        printf("CreteFile() GetLastError reports %d\n", erron);

        return FALSE;
    }

    if (strcmpi(Maik, MY_DEVICE_START) == 0)
    {
        if (FALSE == (DeviceIoControl(hDevice, START_HELLOWORLD, &BLACK, sizeof(BLACK), NULL, 0, &RetBytes, NULL)))
        {
            printf("DeviceIoControl() GetLastError reports %d\n", erron);
            CloseHandle(hDevice);
            return FALSE;
        }
        else {
            printf("start success!\n");
        }
    }
    if (strcmpi(Maik, MY_DEVICE_STOP) == 0)
    {
        if (!(DeviceIoControl(hDevice, STOP_HELLOWORLD, &BLACK, sizeof(BLACK), NULL, 0, &RetBytes, NULL)))
        {
            printf("DeviceIoControl() GetLastError reports %d\n", erron);
            CloseHandle(hDevice);
            return FALSE;
        }
        else {
            printf("stop success!\n");
        }
    }

    if (hDevice)
    {
        CloseHandle(hDevice);
    }

    return TRUE;
}


void Usage(TCHAR* Parameter)
{
    fprintf(stderr,
        "===============================================\n \
        %s -start\t启动\n \
        %s -stop \t停止\n \
        ===============================================\n",
        Parameter,
        Parameter);
}


fracker
驱动太牛
驱动太牛
  • 注册日期2001-06-28
  • 最后登录2021-03-30
  • 粉丝0
  • 关注0
  • 积分219分
  • 威望81点
  • 贡献值0点
  • 好评度23点
  • 原创分0分
  • 专家分1分
  • 社区居民
沙发#
发布于:2008-10-23 10:11
不返回87才怪,
因为你结束IRP的时候就是返回这个错,
之所以返回这个错,是因为你的IoControlCodes = 0,在switch那个地方永远跳到出错的case,实际上IoControlCode应该从IrpStack 里面取。
好好看看IRP_MJ_DEVICE_CONTROL的说明。
游客

返回顶部