- Major improvements to the device manager experience (finally making it useful for users to gather information from)

- Device manager now reports problem codes, shows unknown devices, and displays non-PnP drivers like Windows
- Inspired by Eric's recent work
[DEVMGMT]
- Finally (!!!) add support for showing devices with no drivers installed yet
- Expand the class tree if one of the devices has a problem
[INF]
- Add legcydrv.inf for installing the LegacyDriver class
[NTOSKRNL]
- Fix null termination issues and enable the legacy driver registry code
- Add a service description in legacy device entries
- Return valid flags for a device status query
- Store problem codes for several common device node failure states

svn path=/trunk/; revision=56199
This commit is contained in:
Cameron Gutman
2012-03-21 03:01:31 +00:00
parent 3eb6f2228b
commit 955e4aa159
8 changed files with 107 additions and 31 deletions
@@ -12,6 +12,7 @@
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)
@@ -138,7 +139,8 @@ EnumDeviceClasses(INT ClassIndex,
LPTSTR DevClassName,
LPTSTR DevClassDesc,
BOOL *DevPresent,
INT *ClassImage)
INT *ClassImage,
BOOL *IsUnknown)
{
GUID ClassGuid;
HKEY KeyClass;
@@ -157,7 +159,6 @@ EnumDeviceClasses(INT ClassIndex,
/* all classes enumerated */
if(Ret == CR_NO_SUCH_VALUE)
{
hDevInfo = NULL;
return -1;
}
@@ -169,6 +170,9 @@ EnumDeviceClasses(INT ClassIndex,
/* handle other errors... */
}
/* This case is special because these devices don't show up with normal class enumeration */
*IsUnknown = IsEqualGUID(&ClassGuid, &GUID_DEVCLASS_UNKNOWN);
if (SetupDiClassNameFromGuid(&ClassGuid,
ClassName,
RequiredSize,
@@ -188,13 +192,12 @@ EnumDeviceClasses(INT ClassIndex,
}
/* Get device info for all devices of a particular class */
hDevInfo = SetupDiGetClassDevs(&ClassGuid,
hDevInfo = SetupDiGetClassDevs(*IsUnknown ? NULL : &ClassGuid,
NULL,
NULL,
DIGCF_PRESENT);
DIGCF_PRESENT | (*IsUnknown ? DIGCF_ALLCLASSES : 0));
if (hDevInfo == INVALID_HANDLE_VALUE)
{
hDevInfo = NULL;
return 0;
}
@@ -218,7 +221,7 @@ EnumDeviceClasses(INT ClassIndex,
}
else
{
return -3;
return 0;
}
*DevPresent = TRUE;
@@ -254,6 +257,12 @@ EnumDevices(INT index,
return -1;
}
if (DeviceClassName == NULL && !IsEqualGUID(&DeviceInfoData.ClassGuid, &GUID_NULL))
{
/* we're looking for unknown devices and this isn't one */
return -2;
}
/* get the device ID */
if (!SetupDiGetDeviceInstanceId(hDevInfo,
&DeviceInfoData,
@@ -328,6 +337,7 @@ ListDevicesByType(HWND hTreeView,
INT ClassRet;
INT index = 0;
INT DevImage;
BOOL IsUnknown = FALSE;
do
{
@@ -335,7 +345,8 @@ ListDevicesByType(HWND hTreeView,
DevName,
DevDesc,
&DevExist,
&DevImage);
&DevImage,
&IsUnknown);
if ((ClassRet != -1) && (DevExist))
{
@@ -365,7 +376,7 @@ ListDevicesByType(HWND hTreeView,
do
{
Ret = EnumDevices(DevIndex,
DevName,
IsUnknown ? NULL : DevName,
DeviceName,
&DeviceID);
if (Ret >= 0)
@@ -376,6 +387,13 @@ ListDevicesByType(HWND hTreeView,
DeviceID,
DevImage,
Ret);
if (Ret != 0)
{
/* Expand the class if the device has a problem */
(void)TreeView_Expand(hTreeView,
hDevItem,
TVE_EXPAND);
}
}
DevIndex++;
@@ -472,16 +490,21 @@ AddDeviceToTree(HWND hTreeView,
if (cr == CR_SUCCESS)
{
pSetupGuidFromString(ClassGuidString, &ClassGuid);
}
else
{
/* It's a device with no driver */
ClassGuid = GUID_DEVCLASS_UNKNOWN;
}
if (!SetupDiGetClassImageIndex(&ImageListData,
&ClassGuid,
&ClassImage))
{
/* FIXME: can we do this?
* Set the blank icon: IDI_SETUPAPI_BLANK = 41
* it'll be image 24 in the imagelist */
ClassImage = 24;
}
if (!SetupDiGetClassImageIndex(&ImageListData,
&ClassGuid,
&ClassImage))
{
/* FIXME: can we do this?
* Set the blank icon: IDI_SETUPAPI_BLANK = 41
* it'll be image 24 in the imagelist */
ClassImage = 24;
}
if (DevName != NULL)
@@ -10,6 +10,9 @@
#include <cfgmgr32.h>
#include <commctrl.h>
#include <dll/devmgr/devmgr.h>
#include <initguid.h>
#include <cguid.h>
#include <devguid.h>
#include "resource.h"
#ifdef _MSC_VER
+1
View File
@@ -17,6 +17,7 @@ list(APPEND INF_FILES
ks.inf
kscaptur.inf
layout.inf
legcydrv.inf
machine.inf
monitor.inf
msmouse.inf
Binary file not shown.
+2 -1
View File
@@ -13,7 +13,8 @@ hal.inf
hdc.inf
input.inf
keyboard.inf
machine.inf
legcydrv.inf
machine.inf
monitor.inf
msmouse.inf
NET_NIC.inf
+2 -1
View File
@@ -24,7 +24,8 @@ hal.inf
hdc.inf
input.inf
keyboard.inf
machine.inf
legcydrv.inf
machine.inf
monitor.inf
msmouse.inf
NET_NIC.inf
+44 -4
View File
@@ -406,6 +406,47 @@ IopGetRelatedDevice(PPLUGPLAY_CONTROL_RELATED_DEVICE_DATA RelatedDeviceData)
return Status;
}
static ULONG
IopGetDeviceNodeStatus(PDEVICE_NODE DeviceNode)
{
ULONG Output = 0;
if (DeviceNode->Parent == IopRootDeviceNode)
Output |= DN_ROOT_ENUMERATED;
if (DeviceNode->Flags & DNF_ADDED)
Output |= DN_DRIVER_LOADED;
/* FIXME: DN_ENUM_LOADED */
if (DeviceNode->Flags & DNF_STARTED)
Output |= DN_STARTED;
/* FIXME: Manual */
if (!(DeviceNode->Flags & DNF_PROCESSED))
Output |= DN_NEED_TO_ENUM;
/* DN_NOT_FIRST_TIME is 9x only */
/* FIXME: DN_HARDWARE_ENUM */
/* DN_LIAR and DN_HAS_MARK are 9x only */
if (DeviceNode->Problem != 0)
Output |= DN_HAS_PROBLEM;
/* FIXME: DN_FILTERED */
if (DeviceNode->Flags & DNF_LEGACY_DRIVER)
Output |= DN_LEGACY_DRIVER;
/* FIXME: Implement the rest */
Output |= DN_NT_ENUMERATOR | DN_NT_DRIVER;
return Output;
}
static NTSTATUS
IopDeviceStatus(PPLUGPLAY_CONTROL_STATUS_DATA StatusData)
@@ -453,14 +494,12 @@ IopDeviceStatus(PPLUGPLAY_CONTROL_STATUS_DATA StatusData)
{
case PNP_GET_DEVICE_STATUS:
DPRINT("Get status data\n");
DeviceStatus = DeviceNode->Flags;
DeviceStatus = IopGetDeviceNodeStatus(DeviceNode);
DeviceProblem = DeviceNode->Problem;
break;
case PNP_SET_DEVICE_STATUS:
DPRINT("Set status data\n");
DeviceNode->Flags = DeviceStatus;
DeviceNode->Problem = DeviceProblem;
DPRINT1("Set status data is NOT SUPPORTED\n");
break;
case PNP_CLEAR_DEVICE_STATUS:
@@ -576,6 +615,7 @@ IopResetDevice(PPLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData)
{
/* FIXME: What if the device really is disabled? */
DeviceNode->Flags &= ~DNF_DISABLED;
DeviceNode->Problem = 0;
/* Load service data from the registry */
Status = IopActionConfigureChildServices(DeviceNode, DeviceNode->Parent);
+15 -8
View File
@@ -460,6 +460,7 @@ IopInitializeDevice(PDEVICE_NODE DeviceNode,
&DeviceNode->InstancePath,
Status);
IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
DeviceNode->Problem = CM_PROB_FAILED_ADD;
return Status;
}
@@ -663,6 +664,7 @@ IopStartDevice2(IN PDEVICE_OBJECT DeviceObject)
/* Set the appropriate flag */
DeviceNode->Flags |= DNF_START_FAILED;
DeviceNode->Problem = CM_PROB_FAILED_START;
DPRINT1("Warning: PnP Start failed (%wZ) [Status: 0x%x]\n", &DeviceNode->InstancePath, Status);
return;
@@ -1008,9 +1010,7 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
UNICODE_STRING KeyName, ClassName;
PUNICODE_STRING ServiceName1;
ULONG LegacyValue;
#if 0
UNICODE_STRING ClassGUID;
#endif
HANDLE InstanceHandle;
DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
@@ -1091,17 +1091,21 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
{
RtlInitUnicodeString(&KeyName, L"Class");
RtlInitUnicodeString(&ClassName, L"LegacyDriver");
Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassName.Buffer, ClassName.Length);
#if 0
RtlInitUnicodeString(&ClassName, L"LegacyDriver\0");
Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassName.Buffer, ClassName.Length + sizeof(UNICODE_NULL));
if (NT_SUCCESS(Status))
{
RtlInitUnicodeString(&KeyName, L"ClassGUID");
RtlInitUnicodeString(&ClassGUID, L"{8ECC055D-047F-11D1-A537-0000F8753ED1}");
Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassGUID.Buffer, ClassGUID.Length);
RtlInitUnicodeString(&ClassGUID, L"{8ECC055D-047F-11D1-A537-0000F8753ED1}\0");
Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassGUID.Buffer, ClassGUID.Length + sizeof(UNICODE_NULL));
if (NT_SUCCESS(Status))
{
RtlInitUnicodeString(&KeyName, L"DeviceDesc");
Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ServiceName1->Buffer, ServiceName1->Length + sizeof(UNICODE_NULL));
}
}
#endif
}
}
@@ -2490,6 +2494,7 @@ IopActionConfigureChildServices(PDEVICE_NODE DeviceNode,
}
else
{
DeviceNode->Problem = CM_PROB_FAILED_INSTALL;
IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
}
return STATUS_SUCCESS;
@@ -2621,6 +2626,8 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
{
IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
IopDeviceNodeSetFlag(DeviceNode, DNF_START_FAILED);
DeviceNode->Problem = CM_PROB_FAILED_START;
/* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
DPRINT1("Initialization of service %S failed (Status %x)\n",
DeviceNode->ServiceName.Buffer, Status);