1 // 2 // Copyright (C) Microsoft. All rights reserved. 3 // 4 #include "fxobjectpch.hpp" 5 6 // Tracing support 7 extern "C" { 8 #if defined(EVENT_TRACING) 9 #include "globalskm.tmh" 10 #endif 11 12 // #include <wdfcxbase.h> 13 #include <fxldr.h> 14 15 16 } 17 extern "C" { 18 19 VOID 20 FxFreeAllocatedMdlsDebugInfo( 21 __in FxDriverGlobalsDebugExtension* DebugExtension 22 ) 23 { 24 FxAllocatedMdls* pNext, *pCur; 25 26 pNext = DebugExtension->AllocatedMdls.Next; 27 28 // 29 // MDL leaks were already checked for in FxPoolDestroy, just free all 30 // the tables here. 31 // 32 while (pNext != NULL) { 33 pCur = pNext; 34 pNext = pCur->Next; 35 36 ExFreePool(pCur); 37 } 38 } 39 40 KDEFERRED_ROUTINE FxFlushDpc; 41 42 __drv_functionClass(KDEFERRED_ROUTINE) 43 __drv_maxIRQL(DISPATCH_LEVEL) 44 __drv_minIRQL(DISPATCH_LEVEL) 45 __drv_requiresIRQL(DISPATCH_LEVEL) 46 __drv_sameIRQL 47 VOID 48 STDCALL 49 FxFlushDpc ( 50 __in struct _KDPC *Dpc, 51 __in_opt PVOID DeferredContext, 52 __in_opt PVOID SystemArgument1, 53 __in_opt PVOID SystemArgument2 54 ) 55 56 /*++ 57 58 Routine Description: 59 60 This DPC is called on a processor to assist in flushing previous DPC's 61 62 Arguments: 63 64 Dpc - Supplies a pointer to DPC object. 65 66 DeferredContext - Supplies the deferred context (event object address). 67 68 SystemArgument1 - Supplies the first system context parameter (not used). 69 70 SystemArgument2 - Supplies the second system context parameter (not used). 71 72 Return Value: 73 74 None. 75 76 --*/ 77 78 { 79 80 UNREFERENCED_PARAMETER(Dpc); 81 UNREFERENCED_PARAMETER(SystemArgument1); 82 UNREFERENCED_PARAMETER(SystemArgument2); 83 84 // 85 // Signal that this routine has been called. 86 // 87 ((FxCREvent*)DeferredContext)->Set(); 88 } 89 90 _Must_inspect_result_ 91 BOOLEAN 92 FX_DRIVER_GLOBALS::IsVersionGreaterThanOrEqualTo( 93 __in ULONG Major, 94 __in ULONG Minor 95 ) 96 { 97 if ((WdfBindInfo->Version.Major > Major) || 98 (WdfBindInfo->Version.Major == Major && 99 WdfBindInfo->Version.Minor >= Minor)) { 100 return TRUE; 101 } 102 else { 103 return FALSE; 104 } 105 } 106 107 #define WDF_MAJOR_VERSION_VALUE L"WdfMajorVersion" 108 #define WDF_MINOR_VERSION_VALUE L"WdfMinorVersion" 109 110 _Must_inspect_result_ 111 BOOLEAN 112 FX_DRIVER_GLOBALS::IsCorrectVersionRegistered( 113 _In_ PCUNICODE_STRING ServiceKeyName 114 ) 115 { 116 FxAutoRegKey hDriver, hWdf; 117 DECLARE_CONST_UNICODE_STRING(parametersPath, L"Parameters\\Wdf"); 118 DECLARE_CONST_UNICODE_STRING(wdfMajorValue, WDF_MAJOR_VERSION_VALUE); 119 DECLARE_CONST_UNICODE_STRING(wdfMinorValue, WDF_MINOR_VERSION_VALUE); 120 ULONG registeredMajor = 0, registeredMinor = 0; 121 NTSTATUS status; 122 123 status = FxRegKey::_OpenKey(NULL, 124 ServiceKeyName, 125 &hDriver.m_Key, 126 KEY_READ 127 ); 128 if (!NT_SUCCESS(status)) { 129 return FALSE; 130 } 131 132 status = FxRegKey::_OpenKey(hDriver.m_Key, 133 ¶metersPath, 134 &hWdf.m_Key, 135 KEY_READ 136 ); 137 if (!NT_SUCCESS(status)) { 138 return FALSE; 139 } 140 141 status = FxRegKey::_QueryULong(hWdf.m_Key, 142 &wdfMajorValue, 143 ®isteredMajor); 144 145 if (!NT_SUCCESS(status) || registeredMajor != WdfBindInfo->Version.Major) { 146 return FALSE; 147 } 148 149 status = FxRegKey::_QueryULong(hWdf.m_Key, 150 &wdfMinorValue, 151 ®isteredMinor); 152 153 if (!NT_SUCCESS(status) || registeredMinor != WdfBindInfo->Version.Minor){ 154 return FALSE; 155 } 156 else { 157 return TRUE; 158 } 159 } 160 161 VOID 162 FX_DRIVER_GLOBALS::RegisterClientVersion( 163 _In_ PCUNICODE_STRING ServiceKeyName 164 ) 165 { 166 FxAutoRegKey hDriver, hParameters, hWdf; 167 DECLARE_CONST_UNICODE_STRING(parametersPart, L"Parameters"); 168 DECLARE_CONST_UNICODE_STRING(wdfPart, L"Wdf"); 169 // 170 // Not defined with the macro because ZwSetValue doesn't use PCUNICODE_STRING 171 // 172 UNICODE_STRING wdfMajorValue; 173 UNICODE_STRING wdfMinorValue; 174 NTSTATUS status; 175 176 RtlInitUnicodeString(&wdfMajorValue, WDF_MAJOR_VERSION_VALUE); 177 RtlInitUnicodeString(&wdfMinorValue, WDF_MINOR_VERSION_VALUE); 178 179 status = FxRegKey::_OpenKey(NULL, 180 ServiceKeyName, 181 &hDriver.m_Key, 182 KEY_WRITE | KEY_READ 183 ); 184 if (!NT_SUCCESS(status)) { 185 DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER, 186 "Unable to open driver's service key, status %!STATUS!", status); 187 return; 188 } 189 // 190 // Key creation, unlike user mode, must happen one level at a time, since 191 // create will also open take both steps instead of trying open first 192 // 193 status = FxRegKey::_Create(hDriver.m_Key, 194 ¶metersPart, 195 &hParameters.m_Key, 196 KEY_WRITE | KEY_READ 197 ); 198 if (!NT_SUCCESS(status)) { 199 DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER, 200 "Unable to write Parameters key, status %!STATUS!", status); 201 return; 202 } 203 204 status = FxRegKey::_Create(hParameters.m_Key, 205 &wdfPart, 206 &hWdf.m_Key, 207 KEY_WRITE | KEY_READ 208 ); 209 if (!NT_SUCCESS(status)) { 210 DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER, 211 "Unable to write Parameters key, status %!STATUS!", status); 212 return; 213 } 214 215 // 216 // Using ZwSetValueKey here to avoid having to change the implementation 217 // in FxRegKey of SetValue to a static / thiscall pair 218 // 219 status = ZwSetValueKey(hWdf.m_Key, 220 &wdfMajorValue, 221 0, 222 REG_DWORD, 223 &WdfBindInfo->Version.Major, 224 sizeof(WdfBindInfo->Version.Major) 225 ); 226 227 if (!NT_SUCCESS(status)) { 228 DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER, 229 "Failed to record driver major version value, status %!STATUS!", status); 230 } 231 232 status = ZwSetValueKey(hWdf.m_Key, 233 &wdfMinorValue, 234 0, 235 REG_DWORD, 236 &WdfBindInfo->Version.Minor, 237 sizeof(WdfBindInfo->Version.Minor) 238 ); 239 240 if (!NT_SUCCESS(status)) { 241 DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER, 242 "Failed to record driver version value, status %!STATUS!", status); 243 } 244 } 245 246 } // extern "C" 247 248 _Must_inspect_result_ 249 BOOLEAN 250 FX_DRIVER_GLOBALS::IsDebuggerAttached( 251 VOID 252 ) 253 { 254 return (FALSE == KdRefreshDebuggerNotPresent()); 255 } 256