SetupApi函数
+ -

Devcon hwids命令源代码实现 SetupAPI函数实现

2022-01-28 63 0

Devcon hwids命令显示设备的硬件ID信息。主要的显示包括如下:

了解过之前几个命令的同学应该觉地比较简单,因为或多或少有些信息如设备友名,设备实例名路径我们都获取过,而设备的硬件ID和兼容ID其实与是比较简单是,和设备的友名一样,是通过SetupDiGetDeviceRegistryProperty函数的SPDRP_HARDWAREID和SPDRP_COMPATIBLEIDS属性信息获取的。

int cmdHwIds(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[])
/*++

Routine Description:

    HWIDS <id> ...
    use EnumerateDevices to do hardwareID matching
    for each match, dump hw/compat id's to stdout
    note that we only enumerate present devices

Arguments:

    BaseName  - name of executable
    Machine   - if non-NULL, remote machine
    argc/argv - remaining parameters - passed into EnumerateDevices

Return Value:

    EXIT_xxxx

--*/
{
    GenericContext context;
    int failcode;

    UNREFERENCED_PARAMETER(Flags);

    if(!argc) {
        return EXIT_USAGE;
    }

    context.count = 0;
    context.control = FIND_DEVICE | FIND_HWIDS;
    failcode = EnumerateDevices(BaseName,Machine,DIGCF_PRESENT,argc,argv,FindCallback,&context);

    if(failcode == EXIT_OK) {

        if(!context.count) {
            FormatToStream(stdout,Machine?MSG_FIND_TAIL_NONE:MSG_FIND_TAIL_NONE_LOCAL,Machine);
        } else {
            FormatToStream(stdout,Machine?MSG_FIND_TAIL:MSG_FIND_TAIL_LOCAL,context.count,Machine);
        }
    }
    return failcode;
}

可以看到,cmdHwIds函数是EnumerateDevices函数实现的。注意这里的DIGCF_PRESENT表示当前正在运行的设备和context.control = FIND_DEVICE | FIND_HWIDS获取的设备信息。

