2013年5月6日星期一

IoRegisterPlugPlayNotification.C

/*
文本就命名为:IoRegisterPlugPlayNotification.C吧!
made by correy
made at 2013.05.05
QQ:112426112
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com

usb的GUID可以用工具或者编程得到。如usbview工程。这个工程也能监控usb的变化。

参考资料:http://www.osronline.com/showthread.cfm?link=172042等。

还有待研究的信息有:
GUID_DEVINTERFACE_DISK,GUID_DEVINTERFACE_VOLUME and/or GUID_DEVINTERFACE_PARTITION
*/

#include <ntddk.h>
#include <initguid.h> //解决:error LNK2001: unresolved external symbol _GUID_XXXXXXXXXXXXXXXXXX
//#include <Ntddstor.h>  //GUID_DEVINTERFACE_VOLUME

#define _In_
#define _Inout_
#define _Inout_opt_

/* A5DCBF10-6530-11D2-901F-00C04FB951ED*/
DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE,0xA5DCBF10L,0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED ); //没有找到usbiodef.h

PVOID NotificationEntry;

DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
    /*
    In Windows 7 and later versions of Windows, this function is obsolete and is provided only to support existing drivers.
    Use the IoUnregisterPlugPlayNotificationEx routine instead.

    Warning  The system does not synchronize between the execution of the notification routine and IoUnregisterPlugPlayNotification.
    Therefore, the routine can be called after the IoUnregisterPlugPlayNotification method has returned.
    If necessary, a driver should implement its own mechanism to ignore any notifications after IoUnregisterPlugPlayNotification has been called.

    IoUnregisterPlugPlayNotification removes one PnP notification registration; that is, the registration of one driver callback routine for one PnP event category.

    Drivers should unregister a notification first, then free any related context buffer.

    A driver cannot be unloaded until it removes all of its PnP notification registrations because there is a reference on its driver object for each active registration.
    */

    NTSTATUS status = 0;

    status = IoUnregisterPlugPlayNotification(NotificationEntry);
    if (!NT_SUCCESS(status))  {
        DbgPrint("IoUnregisterPlugPlayNotification fail!\n");  
    }
}

DRIVER_NOTIFICATION_CALLBACK_ROUTINE driver_notification_callback_routine;
//typedef
NTSTATUS driver_notification_callback_routine(_In_ PVOID NotificationStructure, _Inout_opt_ PVOID Context)
{
    //这里不是插上usb接口就能发现了,必须是连接上,比如我选择手机里面的数据存储,才能发现的。
    //相应的usb的拔出不是简单的硬件的拔出,在手机上点击取消连接,即可以运行到这里。

    //奇怪的是QQ电脑管家没有注册这个回调,可是获取的比这个函数得到的消息还要早。
    //理论是用别的内核办法,难道是用应用层的办法?

    //这里更深层次的操作,请看:http://www.osronline.com/article.cfm?id=24

    DbgPrint("pnp发生了?停下来看看吧!\n");
    KdBreakPoint();

    return STATUS_SUCCESS;
}

DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT  * DriverObject, __in PUNICODE_STRING  RegistryPath)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;

    KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()

    DriverObject->DriverUnload = Unload;    

    status = IoRegisterPlugPlayNotification(
        EventCategoryDeviceInterfaceChange,
        PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,//还有:EventCategoryHardwareProfileChange 和 EventCategoryTargetDeviceChange 。
        (PVOID)&GUID_DEVINTERFACE_USB_DEVICE,//GUID_DEVINTERFACE_VOLUME  GUID_DEVINTERFACE_USB_DEVICE
        DriverObject,//To ensure that the driver remains loaded while it is registered for PnP notification, this call increments the reference count on DriverObject.
                     //The PnP manager decrements the reference count when this registration is removed.要ObDereferenceObject一下?没有用也没有蓝屏。
        driver_notification_callback_routine,
        0,//传递的参数。
        &NotificationEntry);
    if (!NT_SUCCESS(status))  {
        DbgPrint("IoRegisterPlugPlayNotification fail!\n");  
        return status;
    }

    return status;//STATUS_SUCCESS
}

没有评论:

发表评论