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