2 * PROJECT: ReactOS Device Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/devmgr/devmgr/node.cpp
5 * PURPOSE: Object for each device in the tree
6 * COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
15 /* PUBLIC METHODS *******************************************/
17 CNode::CNode(_In_ LPGUID ClassGuid
,
18 _In_ PSP_CLASSIMAGELIST_DATA ImageListData
) :
19 m_ImageListData(ImageListData
),
20 m_NodeType(NodeClass
),
28 m_DisplayName
[0] = UNICODE_NULL
;
29 CopyMemory(&m_ClassGuid
, ClassGuid
, sizeof(GUID
));
32 CNode::CNode(_In_opt_ DEVINST Device
,
33 _In_ PSP_CLASSIMAGELIST_DATA ImageListData
) :
34 m_ImageListData(ImageListData
),
35 m_NodeType(NodeDevice
),
43 m_DisplayName
[0] = UNICODE_NULL
;
44 CopyMemory(&m_ClassGuid
, &GUID_NULL
, sizeof(GUID
));
55 // TODO: Make this polymorphic
57 if (m_NodeType
== NodeClass
)
59 return SetupClassNode();
61 else if (m_NodeType
== NodeDevice
)
63 return SetupDeviceNode();
70 CNode::HasProperties()
72 return (m_DeviceId
!= NULL
);
79 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
86 return ((m_Status
& DN_NO_SHOW_IN_DM
) != 0);
96 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
101 if (cr
== CR_SUCCESS
)
103 return (m_NodeType
== NodeDevice
&& ((m_Status
& DN_DISABLEABLE
) != 0));
113 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
118 if (cr
== CR_SUCCESS
)
120 return ((m_ProblemNumber
& (CM_PROB_DISABLED
| CM_PROB_HARDWARE_DISABLED
)) != 0);
130 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
135 if (cr
== CR_SUCCESS
)
137 return ((m_Status
& DN_STARTED
) != 0);
147 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
152 if (cr
== CR_SUCCESS
)
154 return ((m_Status
& DN_HAS_PROBLEM
) != 0 ||
155 (m_Status
& (DN_DRIVER_LOADED
| DN_STARTED
)) != 0);
162 /* PRIVATE METHODS ******************************************/
165 CNode::SetupClassNode()
167 DWORD RequiredSize
, Type
, Size
;
171 // Open the registry key for this class
172 hKey
= SetupDiOpenClassRegKeyExW(&m_ClassGuid
,
177 if (hKey
!= INVALID_HANDLE_VALUE
)
179 Size
= DISPLAY_NAME_LEN
;
182 // Lookup the class description (win7+)
183 Success
= RegQueryValueExW(hKey
,
187 (LPBYTE
)m_DisplayName
,
189 if (Success
== ERROR_SUCCESS
)
191 // Check if the string starts with an @
192 if (m_DisplayName
[0] == L
'@')
194 // The description is located in a module resource
195 Success
= ConvertResourceDescriptorToString(m_DisplayName
, DISPLAY_NAME_LEN
);
198 else if (Success
== ERROR_FILE_NOT_FOUND
)
200 // WinXP stores the description in the default value
201 Success
= RegQueryValueExW(hKey
,
205 (LPBYTE
)m_DisplayName
,
209 // Close the registry key
214 Success
= GetLastError();
217 // Check if we failed to get the class description
218 if (Success
!= ERROR_SUCCESS
)
220 // Use the class name as the description
221 RequiredSize
= DISPLAY_NAME_LEN
;
222 (VOID
)SetupDiClassNameFromGuidW(&m_ClassGuid
,
228 // Get the image index for this class
229 (VOID
)SetupDiGetClassImageIndex(m_ImageListData
,
237 CNode::SetupDeviceNode()
239 WCHAR ClassGuidString
[MAX_GUID_STRING_LEN
];
243 // ATLASSERT(m_DeviceId == NULL);
245 // Get the length of the device id string
246 cr
= CM_Get_Device_ID_Size(&ulLength
, m_DevInst
, 0);
247 if (cr
== CR_SUCCESS
)
249 // We alloc heap here because this will be stored in the lParam of the TV
250 m_DeviceId
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
252 (ulLength
+ 1) * sizeof(WCHAR
));
255 // Now get the actual device id
256 cr
= CM_Get_Device_IDW(m_DevInst
,
260 if (cr
!= CR_SUCCESS
)
262 HeapFree(GetProcessHeap(), 0, m_DeviceId
);
268 // Make sure we got the string
269 if (m_DeviceId
== NULL
)
272 // Get the current status of the device
273 cr
= CM_Get_DevNode_Status_Ex(&m_Status
,
278 if (cr
!= CR_SUCCESS
)
280 HeapFree(GetProcessHeap(), 0, m_DeviceId
);
285 // Check if the device has a problem
286 if (m_Status
& DN_HAS_PROBLEM
)
291 // The disabled overlay takes precidence over the problem overlay
292 if (m_ProblemNumber
& (CM_PROB_DISABLED
| CM_PROB_HARDWARE_DISABLED
))
298 // Get the class guid for this device
299 ulLength
= MAX_GUID_STRING_LEN
* sizeof(WCHAR
);
300 cr
= CM_Get_DevNode_Registry_PropertyW(m_DevInst
,
306 if (cr
== CR_SUCCESS
)
308 // Convert the string to a proper guid
309 CLSIDFromString(ClassGuidString
, &m_ClassGuid
);
313 // It's a device with no driver
314 m_ClassGuid
= GUID_DEVCLASS_UNKNOWN
;
318 // Get the image for the class this device is in
319 SetupDiGetClassImageIndex(m_ImageListData
,
323 // Get the description for the device
324 ulLength
= DISPLAY_NAME_LEN
* sizeof(WCHAR
);
325 cr
= CM_Get_DevNode_Registry_PropertyW(m_DevInst
,
331 if (cr
!= CR_SUCCESS
)
333 ulLength
= DISPLAY_NAME_LEN
* sizeof(WCHAR
);
334 cr
= CM_Get_DevNode_Registry_PropertyW(m_DevInst
,
343 // Cleanup if something failed
344 if (cr
!= CR_SUCCESS
)
346 HeapFree(GetProcessHeap(), 0, m_DeviceId
);
350 return (cr
== CR_SUCCESS
? true : false);
358 HeapFree(GetProcessHeap(), 0, m_DeviceId
);
364 CNode::ConvertResourceDescriptorToString(
365 _Inout_z_ LPWSTR ResourceDescriptor
,
366 _In_ DWORD ResourceDescriptorSize
369 WCHAR ModulePath
[MAX_PATH
];
370 WCHAR ResString
[256];
378 // First check for a semi colon */
379 ptr
= wcschr(ResourceDescriptor
, L
';');
382 // This must be an inf based descriptor, the desc is after the semi colon
383 wcscpy_s(ResourceDescriptor
, ResourceDescriptorSize
, ++ptr
);
384 dwError
= ERROR_SUCCESS
;
388 // This must be a dll resource based descriptor. Find the comma
389 ptr
= wcschr(ResourceDescriptor
, L
',');
390 if (ptr
== NULL
) return ERROR_INVALID_DATA
;
392 // Terminate the string where the comma was
395 // Expand any environment strings
396 Size
= ExpandEnvironmentStringsW(&ResourceDescriptor
[1], ModulePath
, MAX_PATH
);
397 if (Size
> MAX_PATH
) return ERROR_BUFFER_OVERFLOW
;
398 if (Size
== 0) return GetLastError();
400 // Put the comma back and move past it
405 hModule
= LoadLibraryExW(ModulePath
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
406 if (hModule
== NULL
) return GetLastError();
408 // Convert the resource id to a number
409 ResourceId
= _wtoi(ptr
);
411 // If the number is negative, make it positive
412 if (ResourceId
< 0) ResourceId
= -ResourceId
;
414 // Load the string from the dll
415 if (LoadStringW(hModule
, ResourceId
, ResString
, 256))
417 wcscpy_s(ResourceDescriptor
, ResourceDescriptorSize
, ResString
);
418 dwError
= ERROR_SUCCESS
;
422 dwError
= GetLastError();
426 FreeLibrary(hModule
);