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 Files\Windows Kits\8.0\Include\um。这时候就可以在配置属性-->VC++目录-->包含目录中加入上面的路径。
  3. 找到setupApi.lib所在的目录,注意你所需要时32位的还是64位的版本,我的是32位,所以选择C:\Program Files\Windows Kits\8.0\Lib\win8\um\x86。    这时候就可以在配置属性-->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!\n");
        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.\n");
        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\n", (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)\n", 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.\n");
    }

    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!\n");
        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\n", 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

最后出现:

就大功告成了!!

 

 

 

 

 

 

 

 

 

posted on 2013-11-20 16:15  walkwalkwalk  阅读(1385)  评论(0编辑  收藏  举报

导航