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