1*60a1006dSMark Jansen /*
2*60a1006dSMark Jansen * PROJECT: ReactOS NT User Mode Library
3*60a1006dSMark Jansen * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4*60a1006dSMark Jansen * PURPOSE: Verifier support routines
5*60a1006dSMark Jansen * COPYRIGHT: Copyright 2011 Aleksey Bragin (aleksey@reactos.org)
6*60a1006dSMark Jansen * Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
7*60a1006dSMark Jansen */
8*60a1006dSMark Jansen
9*60a1006dSMark Jansen
10*60a1006dSMark Jansen #include <ntdll.h>
11*60a1006dSMark Jansen #include <reactos/verifier.h>
12*60a1006dSMark Jansen
13*60a1006dSMark Jansen #define NDEBUG
14*60a1006dSMark Jansen #include <debug.h>
15*60a1006dSMark Jansen
16*60a1006dSMark Jansen extern PLDR_DATA_TABLE_ENTRY LdrpImageEntry;
17*60a1006dSMark Jansen ULONG AVrfpVerifierFlags = 0;
18*60a1006dSMark Jansen WCHAR AVrfpVerifierDllsString[256] = { 0 };
19*60a1006dSMark Jansen ULONG AVrfpDebug = 0;
20*60a1006dSMark Jansen BOOL AVrfpInitialized = FALSE;
21*60a1006dSMark Jansen RTL_CRITICAL_SECTION AVrfpVerifierLock;
22*60a1006dSMark Jansen LIST_ENTRY AVrfpVerifierProvidersList;
23*60a1006dSMark Jansen
24*60a1006dSMark Jansen #define VERIFIER_DLL_FLAGS_RESOLVED 1
25*60a1006dSMark Jansen
26*60a1006dSMark Jansen
27*60a1006dSMark Jansen typedef struct _VERIFIER_PROVIDER
28*60a1006dSMark Jansen {
29*60a1006dSMark Jansen LIST_ENTRY ListEntry;
30*60a1006dSMark Jansen UNICODE_STRING DllName;
31*60a1006dSMark Jansen PVOID BaseAddress;
32*60a1006dSMark Jansen PVOID EntryPoint;
33*60a1006dSMark Jansen
34*60a1006dSMark Jansen // Provider data
35*60a1006dSMark Jansen PRTL_VERIFIER_DLL_DESCRIPTOR ProviderDlls;
36*60a1006dSMark Jansen RTL_VERIFIER_DLL_LOAD_CALLBACK ProviderDllLoadCallback;
37*60a1006dSMark Jansen RTL_VERIFIER_DLL_UNLOAD_CALLBACK ProviderDllUnloadCallback;
38*60a1006dSMark Jansen RTL_VERIFIER_NTDLLHEAPFREE_CALLBACK ProviderNtdllHeapFreeCallback;
39*60a1006dSMark Jansen } VERIFIER_PROVIDER, *PVERIFIER_PROVIDER;
40*60a1006dSMark Jansen
41*60a1006dSMark Jansen
42*60a1006dSMark Jansen
43*60a1006dSMark Jansen
44*60a1006dSMark Jansen VOID
45*60a1006dSMark Jansen NTAPI
AVrfReadIFEO(HANDLE KeyHandle)46*60a1006dSMark Jansen AVrfReadIFEO(HANDLE KeyHandle)
47*60a1006dSMark Jansen {
48*60a1006dSMark Jansen NTSTATUS Status;
49*60a1006dSMark Jansen
50*60a1006dSMark Jansen Status = LdrQueryImageFileKeyOption(KeyHandle,
51*60a1006dSMark Jansen L"VerifierDlls",
52*60a1006dSMark Jansen REG_SZ,
53*60a1006dSMark Jansen AVrfpVerifierDllsString,
54*60a1006dSMark Jansen sizeof(AVrfpVerifierDllsString) - sizeof(WCHAR),
55*60a1006dSMark Jansen NULL);
56*60a1006dSMark Jansen
57*60a1006dSMark Jansen if (!NT_SUCCESS(Status))
58*60a1006dSMark Jansen AVrfpVerifierDllsString[0] = UNICODE_NULL;
59*60a1006dSMark Jansen
60*60a1006dSMark Jansen Status = LdrQueryImageFileKeyOption(KeyHandle,
61*60a1006dSMark Jansen L"VerifierFlags",
62*60a1006dSMark Jansen REG_DWORD,
63*60a1006dSMark Jansen &AVrfpVerifierFlags,
64*60a1006dSMark Jansen sizeof(AVrfpVerifierFlags),
65*60a1006dSMark Jansen NULL);
66*60a1006dSMark Jansen if (!NT_SUCCESS(Status))
67*60a1006dSMark Jansen AVrfpVerifierFlags = RTL_VRF_FLG_HANDLE_CHECKS | RTL_VRF_FLG_FAST_FILL_HEAP | RTL_VRF_FLG_LOCK_CHECKS;
68*60a1006dSMark Jansen
69*60a1006dSMark Jansen Status = LdrQueryImageFileKeyOption(KeyHandle,
70*60a1006dSMark Jansen L"VerifierDebug",
71*60a1006dSMark Jansen REG_DWORD,
72*60a1006dSMark Jansen &AVrfpDebug,
73*60a1006dSMark Jansen sizeof(AVrfpDebug),
74*60a1006dSMark Jansen NULL);
75*60a1006dSMark Jansen if (!NT_SUCCESS(Status))
76*60a1006dSMark Jansen AVrfpDebug = 0;
77*60a1006dSMark Jansen }
78*60a1006dSMark Jansen
79*60a1006dSMark Jansen
80*60a1006dSMark Jansen NTSTATUS
81*60a1006dSMark Jansen NTAPI
LdrpInitializeApplicationVerifierPackage(HANDLE KeyHandle,PPEB Peb,BOOLEAN SystemWide,BOOLEAN ReadAdvancedOptions)82*60a1006dSMark Jansen LdrpInitializeApplicationVerifierPackage(HANDLE KeyHandle, PPEB Peb, BOOLEAN SystemWide, BOOLEAN ReadAdvancedOptions)
83*60a1006dSMark Jansen {
84*60a1006dSMark Jansen /* If global flags request DPH, perform some additional actions */
85*60a1006dSMark Jansen if (Peb->NtGlobalFlag & FLG_HEAP_PAGE_ALLOCS)
86*60a1006dSMark Jansen {
87*60a1006dSMark Jansen // TODO: Read advanced DPH flags from the registry if requested
88*60a1006dSMark Jansen if (ReadAdvancedOptions)
89*60a1006dSMark Jansen {
90*60a1006dSMark Jansen UNIMPLEMENTED;
91*60a1006dSMark Jansen }
92*60a1006dSMark Jansen
93*60a1006dSMark Jansen /* Enable page heap */
94*60a1006dSMark Jansen RtlpPageHeapEnabled = TRUE;
95*60a1006dSMark Jansen }
96*60a1006dSMark Jansen
97*60a1006dSMark Jansen AVrfReadIFEO(KeyHandle);
98*60a1006dSMark Jansen
99*60a1006dSMark Jansen return STATUS_SUCCESS;
100*60a1006dSMark Jansen }
101*60a1006dSMark Jansen
102*60a1006dSMark Jansen BOOLEAN
AVrfpIsVerifierProviderDll(PVOID BaseAddress)103*60a1006dSMark Jansen AVrfpIsVerifierProviderDll(PVOID BaseAddress)
104*60a1006dSMark Jansen {
105*60a1006dSMark Jansen PLIST_ENTRY Entry;
106*60a1006dSMark Jansen PVERIFIER_PROVIDER Provider;
107*60a1006dSMark Jansen
108*60a1006dSMark Jansen for (Entry = AVrfpVerifierProvidersList.Flink; Entry != &AVrfpVerifierProvidersList; Entry = Entry->Flink)
109*60a1006dSMark Jansen {
110*60a1006dSMark Jansen Provider = CONTAINING_RECORD(Entry, VERIFIER_PROVIDER, ListEntry);
111*60a1006dSMark Jansen
112*60a1006dSMark Jansen if (BaseAddress == Provider->BaseAddress)
113*60a1006dSMark Jansen return TRUE;
114*60a1006dSMark Jansen }
115*60a1006dSMark Jansen
116*60a1006dSMark Jansen return FALSE;
117*60a1006dSMark Jansen }
118*60a1006dSMark Jansen
119*60a1006dSMark Jansen SIZE_T
AVrfpCountThunks(PIMAGE_THUNK_DATA Thunk)120*60a1006dSMark Jansen AVrfpCountThunks(PIMAGE_THUNK_DATA Thunk)
121*60a1006dSMark Jansen {
122*60a1006dSMark Jansen SIZE_T Count = 0;
123*60a1006dSMark Jansen while (Thunk[Count].u1.Function)
124*60a1006dSMark Jansen Count++;
125*60a1006dSMark Jansen return Count;
126*60a1006dSMark Jansen }
127*60a1006dSMark Jansen
128*60a1006dSMark Jansen VOID
AVrfpSnapDllImports(IN PLDR_DATA_TABLE_ENTRY LdrEntry)129*60a1006dSMark Jansen AVrfpSnapDllImports(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
130*60a1006dSMark Jansen {
131*60a1006dSMark Jansen ULONG Size;
132*60a1006dSMark Jansen PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
133*60a1006dSMark Jansen PBYTE DllBase = LdrEntry->DllBase;
134*60a1006dSMark Jansen
135*60a1006dSMark Jansen ImportDescriptor = RtlImageDirectoryEntryToData(DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &Size);
136*60a1006dSMark Jansen if (!ImportDescriptor)
137*60a1006dSMark Jansen {
138*60a1006dSMark Jansen //SHIMENG_INFO("Skipping module 0x%p \"%wZ\" due to no iat found\n", LdrEntry->DllBase, &LdrEntry->BaseDllName);
139*60a1006dSMark Jansen return;
140*60a1006dSMark Jansen }
141*60a1006dSMark Jansen
142*60a1006dSMark Jansen for (; ImportDescriptor->Name && ImportDescriptor->OriginalFirstThunk; ImportDescriptor++)
143*60a1006dSMark Jansen {
144*60a1006dSMark Jansen PIMAGE_THUNK_DATA FirstThunk;
145*60a1006dSMark Jansen PVOID UnprotectedPtr = NULL;
146*60a1006dSMark Jansen SIZE_T UnprotectedSize = 0;
147*60a1006dSMark Jansen ULONG OldProtection = 0;
148*60a1006dSMark Jansen FirstThunk = (PIMAGE_THUNK_DATA)(DllBase + ImportDescriptor->FirstThunk);
149*60a1006dSMark Jansen
150*60a1006dSMark Jansen /* Walk all imports */
151*60a1006dSMark Jansen for (;FirstThunk->u1.Function; FirstThunk++)
152*60a1006dSMark Jansen {
153*60a1006dSMark Jansen PLIST_ENTRY Entry;
154*60a1006dSMark Jansen PVERIFIER_PROVIDER Provider;
155*60a1006dSMark Jansen
156*60a1006dSMark Jansen for (Entry = AVrfpVerifierProvidersList.Flink; Entry != &AVrfpVerifierProvidersList; Entry = Entry->Flink)
157*60a1006dSMark Jansen {
158*60a1006dSMark Jansen PRTL_VERIFIER_DLL_DESCRIPTOR DllDescriptor;
159*60a1006dSMark Jansen
160*60a1006dSMark Jansen Provider = CONTAINING_RECORD(Entry, VERIFIER_PROVIDER, ListEntry);
161*60a1006dSMark Jansen for (DllDescriptor = Provider->ProviderDlls; DllDescriptor && DllDescriptor->DllName; ++DllDescriptor)
162*60a1006dSMark Jansen {
163*60a1006dSMark Jansen PRTL_VERIFIER_THUNK_DESCRIPTOR ThunkDescriptor;
164*60a1006dSMark Jansen
165*60a1006dSMark Jansen for (ThunkDescriptor = DllDescriptor->DllThunks; ThunkDescriptor && ThunkDescriptor->ThunkName; ++ThunkDescriptor)
166*60a1006dSMark Jansen {
167*60a1006dSMark Jansen /* Just compare function addresses, the loader will have handled forwarders and ordinals for us */
168*60a1006dSMark Jansen if ((PVOID)FirstThunk->u1.Function != ThunkDescriptor->ThunkOldAddress)
169*60a1006dSMark Jansen continue;
170*60a1006dSMark Jansen
171*60a1006dSMark Jansen if (!UnprotectedPtr)
172*60a1006dSMark Jansen {
173*60a1006dSMark Jansen PVOID Ptr = &FirstThunk->u1.Function;
174*60a1006dSMark Jansen SIZE_T Size = sizeof(FirstThunk->u1.Function) * AVrfpCountThunks(FirstThunk);
175*60a1006dSMark Jansen NTSTATUS Status;
176*60a1006dSMark Jansen
177*60a1006dSMark Jansen UnprotectedPtr = Ptr;
178*60a1006dSMark Jansen UnprotectedSize = Size;
179*60a1006dSMark Jansen
180*60a1006dSMark Jansen Status = NtProtectVirtualMemory(NtCurrentProcess(),
181*60a1006dSMark Jansen &Ptr,
182*60a1006dSMark Jansen &Size,
183*60a1006dSMark Jansen PAGE_EXECUTE_READWRITE,
184*60a1006dSMark Jansen &OldProtection);
185*60a1006dSMark Jansen
186*60a1006dSMark Jansen if (!NT_SUCCESS(Status))
187*60a1006dSMark Jansen {
188*60a1006dSMark Jansen DbgPrint("AVRF: Unable to unprotect IAT to modify thunks (status %08X).\n", Status);
189*60a1006dSMark Jansen UnprotectedPtr = NULL;
190*60a1006dSMark Jansen continue;
191*60a1006dSMark Jansen }
192*60a1006dSMark Jansen }
193*60a1006dSMark Jansen
194*60a1006dSMark Jansen if (ThunkDescriptor->ThunkNewAddress == NULL)
195*60a1006dSMark Jansen {
196*60a1006dSMark Jansen DbgPrint("AVRF: internal error: New thunk for %s is null.\n", ThunkDescriptor->ThunkName);
197*60a1006dSMark Jansen continue;
198*60a1006dSMark Jansen }
199*60a1006dSMark Jansen FirstThunk->u1.Function = (SIZE_T)ThunkDescriptor->ThunkNewAddress;
200*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWSNAPS)
201*60a1006dSMark Jansen DbgPrint("AVRF: Snapped (%wZ: %s) with (%wZ: %p).\n",
202*60a1006dSMark Jansen &LdrEntry->BaseDllName,
203*60a1006dSMark Jansen ThunkDescriptor->ThunkName,
204*60a1006dSMark Jansen &Provider->DllName,
205*60a1006dSMark Jansen ThunkDescriptor->ThunkNewAddress);
206*60a1006dSMark Jansen }
207*60a1006dSMark Jansen }
208*60a1006dSMark Jansen }
209*60a1006dSMark Jansen }
210*60a1006dSMark Jansen
211*60a1006dSMark Jansen if (UnprotectedPtr)
212*60a1006dSMark Jansen {
213*60a1006dSMark Jansen PVOID Ptr = UnprotectedPtr;
214*60a1006dSMark Jansen SIZE_T Size = UnprotectedSize;
215*60a1006dSMark Jansen NTSTATUS Status;
216*60a1006dSMark Jansen
217*60a1006dSMark Jansen UnprotectedPtr = Ptr;
218*60a1006dSMark Jansen UnprotectedSize = Size;
219*60a1006dSMark Jansen
220*60a1006dSMark Jansen Status = NtProtectVirtualMemory(NtCurrentProcess(),
221*60a1006dSMark Jansen &Ptr,
222*60a1006dSMark Jansen &Size,
223*60a1006dSMark Jansen OldProtection,
224*60a1006dSMark Jansen &OldProtection);
225*60a1006dSMark Jansen if (!NT_SUCCESS(Status))
226*60a1006dSMark Jansen {
227*60a1006dSMark Jansen DbgPrint("AVRF: Unable to reprotect IAT to modify thunks (status %08X).\n", Status);
228*60a1006dSMark Jansen }
229*60a1006dSMark Jansen }
230*60a1006dSMark Jansen }
231*60a1006dSMark Jansen }
232*60a1006dSMark Jansen
233*60a1006dSMark Jansen
234*60a1006dSMark Jansen VOID
AvrfpResolveThunks(IN PLDR_DATA_TABLE_ENTRY LdrEntry)235*60a1006dSMark Jansen AvrfpResolveThunks(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
236*60a1006dSMark Jansen {
237*60a1006dSMark Jansen PLIST_ENTRY Entry;
238*60a1006dSMark Jansen PVERIFIER_PROVIDER Provider;
239*60a1006dSMark Jansen
240*60a1006dSMark Jansen if (!AVrfpInitialized)
241*60a1006dSMark Jansen return;
242*60a1006dSMark Jansen
243*60a1006dSMark Jansen for (Entry = AVrfpVerifierProvidersList.Flink; Entry != &AVrfpVerifierProvidersList; Entry = Entry->Flink)
244*60a1006dSMark Jansen {
245*60a1006dSMark Jansen PRTL_VERIFIER_DLL_DESCRIPTOR DllDescriptor;
246*60a1006dSMark Jansen
247*60a1006dSMark Jansen Provider = CONTAINING_RECORD(Entry, VERIFIER_PROVIDER, ListEntry);
248*60a1006dSMark Jansen
249*60a1006dSMark Jansen for (DllDescriptor = Provider->ProviderDlls; DllDescriptor && DllDescriptor->DllName; ++DllDescriptor)
250*60a1006dSMark Jansen {
251*60a1006dSMark Jansen PRTL_VERIFIER_THUNK_DESCRIPTOR ThunkDescriptor;
252*60a1006dSMark Jansen
253*60a1006dSMark Jansen if ((DllDescriptor->DllFlags & VERIFIER_DLL_FLAGS_RESOLVED) ||
254*60a1006dSMark Jansen _wcsicmp(DllDescriptor->DllName, LdrEntry->BaseDllName.Buffer))
255*60a1006dSMark Jansen continue;
256*60a1006dSMark Jansen
257*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWVERIFIEDEXPORTS)
258*60a1006dSMark Jansen DbgPrint("AVRF: pid 0x%X: found dll descriptor for `%wZ' with verified exports\n",
259*60a1006dSMark Jansen NtCurrentTeb()->ClientId.UniqueProcess,
260*60a1006dSMark Jansen &LdrEntry->BaseDllName);
261*60a1006dSMark Jansen
262*60a1006dSMark Jansen for (ThunkDescriptor = DllDescriptor->DllThunks; ThunkDescriptor && ThunkDescriptor->ThunkName; ++ThunkDescriptor)
263*60a1006dSMark Jansen {
264*60a1006dSMark Jansen if (!ThunkDescriptor->ThunkOldAddress)
265*60a1006dSMark Jansen {
266*60a1006dSMark Jansen ANSI_STRING ThunkName;
267*60a1006dSMark Jansen
268*60a1006dSMark Jansen RtlInitAnsiString(&ThunkName, ThunkDescriptor->ThunkName);
269*60a1006dSMark Jansen /* We cannot call the public api, because that would run init routines! */
270*60a1006dSMark Jansen if (NT_SUCCESS(LdrpGetProcedureAddress(LdrEntry->DllBase, &ThunkName, 0, &ThunkDescriptor->ThunkOldAddress, FALSE)))
271*60a1006dSMark Jansen {
272*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWFOUNDEXPORTS)
273*60a1006dSMark Jansen DbgPrint("AVRF: (%wZ) %Z export found.\n", &LdrEntry->BaseDllName, &ThunkName);
274*60a1006dSMark Jansen }
275*60a1006dSMark Jansen else
276*60a1006dSMark Jansen {
277*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWFOUNDEXPORTS)
278*60a1006dSMark Jansen DbgPrint("AVRF: warning: did not find `%Z' export in %wZ.\n", &ThunkName, &LdrEntry->BaseDllName);
279*60a1006dSMark Jansen }
280*60a1006dSMark Jansen }
281*60a1006dSMark Jansen }
282*60a1006dSMark Jansen
283*60a1006dSMark Jansen DllDescriptor->DllFlags |= VERIFIER_DLL_FLAGS_RESOLVED;
284*60a1006dSMark Jansen }
285*60a1006dSMark Jansen }
286*60a1006dSMark Jansen
287*60a1006dSMark Jansen AVrfpSnapDllImports(LdrEntry);
288*60a1006dSMark Jansen }
289*60a1006dSMark Jansen
290*60a1006dSMark Jansen
291*60a1006dSMark Jansen
292*60a1006dSMark Jansen VOID
293*60a1006dSMark Jansen NTAPI
AVrfDllLoadNotification(IN PLDR_DATA_TABLE_ENTRY LdrEntry)294*60a1006dSMark Jansen AVrfDllLoadNotification(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
295*60a1006dSMark Jansen {
296*60a1006dSMark Jansen PLIST_ENTRY Entry;
297*60a1006dSMark Jansen
298*60a1006dSMark Jansen if (!(NtCurrentPeb()->NtGlobalFlag & FLG_APPLICATION_VERIFIER))
299*60a1006dSMark Jansen return;
300*60a1006dSMark Jansen
301*60a1006dSMark Jansen RtlEnterCriticalSection(&AVrfpVerifierLock);
302*60a1006dSMark Jansen if (!AVrfpIsVerifierProviderDll(LdrEntry->DllBase))
303*60a1006dSMark Jansen {
304*60a1006dSMark Jansen AvrfpResolveThunks(LdrEntry);
305*60a1006dSMark Jansen
306*60a1006dSMark Jansen for (Entry = AVrfpVerifierProvidersList.Flink; Entry != &AVrfpVerifierProvidersList; Entry = Entry->Flink)
307*60a1006dSMark Jansen {
308*60a1006dSMark Jansen PVERIFIER_PROVIDER Provider;
309*60a1006dSMark Jansen RTL_VERIFIER_DLL_LOAD_CALLBACK ProviderDllLoadCallback;
310*60a1006dSMark Jansen
311*60a1006dSMark Jansen Provider = CONTAINING_RECORD(Entry, VERIFIER_PROVIDER, ListEntry);
312*60a1006dSMark Jansen
313*60a1006dSMark Jansen ProviderDllLoadCallback = Provider->ProviderDllLoadCallback;
314*60a1006dSMark Jansen if (ProviderDllLoadCallback)
315*60a1006dSMark Jansen {
316*60a1006dSMark Jansen ProviderDllLoadCallback(LdrEntry->BaseDllName.Buffer,
317*60a1006dSMark Jansen LdrEntry->DllBase,
318*60a1006dSMark Jansen LdrEntry->SizeOfImage,
319*60a1006dSMark Jansen LdrEntry);
320*60a1006dSMark Jansen }
321*60a1006dSMark Jansen }
322*60a1006dSMark Jansen }
323*60a1006dSMark Jansen RtlLeaveCriticalSection(&AVrfpVerifierLock);
324*60a1006dSMark Jansen }
325*60a1006dSMark Jansen
326*60a1006dSMark Jansen VOID
327*60a1006dSMark Jansen NTAPI
AVrfDllUnloadNotification(IN PLDR_DATA_TABLE_ENTRY LdrEntry)328*60a1006dSMark Jansen AVrfDllUnloadNotification(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
329*60a1006dSMark Jansen {
330*60a1006dSMark Jansen PLIST_ENTRY Entry;
331*60a1006dSMark Jansen
332*60a1006dSMark Jansen if (!(NtCurrentPeb()->NtGlobalFlag & FLG_APPLICATION_VERIFIER))
333*60a1006dSMark Jansen return;
334*60a1006dSMark Jansen
335*60a1006dSMark Jansen RtlEnterCriticalSection(&AVrfpVerifierLock);
336*60a1006dSMark Jansen if (!AVrfpIsVerifierProviderDll(LdrEntry->DllBase))
337*60a1006dSMark Jansen {
338*60a1006dSMark Jansen for (Entry = AVrfpVerifierProvidersList.Flink; Entry != &AVrfpVerifierProvidersList; Entry = Entry->Flink)
339*60a1006dSMark Jansen {
340*60a1006dSMark Jansen PVERIFIER_PROVIDER Provider;
341*60a1006dSMark Jansen RTL_VERIFIER_DLL_UNLOAD_CALLBACK ProviderDllUnloadCallback;
342*60a1006dSMark Jansen
343*60a1006dSMark Jansen Provider = CONTAINING_RECORD(Entry, VERIFIER_PROVIDER, ListEntry);
344*60a1006dSMark Jansen
345*60a1006dSMark Jansen ProviderDllUnloadCallback = Provider->ProviderDllUnloadCallback;
346*60a1006dSMark Jansen if (ProviderDllUnloadCallback)
347*60a1006dSMark Jansen {
348*60a1006dSMark Jansen ProviderDllUnloadCallback(LdrEntry->BaseDllName.Buffer,
349*60a1006dSMark Jansen LdrEntry->DllBase,
350*60a1006dSMark Jansen LdrEntry->SizeOfImage,
351*60a1006dSMark Jansen LdrEntry);
352*60a1006dSMark Jansen }
353*60a1006dSMark Jansen }
354*60a1006dSMark Jansen }
355*60a1006dSMark Jansen RtlLeaveCriticalSection(&AVrfpVerifierLock);
356*60a1006dSMark Jansen }
357*60a1006dSMark Jansen
358*60a1006dSMark Jansen
359*60a1006dSMark Jansen VOID
360*60a1006dSMark Jansen NTAPI
AVrfPageHeapDllNotification(IN PLDR_DATA_TABLE_ENTRY LdrEntry)361*60a1006dSMark Jansen AVrfPageHeapDllNotification(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
362*60a1006dSMark Jansen {
363*60a1006dSMark Jansen /* Check if page heap dll notification is turned on */
364*60a1006dSMark Jansen if (!(RtlpDphGlobalFlags & DPH_FLAG_DLL_NOTIFY))
365*60a1006dSMark Jansen return;
366*60a1006dSMark Jansen
367*60a1006dSMark Jansen /* We don't support this flag currently */
368*60a1006dSMark Jansen UNIMPLEMENTED;
369*60a1006dSMark Jansen }
370*60a1006dSMark Jansen
371*60a1006dSMark Jansen
372*60a1006dSMark Jansen VOID
373*60a1006dSMark Jansen NTAPI
AVrfpResnapInitialModules(VOID)374*60a1006dSMark Jansen AVrfpResnapInitialModules(VOID)
375*60a1006dSMark Jansen {
376*60a1006dSMark Jansen PLIST_ENTRY ListHead, ListEntry;
377*60a1006dSMark Jansen
378*60a1006dSMark Jansen ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
379*60a1006dSMark Jansen for (ListEntry = ListHead->Flink; ListHead != ListEntry; ListEntry = ListEntry->Flink)
380*60a1006dSMark Jansen {
381*60a1006dSMark Jansen PLDR_DATA_TABLE_ENTRY LdrEntry;
382*60a1006dSMark Jansen
383*60a1006dSMark Jansen LdrEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
384*60a1006dSMark Jansen
385*60a1006dSMark Jansen if (AVrfpIsVerifierProviderDll(LdrEntry->DllBase))
386*60a1006dSMark Jansen {
387*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWSNAPS)
388*60a1006dSMark Jansen DbgPrint("AVRF: skipped resnapping provider %wZ ...\n", &LdrEntry->BaseDllName);
389*60a1006dSMark Jansen }
390*60a1006dSMark Jansen else
391*60a1006dSMark Jansen {
392*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWSNAPS)
393*60a1006dSMark Jansen DbgPrint("AVRF: resnapping %wZ ...\n", &LdrEntry->BaseDllName);
394*60a1006dSMark Jansen
395*60a1006dSMark Jansen AvrfpResolveThunks(LdrEntry);
396*60a1006dSMark Jansen }
397*60a1006dSMark Jansen }
398*60a1006dSMark Jansen }
399*60a1006dSMark Jansen
400*60a1006dSMark Jansen PVOID
401*60a1006dSMark Jansen NTAPI
AvrfpFindDuplicateThunk(PLIST_ENTRY EndEntry,PWCHAR DllName,PCHAR ThunkName)402*60a1006dSMark Jansen AvrfpFindDuplicateThunk(PLIST_ENTRY EndEntry, PWCHAR DllName, PCHAR ThunkName)
403*60a1006dSMark Jansen {
404*60a1006dSMark Jansen PLIST_ENTRY Entry;
405*60a1006dSMark Jansen
406*60a1006dSMark Jansen for (Entry = AVrfpVerifierProvidersList.Flink; Entry != EndEntry; Entry = Entry->Flink)
407*60a1006dSMark Jansen {
408*60a1006dSMark Jansen PVERIFIER_PROVIDER Provider;
409*60a1006dSMark Jansen PRTL_VERIFIER_DLL_DESCRIPTOR DllDescriptor;
410*60a1006dSMark Jansen
411*60a1006dSMark Jansen Provider = CONTAINING_RECORD(Entry, VERIFIER_PROVIDER, ListEntry);
412*60a1006dSMark Jansen
413*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWCHAINING_DEBUG)
414*60a1006dSMark Jansen DbgPrint("AVRF: chain: searching in %wZ\n", &Provider->DllName);
415*60a1006dSMark Jansen
416*60a1006dSMark Jansen for (DllDescriptor = Provider->ProviderDlls; DllDescriptor && DllDescriptor->DllName; ++DllDescriptor)
417*60a1006dSMark Jansen {
418*60a1006dSMark Jansen PRTL_VERIFIER_THUNK_DESCRIPTOR ThunkDescriptor;
419*60a1006dSMark Jansen
420*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWCHAINING_DEBUG)
421*60a1006dSMark Jansen DbgPrint("AVRF: chain: dll: %ws\n", DllDescriptor->DllName);
422*60a1006dSMark Jansen
423*60a1006dSMark Jansen if (_wcsicmp(DllDescriptor->DllName, DllName))
424*60a1006dSMark Jansen continue;
425*60a1006dSMark Jansen
426*60a1006dSMark Jansen for (ThunkDescriptor = DllDescriptor->DllThunks; ThunkDescriptor && ThunkDescriptor->ThunkName; ++ThunkDescriptor)
427*60a1006dSMark Jansen {
428*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWCHAINING_DEBUG)
429*60a1006dSMark Jansen DbgPrint("AVRF: chain: thunk: %s == %s ?\n", ThunkDescriptor->ThunkName, ThunkName);
430*60a1006dSMark Jansen
431*60a1006dSMark Jansen if (!_stricmp(ThunkDescriptor->ThunkName, ThunkName))
432*60a1006dSMark Jansen {
433*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWCHAINING_DEBUG)
434*60a1006dSMark Jansen DbgPrint("AVRF: Found duplicate for (%ws: %s) in %wZ\n",
435*60a1006dSMark Jansen DllDescriptor->DllName, ThunkDescriptor->ThunkName, &Provider->DllName);
436*60a1006dSMark Jansen
437*60a1006dSMark Jansen return ThunkDescriptor->ThunkNewAddress;
438*60a1006dSMark Jansen }
439*60a1006dSMark Jansen }
440*60a1006dSMark Jansen }
441*60a1006dSMark Jansen }
442*60a1006dSMark Jansen return NULL;
443*60a1006dSMark Jansen }
444*60a1006dSMark Jansen
445*60a1006dSMark Jansen
446*60a1006dSMark Jansen VOID
447*60a1006dSMark Jansen NTAPI
AVrfpChainDuplicateThunks(VOID)448*60a1006dSMark Jansen AVrfpChainDuplicateThunks(VOID)
449*60a1006dSMark Jansen {
450*60a1006dSMark Jansen PLIST_ENTRY Entry;
451*60a1006dSMark Jansen PVERIFIER_PROVIDER Provider;
452*60a1006dSMark Jansen
453*60a1006dSMark Jansen for (Entry = AVrfpVerifierProvidersList.Flink; Entry != &AVrfpVerifierProvidersList; Entry = Entry->Flink)
454*60a1006dSMark Jansen {
455*60a1006dSMark Jansen PRTL_VERIFIER_DLL_DESCRIPTOR DllDescriptor;
456*60a1006dSMark Jansen PRTL_VERIFIER_THUNK_DESCRIPTOR ThunkDescriptor;
457*60a1006dSMark Jansen
458*60a1006dSMark Jansen Provider = CONTAINING_RECORD(Entry, VERIFIER_PROVIDER, ListEntry);
459*60a1006dSMark Jansen
460*60a1006dSMark Jansen for (DllDescriptor = Provider->ProviderDlls; DllDescriptor && DllDescriptor->DllName; ++DllDescriptor)
461*60a1006dSMark Jansen {
462*60a1006dSMark Jansen for (ThunkDescriptor = DllDescriptor->DllThunks; ThunkDescriptor && ThunkDescriptor->ThunkName; ++ThunkDescriptor)
463*60a1006dSMark Jansen {
464*60a1006dSMark Jansen PVOID Ptr;
465*60a1006dSMark Jansen
466*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWCHAINING_DEBUG)
467*60a1006dSMark Jansen DbgPrint("AVRF: Checking %wZ for duplicate (%ws: %s)\n",
468*60a1006dSMark Jansen &Provider->DllName, DllDescriptor->DllName, ThunkDescriptor->ThunkName);
469*60a1006dSMark Jansen
470*60a1006dSMark Jansen Ptr = AvrfpFindDuplicateThunk(Entry, DllDescriptor->DllName, ThunkDescriptor->ThunkName);
471*60a1006dSMark Jansen if (Ptr)
472*60a1006dSMark Jansen {
473*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWCHAINING)
474*60a1006dSMark Jansen DbgPrint("AVRF: Chaining (%ws: %s) to %wZ\n", DllDescriptor->DllName, ThunkDescriptor->ThunkName, &Provider->DllName);
475*60a1006dSMark Jansen
476*60a1006dSMark Jansen ThunkDescriptor->ThunkOldAddress = Ptr;
477*60a1006dSMark Jansen }
478*60a1006dSMark Jansen }
479*60a1006dSMark Jansen }
480*60a1006dSMark Jansen }
481*60a1006dSMark Jansen }
482*60a1006dSMark Jansen
483*60a1006dSMark Jansen NTSTATUS
484*60a1006dSMark Jansen NTAPI
AVrfpLoadAndInitializeProvider(PVERIFIER_PROVIDER Provider)485*60a1006dSMark Jansen AVrfpLoadAndInitializeProvider(PVERIFIER_PROVIDER Provider)
486*60a1006dSMark Jansen {
487*60a1006dSMark Jansen WCHAR StringBuffer[MAX_PATH + 11];
488*60a1006dSMark Jansen UNICODE_STRING DllPath;
489*60a1006dSMark Jansen PRTL_VERIFIER_PROVIDER_DESCRIPTOR Descriptor;
490*60a1006dSMark Jansen PIMAGE_NT_HEADERS ImageNtHeader;
491*60a1006dSMark Jansen NTSTATUS Status;
492*60a1006dSMark Jansen
493*60a1006dSMark Jansen RtlInitEmptyUnicodeString(&DllPath, StringBuffer, sizeof(StringBuffer));
494*60a1006dSMark Jansen RtlAppendUnicodeToString(&DllPath, SharedUserData->NtSystemRoot);
495*60a1006dSMark Jansen RtlAppendUnicodeToString(&DllPath, L"\\System32\\");
496*60a1006dSMark Jansen
497*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_SHOWSNAPS)
498*60a1006dSMark Jansen DbgPrint("AVRF: verifier dll `%wZ'\n", &Provider->DllName);
499*60a1006dSMark Jansen
500*60a1006dSMark Jansen Status = LdrLoadDll(DllPath.Buffer, NULL, &Provider->DllName, &Provider->BaseAddress);
501*60a1006dSMark Jansen if (!NT_SUCCESS(Status))
502*60a1006dSMark Jansen {
503*60a1006dSMark Jansen DbgPrint("AVRF: %wZ: failed to load provider `%wZ' (status %08X) from %wZ\n",
504*60a1006dSMark Jansen &LdrpImageEntry->BaseDllName,
505*60a1006dSMark Jansen &Provider->DllName,
506*60a1006dSMark Jansen Status,
507*60a1006dSMark Jansen &DllPath);
508*60a1006dSMark Jansen return Status;
509*60a1006dSMark Jansen }
510*60a1006dSMark Jansen
511*60a1006dSMark Jansen /* Prevent someone funny from specifying his own application as provider */
512*60a1006dSMark Jansen ImageNtHeader = RtlImageNtHeader(Provider->BaseAddress);
513*60a1006dSMark Jansen if (!ImageNtHeader ||
514*60a1006dSMark Jansen !(ImageNtHeader->FileHeader.Characteristics & IMAGE_FILE_DLL))
515*60a1006dSMark Jansen {
516*60a1006dSMark Jansen DbgPrint("AVRF: provider %wZ is not a DLL image\n", &Provider->DllName);
517*60a1006dSMark Jansen return STATUS_DLL_INIT_FAILED;
518*60a1006dSMark Jansen }
519*60a1006dSMark Jansen
520*60a1006dSMark Jansen Provider->EntryPoint = LdrpFetchAddressOfEntryPoint(Provider->BaseAddress);
521*60a1006dSMark Jansen if (!Provider->EntryPoint)
522*60a1006dSMark Jansen {
523*60a1006dSMark Jansen DbgPrint("AVRF: cannot find an entry point for provider %wZ\n", &Provider->DllName);
524*60a1006dSMark Jansen return STATUS_PROCEDURE_NOT_FOUND;
525*60a1006dSMark Jansen }
526*60a1006dSMark Jansen
527*60a1006dSMark Jansen _SEH2_TRY
528*60a1006dSMark Jansen {
529*60a1006dSMark Jansen if (LdrpCallInitRoutine(Provider->EntryPoint,
530*60a1006dSMark Jansen Provider->BaseAddress,
531*60a1006dSMark Jansen DLL_PROCESS_VERIFIER,
532*60a1006dSMark Jansen &Descriptor))
533*60a1006dSMark Jansen {
534*60a1006dSMark Jansen if (Descriptor && Descriptor->Length == sizeof(RTL_VERIFIER_PROVIDER_DESCRIPTOR))
535*60a1006dSMark Jansen {
536*60a1006dSMark Jansen /* Copy the data */
537*60a1006dSMark Jansen Provider->ProviderDlls = Descriptor->ProviderDlls;
538*60a1006dSMark Jansen Provider->ProviderDllLoadCallback = Descriptor->ProviderDllLoadCallback;
539*60a1006dSMark Jansen Provider->ProviderDllUnloadCallback = Descriptor->ProviderDllUnloadCallback;
540*60a1006dSMark Jansen Provider->ProviderNtdllHeapFreeCallback = Descriptor->ProviderNtdllHeapFreeCallback;
541*60a1006dSMark Jansen
542*60a1006dSMark Jansen /* Update some info for the provider */
543*60a1006dSMark Jansen Descriptor->VerifierImage = LdrpImageEntry->BaseDllName.Buffer;
544*60a1006dSMark Jansen Descriptor->VerifierFlags = AVrfpVerifierFlags;
545*60a1006dSMark Jansen Descriptor->VerifierDebug = AVrfpDebug;
546*60a1006dSMark Jansen
547*60a1006dSMark Jansen /* We don't have these yet */
548*60a1006dSMark Jansen DPRINT1("AVRF: RtlpGetStackTraceAddress MISSING\n");
549*60a1006dSMark Jansen DPRINT1("AVRF: RtlpDebugPageHeapCreate MISSING\n");
550*60a1006dSMark Jansen DPRINT1("AVRF: RtlpDebugPageHeapDestroy MISSING\n");
551*60a1006dSMark Jansen Descriptor->RtlpGetStackTraceAddress = NULL;
552*60a1006dSMark Jansen Descriptor->RtlpDebugPageHeapCreate = NULL;
553*60a1006dSMark Jansen Descriptor->RtlpDebugPageHeapDestroy = NULL;
554*60a1006dSMark Jansen Status = STATUS_SUCCESS;
555*60a1006dSMark Jansen }
556*60a1006dSMark Jansen else
557*60a1006dSMark Jansen {
558*60a1006dSMark Jansen DbgPrint("AVRF: provider %wZ passed an invalid descriptor @ %p\n", &Provider->DllName, Descriptor);
559*60a1006dSMark Jansen Status = STATUS_INVALID_PARAMETER_4;
560*60a1006dSMark Jansen }
561*60a1006dSMark Jansen }
562*60a1006dSMark Jansen else
563*60a1006dSMark Jansen {
564*60a1006dSMark Jansen DbgPrint("AVRF: provider %wZ did not initialize correctly\n", &Provider->DllName);
565*60a1006dSMark Jansen Status = STATUS_DLL_INIT_FAILED;
566*60a1006dSMark Jansen }
567*60a1006dSMark Jansen }
568*60a1006dSMark Jansen _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
569*60a1006dSMark Jansen {
570*60a1006dSMark Jansen Status = _SEH2_GetExceptionCode();
571*60a1006dSMark Jansen }
572*60a1006dSMark Jansen _SEH2_END;
573*60a1006dSMark Jansen
574*60a1006dSMark Jansen if (!NT_SUCCESS(Status))
575*60a1006dSMark Jansen return Status;
576*60a1006dSMark Jansen
577*60a1006dSMark Jansen
578*60a1006dSMark Jansen if (AVrfpDebug & RTL_VRF_DBG_LISTPROVIDERS)
579*60a1006dSMark Jansen DbgPrint("AVRF: initialized provider %wZ (descriptor @ %p)\n", &Provider->DllName, Descriptor);
580*60a1006dSMark Jansen
581*60a1006dSMark Jansen /* Done loading providers, allow dll notifications */
582*60a1006dSMark Jansen AVrfpInitialized = TRUE;
583*60a1006dSMark Jansen
584*60a1006dSMark Jansen AVrfpChainDuplicateThunks();
585*60a1006dSMark Jansen AVrfpResnapInitialModules();
586*60a1006dSMark Jansen
587*60a1006dSMark Jansen /* Manually call with DLL_PROCESS_ATTACH, since the process is not done initializing */
588*60a1006dSMark Jansen _SEH2_TRY
589*60a1006dSMark Jansen {
590*60a1006dSMark Jansen if (!LdrpCallInitRoutine(Provider->EntryPoint,
591*60a1006dSMark Jansen Provider->BaseAddress,
592*60a1006dSMark Jansen DLL_PROCESS_ATTACH,
593*60a1006dSMark Jansen NULL))
594*60a1006dSMark Jansen {
595*60a1006dSMark Jansen DbgPrint("AVRF: provider %wZ did not initialize correctly\n", &Provider->DllName);
596*60a1006dSMark Jansen Status = STATUS_DLL_INIT_FAILED;
597*60a1006dSMark Jansen }
598*60a1006dSMark Jansen
599*60a1006dSMark Jansen }
600*60a1006dSMark Jansen _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
601*60a1006dSMark Jansen {
602*60a1006dSMark Jansen Status = _SEH2_GetExceptionCode();
603*60a1006dSMark Jansen }
604*60a1006dSMark Jansen _SEH2_END;
605*60a1006dSMark Jansen
606*60a1006dSMark Jansen return Status;
607*60a1006dSMark Jansen }
608*60a1006dSMark Jansen
609*60a1006dSMark Jansen
610*60a1006dSMark Jansen NTSTATUS
611*60a1006dSMark Jansen NTAPI
AVrfInitializeVerifier(VOID)612*60a1006dSMark Jansen AVrfInitializeVerifier(VOID)
613*60a1006dSMark Jansen {
614*60a1006dSMark Jansen NTSTATUS Status;
615*60a1006dSMark Jansen PVERIFIER_PROVIDER Provider;
616*60a1006dSMark Jansen PLIST_ENTRY Entry;
617*60a1006dSMark Jansen WCHAR* Ptr, *Next;
618*60a1006dSMark Jansen
619*60a1006dSMark Jansen Status = RtlInitializeCriticalSection(&AVrfpVerifierLock);
620*60a1006dSMark Jansen InitializeListHead(&AVrfpVerifierProvidersList);
621*60a1006dSMark Jansen
622*60a1006dSMark Jansen if (!NT_SUCCESS(Status))
623*60a1006dSMark Jansen return Status;
624*60a1006dSMark Jansen
625*60a1006dSMark Jansen DbgPrint("AVRF: %wZ: pid 0x%X: flags 0x%X: application verifier enabled\n",
626*60a1006dSMark Jansen &LdrpImageEntry->BaseDllName, NtCurrentTeb()->ClientId.UniqueProcess, AVrfpVerifierFlags);
627*60a1006dSMark Jansen
628*60a1006dSMark Jansen Provider = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(VERIFIER_PROVIDER));
629*60a1006dSMark Jansen if (!Provider)
630*60a1006dSMark Jansen return STATUS_NO_MEMORY;
631*60a1006dSMark Jansen
632*60a1006dSMark Jansen RtlInitUnicodeString(&Provider->DllName, L"verifier.dll");
633*60a1006dSMark Jansen InsertTailList(&AVrfpVerifierProvidersList, &Provider->ListEntry);
634*60a1006dSMark Jansen
635*60a1006dSMark Jansen Next = AVrfpVerifierDllsString;
636*60a1006dSMark Jansen
637*60a1006dSMark Jansen do
638*60a1006dSMark Jansen {
639*60a1006dSMark Jansen while (*Next == L' ' || *Next == L'\t')
640*60a1006dSMark Jansen Next++;
641*60a1006dSMark Jansen
642*60a1006dSMark Jansen Ptr = Next;
643*60a1006dSMark Jansen
644*60a1006dSMark Jansen while (*Next != ' ' && *Next != '\t' && *Next)
645*60a1006dSMark Jansen Next++;
646*60a1006dSMark Jansen
647*60a1006dSMark Jansen if (*Next)
648*60a1006dSMark Jansen *(Next++) = '\0';
649*60a1006dSMark Jansen else
650*60a1006dSMark Jansen Next = NULL;
651*60a1006dSMark Jansen
652*60a1006dSMark Jansen if (*Ptr)
653*60a1006dSMark Jansen {
654*60a1006dSMark Jansen Provider = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(VERIFIER_PROVIDER));
655*60a1006dSMark Jansen if (!Provider)
656*60a1006dSMark Jansen return STATUS_NO_MEMORY;
657*60a1006dSMark Jansen RtlInitUnicodeString(&Provider->DllName, Ptr);
658*60a1006dSMark Jansen InsertTailList(&AVrfpVerifierProvidersList, &Provider->ListEntry);
659*60a1006dSMark Jansen }
660*60a1006dSMark Jansen } while (Next);
661*60a1006dSMark Jansen
662*60a1006dSMark Jansen Entry = AVrfpVerifierProvidersList.Flink;
663*60a1006dSMark Jansen while (Entry != &AVrfpVerifierProvidersList)
664*60a1006dSMark Jansen {
665*60a1006dSMark Jansen Provider = CONTAINING_RECORD(Entry, VERIFIER_PROVIDER, ListEntry);
666*60a1006dSMark Jansen Entry = Entry->Flink;
667*60a1006dSMark Jansen
668*60a1006dSMark Jansen Status = AVrfpLoadAndInitializeProvider(Provider);
669*60a1006dSMark Jansen if (!NT_SUCCESS(Status))
670*60a1006dSMark Jansen {
671*60a1006dSMark Jansen RemoveEntryList(&Provider->ListEntry);
672*60a1006dSMark Jansen RtlFreeHeap(RtlGetProcessHeap(), 0, Provider);
673*60a1006dSMark Jansen }
674*60a1006dSMark Jansen }
675*60a1006dSMark Jansen
676*60a1006dSMark Jansen if (!NT_SUCCESS(Status))
677*60a1006dSMark Jansen {
678*60a1006dSMark Jansen DbgPrint("AVRF: %wZ: pid 0x%X: application verifier will be disabled due to an initialization error.\n",
679*60a1006dSMark Jansen &LdrpImageEntry->BaseDllName, NtCurrentTeb()->ClientId.UniqueProcess);
680*60a1006dSMark Jansen NtCurrentPeb()->NtGlobalFlag &= ~FLG_APPLICATION_VERIFIER;
681*60a1006dSMark Jansen }
682*60a1006dSMark Jansen
683*60a1006dSMark Jansen return Status;
684*60a1006dSMark Jansen }
685*60a1006dSMark Jansen
686