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
ReadRegister(__in WDF_DEVICE_HWACCESS_TARGET_SIZE Size,__in PVOID Register)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
ReadRegisterBuffer(__in WDF_DEVICE_HWACCESS_TARGET_SIZE Size,__in PVOID Register,__out_ecount_full (Count)PVOID Buffer,__in ULONG Count)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
WriteRegister(__in WDF_DEVICE_HWACCESS_TARGET_SIZE Size,__in PVOID Register,__in SIZE_T Value)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
WriteRegisterBuffer(__in WDF_DEVICE_HWACCESS_TARGET_SIZE Size,__in PVOID Register,__in_ecount (Count)PVOID Buffer,__in ULONG Count)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*
_GetFxWdmExtension(__in MdDeviceObject DeviceObject)369 FxDevice::_GetFxWdmExtension(
370 __in MdDeviceObject DeviceObject
371 )
372 {
373 return (FxWdmDeviceExtension*)
374 ((static_cast<IWudfDevice2*> (DeviceObject))->GetDeviceExtension());
375 }
376
377 __inline
378 BOOLEAN
IsRemoveLockEnabledForIo(VOID)379 FxDevice::IsRemoveLockEnabledForIo(
380 VOID
381 )
382 {
383 return FALSE;
384 }
385
386 __inline
387 MdRemoveLock
GetRemoveLock(VOID)388 FxDevice::GetRemoveLock(
389 VOID
390 )
391 {
392 return &FxDevice::_GetFxWdmExtension(
393 GetDeviceObject())->IoRemoveLock;
394 }
395
396 __inline
397 NTSTATUS
WmiPkgRegister(VOID)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
WmiPkgDeregister(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
WmiPkgCleanup(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*
GetDeviceStack(VOID)435 FxDevice::GetDeviceStack(
436 VOID
437 )
438 {
439 return m_DevStack;
440 }
441
442 __inline
443 IWudfDeviceStack2 *
GetDeviceStack2()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