huyongtq
驱动牛犊
驱动牛犊
  • 注册日期2009-03-06
  • 最后登录2014-11-30
  • 粉丝0
  • 关注0
  • 积分19分
  • 威望171点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2232回复:2

驱动级模拟鼠标 代码分析

楼主#
更多 发布于:2009-03-24 19:10
小弟不才最近得到一份关于驱动级虚拟鼠标的代码,本想轻松改成自己的作品,
可是真正入手的时候才发现我自己之菜, 代码是C++的源代码,简单分析下他的意思
,他好像是生成SYS文件,源代码结构如下:
function.h, 定义设备名称:

hidmouse.h ,定义鼠标动作,

vhidmou.h,定义一个类,

vmoudev.h

vhidev.cpp
  
vhidmou.cpp:

为了方便看我都文件名列这里了,代码在后面去,)
我现在的问题是,这个sys如何用DELPHI或者VB调用,或者是c也行,请DRIVERDEVELOP各位牛人帮我看看,小弟感激不尽,祝DRIVERDEVELOP越办越好!




function.h,
#define DRIVER_FUNCTION_ADD_DEVICE
#define DRIVER_FUNCTION_UNLOAD
#define DRIVER_FUNCTION_INTERNAL_DEVICE_CONTROL
#define DRIVER_FUNCTION_PNP
#define DRIVER_FUNCTION_POWER
#define DRIVER_FUNCTION_SYSTEM_CONTROL
#define DRIVER_FUNCTION_STARTIO

hidmouse.h
#define IOCTL_VHIDMOU_MOVE \
    CTL_CODE(FILE_DEVICE_MOUSE, 0x801, METHOD_NEITHER, FILE_ANY_ACCESS)

#define IOCTL_VHIDMOU_CLICK \
    CTL_CODE(FILE_DEVICE_MOUSE, 0x802, METHOD_NEITHER, FILE_ANY_ACCESS)
struct MOUSE_MOVE_INFO
{
    ULONG deltaX;
    ULONG deltaY;
};
struct MOUSE_CLICK_INFO
{
    ULONG LeftOrRight;
    ULONG UpOrDown;
};

vhidmou.h,

class VirtualHidMouseDriver : public KHidMiniDriver
{
    SAFE_DESTRUCTORS
    virtual NTSTATUS AddDevice(PDEVICE_OBJECT PnpDeviceObject);
};

vmoudev.h
#define MY_VENDOR_ID    0x0001
#define MY_PRODUCT_ID    0x0002
#define VERSION_NUMBER  0x0101

class VirtualHidMouse : public KHidDevice
{
    SAFE_DESTRUCTORS
public:
    VirtualHidMouse(PDEVICE_OBJECT Fdo);

    virtual NTSTATUS DefaultHidRequestHandler(KIrp I);
    virtual NTSTATUS DefaultPnp(KIrp I);
    virtual NTSTATUS DefaultPower(KIrp I);
    virtual NTSTATUS SystemControl(KIrp I);

    virtual NTSTATUS OnStartDevice(KIrp I);
    virtual NTSTATUS OnStopDevice(KIrp I);
    virtual NTSTATUS OnQueryRemoveDevice(KIrp I);
    virtual NTSTATUS OnQueryStopDevice(KIrp I);
    virtual NTSTATUS OnCancelRemoveDevice(KIrp I);
    virtual NTSTATUS OnCancelStopDevice(KIrp I);
    virtual NTSTATUS OnRemoveDevice(KIrp I);

    virtual VOID StartIo(KIrp I);

    // KHidDevice Overrides

    virtual NTSTATUS ReadReport(KIrp I);

    // Other
    VOID Move(CHAR deltaX, CHAR deltaY);
    VOID Click(ULONG LeftOrRight, ULONG UpOrDown);
    VOID UpdateState(void);

