xref: /reactos/dll/ntdll/ldr/verifier.c (revision 60a1006d)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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