From 955e4aa15931a79866f95fa83fdcfe313a8e9596 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Wed, 21 Mar 2012 03:01:31 +0000 Subject: [PATCH] - 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 --- .../mscutils/devmgmt/enumdevices.c | 57 ++++++++++++------ .../applications/mscutils/devmgmt/precomp.h | 3 + reactos/media/inf/CMakeLists.txt | 1 + reactos/media/inf/legcydrv.inf | Bin 0 -> 1212 bytes reactos/media/inf/syssetup.inf | 3 +- reactos/media/inf/syssetup.inf.tpl | 3 +- reactos/ntoskrnl/io/pnpmgr/plugplay.c | 48 +++++++++++++-- reactos/ntoskrnl/io/pnpmgr/pnpmgr.c | 23 ++++--- 8 files changed, 107 insertions(+), 31 deletions(-) create mode 100644 reactos/media/inf/legcydrv.inf diff --git a/reactos/base/applications/mscutils/devmgmt/enumdevices.c b/reactos/base/applications/mscutils/devmgmt/enumdevices.c index 51c07f7e041..5ac50b0518a 100644 --- a/reactos/base/applications/mscutils/devmgmt/enumdevices.c +++ b/reactos/base/applications/mscutils/devmgmt/enumdevices.c @@ -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) diff --git a/reactos/base/applications/mscutils/devmgmt/precomp.h b/reactos/base/applications/mscutils/devmgmt/precomp.h index 143f1bd2366..2276bfd1b43 100644 --- a/reactos/base/applications/mscutils/devmgmt/precomp.h +++ b/reactos/base/applications/mscutils/devmgmt/precomp.h @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include #include "resource.h" #ifdef _MSC_VER diff --git a/reactos/media/inf/CMakeLists.txt b/reactos/media/inf/CMakeLists.txt index 8f428be09a0..dcb349a88fd 100644 --- a/reactos/media/inf/CMakeLists.txt +++ b/reactos/media/inf/CMakeLists.txt @@ -17,6 +17,7 @@ list(APPEND INF_FILES ks.inf kscaptur.inf layout.inf + legcydrv.inf machine.inf monitor.inf msmouse.inf diff --git a/reactos/media/inf/legcydrv.inf b/reactos/media/inf/legcydrv.inf new file mode 100644 index 0000000000000000000000000000000000000000..6001f11c58322a1e21bba09fc816283d93352c6b GIT binary patch literal 1212 zcmbu9-Ae*d5XH}P(EqSVzNuv&SVRxeW=Ud_Ru9pG^dW+2v{^{>uUEgB>$Vz|4>H{4 z?#!JzXV1*t&yOoz=uS^c)YDJ{U29oOYVp?Pt)pj+h~6o}_Ey%GK@)%%WUc>SqJ$#L%;=fES0;~TeNmQg3S>lkCj zaPR2_&(n{rBb}>8JpHaWZR=16*qXMmSVeZ5s=%kHG8VIn+9$Sw*P_9yWLDgJ=x5#? zsR`l`(-fc;r5?yS;dfFLW3+fL;g$m|MLTzW1YaI0F!hDy?%eL`KkP$ zoz4&&eEkFZ2aRV@YD}R`ydnN(0VU_%-LwT XjzEv7W`CE+J@#LSP&vED$pq;Oo42MQ literal 0 HcmV?d00001 diff --git a/reactos/media/inf/syssetup.inf b/reactos/media/inf/syssetup.inf index 0d7a21c75ab..0cac79e43df 100644 --- a/reactos/media/inf/syssetup.inf +++ b/reactos/media/inf/syssetup.inf @@ -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 diff --git a/reactos/media/inf/syssetup.inf.tpl b/reactos/media/inf/syssetup.inf.tpl index d0069ddfa69..d35fe0cc5a9 100644 --- a/reactos/media/inf/syssetup.inf.tpl +++ b/reactos/media/inf/syssetup.inf.tpl @@ -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 diff --git a/reactos/ntoskrnl/io/pnpmgr/plugplay.c b/reactos/ntoskrnl/io/pnpmgr/plugplay.c index d427bce5d0c..745f7572b28 100644 --- a/reactos/ntoskrnl/io/pnpmgr/plugplay.c +++ b/reactos/ntoskrnl/io/pnpmgr/plugplay.c @@ -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); diff --git a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c index 4f52e539858..710fef0a2bc 100644 --- a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c +++ b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c @@ -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);