int EnumerateDevices(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PWSTR* argv, _In_ CallbackFunc Callback, _In_ LPVOID Context)
/*++

Routine Description:

    Generic enumerator for devices that will be passed the following arguments:
    <id> [<id>...]
    =<class> [<id>...]
    where <id> can either be @instance-id, or hardware-id and may contain wildcards
    <class> is a class name

Arguments:

    BaseName - name of executable
    Machine  - name of machine to enumerate
    Flags    - extra enumeration flags (eg DIGCF_PRESENT)
    argc/argv - remaining arguments on command line
    Callback - function to call for each hit
    Context  - data to pass function for each hit

Return Value:

    EXIT_xxxx

--*/
{
    HDEVINFO devs = INVALID_HANDLE_VALUE;
    IdEntry * templ = NULL;
    int failcode = EXIT_FAIL;
    int retcode;
    int argIndex;
    DWORD devIndex;
    SP_DEVINFO_DATA devInfo;
    SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail;
    BOOL doSearch = FALSE;
    BOOL match;
    BOOL all = FALSE;
    GUID cls;
    DWORD numClass = 0;
    int skip = 0;

    UNREFERENCED_PARAMETER(BaseName);

    if(!argc) {
        return EXIT_USAGE;
    }

    templ = new IdEntry[argc];
    if(!templ) {
        goto final;
    }

    //
    // determine if a class is specified
    //
    if(argc>skip && argv[skip][0]==CLASS_PREFIX_CHAR && argv[skip][1]) {
        if(!SetupDiClassGuidsFromNameEx(argv[skip]+1,&cls,1,&numClass,Machine,NULL) &&
            GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
            goto final;
        }
        if(!numClass) {
            failcode = EXIT_OK;
            goto final;
        }
        skip++;
    }
    if(argc>skip && argv[skip][0]==WILD_CHAR && !argv[skip][1]) {
        //
        // catch convinient case of specifying a single argument '*'
        //
        all = TRUE;
        skip++;
    } else if(argc<=skip) {
        //
        // at least one parameter, but no <id>'s
        //
        all = TRUE;
    }

    //
    // determine if any instance id's were specified
    //
    // note, if =<class> was specified with no id's
    // we'll mark it as not doSearch
    // but will go ahead and add them all
    //
    for(argIndex=skip;argIndex<argc;argIndex++) {
        templ[argIndex] = GetIdType(argv[argIndex]);
        if(templ[argIndex].Wild || !templ[argIndex].InstanceId) {
            //
            // anything other than simple InstanceId's require a search
            //
            doSearch = TRUE;
        }
    }
    if(doSearch || all) {
        //
        // add all id's to list
        // if there's a class, filter on specified class
        //
        devs = SetupDiGetClassDevsEx(numClass ? &cls : NULL,
                                     NULL,
                                     NULL,
                                     (numClass ? 0 : DIGCF_ALLCLASSES) | Flags,
                                     NULL,
                                     Machine,
                                     NULL);

    } else {
        //
        // blank list, we'll add instance id's by hand
        //
        devs = SetupDiCreateDeviceInfoListEx(numClass ? &cls : NULL,
                                             NULL,
                                             Machine,
                                             NULL);
    }
    if(devs == INVALID_HANDLE_VALUE) {
        goto final;
    }
    for(argIndex=skip;argIndex<argc;argIndex++) {
        //
        // add explicit instances to list (even if enumerated all,
        // this gets around DIGCF_PRESENT)
        // do this even if wildcards appear to be detected since they
        // might actually be part of the instance ID of a non-present device
        //
        if(templ[argIndex].InstanceId) {
            SetupDiOpenDeviceInfo(devs,templ[argIndex].String,NULL,0,NULL);
        }
    }

    devInfoListDetail.cbSize = sizeof(devInfoListDetail);
    if(!SetupDiGetDeviceInfoListDetail(devs,&devInfoListDetail)) {
        goto final;
    }

    //
    // now enumerate them
    //
    if(all) {
        doSearch = FALSE;
    }

    devInfo.cbSize = sizeof(devInfo);
    for(devIndex=0;SetupDiEnumDeviceInfo(devs,devIndex,&devInfo);devIndex++) {

        if(doSearch) {
            for(argIndex=skip,match=FALSE;(argIndex<argc) && !match;argIndex++) {
                TCHAR devID[MAX_DEVICE_ID_LEN];
                LPTSTR *hwIds = NULL;
                LPTSTR *compatIds = NULL;
                //
                // determine instance ID
                //
                if(CM_Get_Device_ID_Ex(devInfo.DevInst,devID,MAX_DEVICE_ID_LEN,0,devInfoListDetail.RemoteMachineHandle)!=CR_SUCCESS) {
                    devID[0] = TEXT('\0');
                }

                if(templ[argIndex].InstanceId) {
                    //
                    // match on the instance ID
                    //
                    if(WildCardMatch(devID,templ[argIndex])) {
                        match = TRUE;
                    }
                } else {
                    //
                    // determine hardware ID's
                    // and search for matches
                    //
                    hwIds = GetDevMultiSz(devs,&devInfo,SPDRP_HARDWAREID);
                    compatIds = GetDevMultiSz(devs,&devInfo,SPDRP_COMPATIBLEIDS);

                    if(WildCompareHwIds(hwIds,templ[argIndex]) ||
                        WildCompareHwIds(compatIds,templ[argIndex])) {
                        match = TRUE;
                    }
                }
                DelMultiSz(hwIds);
                DelMultiSz(compatIds);
            }
        } else {
            match = TRUE;
        }
        if(match) {
            retcode = Callback(devs,&devInfo,devIndex,Context);
            if(retcode) {
                failcode = retcode;
                goto final;
            }
        }
    }

    failcode = EXIT_OK;

final:
    if(templ) {
        delete [] templ;
    }
    if(devs != INVALID_HANDLE_VALUE) {
        SetupDiDestroyDeviceInfoList(devs);
    }
    return failcode;

}

关键函数代码段,可以看到

{
  devID[0] = TEXT('\0');
}
  • CM_Get_Device_ID_Ex用于获取设备实例路径名
  • hwIds = GetDevMultiSz(devs,&devInfo,SPDRP_HARDWAREID); 用于获取硬件ID
  • compatIds = GetDevMultiSz(devs,&devInfo,SPDRP_COMPATIBLEIDS);获取兼容ID
