1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxDeviceUM.hpp 8 9 Abstract: 10 11 This is the definition of the FxDevice object UM specific 12 13 Author: 14 15 16 17 Environment: 18 19 User mode only 20 21 Revision History: 22 23 --*/ 24 25 #ifndef _FXDEVICEUM_H_ 26 #define _FXDEVICEUM_H_ 27 28 #define WDF_PATH_SEPARATOR L"\\" 29 #define WUDF_SUB_KEY L"WUDF" 30 #define WUDF_ADDITIONAL_SUB_KEY L"WDF" 31 32 #define FX_DIRECT_HARDWARE_ACCESS L"DirectHardwareAccess" 33 #define FX_DIRECT_HARDWARE_ACCESS_DEFAULT (WdfRejectDirectHardwareAccess) 34 35 #define FX_REGISTER_ACCESS_MODE L"RegisterAccessMode" 36 #define FX_REGISTER_ACCESS_MODE_DEFAULT (WdfRegisterAccessUsingSystemCall) 37 38 #define FX_FILE_OBJECT_POLICY L"FileObjectPolicy" 39 #define FX_FILE_OBJECT_POLICY_DEFAULT (WdfRejectNullAndUnknownFileObjects) 40 41 #define FX_FS_CONTEXT_USE_POLICY L"FsContextUsePolicy" 42 #define FX_FS_CONTEXT_USE_POLICY_DEFAULT (WdfDefaultFsContextUsePolicy) 43 44 #define FX_KERNEL_MODE_CLIENT_POLICY L"KernelModeClientPolicy" 45 #define FX_METHOD_NEITHER_ACTION L"MethodNeitherAction" 46 #define FX_PROCESS_SHARING_ENABLED L"HostProcessSharingEnabled" 47 #define FX_DEVICE_GROUP_ID L"DeviceGroupId" 48 #define FX_FILE_OBJECT_POLICY L"FileObjectPolicy" 49 50 // 51 // READ/WRITE_REGISTER_Xxx macros need compiler and memory barrier. Each 52 // platform has a different set of compiler intrinsics to support that. 53 // In kernel, x86 READ/WRITE macros are implemented in assembly and use 54 // lock prefix to force real access. For amd64, _ReadWriteBarrier 55 // (compiler barrier) is used for reads and __faststorefence (CPU barrier) for 56 // writes. For ARM, _ReadWriteBarrier (compiler barrier) is used for reads and 57 // both _ReadWriteBarrier and __emit(Value) for writes. 58 // 59 // Because of this variation, UMDF will use the macros directly from wdm.h 60 // by autogenerating those macros from wdm.h into a private UMDF header. 61 // For x86, there are no macros so either UMDF could directly link to the 62 // ntosrtl.lib (that has these macros implemented in assembly), or implement 63 // its own macros that use MemoryBarrier() macro from winnt.h. 64 // 65 // Below is UMDF's implementation for x86. The macros for other platforms are 66 // in WudfWdm_private.h. 67 // 68 #if defined(_X86_) 69 70 #define READ_REGISTER_UCHAR(x) \ 71 (MemoryBarrier(), *(volatile UCHAR * const)(x)) 72 73 #define READ_REGISTER_USHORT(x) \ 74 (MemoryBarrier(), *(volatile USHORT * const)(x)) 75 76 #define READ_REGISTER_ULONG(x) \ 77 (MemoryBarrier(), *(volatile ULONG * const)(x)) 78 79 #define READ_REGISTER_ULONG64(x) \ 80 (MemoryBarrier(), *(volatile ULONG64 * const)(x)) 81 82 #define READ_REGISTER_BUFFER_UCHAR(x, y, z) { \ 83 PUCHAR registerBuffer = x; \ 84 PUCHAR readBuffer = y; \ 85 ULONG readCount; \ 86 MemoryBarrier(); \ 87 for (readCount = z; readCount--; readBuffer++, registerBuffer++) { \ 88 *readBuffer = *(volatile UCHAR * const)(registerBuffer); \ 89 } \ 90 } 91 92 #define READ_REGISTER_BUFFER_USHORT(x, y, z) { \ 93 PUSHORT registerBuffer = x; \ 94 PUSHORT readBuffer = y; \ 95 ULONG readCount; \ 96 MemoryBarrier(); \ 97 for (readCount = z; readCount--; readBuffer++, registerBuffer++) { \ 98 *readBuffer = *(volatile USHORT * const)(registerBuffer); \ 99 } \ 100 } 101 102 #define READ_REGISTER_BUFFER_ULONG(x, y, z) { \ 103 PULONG registerBuffer = x; \ 104 PULONG readBuffer = y; \ 105 ULONG readCount; \ 106 MemoryBarrier(); \ 107 for (readCount = z; readCount--; readBuffer++, registerBuffer++) { \ 108 *readBuffer = *(volatile ULONG * const)(registerBuffer); \ 109 } \ 110 } 111 112 #define READ_REGISTER_BUFFER_ULONG64(x, y, z) { \ 113 PULONG64 registerBuffer = x; \ 114 PULONG64 readBuffer = y; \ 115 ULONG readCount; \ 116 MemoryBarrier(); \ 117 for (readCount = z; readCount--; readBuffer++, registerBuffer++) { \ 118 *readBuffer = *(volatile ULONG64 * const)(registerBuffer); \ 119 } \ 120 } 121 122 #define WRITE_REGISTER_UCHAR(x, y) { \ 123 *(volatile UCHAR * const)(x) = y; \ 124 MemoryBarrier(); \ 125 } 126 127 #define WRITE_REGISTER_USHORT(x, y) { \ 128 *(volatile USHORT * const)(x) = y; \ 129 MemoryBarrier(); \ 130 } 131 132 #define WRITE_REGISTER_ULONG(x, y) { \ 133 *(volatile ULONG * const)(x) = y; \ 134 MemoryBarrier(); \ 135 } 136 137 #define WRITE_REGISTER_ULONG64(x, y) { \ 138 *(volatile ULONG64 * const)(x) = y; \ 139 MemoryBarrier(); \ 140 } 141 142 #define WRITE_REGISTER_BUFFER_UCHAR(x, y, z) { \ 143 PUCHAR registerBuffer = x; \ 144 PUCHAR writeBuffer = y; \ 145 ULONG writeCount; \ 146 for (writeCount = z; writeCount--; writeBuffer++, registerBuffer++) { \ 147 *(volatile UCHAR * const)(registerBuffer) = *writeBuffer; \ 148 } \ 149 MemoryBarrier(); \ 150 } 151 152 #define WRITE_REGISTER_BUFFER_USHORT(x, y, z) { \ 153 PUSHORT registerBuffer = x; \ 154 PUSHORT writeBuffer = y; \ 155 ULONG writeCount; \ 156 for (writeCount = z; writeCount--; writeBuffer++, registerBuffer++) { \ 157 *(volatile USHORT * const)(registerBuffer) = *writeBuffer; \ 158 } \ 159 MemoryBarrier(); \ 160 } 161 162 #define WRITE_REGISTER_BUFFER_ULONG(x, y, z) { \ 163 PULONG registerBuffer = x; \ 164 PULONG writeBuffer = y; \ 165 ULONG writeCount; \ 166 for (writeCount = z; writeCount--; writeBuffer++, registerBuffer++) { \ 167 *(volatile ULONG * const)(registerBuffer) = *writeBuffer; \ 168 } \ 169 MemoryBarrier(); \ 170 } 171 172 #define WRITE_REGISTER_BUFFER_ULONG64(x, y, z) { \ 173 PULONG64 registerBuffer = x; \ 174 PULONG64 writeBuffer = y; \ 175 ULONG writeCount; \ 176 for (writeCount = z; writeCount--; writeBuffer++, registerBuffer++) { \ 177 *(volatile ULONG64 * const)(registerBuffer) = *writeBuffer; \ 178 } \ 179 MemoryBarrier(); \ 180 } 181 182 #endif // _X86_ 183 184 __inline 185 SIZE_T 186 FxDevice::ReadRegister( 187 __in WDF_DEVICE_HWACCESS_TARGET_SIZE Size, 188 __in PVOID Register 189 ) 190 { 191 SIZE_T value = 0; 192 193 // 194 // ETW start event for perf measurement 195 // 196 EventWriteEVENT_UMDF_FX_READ_FROM_HARDWARE_START( 197 WdfDeviceHwAccessTargetTypeRegister, Size, 0); 198 199 switch(Size) { 200 case WdfDeviceHwAccessTargetSizeUchar: 201 value = READ_REGISTER_UCHAR((PUCHAR)Register); 202 break; 203 case WdfDeviceHwAccessTargetSizeUshort: 204 value = READ_REGISTER_USHORT((PUSHORT)Register); 205 break; 206 case WdfDeviceHwAccessTargetSizeUlong: 207 value = READ_REGISTER_ULONG((PULONG)Register); 208 break; 209 case WdfDeviceHwAccessTargetSizeUlong64: 210 #if defined(_WIN64) 211 value = READ_REGISTER_ULONG64((PULONG64)Register); 212 #else 213 FX_VERIFY(DRIVER(BadArgument, TODO), CHECK("Invalid call to ULONG64 " 214 "hardware access function", FALSE)); 215 #endif 216 break; 217 default: 218 FX_VERIFY(INTERNAL, TRAPMSG("Unexpected")); 219 break; 220 } 221 222 // 223 // ETW end event for perf measurement 224 // 225 EventWriteEVENT_UMDF_FX_READ_FROM_HARDWARE_END( 226 WdfDeviceHwAccessTargetTypeRegister, Size, 0); 227 228 return value; 229 } 230 231 __inline 232 VOID 233 FxDevice::ReadRegisterBuffer( 234 __in WDF_DEVICE_HWACCESS_TARGET_SIZE Size, 235 __in PVOID Register, 236 __out_ecount_full(Count) PVOID Buffer, 237 __in ULONG Count 238 ) 239 { 240 // 241 // ETW start event for perf measurement 242 // 243 EventWriteEVENT_UMDF_FX_READ_FROM_HARDWARE_START( 244 WdfDeviceHwAccessTargetTypeRegisterBuffer, Size, Count); 245 246 switch(Size) { 247 case WdfDeviceHwAccessTargetSizeUchar: 248 READ_REGISTER_BUFFER_UCHAR(((PUCHAR)Register), (PUCHAR)Buffer, Count ); 249 break; 250 case WdfDeviceHwAccessTargetSizeUshort: 251 #pragma prefast(suppress:26000, "The Size parameter dictates the buffer size") 252 READ_REGISTER_BUFFER_USHORT(((PUSHORT)Register), (PUSHORT)Buffer, Count ); 253 break; 254 case WdfDeviceHwAccessTargetSizeUlong: 255 READ_REGISTER_BUFFER_ULONG(((PULONG)Register), (PULONG)Buffer, Count ); 256 break; 257 case WdfDeviceHwAccessTargetSizeUlong64: 258 #if defined(_WIN64) 259 READ_REGISTER_BUFFER_ULONG64(((PULONG64)Register), (PULONG64)Buffer, Count ); 260 #else 261 FX_VERIFY(DRIVER(BadArgument, TODO), CHECK("Invalid call to ULONG64 " 262 "hardware access function", FALSE)); 263 #endif 264 break; 265 default: 266 FX_VERIFY(INTERNAL, TRAPMSG("Unexpected")); 267 break; 268 } 269 270 // 271 // ETW start event for perf measurement 272 // 273 EventWriteEVENT_UMDF_FX_READ_FROM_HARDWARE_END( 274 WdfDeviceHwAccessTargetTypeRegisterBuffer, Size, Count); 275 } 276 277 __inline 278 VOID 279 FxDevice::WriteRegister( 280 __in WDF_DEVICE_HWACCESS_TARGET_SIZE Size, 281 __in PVOID Register, 282 __in SIZE_T Value 283 ) 284 { 285 // 286 // ETW start event for perf measurement 287 // 288 EventWriteEVENT_UMDF_FX_WRITE_TO_HARDWARE_START( 289 WdfDeviceHwAccessTargetTypeRegister, Size, 0); 290 291 switch(Size) { 292 case WdfDeviceHwAccessTargetSizeUchar: 293 WRITE_REGISTER_UCHAR((PUCHAR)Register, (UCHAR)Value); 294 break; 295 case WdfDeviceHwAccessTargetSizeUshort: 296 WRITE_REGISTER_USHORT((PUSHORT)Register, (USHORT)Value); 297 break; 298 case WdfDeviceHwAccessTargetSizeUlong: 299 WRITE_REGISTER_ULONG((PULONG)Register, (ULONG)Value); 300 break; 301 case WdfDeviceHwAccessTargetSizeUlong64: 302 #if defined(_WIN64) 303 WRITE_REGISTER_ULONG64((PULONG64)Register, (ULONG64)Value); 304 #else 305 FX_VERIFY(DRIVER(BadArgument, TODO), CHECK("Invalid call to ULONG64 " 306 "hardware access function", FALSE)); 307 #endif 308 break; 309 default: 310 FX_VERIFY(INTERNAL, TRAPMSG("Unexpected")); 311 break; 312 } 313 314 // 315 // ETW start event for perf measurement 316 // 317 EventWriteEVENT_UMDF_FX_WRITE_TO_HARDWARE_END( 318 WdfDeviceHwAccessTargetTypeRegister, Size, 0); 319 } 320 321 __inline 322 VOID 323 FxDevice::WriteRegisterBuffer( 324 __in WDF_DEVICE_HWACCESS_TARGET_SIZE Size, 325 __in PVOID Register, 326 __in_ecount(Count) PVOID Buffer, 327 __in ULONG Count 328 ) 329 { 330 // 331 // ETW start event for perf measurement 332 // 333 EventWriteEVENT_UMDF_FX_WRITE_TO_HARDWARE_START( 334 WdfDeviceHwAccessTargetTypeRegisterBuffer, Size, Count); 335 336 switch(Size) { 337 case WdfDeviceHwAccessTargetSizeUchar: 338 WRITE_REGISTER_BUFFER_UCHAR(((PUCHAR)Register), (PUCHAR)Buffer, Count); 339 break; 340 case WdfDeviceHwAccessTargetSizeUshort: 341 #pragma prefast(suppress:26000, "The Size parameter dictates the buffer size") 342 WRITE_REGISTER_BUFFER_USHORT(((PUSHORT)Register), (PUSHORT)Buffer, Count); 343 break; 344 case WdfDeviceHwAccessTargetSizeUlong: 345 WRITE_REGISTER_BUFFER_ULONG(((PULONG)Register), (PULONG)Buffer, Count); 346 break; 347 case WdfDeviceHwAccessTargetSizeUlong64: 348 #if defined(_WIN64) 349 WRITE_REGISTER_BUFFER_ULONG64(((PULONG64)Register), (PULONG64)Buffer, Count); 350 #else 351 FX_VERIFY(DRIVER(BadArgument, TODO), CHECK("Invalid call to ULONG64 " 352 "hardware access function", FALSE)); 353 #endif 354 break; 355 default: 356 FX_VERIFY(INTERNAL, TRAPMSG("Unexpected")); 357 break; 358 } 359 360 // 361 // ETW start event for perf measurement 362 // 363 EventWriteEVENT_UMDF_FX_WRITE_TO_HARDWARE_END( 364 WdfDeviceHwAccessTargetTypeRegisterBuffer, Size, Count); 365 } 366 367 __inline 368 FxWdmDeviceExtension* 369 FxDevice::_GetFxWdmExtension( 370 __in MdDeviceObject DeviceObject 371 ) 372 { 373 return (FxWdmDeviceExtension*) 374 ((static_cast<IWudfDevice2*> (DeviceObject))->GetDeviceExtension()); 375 } 376 377 __inline 378 BOOLEAN 379 FxDevice::IsRemoveLockEnabledForIo( 380 VOID 381 ) 382 { 383 return FALSE; 384 } 385 386 __inline 387 MdRemoveLock 388 FxDevice::GetRemoveLock( 389 VOID 390 ) 391 { 392 return &FxDevice::_GetFxWdmExtension( 393 GetDeviceObject())->IoRemoveLock; 394 } 395 396 __inline 397 NTSTATUS 398 FxDevice::WmiPkgRegister( 399 VOID 400 ) 401 { 402 // 403 // WMI doesn't apply for UMDF 404 // 405 DO_NOTHING(); 406 return STATUS_SUCCESS; 407 } 408 409 __inline 410 VOID 411 FxDevice::WmiPkgDeregister( 412 VOID 413 ) 414 { 415 // 416 // WMI doesn't apply for UMDF 417 // 418 DO_NOTHING(); 419 } 420 421 __inline 422 VOID 423 FxDevice::WmiPkgCleanup( 424 VOID 425 ) 426 { 427 // 428 // WMI doesn't apply for UMDF 429 // 430 DO_NOTHING(); 431 } 432 433 __inline 434 IWudfDeviceStack* 435 FxDevice::GetDeviceStack( 436 VOID 437 ) 438 { 439 return m_DevStack; 440 } 441 442 __inline 443 IWudfDeviceStack2 * 444 FxDevice::GetDeviceStack2( 445 ) 446 { 447 IWudfDeviceStack2 *pDeviceStack2; 448 HRESULT hrQI; 449 450 hrQI = m_DevStack->QueryInterface(IID_IWudfDeviceStack2, 451 (PVOID*)&pDeviceStack2); 452 FX_VERIFY(INTERNAL, CHECK_QI(hrQI, pDeviceStack2)); 453 454 m_DevStack->Release(); 455 456 return pDeviceStack2; 457 } 458 459 #endif //_FXDEVICEUM_H_ 460 461