zoukankan      html  css  js  c++  java
  • UMDF

      看了一周的UMDF,今天就将这些天的心得记下来。

      一开始,老大推荐看《竹林蹊径:深入浅出Windows驱动开发完美补全版.张佩马勇董鉴源.扫描版》。这本书看了前三章,这本书讲的太细,作者又奔着深入的想法写的,所以看完后感觉和没看一样,白白浪费一天时间。不过了解了许多基本概念。

      后来找到了《Windows 7 Device Driver(Windows 7设备驱动程序开发)》这本书,CSDN上有个带标签的不错,因为我只用到UMDF,所以只看了前两部分,这下我对整个体系结构和程序流程了解多了。这时候MSDN也起到很大的帮助。

    这本书中有一个对UMDF Driver Skeleton Sample (UMDF Version 1)程序的详解,程序在

    http://code.msdn.microsoft.com/windowshardware/SKELETON-3a06c09e

    可以下载。

    上面这些看完后,就打算写个最简单的IOCTL了。但是书上没有例子,只能在网上找了。找到一个

    http://www.codeproject.com/Articles/9504/Driver-Development-Part-1-Introduction-to-Drivers

    http://www.codeproject.com/Articles/9575/Driver-Development-Part-2-Introduction-to-Implemen

    作者写的相当不错,而且有源码可以参考。PS:这是一个系列的,我觉得蛮好的。

    下面这个是对上面的翻译:

    http://blogs.ejb.cc/archives/6253/windows-driver-development-a-what-is-the-drive

    但是我使用的是Windows的UMDF框架,所以还要改变一些。不过也很简单。首先新建一个UMDF框架。然后在Internal.h中添加

    #define IOCTL_EXAMPLE_SAMPLE_DIRECT_IN_IO    
            CTL_CODE(FILE_DEVICE_UNKNOWN,        
                     0x800,                      
                     METHOD_IN_DIRECT,           
                     FILE_READ_DATA | FILE_WRITE_DATA)

    然后在IoQueue.cpp中的OnDeviceIoControl函数中添加

     //
        // Process the IOCTLs
        //
    
        switch (ControlCode)
        {
            case IOCTL_EXAMPLE_SAMPLE_DIRECT_IN_IO: 
           
               OutputDebugString("Hello");
          
            break;
          
      
        }

    在这里一个最简单的IOCTL驱动就写成了,然后就进行Build。

    在这里可能会碰到 link error 2019 错误,无法解析的外部命令。这是错误输出框里是哪个函数,很有可能没有VS找不到这个函数的函数库。解决这种问题基本就是三步走:

    下面以无法解析setupAPI的某些函数为例:

    1. VS2中点击项目 -->右键-->属性-->配置属性-->链接器-->输入-->附加依赖项:将相关的lib文件加入到附加依赖项中: 
    2. 找到setupApi.h所在的目录,我的是在C:Program FilesWindows Kits8.0Includeum。这时候就可以在配置属性-->VC++目录-->包含目录中加入上面的路径。
    3. 找到setupApi.lib所在的目录,注意你所需要时32位的还是64位的版本,我的是32位,所以选择C:Program FilesWindows Kits8.0Libwin8umx86。    这时候就可以在配置属性-->VC++目录-->库目录中加入上面的路径。

     第三部新建一个测试工程,我选择的是Win32 console,名字为test。然后在test.cpp中添加

    // testapp.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include <windows.h>
    #include <stdlib.h>
    #include <Setupapi.h>
    #include <strsafe.h>
    #include "devioctl.h"
    #include <initguid.h>
    
    
    
    #define CTL_CODE( DeviceType, Function, Method, Access ) (                 
        ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) 
    )
    
    #define IOCTL_EXAMPLE_SAMPLE_DIRECT_IN_IO    
            CTL_CODE(FILE_DEVICE_UNKNOWN,        
                     0x800,                      
                     METHOD_IN_DIRECT,           
                     FILE_READ_DATA | FILE_WRITE_DATA)
    
    //
    //在这里的GUID 应该和Internal中的保持一致
    //
    DEFINE_GUID(GUID_DEVINTERFACE_UMDFTestDriver,
        0x57bc27d7,0x935c,0x4b57,0x97,0xa3,0x83,0xed,0x17,0x3b,0xbc,0x29);
    
    #define countof(x) (sizeof(x) / sizeof(x[0]))
    
    _Success_ (return != FALSE)
    
    BOOL
    GetDevicePath(
        IN  LPGUID InterfaceGuid,
        _Out_writes_(BufLen) PWSTR DevicePath,
        _In_ size_t BufLen
        )
    {
        HDEVINFO HardwareDeviceInfo;
        SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
        PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData = NULL;
        ULONG Length, RequiredLength = 0;
        BOOL bResult;
        HRESULT     hr;
    
        HardwareDeviceInfo = SetupDiGetClassDevs(
                                 InterfaceGuid,
                                 NULL,
                                 NULL,
                                 (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
    
        if (HardwareDeviceInfo == INVALID_HANDLE_VALUE) {
            wprintf(L"SetupDiGetClassDevs failed!
    ");
            return FALSE;
        }
    
        DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
    
        bResult = SetupDiEnumDeviceInterfaces(HardwareDeviceInfo,
                                                  0,
                                                  InterfaceGuid,
                                                  0,
                                                  &DeviceInterfaceData);
    
        if (bResult == FALSE) {
    
            LPVOID lpMsgBuf;
    
            if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                              FORMAT_MESSAGE_FROM_SYSTEM |
                              FORMAT_MESSAGE_IGNORE_INSERTS,
                              NULL,
                              GetLastError(),
                              MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                              (LPWSTR) &lpMsgBuf,
                              0,
                              NULL
                              )) {
    
                printf("SetupDiEnumDeviceInterfaces failed: %s", (LPSTR)lpMsgBuf);
                LocalFree(lpMsgBuf);
            }
    
            SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
            return FALSE;
        }
    
        SetupDiGetDeviceInterfaceDetail(
            HardwareDeviceInfo,
            &DeviceInterfaceData,
            NULL,
            0,
            &RequiredLength,
            NULL
            );
    
        DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)
                            LocalAlloc(LMEM_FIXED, RequiredLength);
    
        if (DeviceInterfaceDetailData == NULL) {
            SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
            wprintf(L"Failed to allocate memory.
    ");
            return FALSE;
        }
    
        DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
    
        Length = RequiredLength;
    
        bResult = SetupDiGetDeviceInterfaceDetail(
                      HardwareDeviceInfo,
                      &DeviceInterfaceData,
                      DeviceInterfaceDetailData,
                      Length,
                      &RequiredLength,
                      NULL);
    
        if (bResult == FALSE) {
    
            LPVOID lpMsgBuf;
    
            if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                              FORMAT_MESSAGE_FROM_SYSTEM |
                              FORMAT_MESSAGE_IGNORE_INSERTS,
                              NULL,
                              GetLastError(),
                              MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                              (LPWSTR) &lpMsgBuf,
                              0,
                              NULL)) {
    
                printf("Error in SetupDiGetDeviceInterfaceDetail: %s
    ", (LPSTR)lpMsgBuf);
                LocalFree(lpMsgBuf);
            }
    
            SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
            LocalFree(DeviceInterfaceDetailData);
            return FALSE;
        }
    
        hr = StringCchCopy(DevicePath,
                           BufLen,
                           DeviceInterfaceDetailData->DevicePath);
        if (FAILED(hr)) {
            SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
            LocalFree(DeviceInterfaceDetailData);
            return FALSE;
        }
    
        SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
        LocalFree(DeviceInterfaceDetailData);
    
        return TRUE;
    
    }
    
    HANDLE
    OpenDevice(
        _In_ BOOL Synchronous
        )
    
    /*++
    Routine Description:
    
        Called by main() to open an instance of our device after obtaining its name
    
    Arguments:
    
        Synchronous - TRUE, if Device is to be opened for synchronous access.
                      FALSE, otherwise.
    
    Return Value:
    
        Device handle on success else INVALID_HANDLE_VALUE
    
    --*/
    
    {
        HANDLE hDev;
        WCHAR completeDeviceName[MAX_DEVPATH_LENGTH];
    
        if ( !GetDevicePath(
                (LPGUID) &GUID_DEVINTERFACE_UMDFTestDriver,
                completeDeviceName,
                countof(completeDeviceName)) )
        {
                return  INVALID_HANDLE_VALUE;
        }
    
        wprintf(L"DeviceName = (%s)
    ", completeDeviceName);
    
        hDev = CreateFile(completeDeviceName,
                          GENERIC_WRITE | GENERIC_READ,
                          FILE_SHARE_WRITE | FILE_SHARE_READ,
                          NULL, // default security
                          OPEN_EXISTING,
                          ((Synchronous ? FILE_ATTRIBUTE_NORMAL : FILE_FLAG_OVERLAPPED) | SECURITY_IMPERSONATION),
                          NULL);
    
        if (hDev == INVALID_HANDLE_VALUE) {
            wprintf(L"Failed to open the device, error - %d", GetLastError());
        } else {
            wprintf(L"Opened the device successfully.
    ");
        }
    
        return hDev;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
      
        HANDLE          deviceHandle;
        DWORD           code;
        ULONG           index;    
        deviceHandle = OpenDevice(FALSE);
    
        if (deviceHandle == INVALID_HANDLE_VALUE) {
    
            wprintf(L"Unable to find any OSR FX2 devices!
    ");
            return FALSE;
        }
    
        if (!DeviceIoControl(deviceHandle,
                                 IOCTL_EXAMPLE_SAMPLE_DIRECT_IN_IO,
                                 NULL,           // Ptr to InBuffer
                                 0,  // Length of InBuffer
                                 NULL,         // Ptr to OutBuffer
                                 0,            // Length of OutBuffer
                                 &index,       // BytesReturned
                                 0)) {         // Ptr to Overlapped structure
                code = GetLastError();
                wprintf(L"DeviceIoControl failed with error 0x%x
    ", code);
           }
          return 0;
    }

    具体可以参考:

    http://tech.ddvip.com/2008-09/122084165361557.html

    在这里代码都已经敲完了。需要做的就是将驱动安装上。可以参考这篇:

    http://joeyliu.blog.51cto.com/3647812/943368

     OK,接下来就是测试环节,我们使用的是DebugView。可以参考这篇:

    http://blog.sina.com.cn/s/blog_9bd8f0f80100z55t.html

    最后出现:

    就大功告成了!!

  • 相关阅读:
    本地SQL密码破解
    SqlServer2005复制分类
    xpsql.cpp: 错误 2 来自 CreateProcess(第 737 行)
    sql server 复制,镜像,日志传输及故障转移集群区别
    使用SQL操作MySQL数据库
    [技术文摘]Resin服务器的使用
    Tomcat新手攻略
    Java连接数据库谈
    jsp中文乱码问题的解决2
    台风来到
  • 原文地址:https://www.cnblogs.com/SpeakSoftlyLove/p/3433808.html
Copyright © 2011-2022 走看看