__drv_allocatesMem(object)
LPTSTR * GetDevMultiSz(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo, _In_ DWORD Prop)
/*++

Routine Description:

    Get a multi-sz device property
    and return as an array of strings

Arguments:

    Devs    - HDEVINFO containing DevInfo
    DevInfo - Specific device
    Prop    - SPDRP_HARDWAREID or SPDRP_COMPATIBLEIDS

Return Value:

    array of strings. last entry+1 of array contains NULL
    returns NULL on failure

--*/
{
    LPTSTR buffer;
    DWORD size;
    DWORD reqSize;
    DWORD dataType;
    LPTSTR * array;
    DWORD szChars;

    size = 8192; // initial guess, nothing magic about this
    buffer = new TCHAR[(size/sizeof(TCHAR))+2];
    if(!buffer) {
        return NULL;
    }
    while(!SetupDiGetDeviceRegistryProperty(Devs,DevInfo,Prop,&dataType,(LPBYTE)buffer,size,&reqSize)) {
        if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
            goto failed;
        }
        if(dataType != REG_MULTI_SZ) {
            goto failed;
        }
        size = reqSize;
        delete [] buffer;
        buffer = new TCHAR[(size/sizeof(TCHAR))+2];
        if(!buffer) {
            goto failed;
        }
    }
    szChars = reqSize/sizeof(TCHAR);
    buffer[szChars] = TEXT('\0');
    buffer[szChars+1] = TEXT('\0');
    array = GetMultiSzIndexArray(buffer);
    if(array) {
        return array;
    }

failed:
    if(buffer) {
        delete [] buffer;
    }
    return NULL;
}

回调函数


int FindCallback(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo, _In_ DWORD Index, _In_ LPVOID Context)
/*++

Routine Description:

    Callback for use by Find/FindAll
    just simply display the device

Arguments:

    Devs    )_ uniquely identify the device
    DevInfo )
    Index    - index of device
    Context  - GenericContext

Return Value:

    EXIT_xxxx

--*/
{
    GenericContext *pFindContext = (GenericContext*)Context;

    UNREFERENCED_PARAMETER(Index);

    if(!pFindContext->control) {
        DumpDevice(Devs,DevInfo);
        pFindContext->count++;
        return EXIT_OK;
    }
    if(!DumpDeviceWithInfo(Devs,DevInfo,NULL)) {
        return EXIT_OK;
    }
    if(pFindContext->control&FIND_DEVICE) {
        DumpDeviceDescr(Devs,DevInfo);
    }
    if(pFindContext->control&FIND_CLASS) {
        DumpDeviceClass(Devs,DevInfo);
    }
    if(pFindContext->control&FIND_STATUS) {
        DumpDeviceStatus(Devs,DevInfo);
    }
    if(pFindContext->control&FIND_RESOURCES) {
        DumpDeviceResources(Devs,DevInfo);
    }
    if(pFindContext->control&FIND_DRIVERFILES) {
        DumpDeviceDriverFiles(Devs,DevInfo);
    }
    if(pFindContext->control&FIND_STACK) {
        DumpDeviceStack(Devs,DevInfo);
    }
    if(pFindContext->control&FIND_HWIDS) {
        DumpDeviceHwIds(Devs,DevInfo);
    }
    if (pFindContext->control&FIND_DRIVERNODES) {
        DumpDeviceDriverNodes(Devs,DevInfo);
    }
    pFindContext->count++;
    return EXIT_OK;
}

0 篇笔记 写笔记

Devcon hwids命令
任何设备的与驱动都是通过设备的硬件ID进行关联的。设备的ID用于标识设备的身份,DevCon.exe关于ID的操作都是通过HwIDs参数来执行的。设备的ID包括:硬件ID兼容ID和设备实例ID.Devcon.exe HwIDs语法devcon [/m:\computer] hwids {......
解析INF文件中支持的设备硬件ID
安装Windows驱动,首先得知道INF支持的硬件ID.本人手中有一个测试的inf文件,其内容如下:设备支持的硬件ID如下:字符串内容如下:编写一个程序,用来解析INF文件。#include #include #include......
SetupAPI根据硬件ID获取驱动INF文件和驱动日期版本信息
SetupAPI根据硬件ID获取驱动INF文件和驱动日期版本信息。注释掉的代码是获取该硬件的所有可用驱动信息。代码是逐渐完善的,没想到可以直接从注册表信息中获取到。SetupDiOpenDevRegKey打开的注册表路径示例为:计算机HKEY_LOCAL_MACHINESYSTEM......
Devcon hwids命令源代码实现
Devcon hwids命令显示设备的硬件ID信息。主要的显示包括如下:了解过之前几个命令的同学应该觉地比较简单,因为或多或少有些信息如设备友名,设备实例名路径我们都获取过,而设备的硬件ID兼容ID其实与是比较简单是,和设备的友名一样,是通过SetupDiGetDeviceRegistryPro......
虚拟总线创建子设备返回无效ID
虚拟了一个虚拟总线设备,从设备管理器中看来是正常的,但从功能上来看是不正常的。在设备管理器中提示如下:这个设备运转正常。Windows 无法识别与该硬件连接的一个次要设备,原因使该设备没有有效的硬件标识号。请与硬件制造商联系取得协助。从上面的提示来看,是因为无一个有效的硬件标识号。什么是硬件标识号......
作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!