    DEVMEMBER_CANCELIRP (VirtualHidMouse, CancelQueuedIrp)

#ifdef __COMMENT_ONLY
        // The following member functions are actually defined by the
        // a DEVMEMBER_XXX macro (such as DEVMEMBER_DISPATCHERS).
        // The macro __COMMENT_ONLY never gets defined.  These comment-only
        // definitions simply allow easy navigation to the functions within
        // the Developer Studio using the class browser.

    VOID CancelQueuedIrp(KIrp I);                    // COMMENT_ONLY
#endif

    NTSTATUS IsStoppable(void) { return STATUS_SUCCESS; }
    NTSTATUS IsRemovable(void) { return STATUS_SUCCESS; }

    // Data

    CHAR  m_DeltaX;
    CHAR  m_DeltaY;
    UCHAR m_OldButtonState;
    UCHAR m_NewButtonState;

    KSpinLock m_Lock;
//    KVxDInterface m_Vxd;
    KPnpLowerDevice m_Pdo;
};


// Handler for VxD interface
ULONG __stdcall VxdControlMessageHandler(
    ULONG Edi,
    ULONG Esi,
    ULONG Ebp,
    ULONG Esp,
    ULONG Ebx,
    ULONG Edx,
    ULONG Ecx,
    ULONG ControlMessage,
    PVOID Context,
    ULONG* pCarryBitReturn
    );


struct MouseReport
{
    CHAR buttons;
    CHAR deltaX;
    CHAR deltaY;
};

#define LEFT_BUTTON 1
#define RIGHT_BUTTON 2




VHIDMOU.CPP
#define VDW_MAIN

#include <khid.h> // Note: HID minidrivers include this rather than vdw.h
#include "vhidmou.h"    // the device class
#include "vmoudev.h"    // the driver class
#pragma code_seg("INIT")

DECLARE_DRIVER_CLASS(VirtualHidMouseDriver, NULL)

#pragma code_seg()

NTSTATUS VirtualHidMouseDriver::AddDevice(PDEVICE_OBJECT Fdo)
{
    NTSTATUS status;

    VirtualHidMouse* p = new (NonPagedPool) VirtualHidMouse(Fdo);

    if (p == NULL)
        status = STATUS_INSUFFICIENT_RESOURCES;

    else
    {
        status = p->ConstructorStatus();
        if ( !NT_SUCCESS(status) )
            delete p;
    }

    return status;
}



vmoudev.cpp
#include <khid.h>
#include "vmoudev.h"
#include "hidmouse.h"

KTrace T("",TRACE_MONITOR, TraceAlways, BreakNever, KUstring(L"HidMouse"));

#define SCALEX 3
#define SCALEY 3

HID_REPORT_DESCRIPTOR MouseHidReportDesc[] = {
    0x05, 0x01,    // Usage Page (Generic Desktop),
    0x09, 0x02,    // Usage (Mouse),  
    0xA1, 0x01,    // Collection (Application),    
    0x09, 0x01,    // Usage (Pointer),    
    0xA1, 0x00,    // Collection (Physical),        
    0x05, 0x09,    // Usage Page (Buttons),        
    0x19, 0x01,    // Usage Minimum (01),        
    0x29, 0x03,    // Usage Maximun (03),        
    0x15, 0x00,    // Logical Minimum (0),        
    0x25, 0x01,    // Logical Maximum (1),        
    0x95, 0x03,    // Report Count (3),        
    0x75, 0x01,    // Report Size (1),        
    0x81, 0x02,    // Input (Data, Variable, Absolute),    ;3 button bits        
    0x95, 0x01,    // Report Count (1),        
    0x75, 0x05,    // Report Size (5),        
    0x81, 0x01,    // Input (Constant),            ;5 bit padding        
    0x05, 0x01,    // Usage Page (Generic Desktop),        
    0x09, 0x30,    // Usage (X),        
    0x09, 0x31,    // Usage (Y),        
    0x15, 0x81,    // Logical Minimum (-127),        
    0x25, 0x7F,    // Logical Maximum (127),        
    0x75, 0x08,    // Report Size (8),        
    0x95, 0x02,    // Report Count (2),        
    0x81, 0x06,    // Input (Data, Variable, Relative),    ;2 position bytes (X & Y)    
    0xC0,         // End Collection,
    0xC0        // End Collection
    };    

