[LDR] Don't dereference a possible nullptr on a malformed forwarded import
[reactos.git] / dll / ntdll / ldr / verifier.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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