f5d58b9a60aee71528a00eb85e4a624f48cc0ea4
[reactos.git] / reactos / dll / win32 / devmgr / devmgmt / ClassNode.cpp
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
15 CClassNode::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
25 CClassNode::~CClassNode()
26 {
27 }
28
29
30 bool
31 CClassNode::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 Size = DISPLAY_NAME_LEN;
46 Type = REG_SZ;
47
48 // Lookup the class description (win7+)
49 Success = RegQueryValueExW(hKey,
50 L"ClassDesc",
51 NULL,
52 &Type,
53 (LPBYTE)m_DisplayName,
54 &Size);
55 if (Success == ERROR_SUCCESS)
56 {
57 // Check if the string starts with an @
58 if (m_DisplayName[0] == L'@')
59 {
60 // The description is located in a module resource
61 Success = ConvertResourceDescriptorToString(m_DisplayName, DISPLAY_NAME_LEN);
62 }
63 }
64 else if (Success == ERROR_FILE_NOT_FOUND)
65 {
66 // WinXP stores the description in the default value
67 Success = RegQueryValueExW(hKey,
68 NULL,
69 NULL,
70 &Type,
71 (LPBYTE)m_DisplayName,
72 &Size);
73 }
74
75 // Close the registry key
76 RegCloseKey(hKey);
77 }
78 else
79 {
80 Success = GetLastError();
81 }
82
83 // Check if we failed to get the class description
84 if (Success != ERROR_SUCCESS)
85 {
86 // Use the class name as the description
87 RequiredSize = DISPLAY_NAME_LEN;
88 (VOID)SetupDiClassNameFromGuidW(&m_ClassGuid,
89 m_DisplayName,
90 RequiredSize,
91 &RequiredSize);
92 }
93
94 // Get the image index for this class
95 (VOID)SetupDiGetClassImageIndex(m_ImageListData,
96 &m_ClassGuid,
97 &m_ClassImage);
98
99 return true;
100 }
101
102
103 DWORD
104 CClassNode::ConvertResourceDescriptorToString(
105 _Inout_z_ LPWSTR ResourceDescriptor,
106 _In_ DWORD ResourceDescriptorSize
107 )
108 {
109 WCHAR ModulePath[MAX_PATH];
110 WCHAR ResString[256];
111 INT ResourceId;
112 HMODULE hModule;
113 LPWSTR ptr;
114 DWORD Size;
115 DWORD dwError;
116
117 // First check for a semi colon */
118 ptr = wcschr(ResourceDescriptor, L';');
119 if (ptr)
120 {
121 // This must be an inf based descriptor, the desc is after the semi colon
122 StringCbCopyW(ResourceDescriptor, ResourceDescriptorSize, ++ptr);
123 dwError = ERROR_SUCCESS;
124 }
125 else
126 {
127 // This must be a dll resource based descriptor. Find the comma
128 ptr = wcschr(ResourceDescriptor, L',');
129 if (ptr == NULL)
130 return ERROR_INVALID_DATA;
131
132 // Terminate the string where the comma was
133 *ptr = UNICODE_NULL;
134
135 // Expand any environment strings
136 Size = ExpandEnvironmentStringsW(&ResourceDescriptor[1], ModulePath, MAX_PATH);
137 if (Size > MAX_PATH)
138 return ERROR_BUFFER_OVERFLOW;
139 if (Size == 0)
140 return GetLastError();
141
142 // Put the comma back and move past it
143 *ptr = L',';
144 ptr++;
145
146 // Load the dll
147 hModule = LoadLibraryExW(ModulePath, NULL, LOAD_LIBRARY_AS_DATAFILE);
148 if (hModule == NULL)
149 return GetLastError();
150
151 // Convert the resource id to a number
152 ResourceId = _wtoi(ptr);
153
154 // If the number is negative, make it positive
155 if (ResourceId < 0)
156 ResourceId = -ResourceId;
157
158 // Load the string from the dll
159 if (LoadStringW(hModule, ResourceId, ResString, 256))
160 {
161 StringCbCopyW(ResourceDescriptor, ResourceDescriptorSize, ResString);
162 dwError = ERROR_SUCCESS;
163 }
164 else
165 {
166 dwError = GetLastError();
167 }
168
169 // Free the library
170 FreeLibrary(hModule);
171 }
172
173 return dwError;
174 }