// HardwareID for the virtual mouse.

WCHAR HardwareID[]={L"ROOT\\NUMEGA_VIRTUAL_HID_MOUSE\0"};
WCHAR DeviceID[]  ={L"ROOT\\NUMEGA_VIRTUAL_HID_MOUSE\0"};

HID_DEVICE_ATTRIBUTES DeviceAttributes = {
    sizeof(HID_DEVICE_ATTRIBUTES),    
    MY_VENDOR_ID,
    MY_PRODUCT_ID,
    VERSION_NUMBER
    };

// Device String
struct
{
    HID_STRING_DESCRIPTOR Sd1;
    WCHAR Str1[14];
    HID_STRING_DESCRIPTOR Sd2;
    WCHAR Str2[9];
} TheDeviceString = {
        { 30, 3},  {'V','i','r','e','o',' ','S','o','f','t','w','a','r','e'},
        { 20, 3},  {'H','i','d',' ','M','o','u','s','e'}
    };    


// We keep a pointer to an instance of the device class for use
// by the exported functions which are called from other drivers

VirtualHidMouse* g_DeviceInstance=NULL;

// Constructor for the virtual mouse device. It is derived from
// KHidDevice.

VirtualHidMouse::VirtualHidMouse(PDEVICE_OBJECT Fdo) :
    KHidDevice(
        Fdo,
        MouseHidReportDesc,
        sizeof MouseHidReportDesc,
        DeviceID,
        HardwareID,
        NULL,
        NULL,
        &DeviceAttributes,
        &TheDeviceString.Sd1,
        sizeof TheDeviceString,
        0        
        )
{
    T << "VirtualHidMouse()\n";

    g_DeviceInstance = this;

    m_DeltaX = m_DeltaY = 0;
    m_OldButtonState = m_NewButtonState = 0;

// Set up the PDO connection

    m_Pdo.Initialize(PDO(), TopOfStack());

    SetLowerDevice(&m_Pdo);

// Set standard policies
    SetPnpPolicy();

// Customize the policy for canceling the current IRP
    m_Policies.m_QueryRemovePolicy.m_CancelCurrentIrp = TRUE;

// Set up the VxD interface
//    m_Vxd.Initialize("VHIDMSE", VxdControlMessageHandler, this);
}

// HIDCLASS calls this routine when it wants a report. We
// serialize this IRP so that when we get input, we know
// which IRP it is intended for. Note that HIDCLASS actually
// created the device object, so we're assuming that HIDCLASS
// is not using the device queue.

NTSTATUS VirtualHidMouse::ReadReport(KIrp I)
{
    return QueueIrp(I, LinkTo(CancelQueuedIrp));    // queue to device queue.

// Note: A driver that relies on a bus driver or some other
// lower level device to process the IRP should generally not queue
// the IRP. Queueing is primarily used by lowest level drivers.
// If this rule is not followed, then the lower device's dispatch
// routines will be called at raised IRQL, and this is generally
// not good.    
}


VOID VirtualHidMouse::CancelQueuedIrp(KIrp I)
{
    KDeviceQueue dq(DeviceQueue());

    if ( (PIRP)I == CurrentIrp() )
    {
        CurrentIrp() = NULL;
        CancelSpinLock::Release(I.CancelIrql());
        T << "Read IRP canceled " << I << "\n";
        I.Information() = 0;
        I.Status() = STATUS_CANCELLED;
        PnpNextIrp(I);
    }
    else if (dq.RemoveSpecificEntry(I))
    {
        CancelSpinLock::Release(I.CancelIrql());
        T << "Read IRP canceled " << I << "\n";
        I.Information() = 0;
        I.PnpComplete(this, STATUS_CANCELLED);
    }
    else
    {
        CancelSpinLock::Release(I.CancelIrql());
    }
}


