1 // 2 // Copyright (C) Microsoft. All rights reserved. 3 // 4 #ifndef _FX_MACROS_H_ 5 #define _FX_MACROS_H_ 6 7 // 8 // at is for argument type 9 // a is for argument 10 // rt is for return type 11 // fn or FN is for function 12 // qf is for qualifiers 13 // rtDef is for return type default value 14 // 15 #define WDF_FX_VF_SECTION_NAME PAGEWdfV 16 #define QUOTE_EXPANSION(tok) #tok 17 #define FX_VF_SECTION_NAME_QUOTED(tok) QUOTE_EXPANSION(tok) 18 19 20 21 22 23 24 25 #if defined(_M_ARM) || defined(__REACTOS__) 26 #define FX_VF_PAGING 27 #else 28 #define FX_VF_PAGING __declspec(code_seg(FX_VF_SECTION_NAME_QUOTED(WDF_FX_VF_SECTION_NAME))) 29 #endif 30 31 #define FX_VF_NAME_TO_IMP_NAME( fnName ) Vf_##fnName 32 #define FX_VF_NAME_TO_SCOPED_IMP_NAME( classname, fnName ) classname::Vf_##fnName 33 #define FX_VF_QF_VOID 34 #define FX_VF_QF_NTSTATUS _Must_inspect_result_ 35 #define FX_VF_DEFAULT_RT_VOID 36 #define FX_VF_DEFAULT_RT_NTSTATUS STATUS_SUCCESS 37 38 #define FX_VF_FUNCTION_PROTOTYPE( qf, rt, fnName, ...) \ 39 qf \ 40 rt \ 41 FX_VF_FUNCTION( fnName )( _In_ PFX_DRIVER_GLOBALS, ##__VA_ARGS__ ); 42 43 #define FX_VF_METHOD( classname, fnName ) \ 44 FX_VF_PAGING \ 45 FX_VF_NAME_TO_SCOPED_IMP_NAME( classname, fnName ) 46 47 #define FX_VF_FUNCTION( fnName ) \ 48 FX_VF_PAGING \ 49 FX_VF_NAME_TO_IMP_NAME( fnName ) 50 51 #define FX_VF_GLOBAL_CHECK_SCOPE( rt, rtDef, fnName, params ) \ 52 { \ 53 if( FxDriverGlobals->FxVerifierOn ) { \ 54 return FX_VF_NAME_TO_IMP_NAME( fnName ) params; \ 55 } \ 56 else { \ 57 return rtDef; \ 58 } \ 59 } 60 61 // 62 // zero parameters 63 // 64 #define FX_VF_STUB( qf, rt, rtDef, fnName ) \ 65 __inline \ 66 qf \ 67 rt \ 68 fnName( _In_ PFX_DRIVER_GLOBALS FxDriverGlobals ) \ 69 FX_VF_GLOBAL_CHECK_SCOPE( rt, rtDef, fnName, ( FxDriverGlobals ) ) 70 71 #define FX_DECLARE_VF_FUNCTION_EX( qf, rt, rtDef, fnName ) \ 72 FX_VF_FUNCTION_PROTOTYPE( qf, rt, fnName ) \ 73 FX_VF_STUB( qf, rt, rtDef, fnName ) 74 75 #define FX_DECLARE_VF_FUNCTION( rt, fnName ) \ 76 FX_DECLARE_VF_FUNCTION_EX( FX_VF_QF_ ## rt, rt, FX_VF_DEFAULT_RT_ ## rt, fnName ) 77 78 // 79 // 1-Parameter Stub Macro 80 // 81 #define FX_VF_STUB_P1( qf, rt, rtDef, fnName, at1 ) \ 82 __inline \ 83 qf \ 84 rt \ 85 fnName( _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, at1 a1 ) \ 86 FX_VF_GLOBAL_CHECK_SCOPE( rt, rtDef, fnName, (FxDriverGlobals, a1 )) 87 88 // 1-Parameter Extended FUNCTION Declaration Macro 89 #define FX_DECLARE_VF_FUNCTION_P1_EX( qf, rt, rtDef, fnName, at1 ) \ 90 FX_VF_FUNCTION_PROTOTYPE( qf, rt, fnName, at1 ) \ 91 FX_VF_STUB_P1( qf, rt, rtDef, fnName, at1 ) 92 93 // 1-Parameter FUNCTION Declaration Macro 94 #define FX_DECLARE_VF_FUNCTION_P1( rt, fnName, at1 ) \ 95 FX_DECLARE_VF_FUNCTION_P1_EX( FX_VF_QF_ ## rt, rt, FX_VF_DEFAULT_RT_ ## rt, fnName, at1 ) 96 97 // 98 // 2-Parameter Stub Macro 99 // 100 #define FX_VF_STUB_P2( qf, rt, rtDef, fnName, at1, at2 ) \ 101 __inline \ 102 qf \ 103 rt \ 104 fnName( _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, at1 a1, at2 a2 ) \ 105 FX_VF_GLOBAL_CHECK_SCOPE( rt, rtDef, fnName, (FxDriverGlobals, a1, a2 )) 106 107 // 2-Parameter Extended FUNCTION Declaration Macro 108 #define FX_DECLARE_VF_FUNCTION_P2_EX( qf, rt, rtDef, fnName, at1, at2 ) \ 109 FX_VF_FUNCTION_PROTOTYPE( qf, rt, fnName, at1, at2 ) \ 110 FX_VF_STUB_P2( qf, rt, rtDef, fnName, at1, at2 ) 111 112 // 2-Parameter FUNCTION Declaration Macro 113 #define FX_DECLARE_VF_FUNCTION_P2( rt, fnName, at1, at2 ) \ 114 FX_DECLARE_VF_FUNCTION_P2_EX( FX_VF_QF_ ## rt, rt, FX_VF_DEFAULT_RT_ ## rt, fnName, at1, at2 ) 115 116 // 117 // 3-Parameter Stub Macro 118 // 119 #define FX_VF_STUB_P3( qf, rt, rtDef, fnName, at1, at2, at3 ) \ 120 __inline \ 121 qf \ 122 rt \ 123 fnName( _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, at1 a1, at2 a2, at3 a3 ) \ 124 FX_VF_GLOBAL_CHECK_SCOPE( rt, rtDef, fnName, (FxDriverGlobals, a1, a2, a3)) 125 126 // 3-Parameter Extended FUNCTION Declaration Macro 127 #define FX_DECLARE_VF_FUNCTION_P3_EX( qf, rt, rtDef, fnName, at1, at2, at3 ) \ 128 FX_VF_FUNCTION_PROTOTYPE( qf, rt, fnName, at1, at2, at3) \ 129 FX_VF_STUB_P3( qf, rt, rtDef, fnName, at1, at2, at3 ) 130 131 // 3-Parameter FUNCTION Declaration Macro 132 #define FX_DECLARE_VF_FUNCTION_P3( rt, fnName, at1, at2, at3 ) \ 133 FX_DECLARE_VF_FUNCTION_P3_EX( FX_VF_QF_ ## rt, rt, FX_VF_DEFAULT_RT_ ## rt, fnName, at1, at2, at3 ) 134 135 // 136 // 4-Parameter Stub Macro 137 // 138 #define FX_VF_STUB_P4( qf, rt, rtDef, fnName, at1, at2, at3, at4 ) \ 139 __inline \ 140 qf \ 141 rt \ 142 fnName( _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, at1 a1, at2 a2, at3 a3, at4 a4 ) \ 143 FX_VF_GLOBAL_CHECK_SCOPE( rt, rtDef, fnName, (FxDriverGlobals, a1, a2, a3, a4)) 144 145 // 4-Parameter Extended FUNCTION Declaration Macro 146 #define FX_DECLARE_VF_FUNCTION_P4_EX( qf, rt, rtDef, fnName, at1, at2, at3, at4 ) \ 147 FX_VF_FUNCTION_PROTOTYPE( qf, rt, fnName, at1, at2, at3, at4 ) \ 148 FX_VF_STUB_P4( qf, rt, rtDef, fnName, at1, at2, at3, at4 ) 149 150 // 4-Parameter FUNCTION Declaration Macro 151 #define FX_DECLARE_VF_FUNCTION_P4( rt, fnName, at1, at2, at3, at4 ) \ 152 FX_DECLARE_VF_FUNCTION_P4_EX( FX_VF_QF_ ## rt, rt, FX_VF_DEFAULT_RT_ ## rt, fnName, at1, at2, at3, at4 ) 153 154 155 #define FX_TAG 'rDxF' 156 157 #define WDFEXPORT(a) imp_ ## a 158 #define VFWDFEXPORT(a) imp_Vf ## a 159 160 #ifndef ARRAY_SIZE 161 #define ARRAY_SIZE(_x) (sizeof((_x))/sizeof((_x)[0])) 162 #endif 163 164 // VOID 165 // FXVERIFY( 166 // PFX_DRIVER_GLOBALS FxDriverGlobals, 167 // <expression> 168 // ); 169 170 #define FXVERIFY(_globals, exp) \ 171 { \ 172 if (!(exp)) { \ 173 RtlAssert( #exp, __FILE__, __LINE__, NULL );\ 174 } \ 175 } 176 177 // These 2 macros are the equivalent of WDF_ALIGN_SIZE_DOWN and 178 // WDF_ALIGN_SIZE_UP. The difference is that these can evaluate to a constant 179 // while the WDF versions will on a fre build, but not on a chk build. By 180 // evaluating to a constant, we can use this in WDFCASSERT. 181 182 // size_t 183 // __inline 184 // FX_ALIGN_SIZE_DOWN_CONSTANT( 185 // IN size_t Length, 186 // IN size_t AlignTo 187 // ) 188 #define FX_ALIGN_SIZE_DOWN_CONSTANT(Length, AlignTo) ((Length) & ~((AlignTo) - 1)) 189 190 // size_t 191 // __inline 192 // FX_ALIGN_SIZE_UP_CONSTANT( 193 // IN size_t Length, 194 // IN size_t AlignTo 195 // ) 196 #define FX_ALIGN_SIZE_UP_CONSTANT(Length, AlignTo) \ 197 FX_ALIGN_SIZE_DOWN_CONSTANT((Length) + (AlignTo) - 1, (AlignTo)) 198 199 // 200 // Macro which will declare a field within a structure. This field can then be 201 // used to return a WDF handle to the driver since it contains the required 202 // FxContextHeader alongside the object itself. 203 // 204 // DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) is required because FxObject 205 // rounds up m_ObjectSize to be a multiple of MEMORY_ALLOCATION_ALIGNMENT. 206 // Since we cannot compute this value at runtime in operator new, we must 207 // be very careful here and force the alignment ourselves. 208 // 209 #define DEFINE_EMBEDDED_OBJECT_HANDLE(_type, _fieldname) \ 210 DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _type _fieldname; \ 211 DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) FxContextHeader _fieldname##Context 212 213 // 214 // Computes the size of an embedded object in a structure. To be used on a 215 // _embeddedFieldName declared with DEFINE_EMBEDDED_OBJECT_HANDLE. 216 // 217 #define EMBEDDED_OBJECT_SIZE(_owningClass, _embeddedFieldName) \ 218 (FIELD_OFFSET(_owningClass, _embeddedFieldName ## Context) - \ 219 FIELD_OFFSET(_owningClass, _embeddedFieldName)) 220 // 221 // Placeholder macro for a no-op 222 // 223 #define DO_NOTHING() (0) 224 225 // 4127 -- Conditional Expression is Constant warning 226 #define WHILE(constant) \ 227 __pragma(warning(suppress: 4127)) while(constant) 228 229 #if DBG 230 #if defined(_X86_) 231 #define TRAP() {_asm {int 3}} 232 #else 233 #define TRAP() DbgBreakPoint() 234 #endif 235 #else // DBG 236 #define TRAP() 237 #endif // DBG 238 239 #if FX_SUPER_DBG 240 #if defined(_X86_) 241 #define COVERAGE_TRAP() {_asm {int 3}} 242 #else 243 #define COVERAGE_TRAP() DbgBreakPoint() 244 #endif 245 #else // FX_SUPER_DBG 246 #define COVERAGE_TRAP() 247 #endif // FX_SUPER_DBG 248 249 // 250 // This is a macro to keep it as cheap as possible. 251 // 252 #if (FX_CORE_MODE == FX_CORE_USER_MODE) 253 #define FxPointerNotNull(FxDriverGlobals, Ptr) \ 254 FX_VERIFY_WITH_NAME(DRIVER(BadArgument, TODO), CHECK_NOT_NULL(Ptr), \ 255 FxDriverGlobals->Public.DriverName) 256 #else 257 #define FxPointerNotNull(FxDriverGlobals, Ptr) \ 258 (((Ptr) == NULL) ? \ 259 FxVerifierNullBugCheck(FxDriverGlobals, _ReturnAddress()), FALSE : \ 260 TRUE ) 261 #endif 262 263 #define FX_MAKE_WSTR_WORKER(x) L ## #x 264 #define FX_MAKE_WSTR(x) FX_MAKE_WSTR_WORKER(x) 265 266 #define FX_LITERAL_WORKER(a) # a 267 #define FX_LITERAL(a) FX_LITERAL_WORKER(a) 268 269 // 270 // In some cases we assert for some condition to hold (such as asserting a ptr 271 // to be non-NULL before accessing it), but prefast will still complain 272 // (e.g., in the example given, about NULL ptr access). 273 // 274 // This macro combines the assert with corresponding assume for prefast. 275 // 276 #ifdef _PREFAST_ 277 #define FX_ASSERT_AND_ASSUME_FOR_PREFAST(b) \ 278 { \ 279 bool result=(b); \ 280 ASSERTMSG(#b, result); \ 281 __assume(result == true); \ 282 } 283 #else 284 #define FX_ASSERT_AND_ASSUME_FOR_PREFAST(b) \ 285 { \ 286 ASSERT(b); \ 287 } 288 #endif 289 290 // 291 // Macro to make sure that the code is not invoked for UM. 292 // 293 // Although it is usually preferable to move such code to *um file 294 // so that it does not get compiled at all for um, in some cases such approach 295 // might fragment the code too much. In such situation this macro can be used. 296 // 297 #if (FX_CORE_MODE == FX_CORE_USER_MODE) 298 #define WDF_VERIFY_KM_ONLY_CODE() \ 299 Mx::MxAssertMsg("Unexpected invocation in user mode", FALSE); 300 #else 301 #define WDF_VERIFY_KM_ONLY_CODE() 302 #endif 303 304 // 305 // MIN, MAX macros. 306 // 307 #ifndef MAX 308 #define MAX(x,y) ((x) > (y) ? (x) : (y)) 309 #endif 310 311 #ifndef MIN 312 #define MIN(x,y) ((x) < (y) ? (x) : (y)) 313 #endif 314 315 #ifndef SAFE_RELEASE 316 #define SAFE_RELEASE(p) if( NULL != p ) { ( p )->Release(); p = NULL; } 317 #endif 318 319 #endif // _FX_MACROS_H_ 320