1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxDeviceInterfaceKM.cpp
8 
9 Abstract:
10 
11     This module implements the device interface object.
12 
13 Author:
14 
15 
16 
17 Environment:
18 
19     Kernel mode only
20 
21 Revision History:
22 
23 --*/
24 
25 #include "fxsupportpch.hpp"
26 
27 extern "C" {
28 // #include "FxDeviceInterfaceKM.tmh"
29 }
30 
31 FxDeviceInterface::FxDeviceInterface(
32     )
33 /*++
34 
35 Routine Description:
36     Constructor for the object.  Initializes all fields
37 
38 Arguments:
39     None
40 
41 Return Value:
42     None
43 
44   --*/
45 {
46     RtlZeroMemory(&m_InterfaceClassGUID, sizeof(m_InterfaceClassGUID));
47 
48     RtlZeroMemory(&m_SymbolicLinkName, sizeof(m_SymbolicLinkName));
49     RtlZeroMemory(&m_ReferenceString, sizeof(m_ReferenceString));
50 
51     m_Entry.Next = NULL;
52 
53     m_State = FALSE;
54 }
55 
56 FxDeviceInterface::~FxDeviceInterface()
57 /*++
58 
59 Routine Description:
60     Destructor for FxDeviceInterface.  Cleans up any allocations previously
61     allocated.
62 
63 Arguments:
64     None
65 
66 Return Value:
67     None
68 
69   --*/
70 {
71     // the device interface should be off now
72     ASSERT(m_State == FALSE);
73 
74     // should no longer be in any list
75     ASSERT(m_Entry.Next == NULL);
76 
77     if (m_ReferenceString.Buffer != NULL) {
78         FxPoolFree(m_ReferenceString.Buffer);
79         RtlZeroMemory(&m_ReferenceString, sizeof(m_ReferenceString));
80     }
81 
82     if (m_SymbolicLinkName.Buffer != NULL) {
83         RtlFreeUnicodeString(&m_SymbolicLinkName);
84     }
85 }
86 
87 _Must_inspect_result_
88 NTSTATUS
89 FxDeviceInterface::Initialize(
90     __in PFX_DRIVER_GLOBALS FxDriverGlobals,
91     __in CONST GUID* InterfaceGUID,
92     __in_opt PCUNICODE_STRING ReferenceString
93     )
94 /*++
95 
96 Routine Description:
97     Initializes the object with the interface GUID and optional reference string
98 
99 Arguments:
100     InterfaceGUID - GUID describing the interface
101 
102     ReferenceString - string used to differentiate between 2 interfaces on the
103         same PDO
104 
105 Return Value:
106     STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES
107 
108   --*/
109 {
110     RtlCopyMemory(&m_InterfaceClassGUID, InterfaceGUID, sizeof(GUID));
111 
112     if (ReferenceString != NULL) {
113         return FxDuplicateUnicodeString(FxDriverGlobals,
114                                         ReferenceString,
115                                         &m_ReferenceString);
116     }
117     else {
118         return STATUS_SUCCESS;
119     }
120 }
121 
122 
123 VOID
124 FxDeviceInterface::SetState(
125     __in BOOLEAN State
126     )
127 /*++
128 
129 Routine Description:
130     Sets the state of the device interface
131 
132 Arguments:
133     State - the state to set
134 
135 
136 Return Value:
137     None.
138 
139   --*/
140 {
141     m_State = State;
142 
143     //
144     // Only set the state if the interface has been registered
145     //
146     if (m_SymbolicLinkName.Buffer != NULL) {
147         Mx::MxSetDeviceInterfaceState(&m_SymbolicLinkName, m_State);
148     }
149 }
150 
151 _Must_inspect_result_
152 NTSTATUS
153 FxDeviceInterface::Register(
154     __in PDEVICE_OBJECT Pdo
155     )
156 /*++
157 
158 Routine Description:
159     Registers the device interface for a given PDO
160 
161 Arguments:
162     Pdo - PDO for the device stack
163 
164 
165 Return Value:
166     returned by IoRegisterDeviceInterface
167 
168   --*/
169 {
170     PUNICODE_STRING pString;
171 
172     if (m_ReferenceString.Length > 0) {
173         pString = &m_ReferenceString;
174     }
175     else {
176         pString = NULL;
177     }
178 
179     return Mx::MxRegisterDeviceInterface(
180         Pdo, &m_InterfaceClassGUID, pString, &m_SymbolicLinkName);
181 }
182 
183 _Must_inspect_result_
184 NTSTATUS
185 FxDeviceInterface::Register(
186     _In_ FxDevice* Device
187     )
188 {
189     NTSTATUS status;
190     MdDeviceObject pdo;
191 
192     pdo = Device->GetSafePhysicalDevice();
193 
194     if (pdo != NULL) {
195         status = Register(pdo);
196     }
197     else {
198         //
199         // Leave the device interface unregistered.  When we are in hardware
200         // available, we will register there once we know for sure we have a
201         // real live PDO that the system has acknowledged.
202         //
203         DO_NOTHING();
204 
205         status = STATUS_SUCCESS;
206     }
207 
208     return status;
209 }
210 
211 NTSTATUS
212 FxDeviceInterface::GetSymbolicLinkName(
213     _In_ FxString* LinkString
214     )
215 {
216     NTSTATUS status;
217 
218     if (m_SymbolicLinkName.Buffer == NULL) {
219         //
220         // The device interface has not yet been registered b/c it
221         // belongs to a PDO and the PDO has not been recognized by
222         // pnp yet.
223         //
224         status = STATUS_INVALID_DEVICE_STATE;
225         UNREFERENCED_PARAMETER(LinkString);
226     }
227     else {
228         //
229         // Attempt a copy
230         //
231         status = LinkString->Assign(&m_SymbolicLinkName);
232     }
233 
234     return status;
235 }
236 
237