第二章 驱动入口DriverEntry概述

来源:互联网 发布:卡盟主站域名填大全 编辑:程序博客网 时间:2024/05/19 02:03

操作系统在初始化驱动程序的时候会调用DriverEntry,通常会用这个函数来填充dispatch例程的指针,这就象注册回调函数一样。有的设备要创建设备的对象,或者还要创建一个设备名字,以及其他的初始化操作。它的原型:

NTSTATUS DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    ){
}

IN,OUT,INOUT是一个空的宏,只是用来说明这个参数是用于输入参数,还是输出的参数。NTSTATUS实际是个长整型可以在DDK头文件NTSTATUS.H中找到NTSTATUS的代码列表。函数的第一个参数DriverObject是刚被初始化的驱动对象,就是操作系统为这个驱动分配的空间的指针。函数的第二个参数RegistryPath是驱动在注册表中的键值。如果驱动程序需要访问设备的服务键需要保存这个键值以备后用。

本章使用的例子驱动是DDK自带的ioctrl代码。代码位于src\general\ioctl\sys。

NTSTATUS
DriverEntry(
    IN OUT PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    )
/*++

Routine Description:
    This routine is called by the Operating System to initialize the driver.

    It creates the device object, fills in the dispatch entry points and
    completes the initialization.

Arguments:
    DriverObject - a pointer to the object that represents this device
    driver.

    RegistryPath - a pointer to our Services key in the registry.

Return Value:
    STATUS_SUCCESS if initialized; an error otherwise.

--*/


{
    NTSTATUS ntStatus;
    UNICODE_STRING ntUnicodeString; // NT Device Name "\Device\SIOCTL"

    UNICODE_STRING ntWin32NameString; // Win32 Name "\DosDevices\IoctlTest"

    PDEVICE_OBJECT deviceObject = NULL; // ptr to device object



    RtlInitUnicodeString( &ntUnicodeString, NT_DEVICE_NAME );
    
    ntStatus = IoCreateDevice(
        DriverObject, // Our Driver Object

        0, // We don't use a device extension

        &ntUnicodeString,// Device name "\Device\SIOCTL"

        FILE_DEVICE_UNKNOWN, // Device type

        FILE_DEVICE_SECURE_OPEN, // Device characteristics

        FALSE,// Not an exclusive device

        &deviceObject ); // Returned ptr to Device Object


    if ( !NT_SUCCESS( ntStatus ) )
    {
        SIOCTL_KDPRINT(("Couldn't create the device object\n"));
        return ntStatus;
    }
    
    //

    // Initialize the driver object with this driver's entry points.

    //


    DriverObject->MajorFunction[IRP_MJ_CREATE]= SioctlCreateClose;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]= SioctlCreateClose;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]= SioctlDeviceControl;
    DriverObject->DriverUnload= SioctlUnloadDriver;
   
    //

    // Initialize a Unicode String containing the Win32 name

    // for our device.

    //


    RtlInitUnicodeString( &ntWin32NameString, DOS_DEVICE_NAME );

    //

    // Create a symbolic link between our device name and the Win32 name

    //


    ntStatus = IoCreateSymbolicLink(
                        &ntWin32NameString,&ntUnicodeString );

    if ( !NT_SUCCESS( ntStatus ) )
    {
        //

        // Delete everything that this routine has allocated.

        //

        SIOCTL_KDPRINT(("Couldn't create symbolic link\n"));
        IoDeleteDevice( deviceObject );
    }


    return ntStatus;
}

这是一个非常规范的例子,函数首先构造了设备对象,这里并没有把设备对象扩展来存储驱动特需的东西。NT设备名字是"\Device\SIOCTL"。然后填充了派发函数的指针。然后创建了一个设备名字的符号链接。这样这个设备就是命名了的设备,上层应用可以通过打开这个符号链接,从而获得设备handle来访问这个驱动。这里的符号链接是"\DosDevice\IoctlTest",上层应用要想访问这个设备只需要调用CreateFile就可得到这个设备的句柄。如下代码所示:

//

    // open the device

    //

    
    if((hDevice= CreateFile("\\\\.\\IoctlTest",
            GENERIC_READ | GENERIC_WRITE,
            0,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            NULL))== INVALID_HANDLE_VALUE){
//error to open device

}else{
//good get it,:)

}

 

0 0