// StartIo

VOID VirtualHidMouse::StartIo(KIrp I)
{
    ASSERT (I.MajorFunction() == IRP_MJ_INTERNAL_DEVICE_CONTROL);
    ASSERT (I.IoctlCode() == IOCTL_HID_READ_REPORT);

// See if there is any input to report

    UpdateState();
}

// UpdateState
//
// Completes the current IRP if there is anything to report
//
VOID VirtualHidMouse::UpdateState(void)
{
    KIrp I=CurrentIrp();

    if ( !I.IsNull() )
    {
        m_Lock.Lock();

        if ( (m_DeltaX != 0) ||
             (m_DeltaY != 0) ||
             (m_NewButtonState != m_OldButtonState)
           )
        {
            // Before processing the Irp, we need to check to see if it has been
            // canceled.  We also want to set the Irp into an non-cancelable
            // state (cancel routine set to NULL) so we can process it. When
            // performing these operations, it is necessary to hold the global
            // cancel spin lock and take special precautions to ensure the Irp
            // is still valid.  This is accomplished using the routine
            // KIrp::TestAndSetCancelRoutine().
            if ( !I.TestAndSetCancelRoutine(
                LinkTo(CancelQueuedIrp),
                NULL,
                CurrentIrp()) )
            {
                
                // The Irp has been canceled we stop processing and exit.  Since
                // it was in a cancelable state previously, it will be completed by
                // the cancel routine that had been set on it.
                return;
            }

            MouseReport* pReport = (MouseReport*)I.UserBuffer();

            pReport->buttons = m_NewButtonState;
            pReport->deltaX = m_DeltaX;
            pReport->deltaY = m_DeltaY;

            m_DeltaX = m_DeltaY = 0;
            m_OldButtonState = m_NewButtonState;

            I.Information() = sizeof(MouseReport);
            I.Status() = STATUS_SUCCESS;

            m_Lock.Unlock();
            PnpNextIrp(I);
        }
        else
            m_Lock.Unlock();
    }
}

// Called indirectly by other drivers when the virtual mouse
// moves.

VOID VirtualHidMouse::Move(CHAR DeltaX, CHAR DeltaY)
{
    m_Lock.Lock();

    m_DeltaX += DeltaX*SCALEX;
    m_DeltaY += DeltaY*SCALEY;

    m_Lock.Unlock();

    UpdateState();
}

// Called indirectly by other drivers when a virtual mouse
// button is clicked.
//
// Input:
//     LeftOrRight: 1=Left, 0=Right
//     DownOrUp:     1=Down, 0=Up
//
VOID VirtualHidMouse::Click(ULONG LeftOrRight, ULONG DownOrUp)
{
    m_Lock.Lock();

    if (DownOrUp != 0)     // down
    {
        if (LeftOrRight != 0) // left
            m_NewButtonState = (m_OldButtonState | LEFT_BUTTON);
        else // right
            m_NewButtonState = (m_OldButtonState | RIGHT_BUTTON);
    }
    else    // up
    {
        if (LeftOrRight != 0) // left
            m_NewButtonState = (m_OldButtonState & ~LEFT_BUTTON);
        else // right
            m_NewButtonState = (m_OldButtonState & ~RIGHT_BUTTON);
    }

    m_Lock.Unlock();

    UpdateState();
}


NTSTATUS VirtualHidMouse::DefaultHidRequestHandler(KIrp I)
{
    T << "DefaultHidRequestHandler()\n";

    I.ForceReuseOfCurrentStackLocationInCalldown();
    return m_Pdo.PnpCall(this, I);
}



