c++ - 什么 typedef BOOL (WINAPI *FN_SetupDiGetDeviceProperty)?

标签 c++ device wdk

我在这里找到了一些代码,列出了计算机上的所有 USB 设备。这是代码:

#include <windows.h>
#include <devguid.h>    // for GUID_DEVCLASS_CDROM etc
#include <setupapi.h>
#include <cfgmgr32.h>   // for MAX_DEVICE_ID_LEN, CM_Get_Parent and CM_Get_Device_ID
#define INITGUID
#include "c:\WinDDK\7600.16385.1\inc\api\devpkey.h"
#include <tchar.h>
#include <stdio.h>
#include <iostream>

#define ARRAY_SIZE(arr)     (sizeof(arr)/sizeof(arr[0]))

#pragma comment (lib, "setupapi.lib")

typedef BOOL (WINAPI *FN_SetupDiGetDeviceProperty)(
  __in       HDEVINFO DeviceInfoSet,
  __in       PSP_DEVINFO_DATA DeviceInfoData,
  __in       const DEVPROPKEY *PropertyKey,
  __out      DEVPROPTYPE *PropertyType,
  __out_opt  PBYTE PropertyBuffer,
  __in       DWORD PropertyBufferSize,
  __out_opt  PDWORD RequiredSize,
  __in       DWORD Flags
);

// List all USB devices with some additional information
void ListUsbDevices(void)
{
    unsigned i, j;
    DWORD dwSize, dwPropertyRegDataType;
    DEVPROPTYPE ulPropertyType;
    OSVERSIONINFO osvi;
    CONFIGRET r;
    HDEVINFO hDevInfo;
    SP_DEVINFO_DATA DeviceInfoData;
    const static LPCTSTR arPrefix[3] = {TEXT("VID_"), TEXT("PID_"), TEXT("MI_")};
    TCHAR szDeviceInstanceID [MAX_DEVICE_ID_LEN];
    TCHAR szDesc[1024];
    LPTSTR pszToken, pszNextToken;
    TCHAR szVid[MAX_DEVICE_ID_LEN], szPid[MAX_DEVICE_ID_LEN], szMi[MAX_DEVICE_ID_LEN];

#ifdef UNICODE
    FN_SetupDiGetDeviceProperty fn_SetupDiGetDeviceProperty = (FN_SetupDiGetDeviceProperty)
        GetProcAddress (GetModuleHandle (TEXT("Setupapi.dll")), "SetupDiGetDevicePropertyW");
#else
    FN_SetupDiGetDeviceProperty fn_SetupDiGetDeviceProperty = (FN_SetupDiGetDeviceProperty)
        GetProcAddress(GetModuleHandle(TEXT("Setupapi.dll")), "SetupDiGetDevicePropertyA");
#endif

    // List all connected USB devices
    hDevInfo = SetupDiGetClassDevs (NULL, TEXT("USB"), NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);
    if (hDevInfo == INVALID_HANDLE_VALUE)
        return;

    // Find the ones that are driverless
    for (i = 0; ; i++)  {
        DeviceInfoData.cbSize = sizeof (DeviceInfoData);
        if (!SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData))
            break;

        r = CM_Get_Device_ID(DeviceInfoData.DevInst, szDeviceInstanceID , MAX_PATH, 0);
        if (r != CR_SUCCESS)
            continue;

        _tprintf (TEXT("%s\n"), szDeviceInstanceID );

        if (SetupDiGetDeviceRegistryProperty (hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC,
                                              &dwPropertyRegDataType, (BYTE*)szDesc,
                                              sizeof(szDesc),   // The size, in bytes
                                              &dwSize))
            _tprintf (TEXT("    Device Description: \"%s\"\n"), szDesc);

        // Retreive the device description as reported by the device itself
        memset(&osvi, 0, sizeof(OSVERSIONINFO));
        osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
        if ( (GetVersionEx(&osvi) != 0)
            && (osvi.dwBuildNumber >= 7000) ) {
                // On Vista and earlier, we can use only SPDRP_DEVICEDESC
                // On Windows 7, the information we want ("Bus reported device description") is
                // accessed through DEVPKEY_Device_BusReportedDeviceDesc
                if (fn_SetupDiGetDeviceProperty && fn_SetupDiGetDeviceProperty (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_BusReportedDeviceDesc,
                                                                                &ulPropertyType, (BYTE*)szDesc, sizeof(szDesc), &dwSize, 0))
                    _tprintf (TEXT("    Bus Reported Device Description: \"%s\"\n"), szDesc);
        }

        pszToken = _tcstok_s (szDeviceInstanceID , TEXT("\\#&"), &pszNextToken);
        while(pszToken != NULL)
        {
            szVid[0] = TEXT('\0');
            szPid[0] = TEXT('\0');
            szMi[0] = TEXT('\0');
            for (j = 0; j < 3; j++) {
                if (_tcsncmp(pszToken, arPrefix[j], lstrlen(arPrefix[j])) == 0) {
                    switch(j) {
                        case 0:
                            _tcscpy_s(szVid, ARRAY_SIZE(szVid), pszToken);
                            break;
                        case 1:
                            _tcscpy_s(szPid, ARRAY_SIZE(szPid), pszToken);
                            break;
                        case 2:
                            _tcscpy_s(szMi, ARRAY_SIZE(szMi), pszToken);
                            break;
                        default:
                            break;
                    }
                }
            }
            if (szVid[0] != TEXT('\0'))
                _tprintf (TEXT("    vid: \"%s\"\n"), szVid);
            if (szPid[0] != TEXT('\0'))
                _tprintf (TEXT("    pid: \"%s\"\n"), szPid);
            if (szMi[0] != TEXT('\0'))
                _tprintf (TEXT("    mi: \"%s\"\n"), szMi);
            pszToken = _tcstok_s (NULL, TEXT("\\#&"), &pszNextToken);

            //VID and PID for the playstation Move.
            if( szVid[4] == TEXT('8') && 
                szVid[5] == TEXT('8') && 
                szVid[6] == TEXT('8') && 
                szVid[7] == TEXT('8') &&
                szPid[4] == TEXT('0') &&
                szPid[5] == TEXT('3') &&
                szPid[6] == TEXT('0') &&
                szPid[7] == TEXT('8'))
            {
                std::cout << "PlayStation Move Detected!" << std::endl;
                break;
            }
        }

    }

    return;
}

