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