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 // 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 110 DWORD 111 CClassNode::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 } 182