[DEVMGMT]
authorEric Kohl <eric.kohl@reactos.org>
Sun, 5 Oct 2014 08:53:51 +0000 (08:53 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Sun, 5 Oct 2014 08:53:51 +0000 (08:53 +0000)
- Reimplement the 'list by device type' function. The old implementation did not list devices as 'unknown devices' if they had no device class GUID or an unknown class GUID.
- Use overlay images to indicate problems on a device.

svn path=/trunk/; revision=64534

reactos/base/applications/mscutils/devmgmt/enumdevices.c
reactos/base/applications/mscutils/devmgmt/precomp.h

index 9f5b3a3..ac4d345 100644 (file)
@@ -15,9 +15,7 @@
 #include <devguid.h>
 
 static SP_CLASSIMAGELIST_DATA ImageListData;
-static HDEVINFO hDevInfo;
 
-DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
 
 VOID
 FreeDeviceStrings(HWND hTreeView)
@@ -96,7 +94,6 @@ OpenPropSheet(HWND hTreeView,
                             DPF_EXTENDED,
                             FALSE);
     }
-
 }
 
 
@@ -106,7 +103,7 @@ InsertIntoTreeView(HWND hTreeView,
                    LPTSTR lpLabel,
                    LPTSTR DeviceID,
                    INT DevImage,
-                   LONG DevProb)
+                   UINT OverlayImage)
 {
     TV_ITEM tvi;
     TV_INSERTSTRUCT tvins;
@@ -121,15 +118,11 @@ InsertIntoTreeView(HWND hTreeView,
     tvi.iImage = DevImage;
     tvi.iSelectedImage = DevImage;
 
-    if (DevProb != 0)
+    if (OverlayImage != 0)
     {
+        tvi.mask |= TVIF_STATE;
         tvi.stateMask = TVIS_OVERLAYMASK;
-
-        if (DevProb == CM_PROB_DISABLED)
-        {
-            /* FIXME: set the overlay icon */
-        }
-
+        tvi.state = INDEXTOOVERLAYMASK(OverlayImage);
     }
 
     tvins.item = tvi;
@@ -139,212 +132,295 @@ InsertIntoTreeView(HWND hTreeView,
 }
 
 
-static INT
-EnumDeviceClasses(INT ClassIndex,
-                  BOOL ShowHidden,
-                  LPTSTR DevClassName,
-                  LPTSTR DevClassDesc,
-                  BOOL *DevPresent,
-                  INT *ClassImage,
-                  BOOL *IsUnknown,
-                  BOOL *IsHidden)
+static
+ULONG
+GetClassCount(VOID)
 {
+    ULONG ulClassIndex;
     GUID ClassGuid;
-    HKEY KeyClass;
-    TCHAR ClassName[MAX_CLASS_NAME_LEN];
-    DWORD RequiredSize = MAX_CLASS_NAME_LEN;
-    UINT Ret;
+    CONFIGRET cr;
 
-    *DevPresent = FALSE;
-    *DevClassName = _T('\0');
-    *IsHidden = FALSE;
+    for (ulClassIndex = 0; ; ulClassIndex++)
+    {
+        cr = CM_Enumerate_Classes(ulClassIndex,
+                                  &ClassGuid,
+                                  0);
+        if (cr == CR_NO_SUCH_VALUE)
+            return ulClassIndex;
+    }
+}
 
-    Ret = CM_Enumerate_Classes(ClassIndex,
-                               &ClassGuid,
-                               0);
-    if (Ret != CR_SUCCESS)
+
+static
+PDEVCLASS_ENTRY
+GetClassFromClassGuid(
+    PDEVCLASS_ENTRY pClassArray,
+    ULONG ulClassCount,
+    GUID *pGuid)
+{
+    PDEVCLASS_ENTRY pClass, pUnknownClass = NULL;
+    ULONG i;
+
+    for (i = 0; i < ulClassCount; i++)
     {
-        /* all classes enumerated */
-        if(Ret == CR_NO_SUCH_VALUE)
-        {
-            return -1;
-        }
+        pClass = &pClassArray[i];
 
-        if (Ret == CR_INVALID_DATA)
-        {
-            ; /*FIXME: what should we do here? */
-        }
+        if (IsEqualGUID(&pClass->ClassGuid, &GUID_DEVCLASS_UNKNOWN))
+            pUnknownClass = pClass;
 
-        /* handle other errors... */
+        if (IsEqualGUID(&pClass->ClassGuid, pGuid))
+            return pClass;
     }
 
-    /* This case is special because these devices don't show up with normal class enumeration */
-    *IsUnknown = IsEqualGUID(&ClassGuid, &GUID_DEVCLASS_UNKNOWN);
+    return pUnknownClass;
+}
 
-    if (ShowHidden == FALSE &&
-        (IsEqualGUID(&ClassGuid, &GUID_DEVCLASS_LEGACYDRIVER) ||
-         IsEqualGUID(&ClassGuid, &GUID_DEVCLASS_VOLUME)))
-        *IsHidden = TRUE;
 
-    if (SetupDiClassNameFromGuid(&ClassGuid,
-                                 ClassName,
-                                 RequiredSize,
-                                 &RequiredSize))
-    {
-        lstrcpy(DevClassName, ClassName);
-    }
+static
+VOID
+EnumDeviceClasses(
+    HWND hTreeView,
+    HTREEITEM hRoot,
+    PDEVCLASS_ENTRY pClassArray,
+    ULONG ClassCount)
+{
+    WCHAR ClassName[MAX_DEV_LEN];
+    WCHAR ClassDesc[MAX_DEV_LEN];
+    PDEVCLASS_ENTRY pClass;
+    ULONG ClassIndex;
+    DWORD dwSize;
+    LONG lSize;
+    HKEY hKey;
+    CONFIGRET cr;
 
-    if (!SetupDiGetClassImageIndex(&ImageListData,
-                                   &ClassGuid,
-                                   ClassImage))
+    for (ClassIndex = 0; ClassIndex < ClassCount; ClassIndex++)
     {
-        /* FIXME: can we do this?
-         * Set the blank icon: IDI_SETUPAPI_BLANK = 41
-         * it'll be image 24 in the imagelist */
-        *ClassImage = 24;
-    }
+        pClass = &pClassArray[ClassIndex];
+
+        cr = CM_Enumerate_Classes(ClassIndex,
+                                  &pClass->ClassGuid,
+                                  0);
+        if (cr == CR_NO_SUCH_VALUE)
+            return;
+
+        dwSize = MAX_CLASS_NAME_LEN;
+        if (!SetupDiClassNameFromGuid(&pClass->ClassGuid,
+                                      ClassName,
+                                      dwSize,
+                                      &dwSize))
+        {
+            ClassName[0] = _T('\0');
+        }
 
-    /* Get device info for all devices of a particular class */
-    hDevInfo = SetupDiGetClassDevs(*IsUnknown ? NULL : &ClassGuid,
-                                   NULL,
-                                   NULL,
-                                   DIGCF_PRESENT | (*IsUnknown ? DIGCF_ALLCLASSES : 0));
-    if (hDevInfo == INVALID_HANDLE_VALUE)
-    {
-        return 0;
-    }
+        if (!SetupDiGetClassImageIndex(&ImageListData,
+                                       &pClass->ClassGuid,
+                                       &pClass->ClassImage))
+        {
+            /* FIXME: can we do this?
+             * Set the blank icon: IDI_SETUPAPI_BLANK = 41
+             * it'll be image 24 in the imagelist */
+            pClass->ClassImage = 24;
+        }
 
-    KeyClass = SetupDiOpenClassRegKeyEx(&ClassGuid,
+        hKey = SetupDiOpenClassRegKeyEx(&pClass->ClassGuid,
                                         MAXIMUM_ALLOWED,
                                         DIOCR_INSTALLER,
                                         NULL,
                                         0);
-    if (KeyClass != INVALID_HANDLE_VALUE)
-    {
-
-        LONG dwSize = MAX_DEV_LEN;
-
-        if (RegQueryValue(KeyClass,
-                          NULL,
-                          DevClassDesc,
-                          &dwSize) != ERROR_SUCCESS)
+        if (hKey != INVALID_HANDLE_VALUE)
         {
-            *DevClassDesc = _T('\0');
-        }
-    }
-    else
-    {
-        return 0;
-    }
-
-    *DevPresent = TRUE;
+            lSize = MAX_DEV_LEN;
+            if (RegQueryValue(hKey,
+                              NULL,
+                              ClassDesc,
+                              &lSize) != ERROR_SUCCESS)
+            {
+                ClassDesc[0] = _T('\0');
+            }
 
-    RegCloseKey(KeyClass);
+            RegCloseKey(hKey);
+        }
 
-    return 0;
+        pClass->hItem = InsertIntoTreeView(hTreeView,
+                                           hRoot,
+                                           (ClassDesc[0] != _T('\0')) ? ClassDesc : ClassName,
+                                           NULL,
+                                           pClass->ClassImage,
+                                           0);
+    }
 }
 
 
-static LONG
-EnumDevices(INT index,
-            LPTSTR DeviceClassName,
-            LPTSTR DeviceName,
-            LPTSTR *DeviceID)
+static
+VOID
+EnumDevices(
+    HWND hTreeView,
+    PDEVCLASS_ENTRY pClassArray,
+    ULONG ulClassCount,
+    BOOL bShowHidden)
 {
+    HDEVINFO hDevInfo =  INVALID_HANDLE_VALUE;
     SP_DEVINFO_DATA DeviceInfoData;
-    CONFIGRET cr;
-    ULONG Status, ProblemNumber;
+    ULONG Status, Problem;
     DWORD DevIdSize;
+    TCHAR DeviceName[MAX_DEV_LEN];
+    DWORD DevIndex;
+    LPTSTR InstanceId;
+    PDEVCLASS_ENTRY pClass;
+    UINT OverlayImage;
+    CONFIGRET cr;
 
-    *DeviceName = _T('\0');
-    *DeviceID = NULL;
 
-    ZeroMemory(&DeviceInfoData, sizeof(SP_DEVINFO_DATA));
-    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+    /* Get device info for all devices of a particular class */
+    hDevInfo = SetupDiGetClassDevs(NULL,
+                                   NULL,
+                                   NULL,
+                                   DIGCF_PRESENT | DIGCF_ALLCLASSES);
+    if (hDevInfo == INVALID_HANDLE_VALUE)
+        return;
 
-    if (!SetupDiEnumDeviceInfo(hDevInfo,
-                               index,
-                               &DeviceInfoData))
+    for (DevIndex = 0; ; DevIndex++)
     {
-        /* no such device */
-        return -1;
-    }
+        ZeroMemory(&DeviceInfoData, sizeof(SP_DEVINFO_DATA));
+        DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
 
-    if (DeviceClassName == NULL && !IsEqualGUID(&DeviceInfoData.ClassGuid, &GUID_NULL))
-    {
-        /* we're looking for unknown devices and this isn't one */
-        return -2;
-    }
+        InstanceId = NULL;
+        DeviceName[0] = _T('\0');
+        OverlayImage = 0;
 
-    /* get the device ID */
-    if (!SetupDiGetDeviceInstanceId(hDevInfo,
-                                    &DeviceInfoData,
-                                    NULL,
-                                    0,
-                                    &DevIdSize))
-    {
-        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+        if (!SetupDiEnumDeviceInfo(hDevInfo,
+                                   DevIndex,
+                                   &DeviceInfoData))
+            break;
+
+        if (bShowHidden == FALSE &&
+            (IsEqualGUID(&DeviceInfoData.ClassGuid, &GUID_DEVCLASS_LEGACYDRIVER) ||
+             IsEqualGUID(&DeviceInfoData.ClassGuid, &GUID_DEVCLASS_VOLUME)))
+            continue;
+
+        pClass = GetClassFromClassGuid(pClassArray,
+                                       ulClassCount,
+                                       &DeviceInfoData.ClassGuid);
+
+        /* get the device ID */
+        if (!SetupDiGetDeviceInstanceId(hDevInfo,
+                                        &DeviceInfoData,
+                                        NULL,
+                                        0,
+                                        &DevIdSize))
         {
-            (*DeviceID) = (LPTSTR)HeapAlloc(GetProcessHeap(),
-                                            0,
-                                            DevIdSize * sizeof(TCHAR));
-            if (*DeviceID)
+            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
             {
-                if (!SetupDiGetDeviceInstanceId(hDevInfo,
-                                                &DeviceInfoData,
-                                                *DeviceID,
-                                                DevIdSize,
-                                                NULL))
+                InstanceId = (LPTSTR)HeapAlloc(GetProcessHeap(),
+                                             0,
+                                             DevIdSize * sizeof(TCHAR));
+                if (InstanceId != NULL)
                 {
-                    HeapFree(GetProcessHeap(),
-                             0,
-                             *DeviceID);
-                    *DeviceID = NULL;
+                    if (!SetupDiGetDeviceInstanceId(hDevInfo,
+                                                    &DeviceInfoData,
+                                                    InstanceId,
+                                                    DevIdSize,
+                                                    NULL))
+                    {
+                        HeapFree(GetProcessHeap(),
+                                 0,
+                                 InstanceId);
+                        InstanceId = NULL;
+                    }
                 }
             }
         }
-    }
 
-    if (DeviceID != NULL &&
-        _tcscmp(*DeviceID, _T("HTREE\\ROOT\\0")) == 0)
-    {
-        HeapFree(GetProcessHeap(),
-                 0,
-                 *DeviceID);
-        *DeviceID = NULL;
-        return -1;
-    }
+        /* Skip the root device */
+        if (InstanceId != NULL &&
+            _tcscmp(InstanceId, _T("HTREE\\ROOT\\0")) == 0)
+        {
+            HeapFree(GetProcessHeap(),
+                     0,
+                     InstanceId);
+            InstanceId = NULL;
+            continue;
+        }
 
-    /* get the device's friendly name */
-    if (!SetupDiGetDeviceRegistryProperty(hDevInfo,
-                                          &DeviceInfoData,
-                                          SPDRP_FRIENDLYNAME,
-                                          0,
-                                          (BYTE*)DeviceName,
-                                          MAX_DEV_LEN,
-                                          NULL))
-    {
-        /* if the friendly name fails, try the description instead */
-        SetupDiGetDeviceRegistryProperty(hDevInfo,
-                                         &DeviceInfoData,
-                                         SPDRP_DEVICEDESC,
-                                         0,
-                                         (BYTE*)DeviceName,
-                                         MAX_DEV_LEN,
-                                         NULL);
+        /* Get the device's friendly name */
+        if (!SetupDiGetDeviceRegistryProperty(hDevInfo,
+                                              &DeviceInfoData,
+                                              SPDRP_FRIENDLYNAME,
+                                              0,
+                                              (BYTE*)DeviceName,
+                                              MAX_DEV_LEN,
+                                              NULL))
+        {
+            /* If the friendly name fails, try the description instead */
+            SetupDiGetDeviceRegistryProperty(hDevInfo,
+                                             &DeviceInfoData,
+                                             SPDRP_DEVICEDESC,
+                                             0,
+                                             (BYTE*)DeviceName,
+                                             MAX_DEV_LEN,
+                                             NULL);
+        }
+
+        cr = CM_Get_DevNode_Status_Ex(&Status,
+                                      &Problem,
+                                      DeviceInfoData.DevInst,
+                                      0,
+                                      NULL);
+        if ((cr == CR_SUCCESS) &&
+            (Status & DN_HAS_PROBLEM))
+        {
+            if (Problem == CM_PROB_DISABLED ||
+                Problem == CM_PROB_HARDWARE_DISABLED)
+                OverlayImage = 2;
+            else
+                OverlayImage = 1;
+        }
+
+        InsertIntoTreeView(hTreeView,
+                           pClass->hItem,
+                           DeviceName,
+                           InstanceId,
+                           pClass->ClassImage,
+                           OverlayImage);
+
+        if (OverlayImage != 0)
+        {
+             /* Expand the class if the device has a problem */
+             (void)TreeView_Expand(hTreeView,
+                                   pClass->hItem,
+                                   TVE_EXPAND);
+        }
+
+        pClass->bUsed = TRUE;
     }
 
-    cr = CM_Get_DevNode_Status_Ex(&Status,
-                                  &ProblemNumber,
-                                  DeviceInfoData.DevInst,
-                                  0,
-                                  NULL);
-    if (cr == CR_SUCCESS && (Status & DN_HAS_PROBLEM))
+    if (hDevInfo !=  INVALID_HANDLE_VALUE)
+        SetupDiDestroyDeviceInfoList(hDevInfo);
+}
+
+
+static
+VOID
+CleanupDeviceClasses(
+    HWND hTreeView,
+    PDEVCLASS_ENTRY pClassArray,
+    ULONG ulClassCount)
+{
+    PDEVCLASS_ENTRY pClass;
+    ULONG i;
+
+    for (i = 0; i < ulClassCount; i++)
     {
-        return ProblemNumber;
+        pClass = &pClassArray[i];
+
+        if (pClass->bUsed == FALSE)
+            (void)TreeView_DeleteItem(hTreeView,
+                                      pClass->hItem);
+        else
+            (void)TreeView_SortChildren(hTreeView,
+                                        pClass->hItem,
+                                        0);
     }
-
-    return 0;
 }
 
 
@@ -353,105 +429,33 @@ ListDevicesByType(HWND hTreeView,
                   HTREEITEM hRoot,
                   BOOL bShowHidden)
 {
-    HTREEITEM hDevItem;
-    TCHAR DevName[MAX_DEV_LEN];
-    TCHAR DevDesc[MAX_DEV_LEN];
-    LPTSTR DeviceID = NULL;
-    BOOL DevExist = FALSE;
-    INT ClassRet;
-    INT index = 0;
-    INT DevImage;
-    BOOL IsUnknown = FALSE;
-    BOOL IsHidden = FALSE;
-
-    do
-    {
-        ClassRet = EnumDeviceClasses(index,
-                                     bShowHidden,
-                                     DevName,
-                                     DevDesc,
-                                     &DevExist,
-                                     &DevImage,
-                                     &IsUnknown,
-                                     &IsHidden);
-
-        if ((ClassRet != -1) && (DevExist) && !IsHidden)
-        {
-            TCHAR DeviceName[MAX_DEV_LEN];
-            INT DevIndex = 0;
-            LONG Ret;
-
-            if (DevDesc[0] != _T('\0'))
-            {
-                hDevItem = InsertIntoTreeView(hTreeView,
-                                              hRoot,
-                                              DevDesc,
-                                              NULL,
-                                              DevImage,
-                                              0);
-            }
-            else
-            {
-                hDevItem = InsertIntoTreeView(hTreeView,
-                                              hRoot,
-                                              DevName,
-                                              NULL,
-                                              DevImage,
-                                              0);
-            }
-
-            do
-            {
-                Ret = EnumDevices(DevIndex,
-                                  IsUnknown ? NULL : DevName,
-                                  DeviceName,
-                                  &DeviceID);
-                if (Ret >= 0)
-                {
-                    InsertIntoTreeView(hTreeView,
-                                       hDevItem,
-                                       DeviceName,
-                                       DeviceID,
-                                       DevImage,
-                                       Ret);
-                    if (Ret != 0)
-                    {
-                        /* Expand the class if the device has a problem */
-                        (void)TreeView_Expand(hTreeView,
-                                              hDevItem,
-                                              TVE_EXPAND);
-                    }
-                }
+    PDEVCLASS_ENTRY pClassArray;
+    ULONG ulClassCount;
 
-                DevIndex++;
+    ulClassCount = GetClassCount();
 
-            } while (Ret != -1);
+    pClassArray = HeapAlloc(GetProcessHeap(),
+                            HEAP_ZERO_MEMORY,
+                            ulClassCount * sizeof(DEVCLASS_ENTRY));
+    if (pClassArray == NULL)
+        return;
 
-            /* kill InfoList initialized in EnumDeviceClasses */
-            if (hDevInfo)
-            {
-                SetupDiDestroyDeviceInfoList(hDevInfo);
-                hDevInfo = NULL;
-            }
+    EnumDeviceClasses(hTreeView,
+                      hRoot,
+                      pClassArray,
+                      ulClassCount);
 
-            /* don't insert classes with no devices */
-            if (!TreeView_GetChild(hTreeView,
-                                   hDevItem))
-            {
-                (void)TreeView_DeleteItem(hTreeView,
-                                          hDevItem);
-            }
-            else
-            {
-                (void)TreeView_SortChildren(hTreeView,
-                                            hDevItem,
-                                            0);
-            }
-        }
+    EnumDevices(hTreeView,
+                pClassArray,
+                ulClassCount,
+                bShowHidden);
 
-        index++;
+    CleanupDeviceClasses(hTreeView,
+                         pClassArray,
+                         ulClassCount);
 
-    } while (ClassRet != -1);
+    if (pClassArray != NULL)
+        HeapFree(GetProcessHeap(), 0, pClassArray);
 
     (void)TreeView_Expand(hTreeView,
                           hRoot,
@@ -647,26 +651,16 @@ HTREEITEM
 InitTreeView(HWND hTreeView)
 {
     HTREEITEM hRoot;
-    HBITMAP hComp;
     TCHAR ComputerName[MAX_PATH];
     DWORD dwSize = MAX_PATH;
     INT RootImage;
 
     (void)TreeView_DeleteAllItems(hTreeView);
 
-    /* get the device image List */
+    /* Get the device image list */
     ImageListData.cbSize = sizeof(ImageListData);
     SetupDiGetClassImageList(&ImageListData);
 
-    hComp = LoadBitmap(hInstance,
-                       MAKEINTRESOURCE(IDB_ROOT_IMAGE));
-
-    ImageList_Add(ImageListData.ImageList,
-                  hComp,
-                  NULL);
-
-    DeleteObject(hComp);
-
     (void)TreeView_SetImageList(hTreeView,
                                 ImageListData.ImageList,
                                 TVSIL_NORMAL);
@@ -677,9 +671,12 @@ InitTreeView(HWND hTreeView)
         ComputerName[0] = _T('\0');
     }
 
-    RootImage = ImageList_GetImageCount(ImageListData.ImageList) - 1;
+    /* Get the image index of the computer class */
+    SetupDiGetClassImageIndex(&ImageListData,
+                              &GUID_DEVCLASS_COMPUTER,
+                              &RootImage);
 
-    /* insert the root item into the tree */
+    /* Insert the root item into the tree */
     hRoot = InsertIntoTreeView(hTreeView,
                                NULL,
                                ComputerName,
index 6dcf1b9..3813e99 100644 (file)
@@ -46,6 +46,15 @@ typedef struct _MAIN_WND_INFO
 } MAIN_WND_INFO, *PMAIN_WND_INFO;
 
 
+typedef struct _DEVCLASS_ENTRY
+{
+    GUID ClassGuid;
+    INT ClassImage;
+    BOOL bUsed;
+    HTREEITEM hItem;
+} DEVCLASS_ENTRY, *PDEVCLASS_ENTRY;
+
+
 INT_PTR CALLBACK AboutDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);