windows device manager diff(设备管理器内容变化后的比较)

windows device manager diff(设备管理器内容变化后的比较)

前言

打开设备管理器, 插入了一个USB设备, 想在设备管理器中看看, 多了哪些设备.

人工识别, 眼睛都看花了, 感到好无助.

去找了一个网上大神写好的工程(codeproject上的DevMgr-SRC.zip, 一个简版的设备管理器), 准备添加一个导出按钮, 将当前检测结果导出成文本.

在设备插入前后, 分别导出文本列表. 然后用BC4比较, 就知道USB插入后, 设备的变化了.

花了1天, 将这个功能升级完了.

这个实现(设备管理器导出内容的比较)有2个用处:

  • 本机插入设备前后的设备管理器中的设备比较
  • 同型号或相同配置计算机之间的设备比较

实验

网上大神的工程原始url

https://www.codeproject.com/script/Articles/Download.aspx?file=/KB/cpp/DevMgr/DevMgr-SRC.zip&rp=https://www.codeproject.com/

原始效果

请添加图片描述

这就是个设备管理器啊.

和win10自带的设备管理器比较了一下, 基本一致.

实验环境

win10专业工作站版 21H2(19044.1806)

Microsoft Visual Studio Enterprise 2019 版本 16.11.16

实验

原始工程是vc6写的.

手头只有vs2022. 试了一下, vs2022不支持.dsw工程.

装了vs2019企业版, 可以打开.dsw工程, 转换完, 直接能编译运行.

去掉警告

编译选项改成/Zi

请添加图片描述

禁掉警告C4477, C4996

请添加图片描述

启用函数级链接

请添加图片描述

不用最小生成

请添加图片描述

不要CRT函数警告

请添加图片描述

一般低版本vs工程(e.g. VC6)转成高版本vs工程(e.g. VS2017, VS2019), 就这些编译选项要修改.

修改完编译选项, 编译出来0错误, 0警告.

已启动重新生成…
1>------ 已启动全部重新生成: 项目: DevMgr, 配置: Debug Win32 ------
1>DevMgr.c
1>GetTypeInfo.c
1>Setup.c
1>SysSetup.c
1>Util.c
1>WDMSetup.c
1>正在生成代码...
1>DevMgr.vcxproj -> D:\my_dev\my_local_git_prj\soft\windows_device_manager_diff\src\DevMgr_SRC_SP1\Debug\DevMgr.exe
========== 全部重新生成: 成功 1 个,失败 0 个,跳过 0 个 ==========

修正原始工程bug

bug1

程序跑起来后, 在 char EnumWDMDriver(const UINT nIdTree, const UINT nIdBmp) 尾巴处, 要返回的地方报异常如下:

请添加图片描述

看报错, 知道是和变量wImageIdx有关.

在EnumWDMDriver()查找 wImageIdx 参考点, 看了一下, 变量类型定义错了.

原始定义是short int , 但是API要求的都是int.

