1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT:     ReactOS Device Manager
3c2c66affSColin Finck * LICENSE:     GPL - See COPYING in the top level directory
4c2c66affSColin Finck * FILE:        dll/win32/devmgr/devmgmt/ClassNode.cpp
5c2c66affSColin Finck * PURPOSE:     Class object for
6c2c66affSColin Finck * COPYRIGHT:   Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
7c2c66affSColin Finck *
8c2c66affSColin Finck */
9c2c66affSColin Finck 
10c2c66affSColin Finck #include "precomp.h"
11c2c66affSColin Finck #include "devmgmt.h"
12c2c66affSColin Finck #include "DeviceNode.h"
13c2c66affSColin Finck 
14c2c66affSColin Finck 
CDeviceNode(_In_opt_ DEVINST Device,_In_ PSP_CLASSIMAGELIST_DATA ImageListData)15c2c66affSColin Finck CDeviceNode::CDeviceNode(
16c2c66affSColin Finck     _In_opt_ DEVINST Device,
17c2c66affSColin Finck     _In_ PSP_CLASSIMAGELIST_DATA ImageListData
18c2c66affSColin Finck     ) :
19c2c66affSColin Finck     CNode(DeviceNode, ImageListData),
20c2c66affSColin Finck     m_DevInst(Device),
21c2c66affSColin Finck     m_hDevInfo(NULL),
22c2c66affSColin Finck     m_Status(0),
23c2c66affSColin Finck     m_ProblemNumber(0),
24c2c66affSColin Finck     m_OverlayImage(0)
25c2c66affSColin Finck {
26c2c66affSColin Finck     ZeroMemory(&m_DevinfoData, sizeof(SP_DEVINFO_DATA));
27c2c66affSColin Finck }
28c2c66affSColin Finck 
CDeviceNode(_In_ const CDeviceNode & Node)29c2c66affSColin Finck CDeviceNode::CDeviceNode(
30c2c66affSColin Finck     _In_ const CDeviceNode &Node
31c2c66affSColin Finck     ) :
32c2c66affSColin Finck     CNode(Node)
33c2c66affSColin Finck {
34c2c66affSColin Finck     m_DevInst = Node.m_DevInst;
35c2c66affSColin Finck     m_hDevInfo = Node.m_hDevInfo;
36c2c66affSColin Finck     m_Status = Node.m_Status;
37c2c66affSColin Finck     m_ProblemNumber = Node.m_ProblemNumber;
38c2c66affSColin Finck     m_OverlayImage = Node.m_OverlayImage;
39c2c66affSColin Finck     CopyMemory(&m_DevinfoData, &Node.m_DevinfoData, sizeof(SP_DEVINFO_DATA));
40c2c66affSColin Finck 
41c2c66affSColin Finck     size_t size = wcslen(Node.m_DeviceId) + 1;
42c2c66affSColin Finck     m_DeviceId = new WCHAR[size];
43c2c66affSColin Finck     StringCbCopyW(m_DeviceId, size * sizeof(WCHAR), Node.m_DeviceId);
44c2c66affSColin Finck }
45c2c66affSColin Finck 
~CDeviceNode()46c2c66affSColin Finck CDeviceNode::~CDeviceNode()
47c2c66affSColin Finck {
48c2c66affSColin Finck     Cleanup();
49c2c66affSColin Finck }
50c2c66affSColin Finck 
51c2c66affSColin Finck bool
SetupNode()52c2c66affSColin Finck CDeviceNode::SetupNode()
53c2c66affSColin Finck {
54c2c66affSColin Finck     WCHAR ClassGuidString[MAX_GUID_STRING_LEN];
55c2c66affSColin Finck     ULONG ulLength;
56c2c66affSColin Finck     CONFIGRET cr;
57c2c66affSColin Finck 
58c2c66affSColin Finck     // Get the length of the device id string
59c2c66affSColin Finck     cr = CM_Get_Device_ID_Size(&ulLength, m_DevInst, 0);
60c2c66affSColin Finck     if (cr == CR_SUCCESS)
61c2c66affSColin Finck     {
62c2c66affSColin Finck         // We alloc heap here because this will be stored in the lParam of the TV
63c2c66affSColin Finck         m_DeviceId = new WCHAR[ulLength + 1];
64c2c66affSColin Finck 
65c2c66affSColin Finck         // Now get the actual device id
66c2c66affSColin Finck         cr = CM_Get_Device_IDW(m_DevInst,
67c2c66affSColin Finck                                m_DeviceId,
68c2c66affSColin Finck                                ulLength + 1,
69c2c66affSColin Finck                                0);
70c2c66affSColin Finck         if (cr != CR_SUCCESS || wcscmp(m_DeviceId, L"HTREE\\ROOT\\0") == 0)
71c2c66affSColin Finck         {
72c2c66affSColin Finck             delete[] m_DeviceId;
73c2c66affSColin Finck             m_DeviceId = NULL;
74c2c66affSColin Finck         }
75c2c66affSColin Finck     }
76c2c66affSColin Finck 
77c2c66affSColin Finck     // Make sure we got the string
78c2c66affSColin Finck     if (m_DeviceId == NULL)
79c2c66affSColin Finck         return false;
80c2c66affSColin Finck 
81c2c66affSColin Finck     // Build up a handle a and devinfodata struct
82c2c66affSColin Finck     m_hDevInfo = SetupDiCreateDeviceInfoListExW(NULL,
83c2c66affSColin Finck                                                 NULL,
84c2c66affSColin Finck                                                 NULL,
85c2c66affSColin Finck                                                 NULL);
86c2c66affSColin Finck     if (m_hDevInfo != INVALID_HANDLE_VALUE)
87c2c66affSColin Finck     {
88c2c66affSColin Finck         m_DevinfoData.cbSize = sizeof(SP_DEVINFO_DATA);
89c2c66affSColin Finck         SetupDiOpenDeviceInfoW(m_hDevInfo,
90c2c66affSColin Finck                                m_DeviceId,
91c2c66affSColin Finck                                NULL,
92c2c66affSColin Finck                                0,
93c2c66affSColin Finck                                &m_DevinfoData);
94c2c66affSColin Finck     }
95c2c66affSColin Finck 
96c2c66affSColin Finck     // Check if the device has a problem
97c2c66affSColin Finck     if (HasProblem())
98c2c66affSColin Finck     {
99c2c66affSColin Finck         if (IsDisabled())
100c2c66affSColin Finck         {
101c2c66affSColin Finck             m_OverlayImage = OverlayDisabled;
102c2c66affSColin Finck         }
103c2c66affSColin Finck         else
104c2c66affSColin Finck         {
105c2c66affSColin Finck             m_OverlayImage = OverlayProblem;
106c2c66affSColin Finck         }
107c2c66affSColin Finck     }
108c2c66affSColin Finck 
109c2c66affSColin Finck     // Get the class guid for this device
110c2c66affSColin Finck     ulLength = MAX_GUID_STRING_LEN * sizeof(WCHAR);
111c2c66affSColin Finck     cr = CM_Get_DevNode_Registry_PropertyW(m_DevInst,
112c2c66affSColin Finck                                            CM_DRP_CLASSGUID,
113c2c66affSColin Finck                                            NULL,
114c2c66affSColin Finck                                            ClassGuidString,
115c2c66affSColin Finck                                            &ulLength,
116c2c66affSColin Finck                                            0);
117c2c66affSColin Finck     if (cr == CR_SUCCESS)
118c2c66affSColin Finck     {
119c2c66affSColin Finck         // Convert the string to a proper guid
120c2c66affSColin Finck         CLSIDFromString(ClassGuidString, &m_ClassGuid);
121c2c66affSColin Finck     }
122c2c66affSColin Finck     else
123c2c66affSColin Finck     {
124c2c66affSColin Finck         // It's a device with no driver
125c2c66affSColin Finck         m_ClassGuid = GUID_DEVCLASS_UNKNOWN;
126c2c66affSColin Finck     }
127c2c66affSColin Finck 
128c2c66affSColin Finck     // Get the image for the class this device is in
129c2c66affSColin Finck     SetupDiGetClassImageIndex(m_ImageListData,
130c2c66affSColin Finck                               &m_ClassGuid,
131c2c66affSColin Finck                               &m_ClassImage);
132c2c66affSColin Finck 
133c2c66affSColin Finck     // Get the description for the device
134*9c82d16bSSerge Gautherie     ulLength = sizeof(m_DisplayName);
135c2c66affSColin Finck     cr = CM_Get_DevNode_Registry_PropertyW(m_DevInst,
136c2c66affSColin Finck                                            CM_DRP_FRIENDLYNAME,
137c2c66affSColin Finck                                            NULL,
138c2c66affSColin Finck                                            m_DisplayName,
139c2c66affSColin Finck                                            &ulLength,
140c2c66affSColin Finck                                            0);
141c2c66affSColin Finck     if (cr != CR_SUCCESS)
142c2c66affSColin Finck     {
143*9c82d16bSSerge Gautherie         ulLength = sizeof(m_DisplayName);
144c2c66affSColin Finck         cr = CM_Get_DevNode_Registry_PropertyW(m_DevInst,
145c2c66affSColin Finck                                                CM_DRP_DEVICEDESC,
146c2c66affSColin Finck                                                NULL,
147c2c66affSColin Finck                                                m_DisplayName,
148c2c66affSColin Finck                                                &ulLength,
149c2c66affSColin Finck                                                0);
150c2c66affSColin Finck     }
151c2c66affSColin Finck 
152c2c66affSColin Finck     if (cr != CR_SUCCESS)
153c2c66affSColin Finck     {
154c2c66affSColin Finck         CAtlStringW str;
155c2c66affSColin Finck         if (str.LoadStringW(g_hThisInstance, IDS_UNKNOWNDEVICE))
156c2c66affSColin Finck             StringCchCopyW(m_DisplayName, MAX_PATH, str.GetBuffer());
157c2c66affSColin Finck     }
158c2c66affSColin Finck 
159c2c66affSColin Finck     return true;
160c2c66affSColin Finck }
161c2c66affSColin Finck 
162c2c66affSColin Finck bool
HasProblem()163c2c66affSColin Finck CDeviceNode::HasProblem()
164c2c66affSColin Finck {
165c2c66affSColin Finck     CONFIGRET cr;
166c2c66affSColin Finck     cr = CM_Get_DevNode_Status_Ex(&m_Status,
167c2c66affSColin Finck                                   &m_ProblemNumber,
168c2c66affSColin Finck                                   m_DevInst,
169c2c66affSColin Finck                                   0,
170c2c66affSColin Finck                                   NULL);
171c2c66affSColin Finck     if (cr == CR_SUCCESS)
172c2c66affSColin Finck     {
173c2c66affSColin Finck         return ((m_Status & (DN_HAS_PROBLEM | DN_PRIVATE_PROBLEM)) != 0);
174c2c66affSColin Finck     }
175c2c66affSColin Finck 
176c2c66affSColin Finck     return false;
177c2c66affSColin Finck }
178c2c66affSColin Finck 
179c2c66affSColin Finck bool
IsHidden()180c2c66affSColin Finck CDeviceNode::IsHidden()
181c2c66affSColin Finck {
182c2c66affSColin Finck     CONFIGRET cr;
183c2c66affSColin Finck     cr = CM_Get_DevNode_Status_Ex(&m_Status,
184c2c66affSColin Finck                                   &m_ProblemNumber,
185c2c66affSColin Finck                                   m_DevInst,
186c2c66affSColin Finck                                   0,
187c2c66affSColin Finck                                   NULL);
188c2c66affSColin Finck     if (cr == CR_SUCCESS)
189c2c66affSColin Finck     {
190c2c66affSColin Finck         if (m_Status & DN_NO_SHOW_IN_DM)
191c2c66affSColin Finck             return true;
192c2c66affSColin Finck     }
193c2c66affSColin Finck 
194c2c66affSColin Finck     if (IsEqualGUID(*GetClassGuid(), GUID_DEVCLASS_LEGACYDRIVER) ||
195c2c66affSColin Finck         IsEqualGUID(*GetClassGuid(), GUID_DEVCLASS_VOLUME))
196c2c66affSColin Finck         return true;
197c2c66affSColin Finck 
198c2c66affSColin Finck     return false;
199c2c66affSColin Finck }
200c2c66affSColin Finck 
201c2c66affSColin Finck bool
CanDisable()202c2c66affSColin Finck CDeviceNode::CanDisable()
203c2c66affSColin Finck {
204c2c66affSColin Finck     CONFIGRET cr;
205c2c66affSColin Finck     cr = CM_Get_DevNode_Status_Ex(&m_Status,
206c2c66affSColin Finck                                   &m_ProblemNumber,
207c2c66affSColin Finck                                   m_DevInst,
208c2c66affSColin Finck                                   0,
209c2c66affSColin Finck                                   NULL);
210c2c66affSColin Finck     if (cr == CR_SUCCESS)
211c2c66affSColin Finck     {
212c2c66affSColin Finck         return ((m_Status & DN_DISABLEABLE) != 0);
213c2c66affSColin Finck     }
214c2c66affSColin Finck 
215c2c66affSColin Finck     return false;
216c2c66affSColin Finck }
217c2c66affSColin Finck 
218c2c66affSColin Finck bool
IsDisabled()219c2c66affSColin Finck CDeviceNode::IsDisabled()
220c2c66affSColin Finck {
221c2c66affSColin Finck     CONFIGRET cr;
222c2c66affSColin Finck     cr = CM_Get_DevNode_Status_Ex(&m_Status,
223c2c66affSColin Finck                                   &m_ProblemNumber,
224c2c66affSColin Finck                                   m_DevInst,
225c2c66affSColin Finck                                   0,
226c2c66affSColin Finck                                   NULL);
227c2c66affSColin Finck     if (cr == CR_SUCCESS)
228c2c66affSColin Finck     {
229c2c66affSColin Finck         return ((m_ProblemNumber == CM_PROB_DISABLED) || (m_ProblemNumber == CM_PROB_HARDWARE_DISABLED));
230c2c66affSColin Finck     }
231c2c66affSColin Finck 
232c2c66affSColin Finck     return false;
233c2c66affSColin Finck }
234c2c66affSColin Finck 
235c2c66affSColin Finck bool
IsStarted()236c2c66affSColin Finck CDeviceNode::IsStarted()
237c2c66affSColin Finck {
238c2c66affSColin Finck     CONFIGRET cr;
239c2c66affSColin Finck     cr = CM_Get_DevNode_Status_Ex(&m_Status,
240c2c66affSColin Finck                                   &m_ProblemNumber,
241c2c66affSColin Finck                                   m_DevInst,
242c2c66affSColin Finck                                   0,
243c2c66affSColin Finck                                   NULL);
244c2c66affSColin Finck     if (cr == CR_SUCCESS)
245c2c66affSColin Finck     {
246c2c66affSColin Finck         return ((m_Status & DN_STARTED) != 0);
247c2c66affSColin Finck     }
248c2c66affSColin Finck 
249c2c66affSColin Finck     return false;
250c2c66affSColin Finck }
251c2c66affSColin Finck 
252c2c66affSColin Finck bool
IsInstalled()253c2c66affSColin Finck CDeviceNode::IsInstalled()
254c2c66affSColin Finck {
255c2c66affSColin Finck     CONFIGRET cr;
256c2c66affSColin Finck     cr = CM_Get_DevNode_Status_Ex(&m_Status,
257c2c66affSColin Finck                                   &m_ProblemNumber,
258c2c66affSColin Finck                                   m_DevInst,
259c2c66affSColin Finck                                   0,
260c2c66affSColin Finck                                   NULL);
261c2c66affSColin Finck     if (cr == CR_SUCCESS)
262c2c66affSColin Finck     {
263c2c66affSColin Finck         return ((m_Status & DN_HAS_PROBLEM) != 0 ||
264c2c66affSColin Finck                 (m_Status & (DN_DRIVER_LOADED | DN_STARTED)) != 0);
265c2c66affSColin Finck     }
266c2c66affSColin Finck 
267c2c66affSColin Finck     return false;
268c2c66affSColin Finck }
269c2c66affSColin Finck 
270c2c66affSColin Finck bool
CanUninstall()271c2c66affSColin Finck CDeviceNode::CanUninstall()
272c2c66affSColin Finck {
273c2c66affSColin Finck     CONFIGRET cr;
274c2c66affSColin Finck     cr = CM_Get_DevNode_Status_Ex(&m_Status,
275c2c66affSColin Finck                                   &m_ProblemNumber,
276c2c66affSColin Finck                                   m_DevInst,
277c2c66affSColin Finck                                   0,
278c2c66affSColin Finck                                   NULL);
279c2c66affSColin Finck     if (cr == CR_SUCCESS)
280c2c66affSColin Finck     {
281c2c66affSColin Finck         if ((m_Status & DN_ROOT_ENUMERATED) != 0 &&
282c2c66affSColin Finck             (m_Status & DN_DISABLEABLE) == 0)
283c2c66affSColin Finck                 return false;
284c2c66affSColin Finck     }
285c2c66affSColin Finck 
286c2c66affSColin Finck     return true;
287c2c66affSColin Finck }
288c2c66affSColin Finck 
289c2c66affSColin Finck bool
EnableDevice(_In_ bool Enable,_Out_ bool & NeedsReboot)290c2c66affSColin Finck CDeviceNode::EnableDevice(
291c2c66affSColin Finck     _In_ bool Enable,
292c2c66affSColin Finck     _Out_ bool &NeedsReboot
293c2c66affSColin Finck     )
294c2c66affSColin Finck {
295c2c66affSColin Finck     bool Canceled = false;
296c2c66affSColin Finck 
297c2c66affSColin Finck     SetFlags(DI_NODI_DEFAULTACTION, 0);
298c2c66affSColin Finck 
299c2c66affSColin Finck     SP_PROPCHANGE_PARAMS pcp;
300c2c66affSColin Finck     pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
301c2c66affSColin Finck     pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
302c2c66affSColin Finck     pcp.StateChange = (Enable ? DICS_ENABLE : DICS_DISABLE);
303c2c66affSColin Finck     pcp.HwProfile = 0;
304c2c66affSColin Finck 
305c2c66affSColin Finck     // check both scopes to make sure we can make the change
306c2c66affSColin Finck     for (int i = 0; i < 2; i++)
307c2c66affSColin Finck     {
308c2c66affSColin Finck         // Check globally first, then check config specific
309c2c66affSColin Finck         pcp.Scope = (i == 0) ? DICS_FLAG_CONFIGGENERAL : DICS_FLAG_CONFIGSPECIFIC;
310c2c66affSColin Finck 
311c2c66affSColin Finck         if (SetupDiSetClassInstallParamsW(m_hDevInfo,
312c2c66affSColin Finck                                           &m_DevinfoData,
313c2c66affSColin Finck                                           &pcp.ClassInstallHeader,
314c2c66affSColin Finck                                           sizeof(SP_PROPCHANGE_PARAMS)))
315c2c66affSColin Finck         {
316c2c66affSColin Finck             SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
317c2c66affSColin Finck                                       m_hDevInfo,
318c2c66affSColin Finck                                       &m_DevinfoData);
319c2c66affSColin Finck         }
320c2c66affSColin Finck 
321c2c66affSColin Finck         if (GetLastError() == ERROR_CANCELLED)
322c2c66affSColin Finck         {
323c2c66affSColin Finck             Canceled = true;
324c2c66affSColin Finck             break;
325c2c66affSColin Finck         }
326c2c66affSColin Finck     }
327c2c66affSColin Finck 
328c2c66affSColin Finck     if (Canceled == false)
329c2c66affSColin Finck     {
330c2c66affSColin Finck         pcp.Scope = DICS_FLAG_CONFIGSPECIFIC;
331c2c66affSColin Finck         if (SetupDiSetClassInstallParamsW(m_hDevInfo,
332c2c66affSColin Finck                                           &m_DevinfoData,
333c2c66affSColin Finck                                           &pcp.ClassInstallHeader,
334c2c66affSColin Finck                                           sizeof(SP_PROPCHANGE_PARAMS)))
335c2c66affSColin Finck         {
336c2c66affSColin Finck             SetupDiChangeState(m_hDevInfo, &m_DevinfoData);
337c2c66affSColin Finck         }
338c2c66affSColin Finck 
339c2c66affSColin Finck 
340c2c66affSColin Finck         if (Enable)
341c2c66affSColin Finck         {
342c2c66affSColin Finck             // config specific enabling first, then global enabling.
343c2c66affSColin Finck             // The global appears to be the one that starts the device
344c2c66affSColin Finck             pcp.Scope = DICS_FLAG_GLOBAL;
345c2c66affSColin Finck             if (SetupDiSetClassInstallParamsW(m_hDevInfo,
346c2c66affSColin Finck                                               &m_DevinfoData,
347c2c66affSColin Finck                                               &pcp.ClassInstallHeader,
348c2c66affSColin Finck                                               sizeof(SP_PROPCHANGE_PARAMS)))
349c2c66affSColin Finck             {
350c2c66affSColin Finck                 SetupDiChangeState(m_hDevInfo, &m_DevinfoData);
351c2c66affSColin Finck             }
352c2c66affSColin Finck         }
353c2c66affSColin Finck 
354c2c66affSColin Finck         SetFlags(DI_PROPERTIES_CHANGE, 0);
355c2c66affSColin Finck 
356c2c66affSColin Finck         NeedsReboot = ((GetFlags() & (DI_NEEDRESTART | DI_NEEDREBOOT)) != 0);
357c2c66affSColin Finck     }
358c2c66affSColin Finck 
359c2c66affSColin Finck     RemoveFlags(DI_NODI_DEFAULTACTION, 0);
360c2c66affSColin Finck 
361c2c66affSColin Finck     return true;
362c2c66affSColin Finck }
363c2c66affSColin Finck 
364c2c66affSColin Finck bool
UninstallDevice()365c2c66affSColin Finck CDeviceNode::UninstallDevice()
366c2c66affSColin Finck {
367c2c66affSColin Finck     if (CanUninstall() == false)
368c2c66affSColin Finck         return false;
369c2c66affSColin Finck 
370c2c66affSColin Finck     SP_REMOVEDEVICE_PARAMS RemoveDevParams;
371c2c66affSColin Finck     RemoveDevParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
372c2c66affSColin Finck     RemoveDevParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
373c2c66affSColin Finck     RemoveDevParams.Scope = DI_REMOVEDEVICE_GLOBAL;
374c2c66affSColin Finck     RemoveDevParams.HwProfile = 0;
375c2c66affSColin Finck 
376c2c66affSColin Finck     //
377c2c66affSColin Finck     // We probably need to walk all the siblings of this
378c2c66affSColin Finck     // device and ask if they're happy with the uninstall
379c2c66affSColin Finck     //
380c2c66affSColin Finck 
381c2c66affSColin Finck     // Remove it
382c2c66affSColin Finck     SetupDiSetClassInstallParamsW(m_hDevInfo,
383c2c66affSColin Finck                                   &m_DevinfoData,
384c2c66affSColin Finck                                   &RemoveDevParams.ClassInstallHeader,
385c2c66affSColin Finck                                   sizeof(SP_REMOVEDEVICE_PARAMS));
386c2c66affSColin Finck     SetupDiCallClassInstaller(DIF_REMOVE, m_hDevInfo, &m_DevinfoData);
387c2c66affSColin Finck 
388c2c66affSColin Finck     // Clear the install params
389c2c66affSColin Finck     SetupDiSetClassInstallParamsW(m_hDevInfo,
390c2c66affSColin Finck                                   &m_DevinfoData,
391c2c66affSColin Finck                                   NULL,
392c2c66affSColin Finck                                   0);
393c2c66affSColin Finck 
394c2c66affSColin Finck     return true;
395c2c66affSColin Finck }
396c2c66affSColin Finck 
397c2c66affSColin Finck /* PRIVATE METHODS ******************************************************/
398c2c66affSColin Finck 
399c2c66affSColin Finck void
Cleanup()400c2c66affSColin Finck CDeviceNode::Cleanup()
401c2c66affSColin Finck {
402c2c66affSColin Finck     if (m_DeviceId)
403c2c66affSColin Finck     {
404c2c66affSColin Finck         delete[] m_DeviceId;
405c2c66affSColin Finck         m_DeviceId = NULL;
406c2c66affSColin Finck     }
407c2c66affSColin Finck     if (m_hDevInfo)
408c2c66affSColin Finck     {
409c2c66affSColin Finck         SetupDiDestroyDeviceInfoList(m_hDevInfo);
410c2c66affSColin Finck         m_hDevInfo = NULL;
411c2c66affSColin Finck     }
412c2c66affSColin Finck }
413c2c66affSColin Finck 
414c2c66affSColin Finck DWORD
GetFlags()415c2c66affSColin Finck CDeviceNode::GetFlags()
416c2c66affSColin Finck {
417c2c66affSColin Finck     SP_DEVINSTALL_PARAMS DevInstallParams;
418c2c66affSColin Finck     DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
419c2c66affSColin Finck     if (SetupDiGetDeviceInstallParamsW(m_hDevInfo,
420c2c66affSColin Finck                                        &m_DevinfoData,
421c2c66affSColin Finck                                        &DevInstallParams))
422c2c66affSColin Finck     {
423c2c66affSColin Finck         return DevInstallParams.Flags;
424c2c66affSColin Finck     }
425c2c66affSColin Finck     return 0;
426c2c66affSColin Finck }
427c2c66affSColin Finck 
428c2c66affSColin Finck bool
SetFlags(_In_ DWORD Flags,_In_ DWORD FlagsEx)429c2c66affSColin Finck CDeviceNode::SetFlags(
430c2c66affSColin Finck     _In_ DWORD Flags,
431c2c66affSColin Finck     _In_ DWORD FlagsEx
432c2c66affSColin Finck     )
433c2c66affSColin Finck {
434c2c66affSColin Finck     SP_DEVINSTALL_PARAMS DevInstallParams;
435c2c66affSColin Finck     DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
436c2c66affSColin Finck     if (SetupDiGetDeviceInstallParamsW(m_hDevInfo,
437c2c66affSColin Finck                                        &m_DevinfoData,
438c2c66affSColin Finck                                        &DevInstallParams))
439c2c66affSColin Finck     {
440c2c66affSColin Finck         DevInstallParams.Flags |= Flags;
441c2c66affSColin Finck         DevInstallParams.FlagsEx |= FlagsEx;
442c2c66affSColin Finck         return (SetupDiSetDeviceInstallParamsW(m_hDevInfo,
443c2c66affSColin Finck                                                &m_DevinfoData,
444c2c66affSColin Finck                                                &DevInstallParams) != 0);
445c2c66affSColin Finck     }
446c2c66affSColin Finck     return false;
447c2c66affSColin Finck }
448c2c66affSColin Finck 
449c2c66affSColin Finck bool
RemoveFlags(_In_ DWORD Flags,_In_ DWORD FlagsEx)450c2c66affSColin Finck CDeviceNode::RemoveFlags(
451c2c66affSColin Finck     _In_ DWORD Flags,
452c2c66affSColin Finck     _In_ DWORD FlagsEx
453c2c66affSColin Finck     )
454c2c66affSColin Finck {
455c2c66affSColin Finck     SP_DEVINSTALL_PARAMS DevInstallParams;
456c2c66affSColin Finck     DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
457c2c66affSColin Finck     if (SetupDiGetDeviceInstallParamsW(m_hDevInfo,
458c2c66affSColin Finck                                        &m_DevinfoData,
459c2c66affSColin Finck                                        &DevInstallParams))
460c2c66affSColin Finck     {
461c2c66affSColin Finck         DevInstallParams.Flags &= ~Flags;
462c2c66affSColin Finck         DevInstallParams.FlagsEx &= ~FlagsEx;
463c2c66affSColin Finck         return (SetupDiSetDeviceInstallParamsW(m_hDevInfo,
464c2c66affSColin Finck                                                &m_DevinfoData,
465c2c66affSColin Finck                                                &DevInstallParams) != 0);
466c2c66affSColin Finck     }
467c2c66affSColin Finck     return false;
468c2c66affSColin Finck }
469