836c5ce889d344f9afbac6af9ccd099d4e244768
[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
118 // First check for a semi colon */
119 ptr = wcschr(ResourceDescriptor, L';');
120 if (ptr)
121 {
122 // This must be an inf based descriptor, the desc is after the semi colon
123 StringCbCopyW(ResourceDescriptor, ResourceDescriptorSize, ++ptr);
124 dwError = ERROR_SUCCESS;
125 }
126 else
127 {
128 // This must be a dll resource based descriptor. Find the comma
129 ptr = wcschr(ResourceDescriptor, L',');
130 if (ptr == NULL) 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) return ERROR_BUFFER_OVERFLOW;
138 if (Size == 0) return GetLastError();
139
140 // Put the comma back and move past it
141 *ptr = L',';
142 ptr++;
143
144 // Load the dll
145 hModule = LoadLibraryExW(ModulePath, NULL, LOAD_LIBRARY_AS_DATAFILE);
146 if (hModule == NULL) return GetLastError();
147
148 // Convert the resource id to a number
149 ResourceId = _wtoi(ptr);
150
151 // If the number is negative, make it positive
152 if (ResourceId < 0) ResourceId = -ResourceId;
153
154 // Load the string from the dll
155 if (LoadStringW(hModule, ResourceId, ResString, 256))
156 {
157 StringCbCopyW(ResourceDescriptor, ResourceDescriptorSize, ResString);
158 dwError = ERROR_SUCCESS;
159 }
160 else
161 {
162 dwError = GetLastError();
163 }
164
165 // Free the library
166 FreeLibrary(hModule);
167 }
168
169 return dwError;
170 }