//////////////////////////////////////////////////////////////////
// VirtualHidMouse::DefaultPnp
//
// This handler is the override of KPnpDdevice::Default. It provides
// default functionality for IRP_MJ_PNP. The
// system invokes this function whenever the device receives a
// Pnp IRP having a minor function for which the corresponding
// member function of KPnpDevice is not overridden. Note that
// KHidDevice provides overrides for some of the KPnpDevice members
// (e.g. OnRemoveDevice).
//
// Subclasses should consider if this is the appropriate default
// functionality. If not, override the function.
//
NTSTATUS VirtualHidMouse::DefaultPnp(KIrp I)
{
    T << "DefaultPnp Pnp request, minor=" << ULONG(I.MinorFunction()) << "\n";
    
    I.ForceReuseOfCurrentStackLocationInCalldown();
    return m_Pdo.PnpCall(this, I);
}

//////////////////////////////////////////////////////////////////
// VirtualHidMouse::DefaultPower
//
// This handler is the override of KPnpDdevice::Default. It provides
// default functionality for IRP_MJ_POWER. The
// system invokes this function whenever the device receives a
// Power IRP having a minor function for which the corresponding
// member function of KPnpDevice is not overridden.
//
// Subclasses should consider if this is the appropriate default
// functionality. If not, override the function.
//
NTSTATUS VirtualHidMouse::DefaultPower(KIrp I)
{
    T << "DefaultPower Power request, minor=" << ULONG(I.MinorFunction()) << "\n";

    I.IndicatePowerIrpProcessed();
    I.CopyParametersDown();
    return m_Pdo.PnpPowerCall(this, I);
}


////////////////////////////////////////////////////////////////////////////////
// SystemControl
//
// This routine just passes the IRP through to the next device since this driver
// is not a WMI provider.
//
NTSTATUS VirtualHidMouse::SystemControl(KIrp I)
{
    I.ForceReuseOfCurrentStackLocationInCalldown();
    return m_Pdo.PnpCall(this, I);
}


///////////////////////////////////////////////////////////////////
// OnQueryStopDevice
//
// This call queries the device to determine if a STOP can be done
//
NTSTATUS VirtualHidMouse::OnQueryStopDevice(KIrp I)
{
    T << "OnQueryStopDevice()\n";
    return STATUS_SUCCESS;
}

///////////////////////////////////////////////////////////////////
// OnQueryRemoveDevice
//
// The system is querying the device to determine if a REMOVE can be done
//
NTSTATUS VirtualHidMouse::OnQueryRemoveDevice(KIrp I)
{
    T << "OnQueryRemoveDevice()\n";
    return STATUS_SUCCESS;
}


///////////////////////////////////////////////////////////////////
// OnCancelStopDevice
//
// This call instructs the device to cancel a pending stop operation
//
NTSTATUS VirtualHidMouse::OnCancelStopDevice(KIrp I)
{
    T << "OnCancelStopDevice()\n";
    return STATUS_SUCCESS;
}


///////////////////////////////////////////////////////////////////
// OnCancelRemoveDevice
//
// This call instructs the device to cancel a pending stop operation
//
NTSTATUS VirtualHidMouse::OnCancelRemoveDevice(KIrp I)
{
    T << "OnCancelRemoveDevice()\n";
    return STATUS_SUCCESS;
}

///////////////////////////////////////////////////////////////////
// OnStartDevice
//
// This call instructs the device to start operation. Relevant
// policies:
//
//        m_Policies.m_CompletedByDriverWorks.m_StartDevice = TRUE
//        m_Policies.m_ForwardToPdoPolicy.m_CallBeforeStart = TRUE
//
NTSTATUS VirtualHidMouse::OnStartDevice(KIrp I)
{
    T << "OnStartDevice()\n";

    if (!m_State.m_Started)
    {
        // initialize the device
    }

    return STATUS_SUCCESS;
}

