1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxDeviceInterfaceAPI.cpp 8 9 Abstract: 10 11 This module implements the device interface object external APIs 12 13 Author: 14 15 16 17 18 Environment: 19 20 kernel and user mode 21 22 Revision History: 23 24 --*/ 25 26 #include "fxsupportpch.hpp" 27 28 extern "C" { 29 // #include "FxDeviceInterfaceAPI.tmh" 30 } 31 32 // 33 // extern "C" the entire file 34 // 35 extern "C" { 36 37 _Must_inspect_result_ 38 __drv_maxIRQL(PASSIVE_LEVEL) 39 NTSTATUS 40 STDCALL 41 WDFEXPORT(WdfDeviceCreateDeviceInterface)( 42 __in 43 PWDF_DRIVER_GLOBALS DriverGlobals, 44 __in 45 WDFDEVICE Device, 46 __in 47 CONST GUID *InterfaceClassGUID, 48 __in_opt 49 PCUNICODE_STRING ReferenceString 50 ) 51 /*++ 52 53 Routine Description: 54 Creates a device interface associated with the passed in device object 55 56 Arguments: 57 Device - Handle which represents the device exposing the interface 58 59 InterfaceGUID - GUID describing the interface being exposed 60 61 ReferenceString - OPTIONAL string which allows the driver writer to 62 distinguish between different exposed interfaces 63 64 Return Value: 65 STATUS_SUCCESS or appropriate NTSTATUS code 66 67 --*/ 68 { 69 DDI_ENTRY(); 70 71 SINGLE_LIST_ENTRY **ppPrev, *pCur; 72 PFX_DRIVER_GLOBALS pFxDriverGlobals; 73 FxDeviceInterface *pDeviceInterface; 74 FxDevice *pDevice; 75 FxPkgPnp* pPkgPnp; 76 NTSTATUS status; 77 78 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 79 Device, 80 FX_TYPE_DEVICE, 81 (PVOID*) &pDevice, 82 &pFxDriverGlobals); 83 84 FxPointerNotNull(pFxDriverGlobals, InterfaceClassGUID); 85 86 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 87 if (!NT_SUCCESS(status)) { 88 return status; 89 } 90 91 if (ReferenceString != NULL) { 92 status = FxValidateUnicodeString(pFxDriverGlobals, ReferenceString); 93 if (!NT_SUCCESS(status)) { 94 return status; 95 } 96 } 97 98 if (pDevice->IsLegacy()) { 99 status = STATUS_INVALID_DEVICE_REQUEST; 100 101 DoTraceLevelMessage( 102 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 103 "WDFDEVICE %p is not a PNP device, device interface creation not " 104 "allowed %!STATUS!", Device, status); 105 106 return status; 107 } 108 109 pDeviceInterface = new(pFxDriverGlobals, PagedPool) FxDeviceInterface(); 110 111 if (pDeviceInterface == NULL) { 112 status = STATUS_INSUFFICIENT_RESOURCES; 113 114 DoTraceLevelMessage( 115 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 116 "WDFDEVICE %p DeviceInterface object creation failed, %!STATUS!", 117 Device, status); 118 119 return status; 120 } 121 122 status = pDeviceInterface->Initialize(pFxDriverGlobals, 123 InterfaceClassGUID, 124 ReferenceString); 125 126 if (!NT_SUCCESS(status)) { 127 DoTraceLevelMessage( 128 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 129 "WDFDEVICE %p, DeviceInterface object initialization failed, %!STATUS!", 130 Device, status ); 131 132 goto Done; 133 } 134 135 pPkgPnp = pDevice->m_PkgPnp; 136 137 pPkgPnp->m_DeviceInterfaceLock.AcquireLock(pFxDriverGlobals); 138 139 status = pDeviceInterface->Register(pDevice); 140 141 if (NT_SUCCESS(status)) { 142 // 143 // Insert into the end of the list 144 // 145 ppPrev = &pPkgPnp->m_DeviceInterfaceHead.Next; 146 pCur = pPkgPnp->m_DeviceInterfaceHead.Next; 147 while (pCur != NULL) { 148 ppPrev = &pCur->Next; 149 pCur = pCur->Next; 150 } 151 152 *ppPrev = &pDeviceInterface->m_Entry; 153 } 154 155 pPkgPnp->m_DeviceInterfaceLock.ReleaseLock(pFxDriverGlobals); 156 157 Done: 158 if (!NT_SUCCESS(status)) { 159 delete pDeviceInterface; 160 pDeviceInterface = NULL; 161 } 162 163 return status; 164 } 165 166 __drv_maxIRQL(PASSIVE_LEVEL) 167 VOID 168 STDCALL 169 WDFEXPORT(WdfDeviceSetDeviceInterfaceState)( 170 __in 171 PWDF_DRIVER_GLOBALS DriverGlobals, 172 __in 173 WDFDEVICE Device, 174 __in 175 CONST GUID *InterfaceClassGUID, 176 __in_opt 177 PCUNICODE_STRING RefString, 178 __in 179 BOOLEAN State 180 ) 181 { 182 DDI_ENTRY(); 183 184 PSINGLE_LIST_ENTRY ple; 185 PFX_DRIVER_GLOBALS pFxDriverGlobals; 186 NTSTATUS status; 187 FxDevice* pDevice; 188 FxPkgPnp* pPkgPnp; 189 190 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 191 Device, 192 FX_TYPE_DEVICE, 193 (PVOID*) &pDevice, 194 &pFxDriverGlobals); 195 196 FxPointerNotNull(pFxDriverGlobals, InterfaceClassGUID); 197 198 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 199 if (!NT_SUCCESS(status)) { 200 FxVerifierDbgBreakPoint(pFxDriverGlobals); 201 return; 202 } 203 204 if (RefString != NULL) { 205 status = FxValidateUnicodeString(pFxDriverGlobals, RefString); 206 if (!NT_SUCCESS(status)) { 207 FxVerifierDbgBreakPoint(pFxDriverGlobals); 208 return; 209 } 210 } 211 212 if (pDevice->IsLegacy()) { 213 DoTraceLevelMessage( 214 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 215 "WDFDEVICE %p is not a PNP device, device interfaces not allowed", 216 Device); 217 FxVerifierDbgBreakPoint(pFxDriverGlobals); 218 return; 219 } 220 221 pPkgPnp = pDevice->m_PkgPnp; 222 223 pPkgPnp->m_DeviceInterfaceLock.AcquireLock(pFxDriverGlobals); 224 225 // 226 // Iterate over the interfaces and see if we have a match 227 // 228 for (ple = pPkgPnp->m_DeviceInterfaceHead.Next; ple != NULL; ple = ple->Next) { 229 FxDeviceInterface *pDI; 230 231 pDI = FxDeviceInterface::_FromEntry(ple); 232 233 if (FxIsEqualGuid(&pDI->m_InterfaceClassGUID, InterfaceClassGUID)) { 234 if (RefString != NULL) { 235 if ((RefString->Length == pDI->m_ReferenceString.Length) 236 && 237 (RtlCompareMemory(RefString->Buffer, 238 pDI->m_ReferenceString.Buffer, 239 RefString->Length) == RefString->Length)) { 240 // 241 // They match, carry on 242 // 243 DO_NOTHING(); 244 } 245 else { 246 // 247 // The ref strings do not match, continue on in the search 248 // of the collection. 249 // 250 continue; 251 } 252 } 253 else if (pDI->m_ReferenceString.Length > 0) { 254 // 255 // Caller didn't specify a ref string but this interface has 256 // one, continue on in the search through the collection. 257 // 258 continue; 259 } 260 261 // 262 // Set the state and break out of the loop because we found our 263 // interface. 264 // 265 pDI->SetState(State); 266 break; 267 } 268 } 269 270 pPkgPnp->m_DeviceInterfaceLock.ReleaseLock(pFxDriverGlobals); 271 } 272 273 _Must_inspect_result_ 274 __drv_maxIRQL(PASSIVE_LEVEL) 275 NTSTATUS 276 STDCALL 277 WDFEXPORT(WdfDeviceRetrieveDeviceInterfaceString)( 278 __in 279 PWDF_DRIVER_GLOBALS DriverGlobals, 280 __in 281 WDFDEVICE Device, 282 __in 283 CONST GUID* InterfaceClassGUID, 284 __in_opt 285 PCUNICODE_STRING RefString, 286 __in 287 WDFSTRING String 288 ) 289 /*++ 290 291 Routine Description: 292 Returns the symbolic link value of the registered device interface. 293 294 Arguments: 295 296 297 Return Value: 298 299 300 --*/ 301 302 { 303 DDI_ENTRY(); 304 305 PSINGLE_LIST_ENTRY ple; 306 PFX_DRIVER_GLOBALS pFxDriverGlobals; 307 FxDevice* pDevice; 308 FxPkgPnp* pPkgPnp; 309 FxString* pString; 310 NTSTATUS status; 311 312 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 313 Device, 314 FX_TYPE_DEVICE, 315 (PVOID*) &pDevice, 316 &pFxDriverGlobals ); 317 318 FxPointerNotNull(pFxDriverGlobals, InterfaceClassGUID); 319 320 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 321 if (!NT_SUCCESS(status)) { 322 return status; 323 } 324 325 if (RefString != NULL) { 326 status = FxValidateUnicodeString(pFxDriverGlobals, RefString); 327 if (!NT_SUCCESS(status)) { 328 return status; 329 } 330 } 331 332 if (pDevice->IsLegacy()) { 333 status = STATUS_INVALID_DEVICE_REQUEST; 334 335 DoTraceLevelMessage( 336 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 337 "WDFDEVICE %p is not a PNP device, device interface creation not " 338 "allowed %!STATUS!", Device, status); 339 340 return status; 341 } 342 343 FxObjectHandleGetPtr(pFxDriverGlobals, 344 String, 345 FX_TYPE_STRING, 346 (PVOID*) &pString); 347 348 pPkgPnp = pDevice->m_PkgPnp; 349 350 status = STATUS_OBJECT_NAME_NOT_FOUND; 351 352 pPkgPnp->m_DeviceInterfaceLock.AcquireLock(pFxDriverGlobals); 353 354 // 355 // Iterate over the interfaces and see if we have a match 356 // 357 for (ple = pPkgPnp->m_DeviceInterfaceHead.Next; 358 ple != NULL; 359 ple = ple->Next) { 360 FxDeviceInterface *pDI; 361 362 pDI = FxDeviceInterface::_FromEntry(ple); 363 364 if (FxIsEqualGuid(&pDI->m_InterfaceClassGUID, InterfaceClassGUID)) { 365 if (RefString != NULL) { 366 if ((RefString->Length == pDI->m_ReferenceString.Length) 367 && 368 (RtlCompareMemory(RefString->Buffer, 369 pDI->m_ReferenceString.Buffer, 370 RefString->Length) == RefString->Length)) { 371 // 372 // They match, carry on 373 // 374 DO_NOTHING(); 375 } 376 else { 377 // 378 // The ref strings do not match, continue on in the search 379 // of the collection. 380 // 381 continue; 382 } 383 } 384 else if (pDI->m_ReferenceString.Length > 0) { 385 // 386 // Caller didn't specify a ref string but this interface has 387 // one, continue on in the search through the collection. 388 // 389 continue; 390 } 391 392 status = pDI->GetSymbolicLinkName(pString); 393 394 break; 395 } 396 } 397 398 pPkgPnp->m_DeviceInterfaceLock.ReleaseLock(pFxDriverGlobals); 399 400 return status; 401 } 402 403 } // extern "C" 404