Reactos
1/*
2* PROJECT: ReactOS Device Manager
3* LICENSE: GPL - See COPYING in the top level directory
4* FILE: dll/win32/devmgr/devmgmt/ClassNode.cpp
5* PURPOSE: Class object for
6* COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
7*
8*/
9
10#include "precomp.h"
11#include "devmgmt.h"
12#include "ClassNode.h"
13
14
15CClassNode::CClassNode(
16 _In_ LPGUID ClassGuid,
17 _In_ PSP_CLASSIMAGELIST_DATA ImageListData
18 ) :
19 CNode(ClassNode, ImageListData)
20{
21 CopyMemory(&m_ClassGuid, ClassGuid, sizeof(GUID));
22}
23
24
25CClassNode::~CClassNode()
26{
27}
28
29
30bool
31CClassNode::SetupNode()
32{
33 DWORD RequiredSize, Type, Size;
34 DWORD Success;
35 HKEY hKey;
36
37 // Open the registry key for this class
38 hKey = SetupDiOpenClassRegKeyExW(&m_ClassGuid,
39 MAXIMUM_ALLOWED,
40 DIOCR_INSTALLER,
41 NULL,
42 0);
43 if (hKey != INVALID_HANDLE_VALUE)
44 {
45 // Lookup the class description (win7+)
46 Size = sizeof(m_DisplayName);
47 Success = RegQueryValueExW(hKey,
48 L"ClassDesc",
49 NULL,
50 &Type,
51 (LPBYTE)m_DisplayName,
52 &Size);
53 if (Success == ERROR_SUCCESS)
54 {
55 if (Type != REG_SZ)
56 {
57 Success = ERROR_INVALID_DATA;
58 }
59 // Check if the string starts with an @
60 else if (m_DisplayName[0] == L'@')
61 {
62 // The description is located in a module resource
63 Success = ConvertResourceDescriptorToString(m_DisplayName, sizeof(m_DisplayName));
64 }
65 }
66 else if (Success == ERROR_FILE_NOT_FOUND)
67 {
68 // WinXP stores the description in the default value
69 Size = sizeof(m_DisplayName);
70 Success = RegQueryValueExW(hKey,
71 NULL,
72 NULL,
73 &Type,
74 (LPBYTE)m_DisplayName,
75 &Size);
76 if (Success == ERROR_SUCCESS && Type != REG_SZ)
77 {
78 Success = ERROR_INVALID_DATA;
79 }
80 }
81
82 // Close the registry key
83 RegCloseKey(hKey);
84 }
85 else
86 {
87 Success = GetLastError();
88 }
89
90 // Check if we failed to get the class description
91 if (Success != ERROR_SUCCESS)
92 {
93 // Use the class name as the description
94 RequiredSize = _countof(m_DisplayName);
95 (VOID)SetupDiClassNameFromGuidW(&m_ClassGuid,
96 m_DisplayName,
97 RequiredSize,
98 &RequiredSize);
99 }
100
101 // Get the image index for this class
102 (VOID)SetupDiGetClassImageIndex(m_ImageListData,
103 &m_ClassGuid,
104 &m_ClassImage);
105
106 return true;
107}
108
109
110DWORD
111CClassNode::ConvertResourceDescriptorToString(
112 _Inout_z_ LPWSTR ResourceDescriptor,
113 _In_ DWORD ResourceDescriptorSize
114 )
115{
116 WCHAR ModulePath[MAX_PATH];
117 WCHAR ResString[256];
118 INT ResourceId;
119 HMODULE hModule;
120 LPWSTR ptr;
121 DWORD Size;
122 DWORD dwError;
123
124 // First check for a semi colon */
125 ptr = wcschr(ResourceDescriptor, L';');
126 if (ptr)
127 {
128 // This must be an inf based descriptor, the desc is after the semi colon
129 StringCbCopyW(ResourceDescriptor, ResourceDescriptorSize, ++ptr);
130 dwError = ERROR_SUCCESS;
131 }
132 else
133 {
134 // This must be a dll resource based descriptor. Find the comma
135 ptr = wcschr(ResourceDescriptor, L',');
136 if (ptr == NULL)
137 return ERROR_INVALID_DATA;
138
139 // Terminate the string where the comma was
140 *ptr = UNICODE_NULL;
141
142 // Expand any environment strings
143 Size = ExpandEnvironmentStringsW(&ResourceDescriptor[1], ModulePath, MAX_PATH);
144 if (Size > MAX_PATH)
145 return ERROR_BUFFER_OVERFLOW;
146 if (Size == 0)
147 return GetLastError();
148
149 // Put the comma back and move past it
150 *ptr = L',';
151 ptr++;
152
153 // Load the dll
154 hModule = LoadLibraryExW(ModulePath, NULL, LOAD_LIBRARY_AS_DATAFILE);
155 if (hModule == NULL)
156 return GetLastError();
157
158 // Convert the resource id to a number
159 ResourceId = _wtoi(ptr);
160
161 // If the number is negative, make it positive
162 if (ResourceId < 0)
163 ResourceId = -ResourceId;
164
165 // Load the string from the dll
166 if (LoadStringW(hModule, ResourceId, ResString, 256))
167 {
168 StringCbCopyW(ResourceDescriptor, ResourceDescriptorSize, ResString);
169 dwError = ERROR_SUCCESS;
170 }
171 else
172 {
173 dwError = GetLastError();
174 }
175
176 // Free the library
177 FreeLibrary(hModule);
178 }
179
180 return dwError;
181}