///////////////////////////////////////////////////////////////////
// OnStopDevice
//
// This call instructs the device to uninitialize itself. Relevant
// policies:
//
//        m_Policies.m_CompletedByDriverWorks.m_StopDevice = TRUE
//        m_Policies.m_ForwardToPdoPolicy.m_CallAfterStop = TRUE
//        m_Policies.m_HoldPolicy.m_CancelAllOnStop = TRUE
//
NTSTATUS VirtualHidMouse::OnStopDevice(KIrp I)
{
    T << "OnStopDevice()\n";

    if (m_State.m_Started)
    {
        // undo OnStartDevice here
    }

    return STATUS_SUCCESS;    // IRP completed by D::W
}

//////////////////////////////////////////////////////////////////
// VirtualHidMouse::OnRemoveDevice
//
// Override of KPnpDevice member. The system calls when the device
// is removed. If a device has outstanding IRPs, it should make
// sure they are all complete before deleting itself.

NTSTATUS VirtualHidMouse::OnRemoveDevice(KIrp I)
{
    T << "OnRemoveDevice()\n";
    return STATUS_SUCCESS;
}

ULONG __stdcall VxdControlMessageHandler(
    ULONG Edi,
    ULONG Esi,
    ULONG Ebp,
    ULONG Esp,
    ULONG Ebx,
    ULONG Edx,
    ULONG Ecx,
    ULONG ControlMessage,
    PVOID Context,
    ULONG* pCarryBitReturn
    )
{
    if (ControlMessage == W32_DEVICEIOCONTROL)
    {
        PIOCTLPARAMS p = PIOCTLPARAMS(Esi);
        MOUSE_MOVE_INFO* pMove = (MOUSE_MOVE_INFO*)p->dioc_InBuf;
        MOUSE_CLICK_INFO* pClick = (MOUSE_CLICK_INFO*)p->dioc_InBuf;

        switch (p->dioc_IOCtlCode)
        {
        case IOCTL_VHIDMOU_MOVE:

            T << "Move x=" << pMove->deltaX << " y=" << pMove->deltaY << "\n";

            g_DeviceInstance->Move(UCHAR(pMove->deltaX), UCHAR(pMove->deltaY));
            return STATUS_SUCCESS;

        case IOCTL_VHIDMOU_CLICK:

            T << "Click U/D=" << pClick->UpOrDown << " L/R=" << pClick->LeftOrRight << "\n";

            g_DeviceInstance->Click(pClick->LeftOrRight, pClick->UpOrDown);
            return STATUS_SUCCESS;

        default:
            return STATUS_NOT_IMPLEMENTED;
        }
    }
    else
    {
        *pCarryBitReturn = 0;
        return 0;
    }
}

附件名称/大小 下载次数 最后更新
hidmouse.rar (62KB)  61 2009-03-24 19:10
未来,为我而来!
AllenZh
驱动老牛
驱动老牛
  • 注册日期2001-08-19
  • 最后登录2015-11-27
  • 粉丝19
  • 关注10
  • 积分1316分
  • 威望2387点
  • 贡献值7点
  • 好评度321点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2009-03-25 17:26
如果没有记错这个是DriverStudio中的代码,我记的只支持9x,如果你要做2K/XP的可能要做修改
个人建议用DDK去做
1,承接Windows下驱动/应用开发 2,本人原创虚拟鼠标/键盘,触摸屏,虚拟显卡,Mirror驱动,XP无盘的SCSI虚拟磁盘驱动等 3,windows下有尝技术服务(包括BUG调试,员工培训等) 欢迎深圳和海外企业联系.msn:mfczmh@sina.com
huyongtq
驱动牛犊
驱动牛犊
  • 注册日期2009-03-06
  • 最后登录2014-11-30
  • 粉丝0
  • 关注0
  • 积分19分
  • 威望171点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2009-03-26 00:48
哦~,谢谢楼上的意见,不过我还有好多原理都不太明白,总之感觉是不知道该如何出手啦,我只要一个模拟鼠标的功能,我不想去学习一门新的语言,我没有那么多时间,,,,
唉,,期待有高人能直接贴出源代码
未来,为我而来!
游客

返回顶部