int main()
{
    int iQuit;
    ListUsbDevices();
    std::cin >> iQuit;

    return 0;
}

为什么我们需要先定义 FN_SetupDiGetDeviceProperty 代码块?它实际上做了什么?我以为 SetupDiGetDeviceProperty 函数是 WDK 的一部分,所以我们可以直接使用它??

最佳答案

typedef BOOL (WINAPI *FN_SetupDiGetDeviceProperty)(
  __in       HDEVINFO DeviceInfoSet,
  __in       PSP_DEVINFO_DATA DeviceInfoData,
  __in       const DEVPROPKEY *PropertyKey,
  __out      DEVPROPTYPE *PropertyType,
  __out_opt  PBYTE PropertyBuffer,
  __in       DWORD PropertyBufferSize,
  __out_opt  PDWORD RequiredSize,
  __in       DWORD Flags
);

上面的代码将 FN_SetupDiGetDeviceProperty 定义为一个指向函数的指针,该函数采用该(长)参数列表并返回一个 BOOLWINAPI 是一个宏,指定函数的调用约定(__stdcall__cdecl 等)。

稍后在您的代码中,函数指针 fn_SetupDiGetDeviceProperty 有条件地设置为 SetupDiGetDevicePropertyWSetupDiGetDevicePropertyA,具体取决于您是否正在编译是否定义了 UNICODE 宏。

DLL 实际上并没有导出名为SetupDiGetDeviceProperty 的函数。如果您深入了解您正在使用的库的标题,您会发现类似这样的内容:

#ifdef UNICODE
#define SetupDiGetDeviceProperty SetupDiGetDevicePropertyW
#else
#define SetupDiGetDeviceProperty SetupDiGetDevicePropertyA
#endif

因此,当您调用 SetupDiGetDeviceProperty 时,您实际上是在调用该函数的 2 个变体 (A/W) 之一。

关于c++ - 什么 typedef BOOL (WINAPI *FN_SetupDiGetDeviceProperty)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10555709/

相关文章:

c++ - ifstream.read() 如果读取的数据少于可用数据则设置失败位

c++ - 适用于 Mac 的 C++ 中的 HTTP 查询

c++ - 我应该如何管理 C 或 C++ 开源项目中的依赖项?

windows - 如何使用 NDIS 过滤器驱动程序发送任意数据包?

c++ - 在另一个 COM 对象中创建一个 COM 对象

ios - 在真实设备上测试 PhoneGap 应用程序

html - 菜单在移动设备上扭曲页面并在右侧创建空白

windows-mobile - 如何将Windows Mobile PDA连接到Windows 10

c - Hook NtReadFile。更改文字

driver - 如何安装和运行驱动程序