修正后如下:

    while (1)
    {
        if (SetupDiEnumDeviceInfo(hDevInfo,
                                  wIndex,
                                  &spDevInfoData))
        {
            char  szBuf[MAX_PATH] = {0};

            // short wImageIdx = 0;
            int wImageIdx       = 0; // to fix : when this function return, reprot exception : Run-Time Check Failure #2 - Stack around the variable 'wImageIdx' was corrupted.
            short wItem           = 0;

重新编译运行, 异常消失.

bug2

SP_DRVINFO_DETAIL_DATA 变量的长度使用了硬编码, 导致栈溢出.

从这个 bug能看出, 在工程中使用可能会被第三方改掉的常数, 是陋习.

e.g. 一个第三方SDK的结构size, 人家以后有权修改啊. 非要操作第三方的结构size, 要使用sizeof(结构类型名称), 不要直接使用当前类型的数字size.

修正如下

        while (1)
        {
            spDrvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
            if (SetupDiEnumDriverInfo(hDevInfo,
                                      &spDevInfoData,
                                      SPDIT_COMPATDRIVER,
                                      wIdx++,
                                      &spDrvInfoData))
            {
                // char szBuf[2048] = {0};
                // int temp = sizeof(spDrvInfoDetail); // 796

                // memcpy(&spDrvInfoDetail, szBuf, sizeof(SP_DRVINFO_DETAIL_DATA));
                memset(&spDrvInfoDetail, 0, sizeof(SP_DRVINFO_DETAIL_DATA));

测试原始工程

正常用了用, 改过之后, 原始工程没报异常了, 正常使用.

开始修改原始工程

准备加个按钮, 将手工点击左边设备数显示的右边的设备内容导出为文本, 用于BC4比较设备插入前后的不同.

请添加图片描述

请添加图片描述

按钮消息处理

 case IDC_EXPORT_TXT:
                {
                    cb_export_txt(hDlg, uMsg, wParam, lParam);
                };
                break;

//
                case IDC_COPYPATHBTN:
                {
                    HGLOBAL hMem            = 0L;
INT_PTR CALLBACK cb_export_txt(HWND hDlg, UINT uMsg,
    WPARAM wParam, LPARAM lParam)
{
    // cb_export_txt(hDlg, uMsg, wParam, lParam);
    return 0;
}

现在的任务, 就是实现cb_export_txt()

写好的cb_export_txt()和相关实现

就用git比较修改前后的代码, 直接贴在这了.


INT_PTR CALLBACK cb_export_txt(HWND hDlg, UINT uMsg,
    WPARAM wParam, LPARAM lParam)
{
    int iCnt = 0;

    iCnt = getAllDeviceCnt(); // 192
    enumTreeCtrl(IDC_TREE1);
    MessageBox(hDlg, "export finished!", "info", MB_ICONINFORMATION);
    return 0;
}

HTREEITEM fn_get_tree_root_node(HWND hTreeView, const UINT nIdTree)
{
    HTREEITEM hNode = NULL;
    TVITEM    tvItem = { 0 };
    char      szText[256] = { 0 };
    int nNodeCnt = 0;

    nNodeCnt = (int)SendMessage(hTreeView, TVM_GETCOUNT, 0, 0); // 220

    hNode = (HTREEITEM)SendMessage(hTreeView,
        TVM_GETNEXTITEM,
        TVGN_ROOT, // TVGN_ROOT or TVGN_CHILD, not be TVGN_NEXT
        (LPARAM)NULL
    );

    if (NULL != hNode)
    {
        tvItem.mask = TVIF_TEXT | TVIF_HANDLE;
        tvItem.pszText = szText;
        tvItem.cchTextMax = sizeof(szText) - 1;
        RtlZeroMemory(szText, sizeof(szText));

        tvItem.hItem = hNode; // !
        SendMessage(hTreeView, TVM_GETITEM, 0, (LPARAM)&tvItem); // param1 must be hTreeView
        if (*szText)
        {
            // watch szText
            // LS-PRECISION356
        };
    }


    return hNode;
}

#define OUTPUT_FILE_NAME "device_manager_export.txt"

void fn_get_tree_Level_3_node(HWND hTreeView, HTREEITEM hNodeL1, const char* psz_NodeL1_name, HTREEITEM hNodeL2, const char* psz_NodeL2_name)
{
    FILE* pFile = NULL;
    char szBuf[4096] = { '\0' };

    pFile = fopen(OUTPUT_FILE_NAME, "a");
    if (NULL != pFile)
    {
        memset(szBuf, 0, sizeof(szBuf));
        sprintf(szBuf, "%s : %s\r\n", psz_NodeL1_name, psz_NodeL2_name);
        fwrite(szBuf, sizeof(char), strlen(szBuf), pFile);

        fclose(pFile);
    }
}

void fn_get_tree_Level_2_node(HWND hTreeView, HTREEITEM hNodeL1, const char* psz_NodeL1_name)
{
    HTREEITEM hNode = NULL;
    TVITEM    tvItem = { 0 };
    char      szText[256] = { 0 };
    int nNodeCnt = 0;
    BOOL bFirtLoop = TRUE;

    // psz_NodeL1_name like below
    // 安全设备
    // 处理器
    do {
        hNode = (HTREEITEM)SendMessage(hTreeView,
            TVM_GETNEXTITEM,
            bFirtLoop ? TVGN_CHILD : TVGN_NEXT,
            bFirtLoop ? (LPARAM)hNodeL1 : (LPARAM)hNode
        );

        bFirtLoop = FALSE;

        if (NULL != hNode)
        {
            tvItem.mask = TVIF_TEXT | TVIF_HANDLE;
            tvItem.pszText = szText;
            tvItem.cchTextMax = sizeof(szText) - 1;
            RtlZeroMemory(szText, sizeof(szText));

            tvItem.hItem = hNode; // !
            SendMessage(hTreeView, TVM_GETITEM, 0, (LPARAM)&tvItem);
            if (*szText)
            {
                // watch szText

            };

            nNodeCnt++;
            if (nNodeCnt >= 2)
            {
                nNodeCnt = nNodeCnt;
            }

            fn_get_tree_Level_3_node(hTreeView, hNodeL1, psz_NodeL1_name, hNode, szText);

            continue;
        }

        break;
    } while (TRUE);
}

void fn_get_tree_Level_1_node(HWND hTreeView, HTREEITEM hRoot)
{
    HTREEITEM hNode = NULL;
    TVITEM    tvItem = { 0 };
    char      szText[256] = { 0 };
    int nNodeCnt = 0;
    BOOL bFirtLoop = TRUE;

    
    do {
        hNode = (HTREEITEM)SendMessage(hTreeView,
            TVM_GETNEXTITEM,
            bFirtLoop ? TVGN_CHILD : TVGN_NEXT,
            bFirtLoop ? (LPARAM)hRoot : (LPARAM)hNode
        );

        bFirtLoop = FALSE;

        if (NULL != hNode)
        {
            tvItem.mask = TVIF_TEXT | TVIF_HANDLE;
            tvItem.pszText = szText;
            tvItem.cchTextMax = sizeof(szText) - 1;
            RtlZeroMemory(szText, sizeof(szText));

            tvItem.hItem = hNode; // !
            SendMessage(hTreeView, TVM_GETITEM, 0, (LPARAM)&tvItem);
            if (*szText)
            {
                // watch szText
                // IDE ATA/ATAPI 控制器
                // USB 连接器管理器
                // 安全设备
                // 处理器

            };

            fn_get_tree_Level_2_node(hTreeView, hNode, szText);

            continue;
        }

        break;
    } while (TRUE);
}

void enumTreeCtrl(const UINT nIdTree)
{
    HWND                   hTreeView = GetDlgItem(_hDlg, nIdTree);
    HTREEITEM hRoot = 0L;
    HTREEITEM hChildItem = 0L;
    HTREEITEM hParentItem = NULL;
    char      szText[128] = { 0 };
    TVITEM    tvItem = { 0 };
    int       iLoop = 0;
    int       nNodeAllCnt = 0;
    //
    tvItem.mask = TVIF_TEXT | TVIF_HANDLE;
    tvItem.pszText = szText;
    tvItem.cchTextMax = sizeof(char) * 127;
    // nNodeAllCnt = (int)SendMessage(hTreeView, TVM_GETCOUNT, 0, 0);
    RtlZeroMemory(szText, sizeof(char) * 128);

    hRoot = fn_get_tree_root_node(hTreeView, nIdTree);
    if (NULL != hRoot)
    {
        fn_get_tree_Level_1_node(hTreeView, hRoot);
    }
    

    /*

    hParentItem = hRoot;
    for (iLoop = 0; iLoop < nNodeAllCnt; iLoop++)
    {
        hChildItem = (HTREEITEM)SendMessage(hTreeView,
            TVM_GETNEXTITEM,
            TVGN_NEXT,
            (LPARAM)hParentItem
        );

        if (0 == iLoop)
        {

        }
        else {
            hChildItem = (HTREEITEM)SendMessage(hTreeView,
                TVM_GETNEXTITEM,
                TVGN_NEXT,
                (LPARAM)hParentItem
            );

            if (NULL == hChildItem)
            {
                hChildItem = (HTREEITEM)SendMessage(hTreeView,
                    TVM_GETNEXTITEM,
                    TVGN_CHILD,
                    (LPARAM)hParentItem
                );
            }
        }
        
        tvItem.hItem = hChildItem;
        SendMessage(hTreeView, TVM_GETITEM, 0, (LPARAM)&tvItem);
        if (*szText)
        {
            // watch szText
        };
        hParentItem = hChildItem;
    };
    */
}

运行效果

请添加图片描述

设备管理器内容变化后的比较

设备插入前, 导出一份device_manager_export.txt, 改名为 device_manager_export_before.txt

设备插入后, 导出一份device_manager_export.txt, 改名为 device_manager_export_after.txt

打开BC4, 建立文本比较的工程, 将2个文本都拖进去, 点击跳到区别的按钮, 就可以看到差别了.

请添加图片描述

比如, 我插入了一个1拖4的USB扩展坞, 在导出列表进行比较时, 就能看到插入设备后, 多了2个设备(USB集线器和USB高速集线器)

修改后的工程下载点

本来想传到码云, 奈何不方便. 码云光审核就要2个工作日.

github就不奢望了, 能偶尔顺利迁出大神的工程就满意了.

当前就只有传到csdn的下载区方便一些(随时可以上传, 审核时间短), 而且稳定安全. csdn如果非要加下载积分, 就随他了. 虽然吃相挺难看的(将用户上传的免费资源, 当作收费的资源来挣钱).

十全十美的事情不存在的, 总有一些瑕疵(bug数量多少而已), 就像人生也不可能完美一样, 总有缺憾, 自己能接受就好.

工程下载点 : prj_windows_device_manager_diff_2022_0708_1453.zip

备注

有同学说下载资源失效了,那是因为俺不想跟CSDN玩了,CSDN吃相是真难看啊。
参见CSDN - 从CSDN下载自己上传的资源要下载码, 自己无法下载

就当CSDN是个纯博客网站, 写个纯文字笔记还是挺舒服的。

备注

CSDN的同学说笔记中没有getAllDeviceCn()的实现
在这里插入图片描述
将工程找出来,将getAllDeviceCn()所在的.cpp贴出来,供这位同学参考。
在这里插入图片描述

Setup.h

#ifndef __ICE_SETUP_H
#define __ICE_SETUP_H
//
#ifdef __cplusplus
extern "C" {
#endif
//
#pragma once
//
#include "devmgr.h"
#include <cfgmgr32.h>
#include <newdev.h>
#include <setupapi.h>
#include <shlobj.h>
#include "gettypeinfo.h"
#include "util.h"
//
#pragma comment(lib, "setupapi.lib")
#pragma comment(lib, "newdev.lib")
#pragma comment(lib, "shell32.lib")
//
typedef struct _tagDEVICE_ORDER
{
    char szDevName[LINE_LEN];
    struct _tagDEVICE_ORDER *pNext;
} DEVICE_ORDER, *PDEVICE_ORDER;
//
typedef struct _tagDEVLIST
{
    GUID               guid;
    short              wOrder;
    short              wIndex;
    char               szInstallID[LINE_LEN];
    char               szName[MAX_PATH];
    char               szPath[MAX_PATH];
    struct _tagDEVLIST *pNext;
}DEVICE_LIST, *PDEVICE_LIST;
//
void InitialImageData();
void ListImageDataInitial(const UINT);
char EnumWDMDriver(const UINT, const UINT);
void GetDriverDetialInfo(HTREEITEM, const UINT, const char *, const int, const int);
void GetDeviceInstanceID(HDEVINFO, SP_DEVINFO_DATA*, char*);
void GetDeviceInterfaceInfo(HDEVINFO, SP_DEVINFO_DATA, char*);
void GetOtherInfo(GUID, const short, const UINT, const UINT);
void FindSpecResource(const DEVINST, const DWORD, const short, const UINT);
//
HTREEITEM MakeRootTree();
//
char InitialDeviceOrder();
DEVICE_ORDER* AllocNewDeviceOrderNode();
char AddNewDeviceOrderNode(const char*);
short FindDeviceOrder(const char*);
int getAllDeviceCnt(); // ls
void enumTreeCtrl(const UINT nIdTree); // ls
void FreeAllDeviceOrderNode();
//
char InitialDeviceList();
DEVICE_LIST* AllocNewDeviceNode();
char AddNewDeviceNode(const GUID, const char*, const char*,
                      const char*, const int, const short);
char FindDeviceName(const char*, const UINT, const UINT);
void GetDeviceDetailInfo(DEVICE_LIST*);
void DisplayDriverDetailInfo(HTREEITEM, const UINT, 
                             const char*, const int, const int);
void FreeAllocDeviceNode();
//
void GetMemoryResource(MEM_DES*, const ULONG, const UINT);
void GetIOResource(IO_DES*, const ULONG, const UINT);
void GetDMAResource(DMA_DES*, const ULONG, const UINT);
void GetIRQResource(IRQ_DES*, const ULONG, const UINT);
//
void GetMoreInformation(HDEVINFO, SP_DEVINFO_DATA, const UINT);
//
#ifdef __cplusplus
}
#endif
//
#endif

Setup.c

//
// (w)ritten by Chuan-Liang Teng 2006, mailto:clteng@ms6.hinet.net
//
#include "setup.h"
#include "resource.h"
//
SP_CLASSIMAGELIST_DATA _spImageData = {0};
//
extern HINSTANCE _hInst;
extern HWND      _hDlg;
//
DEVICE_LIST  *_pHead      = 0L;
DEVICE_ORDER *_pOrderHead = 0L;
//
char InitialDeviceOrder()
{
    _pOrderHead = AllocNewDeviceOrderNode();
    return (_pOrderHead) ? 1 : 0;
};
//
DEVICE_ORDER* AllocNewDeviceOrderNode()
{
    DEVICE_ORDER* pNew = (DEVICE_ORDER*)LocalAlloc(LPTR, sizeof(DEVICE_ORDER));
//
    if (!pNew)
    {
        ShowErrorMsg(_hDlg, GetLastError(), "LocalAlloc");
        return 0;
    };
    RtlZeroMemory(pNew->szDevName, sizeof(char)*LINE_LEN);
    pNew->pNext = 0L;
    return pNew;
};
//
char AddNewDeviceOrderNode(const char* szDevName)
{
    DEVICE_ORDER* pAdd = AllocNewDeviceOrderNode();
//
    if (!pAdd)
        return 0;
    memcpy(pAdd->szDevName, szDevName, strlen(szDevName));
    pAdd->pNext = _pOrderHead->pNext;
    _pOrderHead->pNext = pAdd;
    return 1;
};
//
short FindDeviceOrder(const char* szName)
{
    DEVICE_ORDER *pList = _pOrderHead->pNext;
    short        wOrder = 0;
//
    while (pList)
    {
        if (!strcmp(pList->szDevName, szName))
            wOrder++;
        pList = pList->pNext;
    };
    return wOrder;
};

int getAllDeviceCnt()
{
    DEVICE_ORDER* pList = _pOrderHead->pNext;
    short        wOrder = 0;
    //
    while (pList)
    {
        wOrder++; // watch pList->szDevName
        pList = pList->pNext;
    };
    return wOrder;
}
//
void FreeAllDeviceOrderNode()
{
    DEVICE_ORDER *pDel = _pOrderHead->pNext;
    DEVICE_ORDER *pTmp = 0L;
//
    while (pDel->pNext)
    {
        pTmp = pDel;
        pDel = pDel->pNext;
        LocalFree(pTmp);
    };
    LocalFree(_pOrderHead);
    _pOrderHead = 0L;
};
//
char InitialDeviceList()
{
    _pHead = AllocNewDeviceNode();
    return (_pHead) ? 1 : 0;
};
//
DEVICE_LIST* AllocNewDeviceNode()
{
    DEVICE_LIST* pNew = (DEVICE_LIST*)LocalAlloc(LPTR, sizeof(DEVICE_LIST));
//
    if (!pNew)
    {
        ShowErrorMsg(_hDlg, GetLastError(), "LocalAlloc");
        return 0;
    };
    RtlZeroMemory(&pNew->guid, sizeof(GUID));
    RtlZeroMemory(pNew->szInstallID, sizeof(char)*LINE_LEN);
    RtlZeroMemory(pNew->szName, sizeof(char)*MAX_PATH);
    RtlZeroMemory(pNew->szPath, sizeof(char)*MAX_PATH);
    pNew->wOrder = -1;
    pNew->wIndex = -1;
    pNew->pNext = 0L;
    return pNew;
};
//
char AddNewDeviceNode(const GUID guid,
                      const char* szName,
                      const char* szInstallID,
                      const char* szPath,
                      const int wIndex,
                      const short wOrder)
{
    DEVICE_LIST* pAdd = AllocNewDeviceNode();
//
    if (!pAdd)
        return 0;
    memcpy(&pAdd->guid, &guid, sizeof(GUID));
    memcpy(pAdd->szInstallID, szInstallID, strlen(szInstallID));
    memcpy(pAdd->szName, szName, strlen(szName));
    memcpy(pAdd->szPath, szPath, strlen(szPath));
    pAdd->wIndex = wIndex;
    pAdd->wOrder = wOrder;
    pAdd->pNext = _pHead->pNext;
    _pHead->pNext = pAdd;
    return 1;
};
//
char FindDeviceName(const char* szName, const UINT nIDList1,
                    const UINT nIDList2)
{
    DEVICE_LIST *pList = _pHead->pNext;
//
    while (pList)
    {
        if (!strcmp(pList->szName, szName))
        {
            GetOtherInfo(pList->guid, pList->wOrder, nIDList1, nIDList2);
            GetDeviceDetailInfo(pList);
            return 1;
        };
        pList = pList->pNext;
    };
    return 0;
};
//
void FreeAllocDeviceNode()
{
    DEVICE_LIST *pDel = _pHead->pNext;
    DEVICE_LIST *pTmp = 0L;
//
    while (pDel->pNext)
    {
        pTmp = pDel;
        pDel = pDel->pNext;
        LocalFree(pTmp);
    };
    LocalFree(_pHead);
    _pHead = 0L;
};
//
void GetDeviceDetailInfo(DEVICE_LIST* pList)
{
    char       szBuf[MAX_PATH] = {0};
    HWND       hList           = GetDlgItem(_hDlg, IDC_LIST1);
//
    ConvertGUIDToString(pList->guid, szBuf);
    ListViewInsertItemText(hList, 0, 1, szBuf);
    ListViewInsertItemText(hList, 2, 1, pList->szInstallID);
    sprintf(szBuf, "%d", pList->wIndex);
    ListViewInsertItemText(hList, 10, 1, szBuf);
    ListViewInsertItemText(hList, 11, 1, pList->szPath);
};
//
void InitialImageData()
{
    HIMAGELIST hImageListView  = 0L;
//
    SetupDiDestroyClassImageList(&_spImageData);
    RtlZeroMemory(&_spImageData, sizeof(SP_CLASSIMAGELIST_DATA));
    _spImageData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
    SetupDiGetClassImageList(&_spImageData);
};
//
void DisplayDriverDetailInfo(HTREEITEM hTreeChild, const UINT nID, 
                             const char *szBuf, const int iImageIdx, const int iSelectImage)
{
    TVINSERTSTRUCT tvStruct = {0};
    HWND           hTree    = GetDlgItem(_hDlg, nID);
//
    tvStruct.hParent      = hTreeChild;
    tvStruct.hInsertAfter = TVI_LAST;
    tvStruct.item.mask    = TVIF_IMAGE | TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_HANDLE;
    tvStruct.item.mask   |= TVIF_PARAM;
    tvStruct.item.lParam  = 1;
    tvStruct.item.pszText = (char*)szBuf;
    tvStruct.item.iImage  = iImageIdx;
    tvStruct.item.iSelectedImage = iImageIdx;
    SendMessage(hTree, TVM_INSERTITEM, 0, (LPARAM)&tvStruct);
};
//
void GetDeviceInstanceID(HDEVINFO hDevInfo,
                         SP_DEVINFO_DATA* pspDevInfoData,
                         char *szInstanceID)
{
    if (!SetupDiGetDeviceInstanceId(hDevInfo,
                                    pspDevInfoData,
                                    szInstanceID,
                                    LINE_LEN,
                                    0))
        ShowErrorMsg(_hDlg, GetLastError(), "SetupDiBuildDriverInfoList");
};


//
char EnumWDMDriver(const UINT nIdTree, const UINT nIdBmp)
{
    HDEVINFO        hDevInfo         = 0L;
    SP_DEVINFO_DATA spDevInfoData    = {0};
    short           wIndex           = 0;
    HTREEITEM       hTreeChild       = 0L;
//
    hTreeChild = MakeDeviceRootTree(_spImageData, nIdTree, nIdBmp);
    if (!hTreeChild)
        return 0;
//
    hDevInfo = SetupDiGetClassDevs(0L, 0L, _hDlg, DIGCF_PRESENT |
                                   DIGCF_ALLCLASSES | DIGCF_PROFILE);
    if (hDevInfo == (void*)-1)
    {
        ShowErrorMsg(_hDlg, GetLastError(), "SetupDiGetClassDevs");
        return 0;
    };
//
    wIndex = 0;
    spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
    SendMessage(GetDlgItem(_hDlg, nIdTree), TVM_SETIMAGELIST,
                TVSIL_NORMAL, (LPARAM)_spImageData.ImageList);
//
    while (1)
    {
        if (SetupDiEnumDeviceInfo(hDevInfo,
                                  wIndex,
                                  &spDevInfoData))
        {
            char  szBuf[MAX_PATH] = {0};

            // short wImageIdx = 0;
            int wImageIdx       = 0; // to fix : when this function return, reprot exception : Run-Time Check Failure #2 - Stack around the variable 'wImageIdx' was corrupted.
            short wItem           = 0;
//
            if (!SetupDiGetDeviceRegistryProperty(hDevInfo,
                                                  &spDevInfoData,
                                                  SPDRP_CLASS, //SPDRP_DEVICEDESC,
                                                  0L,
                                                  (PBYTE)szBuf,
                                                  2048,
                                                  0))
            {
                wIndex++;
                continue;
            };
//
            if (SetupDiGetClassImageIndex(&_spImageData,
                                          &spDevInfoData.ClassGuid,
                                          (int*)&wImageIdx))
            {
                TVINSERTSTRUCT         tvStruct        = {0};
                HWND                   hTree           = GetDlgItem(_hDlg, nIdTree);
                char                   szName[64]      = {0};
                char                   szID[LINE_LEN]  = {0};
                char                   szPath[MAX_PATH] = {0};
                HTREEITEM              hItem;
                DWORD                  dwRequireSize;
                short                  wOrder;
//
                if (!SetupDiGetClassDescription(&spDevInfoData.ClassGuid,
                                                szBuf,
                                                MAX_PATH,
                                                &dwRequireSize))
                {
                    wIndex++;
                    continue;
                };
                wOrder = FindDeviceOrder(szBuf);
                if (!AddNewDeviceOrderNode(szBuf))
                {
                    wIndex++;
                    continue;
                };
                hItem = TreeViewFindChild(hTree, hTreeChild, szBuf);
                if (!hItem)
                {
                    tvStruct.hParent      = hTreeChild;
                    tvStruct.hInsertAfter = TVI_LAST;
                    tvStruct.item.mask    = TVIF_IMAGE | TVIF_TEXT | TVIF_SELECTEDIMAGE;
                    tvStruct.item.mask   |= TVIF_PARAM;
                    tvStruct.item.lParam  = 1;
                    tvStruct.item.pszText = szBuf;
                    tvStruct.item.iImage  = wImageIdx;
                    tvStruct.item.iSelectedImage = wImageIdx;
                    hItem = (HTREEITEM)SendMessage(hTree, TVM_INSERTITEM, 0, (LPARAM)&tvStruct);
                    wOrder = 0;
                };
                GetDeviceInstanceID(hDevInfo, &spDevInfoData, szID);
                GetDeviceInterfaceInfo(hDevInfo, spDevInfoData, szPath);
//
                if (SetupDiGetDeviceRegistryProperty(hDevInfo,
                                                     &spDevInfoData,
                                                     SPDRP_FRIENDLYNAME,
                                                     0L,
                                                     (PBYTE)szName,
                                                     63,
                                                     0))
                {
                    DisplayDriverDetailInfo(hItem, nIdTree, szName, wImageIdx, wImageIdx);
                    AddNewDeviceNode(spDevInfoData.ClassGuid, szName, szID, szPath, wIndex, wOrder);
                }
                else if (SetupDiGetDeviceRegistryProperty(hDevInfo,
                                                     &spDevInfoData,
                                                     SPDRP_DEVICEDESC,
                                                     0L,
                                                     (PBYTE)szName,
                                                     63,
                                                     0))
                {
                    DisplayDriverDetailInfo(hItem, nIdTree, szName, wImageIdx, wImageIdx);
                    AddNewDeviceNode(spDevInfoData.ClassGuid, szName, szID, szPath, wIndex, wOrder);
//                    if (!GetFirmwareEnvironmentVariable(szName, (LPCSTR)&spDevInfoData.ClassGuid, szBuf, 127))
//                        ShowErrorMsg(_hDlg, GetLastError(), "GetFirmwareEnvironmentVariable");
                };
            };
//            SetupDiDestroyDriverInfoList(hDevInfo, &spDevInfoData, SPDIT_COMPATDRIVER);
        }
        else
            break;
        wIndex++;
    };
    SendMessage(GetDlgItem(_hDlg, nIdTree), TVM_EXPAND,
                TVE_EXPAND, (LPARAM)hTreeChild);
    SendMessage(GetDlgItem(_hDlg, nIdTree), TVM_SORTCHILDREN,
                0, (LPARAM)hTreeChild);
    TreeView_SetItemState(GetDlgItem(_hDlg, nIdTree), hTreeChild, TVIS_SELECTED, TVIS_SELECTED);
//    SendMessage(GetDlgItem(_hDlg, nIdTree), TVM_SELECTITEM,
//                TVGN_FIRSTVISIBLE, (LPARAM)hTreeChild);
    SetupDiDestroyDeviceInfoList(hDevInfo);
    return 1;
};
//
void GetMemoryResource(MEM_DES* pMemDes, const ULONG ulSize, const UINT nID)
{
    char  szBuf[128] = {0};
    HWND  hListView  = GetDlgItem(_hDlg, nID);
    short wLoop      = 0;
    short wCnt       = ListViewGetItemCount(hListView);
//
    sprintf(szBuf, "%08X - ", (unsigned int)pMemDes->MD_Alloc_Base);
    sprintf(szBuf+strlen(szBuf), "%08X", (unsigned int)pMemDes->MD_Alloc_End);
    if (GetACP() == 950)
        ListViewInsertItemText(hListView, wCnt, 0, "癘拘砰絛瞅");
    else
        ListViewInsertItemText(hListView, wCnt, 0, "Memory Range");
    ListViewInsertItemText(hListView, wCnt, 1, szBuf);
//
    if (pMemDes->MD_Count)
    {
        for (wLoop = 0; wLoop < (short)(ulSize - 
                               (LONG)(sizeof(MEM_DES) / pMemDes->MD_Type)); wLoop++)
        {
            MEM_RANGE *pMemRange = (MEM_RANGE*)(pMemDes + 1);// + pMemDes->MD_Type);
            if (pMemRange->MR_Min != 0 && pMemRange->MR_Max != 0 &&
                (pMemRange->MR_Min < pMemRange->MR_Max))
            {
                sprintf(szBuf, "%08X - ", (unsigned int)pMemRange->MR_Min);
                sprintf(szBuf+strlen(szBuf), "%08X", (unsigned int)pMemRange->MR_Max);
                if (GetACP() == 950)
                    ListViewInsertItemText(hListView, wCnt+wLoop+1, 0, "癘拘砰絛瞅");
                else
                    ListViewInsertItemText(hListView, wCnt+wLoop+1, 0, "Memory Range");
                ListViewInsertItemText(hListView, wCnt+wLoop+1, 1, szBuf);
            };
        };
    };
};
//
void GetIOResource(IO_DES *pIODes, const ULONG ulSize, const UINT nID)
{
    char  szBuf[128] = {0};
    HWND  hListView  = GetDlgItem(_hDlg, nID);
    short wLoop      = 0;
    short wCnt       = ListViewGetItemCount(hListView);
//
    sprintf(szBuf, "%04X - ", (unsigned int)pIODes->IOD_Alloc_Base);
    sprintf(szBuf+strlen(szBuf), "%04X", (unsigned int)pIODes->IOD_Alloc_End);
//
    if (GetACP() == 950)
        ListViewInsertItemText(hListView, wCnt, 0, "块/块絛瞅");
    else
        ListViewInsertItemText(hListView, wCnt, 0, "IO Range");
    ListViewInsertItemText(hListView, wCnt, 1, szBuf);
//
    if (pIODes->IOD_Count)
    {
        for (wLoop = 0; wLoop < (short)(ulSize -
                            (ULONG)(sizeof(IO_DES) / pIODes->IOD_Type)); wLoop++)
        {
            IO_RANGE *pIORange = (IO_RANGE*)(pIODes + 1); // + (wLoop * pIODes->IOD_Type));
            if (pIORange->IOR_Min != 0 && pIORange->IOR_Max != 0 &&
                (pIORange->IOR_Min < pIORange->IOR_Max))
            {
                sprintf(szBuf, "%04X - ", (unsigned int)pIORange->IOR_Min);
                sprintf(szBuf+strlen(szBuf), "%04X", (unsigned int)pIORange->IOR_Max);
                if (GetACP() == 950)
                    ListViewInsertItemText(hListView, wCnt+wLoop+1, 0, "块/块絛瞅");
                else
                    ListViewInsertItemText(hListView, wCnt, 0, "IO Range");
                ListViewInsertItemText(hListView, wCnt+wLoop+1, 1, szBuf);
            };
        };
    };
};
//
void GetDMAResource(DMA_DES* pDMADes, const ULONG ulSize, const UINT nID)
{
    char  szBuf[128] = {0};
    HWND  hListView  = GetDlgItem(_hDlg, nID);
    short wLoop      = 0;
    short wCnt       = ListViewGetItemCount(hListView);
//
    sprintf(szBuf, "%02d", pDMADes->DD_Alloc_Chan);
    ListViewInsertItemText(hListView, wCnt, 0, "DMA");
    ListViewInsertItemText(hListView, wCnt, 1, szBuf);
//
    if (pDMADes->DD_Count)
    {
        for (wLoop = 0; wLoop < (short)(ulSize -
                            (ULONG)(sizeof(DMA_DES) / pDMADes->DD_Type)); wLoop++)
        {
            DMA_RANGE *pDMARange = (DMA_RANGE*)(pDMADes + 1); // + (wLoop * pIODes->IOD_Type));
            if (pDMARange->DR_Min != 0 && pDMARange->DR_Max != 0 &&
                (pDMARange->DR_Min < pDMARange->DR_Max))
            {
                sprintf(szBuf, "%02d - ", pDMARange->DR_Min);
                sprintf(szBuf+strlen(szBuf), "%02d", pDMARange->DR_Max);
                ListViewInsertItemText(hListView, wCnt+wLoop+1, 0, "DMA");
                ListViewInsertItemText(hListView, wCnt+wLoop+1, 1, szBuf);
            };
        };
    };
};
//
void GetIRQResource(IRQ_DES* pIRQDes, const ULONG ulSize, const UINT nID)
{
    char  szBuf[128] = {0};
    HWND  hListView  = GetDlgItem(_hDlg, nID);
    short wLoop      = 0;
    short wCnt       = ListViewGetItemCount(hListView);
//
    sprintf(szBuf, "%02d", pIRQDes->IRQD_Alloc_Num);
    ListViewInsertItemText(hListView, wCnt, 0, "IRQ");
    ListViewInsertItemText(hListView, wCnt, 1, szBuf);
//
    if (pIRQDes->IRQD_Count)
    {
        for (wLoop = 0; wLoop < (short)(ulSize -
                            (ULONG)(sizeof(IRQ_DES) / pIRQDes->IRQD_Type)); wLoop++)
        {
            IRQ_RANGE *pIRQRange = (IRQ_RANGE*)(pIRQDes + 1); // + (wLoop * pIODes->IOD_Type));
            if (pIRQRange->IRQR_Min != 0 && pIRQRange->IRQR_Max != 0 &&
                (pIRQRange->IRQR_Min < pIRQRange->IRQR_Max))
            {
                sprintf(szBuf, "%02d - ", pIRQRange->IRQR_Min);
                sprintf(szBuf+strlen(szBuf), "%02d", pIRQRange->IRQR_Max);
                ListViewInsertItemText(hListView, wCnt+wLoop+1, 0, "IRQ");
                ListViewInsertItemText(hListView, wCnt+wLoop+1, 1, szBuf);
            };
        };
    };
};
//
void FindSpecResource(const DEVINST DevInst, const DWORD dwResType,
                      const short wOrder, const UINT nID)
{
    char  *pBuf  = 0L;
    short wHeaderSize;
    ULONG ulSize;
//
    CONFIGRET cmRet;
    LOG_CONF  firstLogConf;
    LOG_CONF  nextLogConf;
    RES_DES   rdPrevResDes;
//
    switch(dwResType)
    {
        case ResType_Mem:
            wHeaderSize = sizeof(MEM_DES);
        break;
//
        case ResType_IO:
            wHeaderSize = sizeof(IO_DES);
        break;
//
        case ResType_DMA:
            wHeaderSize = sizeof(DMA_DES);
        break;
//
        case ResType_IRQ: 
            wHeaderSize = sizeof(IRQ_DES);
        break;
    };
//
    cmRet = CM_Get_First_Log_Conf(&firstLogConf, DevInst, ALLOC_LOG_CONF);
    if (cmRet != CR_SUCCESS)
    {
        cmRet = CM_Get_First_Log_Conf(&firstLogConf, DevInst, BOOT_LOG_CONF);
        if (cmRet != CR_SUCCESS)
            return;
    };
//
    cmRet = CM_Get_Next_Res_Des(&nextLogConf,
                                firstLogConf,
                                dwResType,
                                0L,
                                0L);
    if (cmRet != CR_SUCCESS)
    {
        CM_Free_Res_Des_Handle(firstLogConf);
        return;
    };
//
    while (1)
    {
//
        ulSize = 0;
        cmRet = CM_Get_Res_Des_Data_Size(&ulSize, nextLogConf, 0L);
        if (cmRet != CR_SUCCESS)
        {
            CM_Free_Res_Des_Handle(nextLogConf);
            break;
        };
//
        pBuf = (char*)LocalAlloc(LPTR, 2048);
        if (!pBuf)
        {
            ShowErrorMsg(_hDlg, GetLastError(), "LocalAlloc");
            CM_Free_Res_Des_Handle(nextLogConf);
            break;
        };
//
        cmRet = CM_Get_Res_Des_Data(nextLogConf, pBuf, ulSize, 0L);
        if (cmRet != CR_SUCCESS)
        {
            CM_Free_Res_Des_Handle(nextLogConf);
            LocalFree(pBuf);
            break;
        };
//
        switch(dwResType)
        {
            case ResType_Mem:
                GetMemoryResource((MEM_DES*)pBuf, ulSize, nID);
            break;
//
            case ResType_IO:
                GetIOResource((IO_DES*)pBuf, ulSize, nID);
            break;
//
            case ResType_DMA:
                GetDMAResource((DMA_DES*)pBuf, ulSize, nID);
            break;
//
            case ResType_IRQ: 
                GetIRQResource((IRQ_DES*)pBuf, ulSize, nID);
            break;
        };
        rdPrevResDes = 0;
        cmRet = CM_Get_Next_Res_Des(&rdPrevResDes,
                                    nextLogConf,
                                    dwResType,
                                    0L,
                                    0L);
        LocalFree(pBuf);
        if (cmRet != CR_SUCCESS)
           break;
        else
        {
            CM_Free_Res_Des_Handle(nextLogConf);
            nextLogConf = rdPrevResDes;
        };
    };
    CM_Free_Res_Des_Handle(nextLogConf);
};
//
void GetOtherInfo(GUID guid, const short wOrder,
          const UINT nIDList1, const UINT nIDList2)
{
    HDEVINFO         hDevInfo      = 0L;
    SP_DEVINFO_DATA  spDevInfoData = {0};
//
    hDevInfo = SetupDiGetClassDevs(&guid, 0L, _hDlg, DIGCF_PRESENT);
    if (hDevInfo == (void*)-1)
    {
        ShowErrorMsg(_hDlg, GetLastError(), "SetupDiGetClassDevs");
        return;
    };
//
//    wIndex = 0;
    spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
    if (SetupDiEnumDeviceInfo(hDevInfo,
                              wOrder,
                              &spDevInfoData))
    {
        SP_DRVINFO_DATA        spDrvInfoData      = {0};
        SP_DRVINFO_DETAIL_DATA spDrvInfoDetail    = {0};
        char                   szHardware[128]    = {0};
        HWND                   hList              = GetDlgItem(_hDlg, nIDList1);
        DWORD                  dwRequireSize;
        short                  wIdx;
//
        GetMoreInformation(hDevInfo, spDevInfoData, nIDList1);
        // Show Resource Information  
        for (wIdx = ResType_Mem; wIdx <= ResType_IRQ; wIdx++)
            FindSpecResource(spDevInfoData.DevInst,
                             wIdx, wOrder, nIDList2);
//
        if (!SetupDiBuildDriverInfoList(hDevInfo,
                                        &spDevInfoData,
                                        SPDIT_COMPATDRIVER))
            ShowErrorMsg(_hDlg, GetLastError(), "SetupDiBuildDriverInfoList");
        wIdx = 0;
        while (1)
        {
            spDrvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
            if (SetupDiEnumDriverInfo(hDevInfo,
                                      &spDevInfoData,
                                      SPDIT_COMPATDRIVER,
                                      wIdx++,
                                      &spDrvInfoData))
            {
                // char szBuf[2048] = {0};
                // int temp = sizeof(spDrvInfoDetail); // 796

                // memcpy(&spDrvInfoDetail, szBuf, sizeof(SP_DRVINFO_DETAIL_DATA));
                memset(&spDrvInfoDetail, 0, sizeof(SP_DRVINFO_DETAIL_DATA));
                spDrvInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
                dwRequireSize = 0;
                if (SetupDiGetDriverInfoDetail(hDevInfo,
                                               &spDevInfoData,
                                               &spDrvInfoData,
                                               &spDrvInfoDetail,
                                                sizeof(SP_DRVINFO_DETAIL_DATA),
                                               &dwRequireSize))
                {
                    SYSTEMTIME sysTime   = {0};
                    char       szTmp[64] = {0};
//
                    memcpy(szHardware, spDrvInfoDetail.HardwareID,
                           strlen(spDrvInfoDetail.HardwareID));
                    ListViewInsertItemText(hList, 1, 1, szHardware);
                    ListViewInsertItemText(hList, 3, 1, spDrvInfoData.MfgName);
                    ListViewInsertItemText(hList, 4, 1, spDrvInfoData.ProviderName);
                    ListViewInsertItemText(hList, 5, 1, spDrvInfoData.Description);
                    FileTimeToSystemTime(&spDrvInfoData.DriverDate, &sysTime);
                    sprintf(szTmp, "%02d/%02d/%04d", sysTime.wMonth,
                             sysTime.wDay, sysTime.wYear);
                    ListViewInsertItemText(hList, 7, 1, szTmp);
                    ListViewInsertItemText(hList, 6, 1, spDrvInfoDetail.SectionName);
                    ListViewInsertItemText(hList, 8, 1, spDrvInfoDetail.InfFileName);
                }
                else
                    RtlZeroMemory(szHardware, sizeof(char)*128);
            }
            else
            {
                DWORD dwError = GetLastError();
//
                if (dwError != ERROR_NO_MORE_ITEMS)
                    ShowErrorMsg(_hDlg, dwError, "SetupDiEnumDriverInfo");
                break;
            };
            SetupDiDestroyDriverInfoList(hDevInfo, &spDevInfoData, SPDIT_COMPATDRIVER);
        };
        SetupDiDestroyDeviceInfoList(hDevInfo);
    };
};
//
void GetDeviceInterfaceInfo(HDEVINFO hDevInfo, SP_DEVINFO_DATA spDevInfoData,
                            char *szPath)
{
    SP_DEVICE_INTERFACE_DATA spDevInterfaceData = {0};
//
    spDevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
    if (!SetupDiCreateDeviceInterface(hDevInfo,
                                      &spDevInfoData,
                                      &spDevInfoData.ClassGuid,
                                      0L,
                                      0L,
                                      &spDevInterfaceData))
        ShowErrorMsg(_hDlg, GetLastError(), "SetupDiBuildDriverInfoList");
    else
    {
        SP_DEVICE_INTERFACE_DETAIL_DATA *pspDevInterfaceDetail = 0L;
        DWORD                           dwRequire              = 0L;
//
        if (!SetupDiGetDeviceInterfaceDetail(hDevInfo,
                                             &spDevInterfaceData,
                                             0L,
                                             0,
                                             &dwRequire,
                                             0L))
        {
            DWORD dwError = GetLastError();
//
            if (dwError != ERROR_INSUFFICIENT_BUFFER)
            {
                ShowErrorMsg(_hDlg, dwError, "SetupDiBuildDriverInfoList");
                return;
            };
        };
//
        pspDevInterfaceDetail = (SP_DEVICE_INTERFACE_DETAIL_DATA*)LocalAlloc(LPTR,
                                    sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA)*dwRequire);
        pspDevInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
        if (!SetupDiGetDeviceInterfaceDetail(hDevInfo,
                                             &spDevInterfaceData,
                                             pspDevInterfaceDetail,
                                             dwRequire,
                                             &dwRequire,
                                             0L))
        {
            DWORD dwError = GetLastError();
//
            if (dwError != ERROR_INSUFFICIENT_BUFFER)
                ShowErrorMsg(_hDlg, dwError, "SetupDiBuildDriverInfoList");
        }
        else
        {
            memcpy(szPath, pspDevInterfaceDetail->DevicePath,
                   strlen(pspDevInterfaceDetail->DevicePath));
//            switch(spDevInterfaceData.                    
        };
//
        if (pspDevInterfaceDetail)
            LocalFree(pspDevInterfaceDetail);
    };
};

DevMgr.h

#ifndef __ICE_DEVMGR_H
#define __ICE_DEVMGR_H
//
#ifdef __cplusplus
extern "C" {
#endif
//
#pragma once
//
#include <windows.h>
#include <dbt.h>
#include <stdio.h>
#include "util.h"
#include "setup.h"
#include "wdmsetup.h"
#include "syssetup.h"
#include "resource.h"
//
INT_PTR CALLBACK MainDialog(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK InstallDialog(HWND, UINT, WPARAM, LPARAM);
//
void DisableRadioBtn(HWND, const char);
void GetInstallOption(HWND, short*, short*);
char OpenINFFile(const char, char*);
void SetCharSet(const UINT, const UINT);
void DeleteINFFile(const char*);
BOOL EnablePrivilege(LPCTSTR);
//
INT_PTR CALLBACK cb_export_txt(HWND hDlg, UINT uMsg,
    WPARAM wParam, LPARAM lParam);

#ifdef __cplusplus
}
#endif
//
#endif

DevMgr.c

//
// (w)ritten by Chuan-Liang Teng 2006, mailto:clteng@ms6.hinet.net
//
#include "devmgr.h"
//
HINSTANCE _hInst = 0L;
HWND      _hDlg  = 0L;
//
BOOL EnablePrivilege(LPCTSTR PrviName)
{
    HANDLE           hToken = 0L;
    TOKEN_PRIVILEGES Newtp;
    BOOL             bRtn = FALSE;
//
    OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
    if (LookupPrivilegeValue(NULL,PrviName, &Newtp.Privileges[0].Luid))
    {
        Newtp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        Newtp.PrivilegeCount = 1;
        if (AdjustTokenPrivileges(hToken, FALSE, &Newtp, sizeof(Newtp), NULL, NULL))
            bRtn = TRUE;
    };
//
    CloseHandle(hToken);
//
    return bRtn;
};
char OpenINFFile(const char bType, char *pszName)
{
    char         szFile[MAX_PATH] = {0};
    char         szTitle[64]      = {0L};
    OPENFILENAME openFile         = {0L};
//
    openFile.lStructSize    = sizeof(OPENFILENAME);
    openFile.hwndOwner      = _hDlg;
    openFile.hInstance      = _hInst;
    if (bType)
        openFile.lpstrFilter    = "INF File(*.inf)\0*.inf\0";
    else
        openFile.lpstrFilter    = "System File(*.sys)\0*.sys\0";
    openFile.lpstrFile      = szFile;
    openFile.lpstrTitle     = szTitle;
    openFile.nMaxFileTitle  = 64;
    openFile.nMaxFile       = MAX_PATH;
    openFile.Flags          = OFN_FILEMUSTEXIST | OFN_EXPLORER;
    openFile.Flags         |= OFN_HIDEREADONLY; //  | OFN_ENABLETEMPLATE;
    if (GetOpenFileName(&openFile))
    {
        strcpy(pszName, szFile);
        return 1;
    };
    return 0;
};
//
void SetCharSet(const UINT nIDList1, const UINT nIDList2)
{
    HWND hListView1 = GetDlgItem(_hDlg, nIDList1);
    HWND hListView2 = GetDlgItem(_hDlg, nIDList2);
//
    if (GetACP() == 950)
    {
        ListViewInsertColumnText(hListView1, 0, 0, "逆(Field)", 0);
        ListViewInsertColumnText(hListView1, 1, 0, "弧(Descritption)", 1);
        ListViewInsertItemText(hListView1, 0, 0, "GUID");
        ListViewInsertItemText(hListView1, 1, 0, "祑砰醚絏");
        ListViewInsertItemText(hListView1, 2, 0, "杆醚絏");
        ListViewInsertItemText(hListView1, 3, 0, "紅坝");
        ListViewInsertItemText(hListView1, 4, 0, "ㄑ莱");
        ListViewInsertItemText(hListView1, 5, 0, "弧");
        ListViewInsertItemText(hListView1, 6, 0, "跋琿嘿");
        ListViewInsertItemText(hListView1, 7, 0, "INF ら戳");
        ListViewInsertItemText(hListView1, 8, 0, "INF 隔畖");
        ListViewInsertItemText(hListView1, 9, 0, "祘Α隔畖");
        ListViewInsertItemText(hListView1, 10, 0, "ま");
        ListViewInsertItemText(hListView1, 11, 0, "砞称隔畖");
        ListViewInsertItemText(hListView1, 12, 0, "竤舱");
        ListViewInsertItemText(hListView1, 13, 0, "币笆よΑ");
//
        ListViewInsertColumnText(hListView2, 0, 0, "戈方篈", 0);
        ListViewInsertColumnText(hListView2, 1, 0, "砞﹚", 1);
    }
    else
    {
        ListViewInsertColumnText(hListView1, 0, 0, "Field", 0);
        ListViewInsertColumnText(hListView1, 1, 0, "Descritption", 1);
        ListViewInsertItemText(hListView1, 0, 0, "GUID");
        ListViewInsertItemText(hListView1, 1, 0, "Hardware ID");
        ListViewInsertItemText(hListView1, 2, 0, "Install ID");
        ListViewInsertItemText(hListView1, 3, 0, "Manufacturer");
        ListViewInsertItemText(hListView1, 4, 0, "Provider");
        ListViewInsertItemText(hListView1, 5, 0, "Driver Description");
        ListViewInsertItemText(hListView1, 6, 0, "Section Name");
        ListViewInsertItemText(hListView1, 7, 0, "INF Date");
        ListViewInsertItemText(hListView1, 8, 0, "INF Path");
        ListViewInsertItemText(hListView1, 9, 0, "Image Path");
        ListViewInsertItemText(hListView1, 10, 0, "Index");
        ListViewInsertItemText(hListView1, 11, 0, "Device Path");
        ListViewInsertItemText(hListView1, 12, 0, "Group");
        ListViewInsertItemText(hListView1, 13, 0, "Start");
//
        ListViewInsertColumnText(hListView2, 0, 0, "Resource Type", 0);
        ListViewInsertColumnText(hListView2, 1, 0, "Setting", 1);
    };
};
//
void DisableRadioBtn(HWND hDlg, const char bEnable)
{
    short wLoop;
//
    for (wLoop = IDC_PARAMOPT1; wLoop <= IDC_PARAMOPT9; wLoop++)
         EnableWindow(GetDlgItem(hDlg, wLoop), bEnable);
    SendMessage(GetDlgItem(hDlg, IDC_PARAMOPT3), BM_SETCHECK, BST_CHECKED, 0);
    SendMessage(GetDlgItem(hDlg, IDC_PARAMOPT8), BM_SETCHECK, BST_CHECKED, 0);
};
//
void GetInstallOption(HWND hDlg, short *wError, short *wStart)
{
    HWND  hOption = 0L;
    short wLoop;
//
    for (wLoop = IDC_PARAMOPT1; wLoop <= IDC_PARAMOPT4; wLoop++)
    {
        hOption = GetDlgItem(hDlg, wLoop);
        if (SendMessage(hOption, BM_GETCHECK, 0, 0) == BST_CHECKED)
        {
            switch(wLoop)
            {
                case IDC_PARAMOPT1:
                    *wError = SERVICE_ERROR_CRITICAL;
                break;
//
                case IDC_PARAMOPT2:
                    *wError = SERVICE_ERROR_IGNORE;
                break;
//
                case IDC_PARAMOPT3:
                    *wError = SERVICE_ERROR_NORMAL;
                break;
//
                case IDC_PARAMOPT4:
                    *wError = SERVICE_ERROR_SEVERE;
                break;
//
            };
            break;
        };
    };
    if (wLoop > IDC_PARAMOPT4)
        *wError = -1;
    for (wLoop = IDC_PARAMOPT5; wLoop <= IDC_PARAMOPT9; wLoop++)
    {
        hOption = GetDlgItem(hDlg, wLoop);
        if (SendMessage(hOption, BM_GETCHECK, 0, 0) == BST_CHECKED)
        {
            switch(wLoop)
            {
                case IDC_PARAMOPT5:
                    *wStart = SERVICE_BOOT_START;
                break;
//
                case IDC_PARAMOPT6:
                    *wStart = SERVICE_SYSTEM_START;
                break;
//
                case IDC_PARAMOPT7:
                    *wStart = SERVICE_AUTO_START;
                break;
//
                case IDC_PARAMOPT8:
                    *wStart = SERVICE_DEMAND_START;
                break;
//
                case IDC_PARAMOPT9:
                    *wStart = SERVICE_DISABLED;
                break;
            };
            break;
        };
    };
    if (wLoop > IDC_PARAMOPT9)
        *wStart = -1;
};
//
INT_PTR CALLBACK InstallDialog(HWND hDlg, UINT uMsg,
                               WPARAM wParam, LPARAM lParam)
{
    static FILE *pf             = 0L;    
    static char szINF[MAX_PATH] = {0};
    static char bType;
//
    switch(uMsg)
    {
        case WM_INITDIALOG:
        {
            DisableCloseBox(hDlg);
            DisableRadioBtn(hDlg, 0);
            bType = (!lParam) ? 0 : 1;
            EnableWindow(GetDlgItem(hDlg, IDC_INSTALLBTN), 0);
            EnableWindow(GetDlgItem(hDlg, IDC_RESETBTN), 0);
            EnableWindow(GetDlgItem(hDlg, IDC_DRVNAMETXT), 0);
            EnableWindow(GetDlgItem(hDlg, IDC_ENABLEDRVBTN), 0);
            SetFocus(GetDlgItem(hDlg, IDC_OPENINFBTN));
        };
        break;
//
        case WM_COMMAND:
        {
            switch(LOWORD(wParam))
            {
                case IDC_OPENINFBTN:
                {
                    if (pf)
                        fclose(pf);
                    InitialGlobalVar();
                    pf = 0L;
                    if (!OpenINFFile(bType, szINF))
                        break;
                    SendMessage(GetDlgItem(hDlg, IDC_INFLBL), WM_SETTEXT,
                                0, (LPARAM)szINF);
                    pf = fopen(szINF, "r");
                    if (!pf)
                    {
                        sprintf(szINF, "Erro Open File!Code:%d", errno);
                        MessageBox(hDlg, szINF, "ERROR", MB_ICONSTOP);
                        break;
                    };
                    EnableWindow(GetDlgItem(hDlg, IDC_INSTALLBTN), 1);
                    EnableWindow(GetDlgItem(hDlg, IDC_RESETBTN), 1);
                    if (!bType)
                    {
                        DisableRadioBtn(hDlg, 1);
                        EnableWindow(GetDlgItem(hDlg, IDC_DRVNAMETXT), 1);
                        SetFocus(GetDlgItem(hDlg, IDC_DRVNAMETXT));
                    };
                };
                break;
//
                case IDC_INSTALLBTN:
                {
                    if (bType)
                    {
                        if (pf)
                            GetINFData(pf);
                        EnableWindow(GetDlgItem(hDlg, IDC_INSTALLBTN), 0);
                        EnableWindow(GetDlgItem(hDlg, IDC_RESETBTN), 0);
                        if (!StartInstallWDMDriver(szINF))
                        {
                            EnableWindow(GetDlgItem(hDlg, IDC_INSTALLBTN), 0);
                            EnableWindow(GetDlgItem(hDlg, IDC_RESETBTN), 0);
                            SetFocus(GetDlgItem(hDlg, IDC_OPENINFBTN));
                        }
                        else
                        {
                            EnableWindow(GetDlgItem(hDlg, IDC_INSTALLBTN), 1);
                            EnableWindow(GetDlgItem(hDlg, IDC_RESETBTN), 1);
                        };
                    }
                    else
                    {
                        short wError;
                        short wStart;
                        char  szDevName[64] = {0};
                        char szName[MAX_PATH] = {"\\\\.\\\0"};
//
                        GetInstallOption(hDlg, &wError, &wStart);
                        if (!wError || !wStart)
                            break;
                        SendMessage(GetDlgItem(hDlg, IDC_DRVNAMETXT), WM_GETTEXT,
                                    sizeof(char)*63, (LPARAM)szDevName);
                        if (!*szDevName)
                        {
                            RtlZeroMemory(szINF, sizeof(char)*MAX_PATH);
                            if (pf)
                                fclose(pf);
                            pf = 0L;
                            SendMessage(GetDlgItem(hDlg, IDC_INFLBL), WM_SETTEXT,
                                        0, 0L);
                            EnableWindow(GetDlgItem(hDlg, IDC_DRVNAMETXT), 0);
                            for (wStart = IDC_PARAMOPT1; wStart <= IDC_PARAMOPT9; wStart++)
                                 SendMessage(GetDlgItem(hDlg, wStart), BM_SETCHECK, BST_UNCHECKED, 0);
                            SetFocus(GetDlgItem(hDlg, IDC_OPENINFBTN));
                        }
                        else
                        {
                            strcat(szName, szDevName);
                            StartDriver(wError, wStart, szINF, szDevName);
                        };
                    };
                };
                break;
//
                case IDC_RESETBTN:
                {
                    short wLoop;
//
                    if (pf)
                        fclose(pf);
                    pf = 0L;
                    SendMessage(GetDlgItem(hDlg, IDC_INFLBL), WM_SETTEXT,
                                0, (LPARAM)"");
                    RtlZeroMemory(szINF, sizeof(char)*MAX_PATH);
                    SetFocus(GetDlgItem(hDlg, IDC_OPENINFBTN));
                    for (wLoop = IDC_PARAMOPT1; wLoop <= IDC_PARAMOPT9; wLoop++)
                        SendMessage(GetDlgItem(hDlg, wLoop), BM_SETCHECK, BST_UNCHECKED, 0);
                };
                break;
//
                case IDC_IEXIT:
                {
                    EndDialog(hDlg, 0);
                };
                break;
            };
        };
        break;
    };
    return 0;                     
};
//
void DeleteINFFile(const char *szINF)
{
    WIN32_FIND_DATA w32Data = {0};
    HANDLE          hFind   = 0L;
    char            szName[MAX_PATH] = {0};
    char            szDel[MAX_PATH] = {0};
//
    strcpy(szName, szINF);
    strcat(szName, ".*");
//
    hFind = FindFirstFile(szName, &w32Data);
    if (hFind != INVALID_HANDLE_VALUE)
    {
        do
        {
            _splitpath(szINF, szDel, szName, 0L, 0L);
            strcat(szDel, szName);
            strcat(szDel, w32Data.cFileName);
            _unlink(szDel);
        } while (FindNextFile(hFind, &w32Data));
    };
};



//
INT_PTR CALLBACK MainDialog(HWND hDlg, UINT uMsg,
                            WPARAM wParam, LPARAM lParam)
{
    static CRITICAL_SECTION criticalSection = {0};
//
    switch(uMsg)
    {
        case WM_INITDIALOG:
        {
            HWND hListView = GetDlgItem(hDlg, IDC_LIST1);
//
            _hDlg = hDlg;
            WaitCursor(1);
            EnablePrivilege(SE_DEBUG_NAME);
            EnablePrivilege(SE_LOAD_DRIVER_NAME);
            DisableCloseBox(hDlg);
            if (!InitialDeviceList() || !InitialDeviceOrder())
                EndDialog(hDlg, 0);
            ListViewSetExtStyle(GetDlgItem(hDlg, IDC_LIST1), 0);
            ListViewSetExtStyle(GetDlgItem(hDlg, IDC_LIST2), 0);
            SetCharSet(IDC_LIST1, IDC_LIST2);
            TreeViewRemoveAllNodes(hDlg, IDC_TREE1);
            InitialImageData();
            EnumWDMDriver(IDC_TREE1, IDB_MYCOMP);
            SendMessage(GetDlgItem(hDlg, IDC_RADIO2), BM_SETCHECK, BST_CHECKED, 0);
            EnableWindow(GetDlgItem(hDlg, IDC_DELBTN), 0);
            EnableWindow(GetDlgItem(hDlg, IDC_COPYPATHBTN), 0);
            WaitCursor(0);
            InitializeCriticalSection(&criticalSection);
        };
        break;
//
        case WM_COMMAND:
        {
            switch(LOWORD(wParam))
            {
                case IDC_ADDBTN:
                {
                    short wLegacy = 0;
//
                    if (SendMessage(GetDlgItem(hDlg, IDC_RADIO2),
                                    BM_GETCHECK, 0, 0) == BST_CHECKED)
                        wLegacy = 1;
                    if (DialogBoxParam(_hInst, MAKEINTRESOURCE(IDD_DIALOG2),
                                        hDlg, InstallDialog, wLegacy) == -1)
                        ShowErrorMsg(hDlg, GetLastError(), "DialogBox");
                };
                break;
//
                case IDC_DELBTN:
                {
                    char  szHardware[64]   = {0};
                    char  szPath[MAX_PATH] = {0};
                    short wIndex;
//
                    ListViewGetSpecItem(GetDlgItem(hDlg, IDC_LIST1), 10, 1, szHardware);
                    wIndex = atoi(szHardware);
                    RtlZeroMemory(szHardware, sizeof(char)*64);
                    ListViewGetSpecItem(GetDlgItem(hDlg, IDC_LIST1), 1, 1, szHardware);
                    ListViewGetSpecItem(GetDlgItem(hDlg, IDC_LIST1), 8, 1, szPath);
                    UninstallWDMDriver(wIndex, szHardware);
                    {
                        char *p              = strchr(szPath, '.');
                        char szTmp[MAX_PATH] = {0};
                        memcpy(szTmp, szPath, p-szPath);
                        DeleteINFFile(szTmp);
                    };
                    ListViewGetSpecItem(GetDlgItem(hDlg, IDC_LIST1), 9, 1, szPath);
                    _unlink(szPath);
                    EnableWindow(GetDlgItem(hDlg, IDC_DELBTN), 0);
                    EnableWindow(GetDlgItem(hDlg, IDC_COPYPATHBTN), 0);
                };
                break;
//
                case IDC_REFBTN:
                {
                    SendMessage(hDlg, WM_DEVICECHANGE, 0, 0);
                };
                break;

                case IDC_EXPORT_TXT:
                {
                    cb_export_txt(hDlg, uMsg, wParam, lParam);
                };
                break;

//
                case IDC_COPYPATHBTN:
                {
                    HGLOBAL hMem            = 0L;
                    char    *p              = 0L;
                    char    szBuf[MAX_PATH] = {0};
//
                    if (!IsClipboardFormatAvailable(CF_TEXT))
                        break;
                    if (!OpenClipboard(hDlg))
                    {
                        ShowErrorMsg(hDlg, GetLastError(), "OpenClipboard");
                        break;
                    };
                    EmptyClipboard();
                    ListViewGetSpecItem(GetDlgItem(hDlg, IDC_LIST1), 11, 1, szBuf);
                    if (!*szBuf)
                        break;
                    hMem = LocalAlloc(LMEM_MOVEABLE, sizeof(char)*strlen(szBuf)+1);
                    if (!hMem)
                    {
                        ShowErrorMsg(hDlg, GetLastError(), "LocalAlloc");
                        break;
                    };
                    p = LocalLock(hMem);
                    memcpy(p, szBuf, strlen(szBuf));
                    p[strlen(szBuf)] = 0;
                    LocalUnlock(hMem);
                    SetClipboardData(CF_TEXT, p);
                    LocalFree(hMem);
                    CloseClipboard();
                };
                break;
//
                case IDC_EXIT:
                    FreeAllocDeviceNode();
                    FreeAllDeviceOrderNode();
                    DeleteCriticalSection(&criticalSection);
                    EndDialog(hDlg, 0);
                break;
            };
            break;
//
        };
        break;
//
        case WM_DEVICECHANGE:
        {
            EnterCriticalSection(&criticalSection);
            WaitCursor(1);
            FreeAllocDeviceNode();
            FreeAllDeviceOrderNode();
            if (!InitialDeviceList() || !InitialDeviceOrder())
                EndDialog(hDlg, 0);
            ListViewRemoveAllItems(GetDlgItem(hDlg, IDC_LIST1));
            ListViewRemoveAllItems(GetDlgItem(hDlg, IDC_LIST2));
            SetCharSet(IDC_LIST1, IDC_LIST2);
            TreeViewRemoveAllNodes(hDlg, IDC_TREE1);
            InitialImageData();
            EnumWDMDriver(IDC_TREE1, IDB_MYCOMP);
            WaitCursor(0);
            LeaveCriticalSection(&criticalSection);
        };
        break;
//
        case WM_NOTIFY:
        {
            NMHDR *pnmh = (NMHDR*)lParam;
//
            switch(pnmh->idFrom)
            {
                case IDC_LIST1:
                {
                    if (pnmh->code == NM_CLICK)
                    {
                        char  szBuf[MAX_PATH] = {0};
                        HWND  hList           = GetDlgItem(hDlg, IDC_LIST1);
//
                        if (ListViewGetItemSelect(hList) == 10 ||
                            ListViewGetItemSelect(hList) == 11)
                        {
                            ListViewGetSpecItem(hList, 10, 1, szBuf);
                            if (*szBuf)
                                EnableWindow(GetDlgItem(hDlg, IDC_DELBTN), 1);
                            ListViewGetSpecItem(hList, 11, 1, szBuf);
                            if (*szBuf)
                                EnableWindow(GetDlgItem(hDlg, IDC_COPYPATHBTN), 1);
                        }
                        else
                        {
                            EnableWindow(GetDlgItem(hDlg, IDC_DELBTN), 0);
                            EnableWindow(GetDlgItem(hDlg, IDC_COPYPATHBTN), 0);
                        };
                    };
                };
                break;
//
                case IDC_TREE1:
                {
                    if (pnmh->code == TVN_SELCHANGED)
                    {
                        TVITEM     tvItem = {0};
                        NMTREEVIEW *pnmhTree = (NMTREEVIEW*)lParam;
//
                        TreeViewGetSelectText(GetDlgItem(hDlg, IDC_TREE1),
                                              (NMHDR*)lParam, &tvItem);
                        if (tvItem.pszText)
                        {
                            char szData[LINE_LEN] = {0};
//
                            memcpy(szData, tvItem.pszText, strlen(tvItem.pszText));
                            ListViewRemoveAllItems(GetDlgItem(_hDlg, IDC_LIST1));
                            ListViewRemoveAllItems(GetDlgItem(_hDlg, IDC_LIST2));
                            SetCharSet(IDC_LIST1, IDC_LIST2);
                            FindDeviceName(szData, IDC_LIST1, IDC_LIST2);
                        };
                    };
                };
                break;
            };
        };
        break;
    };
    return 0;
};
//
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
                     LPSTR lpCmdLine, int nShowCmd)
{
    InitCommonControls();
    _hInst = hInst;
    if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_DIALOG1),
                       0L, MainDialog, 0L) == -1)
        ShowErrorMsg(0L, GetLastError(), "DialogBoxParam");
    ExitProcess(0);
    return 0;
};

INT_PTR CALLBACK cb_export_txt(HWND hDlg, UINT uMsg,
    WPARAM wParam, LPARAM lParam)
{
    int iCnt = 0;

    iCnt = getAllDeviceCnt(); // 192
    enumTreeCtrl(IDC_TREE1);
    MessageBox(hDlg, "export finished!", "info", MB_ICONINFORMATION);
    return 0;
}

HTREEITEM fn_get_tree_root_node(HWND hTreeView, const UINT nIdTree)
{
    HTREEITEM hNode = NULL;
    TVITEM    tvItem = { 0 };
    char      szText[256] = { 0 };
    int nNodeCnt = 0;

    nNodeCnt = (int)SendMessage(hTreeView, TVM_GETCOUNT, 0, 0); // 220

    hNode = (HTREEITEM)SendMessage(hTreeView,
        TVM_GETNEXTITEM,
        TVGN_ROOT, // TVGN_ROOT or TVGN_CHILD, not be TVGN_NEXT
        (LPARAM)NULL
    );

    if (NULL != hNode)
    {
        tvItem.mask = TVIF_TEXT | TVIF_HANDLE;
        tvItem.pszText = szText;
        tvItem.cchTextMax = sizeof(szText) - 1;
        RtlZeroMemory(szText, sizeof(szText));

        tvItem.hItem = hNode; // !
        SendMessage(hTreeView, TVM_GETITEM, 0, (LPARAM)&tvItem); // param1 must be hTreeView
        if (*szText)
        {
            // watch szText
            // LS-PRECISION356
        };
    }


    return hNode;
}

#define OUTPUT_FILE_NAME "device_manager_export.txt"

void fn_get_tree_Level_3_node(HWND hTreeView, HTREEITEM hNodeL1, const char* psz_NodeL1_name, HTREEITEM hNodeL2, const char* psz_NodeL2_name)
{
    FILE* pFile = NULL;
    char szBuf[4096] = { '\0' };

    pFile = fopen(OUTPUT_FILE_NAME, "a");
    if (NULL != pFile)
    {
        memset(szBuf, 0, sizeof(szBuf));
        sprintf(szBuf, "%s : %s\r\n", psz_NodeL1_name, psz_NodeL2_name);
        fwrite(szBuf, sizeof(char), strlen(szBuf), pFile);

        fclose(pFile);
    }
}

void fn_get_tree_Level_2_node(HWND hTreeView, HTREEITEM hNodeL1, const char* psz_NodeL1_name)
{
    HTREEITEM hNode = NULL;
    TVITEM    tvItem = { 0 };
    char      szText[256] = { 0 };
    int nNodeCnt = 0;
    BOOL bFirtLoop = TRUE;

    // psz_NodeL1_name like below
    // 安全设备
    // 处理器
    do {
        hNode = (HTREEITEM)SendMessage(hTreeView,
            TVM_GETNEXTITEM,
            bFirtLoop ? TVGN_CHILD : TVGN_NEXT,
            bFirtLoop ? (LPARAM)hNodeL1 : (LPARAM)hNode
        );

        bFirtLoop = FALSE;

        if (NULL != hNode)
        {
            tvItem.mask = TVIF_TEXT | TVIF_HANDLE;
            tvItem.pszText = szText;
            tvItem.cchTextMax = sizeof(szText) - 1;
            RtlZeroMemory(szText, sizeof(szText));

            tvItem.hItem = hNode; // !
            SendMessage(hTreeView, TVM_GETITEM, 0, (LPARAM)&tvItem);
            if (*szText)
            {
                // watch szText

            };

            nNodeCnt++;
            if (nNodeCnt >= 2)
            {
                nNodeCnt = nNodeCnt;
            }

            fn_get_tree_Level_3_node(hTreeView, hNodeL1, psz_NodeL1_name, hNode, szText);

            continue;
        }

        break;
    } while (TRUE);
}

void fn_get_tree_Level_1_node(HWND hTreeView, HTREEITEM hRoot)
{
    HTREEITEM hNode = NULL;
    TVITEM    tvItem = { 0 };
    char      szText[256] = { 0 };
    int nNodeCnt = 0;
    BOOL bFirtLoop = TRUE;

    
    do {
        hNode = (HTREEITEM)SendMessage(hTreeView,
            TVM_GETNEXTITEM,
            bFirtLoop ? TVGN_CHILD : TVGN_NEXT,
            bFirtLoop ? (LPARAM)hRoot : (LPARAM)hNode
        );

        bFirtLoop = FALSE;

        if (NULL != hNode)
        {
            tvItem.mask = TVIF_TEXT | TVIF_HANDLE;
            tvItem.pszText = szText;
            tvItem.cchTextMax = sizeof(szText) - 1;
            RtlZeroMemory(szText, sizeof(szText));

            tvItem.hItem = hNode; // !
            SendMessage(hTreeView, TVM_GETITEM, 0, (LPARAM)&tvItem);
            if (*szText)
            {
                // watch szText
                // IDE ATA/ATAPI 控制器
                // USB 连接器管理器
                // 安全设备
                // 处理器

            };

            fn_get_tree_Level_2_node(hTreeView, hNode, szText);

            continue;
        }

        break;
    } while (TRUE);
}

void enumTreeCtrl(const UINT nIdTree)
{
    HWND                   hTreeView = GetDlgItem(_hDlg, nIdTree);
    HTREEITEM hRoot = 0L;
    HTREEITEM hChildItem = 0L;
    HTREEITEM hParentItem = NULL;
    char      szText[128] = { 0 };
    TVITEM    tvItem = { 0 };
    int       iLoop = 0;
    int       nNodeAllCnt = 0;
    //
    tvItem.mask = TVIF_TEXT | TVIF_HANDLE;
    tvItem.pszText = szText;
    tvItem.cchTextMax = sizeof(char) * 127;
    // nNodeAllCnt = (int)SendMessage(hTreeView, TVM_GETCOUNT, 0, 0);
    RtlZeroMemory(szText, sizeof(char) * 128);

    hRoot = fn_get_tree_root_node(hTreeView, nIdTree);
    if (NULL != hRoot)
    {
        fn_get_tree_Level_1_node(hTreeView, hRoot);
    }
    

    /*

    hParentItem = hRoot;
    for (iLoop = 0; iLoop < nNodeAllCnt; iLoop++)
    {
        hChildItem = (HTREEITEM)SendMessage(hTreeView,
            TVM_GETNEXTITEM,
            TVGN_NEXT,
            (LPARAM)hParentItem
        );

        if (0 == iLoop)
        {

        }
        else {
            hChildItem = (HTREEITEM)SendMessage(hTreeView,
                TVM_GETNEXTITEM,
                TVGN_NEXT,
                (LPARAM)hParentItem
            );

            if (NULL == hChildItem)
            {
                hChildItem = (HTREEITEM)SendMessage(hTreeView,
                    TVM_GETNEXTITEM,
                    TVGN_CHILD,
                    (LPARAM)hParentItem
                );
            }
        }
        
        tvItem.hItem = hChildItem;
        SendMessage(hTreeView, TVM_GETITEM, 0, (LPARAM)&tvItem);
        if (*szText)
        {
            // watch szText
        };
        hParentItem = hChildItem;
    };
    */
}

END

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值