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                                 &parametersPath,
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                                    &registeredMajor);
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                                    &registeredMinor);
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                                &parametersPart,
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