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)
11 #include <reactos/verifier.h>
16 extern PLDR_DATA_TABLE_ENTRY LdrpImageEntry
;
17 ULONG AVrfpVerifierFlags
= 0;
18 WCHAR AVrfpVerifierDllsString
[256] = { 0 };
20 BOOL AVrfpInitialized
= FALSE
;
21 RTL_CRITICAL_SECTION AVrfpVerifierLock
;
22 LIST_ENTRY AVrfpVerifierProvidersList
;
24 #define VERIFIER_DLL_FLAGS_RESOLVED 1
27 typedef struct _VERIFIER_PROVIDER
30 UNICODE_STRING DllName
;
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
;
46 AVrfReadIFEO(HANDLE KeyHandle
)
50 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
53 AVrfpVerifierDllsString
,
54 sizeof(AVrfpVerifierDllsString
) - sizeof(WCHAR
),
57 if (!NT_SUCCESS(Status
))
58 AVrfpVerifierDllsString
[0] = UNICODE_NULL
;
60 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
64 sizeof(AVrfpVerifierFlags
),
66 if (!NT_SUCCESS(Status
))
67 AVrfpVerifierFlags
= RTL_VRF_FLG_HANDLE_CHECKS
| RTL_VRF_FLG_FAST_FILL_HEAP
| RTL_VRF_FLG_LOCK_CHECKS
;
69 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
75 if (!NT_SUCCESS(Status
))
82 LdrpInitializeApplicationVerifierPackage(HANDLE KeyHandle
, PPEB Peb
, BOOLEAN SystemWide
, BOOLEAN ReadAdvancedOptions
)
84 /* If global flags request DPH, perform some additional actions */
85 if (Peb
->NtGlobalFlag
& FLG_HEAP_PAGE_ALLOCS
)
87 // TODO: Read advanced DPH flags from the registry if requested
88 if (ReadAdvancedOptions
)
93 /* Enable page heap */
94 RtlpPageHeapEnabled
= TRUE
;
97 AVrfReadIFEO(KeyHandle
);
99 return STATUS_SUCCESS
;
103 AVrfpIsVerifierProviderDll(PVOID BaseAddress
)
106 PVERIFIER_PROVIDER Provider
;
108 for (Entry
= AVrfpVerifierProvidersList
.Flink
; Entry
!= &AVrfpVerifierProvidersList
; Entry
= Entry
->Flink
)
110 Provider
= CONTAINING_RECORD(Entry
, VERIFIER_PROVIDER
, ListEntry
);
112 if (BaseAddress
== Provider
->BaseAddress
)
120 AVrfpCountThunks(PIMAGE_THUNK_DATA Thunk
)
123 while (Thunk
[Count
].u1
.Function
)
129 AVrfpSnapDllImports(IN PLDR_DATA_TABLE_ENTRY LdrEntry
)
132 PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor
;
133 PBYTE DllBase
= LdrEntry
->DllBase
;
135 ImportDescriptor
= RtlImageDirectoryEntryToData(DllBase
, TRUE
, IMAGE_DIRECTORY_ENTRY_IMPORT
, &Size
);
136 if (!ImportDescriptor
)
138 //SHIMENG_INFO("Skipping module 0x%p \"%wZ\" due to no iat found\n", LdrEntry->DllBase, &LdrEntry->BaseDllName);
142 for (; ImportDescriptor
->Name
&& ImportDescriptor
->OriginalFirstThunk
; ImportDescriptor
++)
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
);
150 /* Walk all imports */
151 for (;FirstThunk
->u1
.Function
; FirstThunk
++)
154 PVERIFIER_PROVIDER Provider
;
156 for (Entry
= AVrfpVerifierProvidersList
.Flink
; Entry
!= &AVrfpVerifierProvidersList
; Entry
= Entry
->Flink
)
158 PRTL_VERIFIER_DLL_DESCRIPTOR DllDescriptor
;
160 Provider
= CONTAINING_RECORD(Entry
, VERIFIER_PROVIDER
, ListEntry
);
161 for (DllDescriptor
= Provider
->ProviderDlls
; DllDescriptor
&& DllDescriptor
->DllName
; ++DllDescriptor
)
163 PRTL_VERIFIER_THUNK_DESCRIPTOR ThunkDescriptor
;
165 for (ThunkDescriptor
= DllDescriptor
->DllThunks
; ThunkDescriptor
&& ThunkDescriptor
->ThunkName
; ++ThunkDescriptor
)
167 /* Just compare function addresses, the loader will have handled forwarders and ordinals for us */
168 if ((PVOID
)FirstThunk
->u1
.Function
!= ThunkDescriptor
->ThunkOldAddress
)
173 PVOID Ptr
= &FirstThunk
->u1
.Function
;
174 SIZE_T Size
= sizeof(FirstThunk
->u1
.Function
) * AVrfpCountThunks(FirstThunk
);
177 UnprotectedPtr
= Ptr
;
178 UnprotectedSize
= Size
;
180 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
183 PAGE_EXECUTE_READWRITE
,
186 if (!NT_SUCCESS(Status
))
188 DbgPrint("AVRF: Unable to unprotect IAT to modify thunks (status %08X).\n", Status
);
189 UnprotectedPtr
= NULL
;
194 if (ThunkDescriptor
->ThunkNewAddress
== NULL
)
196 DbgPrint("AVRF: internal error: New thunk for %s is null.\n", ThunkDescriptor
->ThunkName
);
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
,
205 ThunkDescriptor
->ThunkNewAddress
);
213 PVOID Ptr
= UnprotectedPtr
;
214 SIZE_T Size
= UnprotectedSize
;
217 UnprotectedPtr
= Ptr
;
218 UnprotectedSize
= Size
;
220 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
225 if (!NT_SUCCESS(Status
))
227 DbgPrint("AVRF: Unable to reprotect IAT to modify thunks (status %08X).\n", Status
);
235 AvrfpResolveThunks(IN PLDR_DATA_TABLE_ENTRY LdrEntry
)
238 PVERIFIER_PROVIDER Provider
;
240 if (!AVrfpInitialized
)
243 for (Entry
= AVrfpVerifierProvidersList
.Flink
; Entry
!= &AVrfpVerifierProvidersList
; Entry
= Entry
->Flink
)
245 PRTL_VERIFIER_DLL_DESCRIPTOR DllDescriptor
;
247 Provider
= CONTAINING_RECORD(Entry
, VERIFIER_PROVIDER
, ListEntry
);
249 for (DllDescriptor
= Provider
->ProviderDlls
; DllDescriptor
&& DllDescriptor
->DllName
; ++DllDescriptor
)
251 PRTL_VERIFIER_THUNK_DESCRIPTOR ThunkDescriptor
;
253 if ((DllDescriptor
->DllFlags
& VERIFIER_DLL_FLAGS_RESOLVED
) ||
254 _wcsicmp(DllDescriptor
->DllName
, LdrEntry
->BaseDllName
.Buffer
))
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
);
262 for (ThunkDescriptor
= DllDescriptor
->DllThunks
; ThunkDescriptor
&& ThunkDescriptor
->ThunkName
; ++ThunkDescriptor
)
264 if (!ThunkDescriptor
->ThunkOldAddress
)
266 ANSI_STRING ThunkName
;
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
)))
272 if (AVrfpDebug
& RTL_VRF_DBG_SHOWFOUNDEXPORTS
)
273 DbgPrint("AVRF: (%wZ) %Z export found.\n", &LdrEntry
->BaseDllName
, &ThunkName
);
277 if (AVrfpDebug
& RTL_VRF_DBG_SHOWFOUNDEXPORTS
)
278 DbgPrint("AVRF: warning: did not find `%Z' export in %wZ.\n", &ThunkName
, &LdrEntry
->BaseDllName
);
283 DllDescriptor
->DllFlags
|= VERIFIER_DLL_FLAGS_RESOLVED
;
287 AVrfpSnapDllImports(LdrEntry
);
294 AVrfDllLoadNotification(IN PLDR_DATA_TABLE_ENTRY LdrEntry
)
298 if (!(NtCurrentPeb()->NtGlobalFlag
& FLG_APPLICATION_VERIFIER
))
301 RtlEnterCriticalSection(&AVrfpVerifierLock
);
302 if (!AVrfpIsVerifierProviderDll(LdrEntry
->DllBase
))
304 AvrfpResolveThunks(LdrEntry
);
306 for (Entry
= AVrfpVerifierProvidersList
.Flink
; Entry
!= &AVrfpVerifierProvidersList
; Entry
= Entry
->Flink
)
308 PVERIFIER_PROVIDER Provider
;
309 RTL_VERIFIER_DLL_LOAD_CALLBACK ProviderDllLoadCallback
;
311 Provider
= CONTAINING_RECORD(Entry
, VERIFIER_PROVIDER
, ListEntry
);
313 ProviderDllLoadCallback
= Provider
->ProviderDllLoadCallback
;
314 if (ProviderDllLoadCallback
)
316 ProviderDllLoadCallback(LdrEntry
->BaseDllName
.Buffer
,
318 LdrEntry
->SizeOfImage
,
323 RtlLeaveCriticalSection(&AVrfpVerifierLock
);
328 AVrfDllUnloadNotification(IN PLDR_DATA_TABLE_ENTRY LdrEntry
)
332 if (!(NtCurrentPeb()->NtGlobalFlag
& FLG_APPLICATION_VERIFIER
))
335 RtlEnterCriticalSection(&AVrfpVerifierLock
);
336 if (!AVrfpIsVerifierProviderDll(LdrEntry
->DllBase
))
338 for (Entry
= AVrfpVerifierProvidersList
.Flink
; Entry
!= &AVrfpVerifierProvidersList
; Entry
= Entry
->Flink
)
340 PVERIFIER_PROVIDER Provider
;
341 RTL_VERIFIER_DLL_UNLOAD_CALLBACK ProviderDllUnloadCallback
;
343 Provider
= CONTAINING_RECORD(Entry
, VERIFIER_PROVIDER
, ListEntry
);
345 ProviderDllUnloadCallback
= Provider
->ProviderDllUnloadCallback
;
346 if (ProviderDllUnloadCallback
)
348 ProviderDllUnloadCallback(LdrEntry
->BaseDllName
.Buffer
,
350 LdrEntry
->SizeOfImage
,
355 RtlLeaveCriticalSection(&AVrfpVerifierLock
);
361 AVrfPageHeapDllNotification(IN PLDR_DATA_TABLE_ENTRY LdrEntry
)
363 /* Check if page heap dll notification is turned on */
364 if (!(RtlpDphGlobalFlags
& DPH_FLAG_DLL_NOTIFY
))
367 /* We don't support this flag currently */
374 AVrfpResnapInitialModules(VOID
)
376 PLIST_ENTRY ListHead
, ListEntry
;
378 ListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
379 for (ListEntry
= ListHead
->Flink
; ListHead
!= ListEntry
; ListEntry
= ListEntry
->Flink
)
381 PLDR_DATA_TABLE_ENTRY LdrEntry
;
383 LdrEntry
= CONTAINING_RECORD(ListEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
385 if (AVrfpIsVerifierProviderDll(LdrEntry
->DllBase
))
387 if (AVrfpDebug
& RTL_VRF_DBG_SHOWSNAPS
)
388 DbgPrint("AVRF: skipped resnapping provider %wZ ...\n", &LdrEntry
->BaseDllName
);
392 if (AVrfpDebug
& RTL_VRF_DBG_SHOWSNAPS
)
393 DbgPrint("AVRF: resnapping %wZ ...\n", &LdrEntry
->BaseDllName
);
395 AvrfpResolveThunks(LdrEntry
);
402 AvrfpFindDuplicateThunk(PLIST_ENTRY EndEntry
, PWCHAR DllName
, PCHAR ThunkName
)
406 for (Entry
= AVrfpVerifierProvidersList
.Flink
; Entry
!= EndEntry
; Entry
= Entry
->Flink
)
408 PVERIFIER_PROVIDER Provider
;
409 PRTL_VERIFIER_DLL_DESCRIPTOR DllDescriptor
;
411 Provider
= CONTAINING_RECORD(Entry
, VERIFIER_PROVIDER
, ListEntry
);
413 if (AVrfpDebug
& RTL_VRF_DBG_SHOWCHAINING_DEBUG
)
414 DbgPrint("AVRF: chain: searching in %wZ\n", &Provider
->DllName
);
416 for (DllDescriptor
= Provider
->ProviderDlls
; DllDescriptor
&& DllDescriptor
->DllName
; ++DllDescriptor
)
418 PRTL_VERIFIER_THUNK_DESCRIPTOR ThunkDescriptor
;
420 if (AVrfpDebug
& RTL_VRF_DBG_SHOWCHAINING_DEBUG
)
421 DbgPrint("AVRF: chain: dll: %ws\n", DllDescriptor
->DllName
);
423 if (_wcsicmp(DllDescriptor
->DllName
, DllName
))
426 for (ThunkDescriptor
= DllDescriptor
->DllThunks
; ThunkDescriptor
&& ThunkDescriptor
->ThunkName
; ++ThunkDescriptor
)
428 if (AVrfpDebug
& RTL_VRF_DBG_SHOWCHAINING_DEBUG
)
429 DbgPrint("AVRF: chain: thunk: %s == %s ?\n", ThunkDescriptor
->ThunkName
, ThunkName
);
431 if (!_stricmp(ThunkDescriptor
->ThunkName
, ThunkName
))
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
);
437 return ThunkDescriptor
->ThunkNewAddress
;
448 AVrfpChainDuplicateThunks(VOID
)
451 PVERIFIER_PROVIDER Provider
;
453 for (Entry
= AVrfpVerifierProvidersList
.Flink
; Entry
!= &AVrfpVerifierProvidersList
; Entry
= Entry
->Flink
)
455 PRTL_VERIFIER_DLL_DESCRIPTOR DllDescriptor
;
456 PRTL_VERIFIER_THUNK_DESCRIPTOR ThunkDescriptor
;
458 Provider
= CONTAINING_RECORD(Entry
, VERIFIER_PROVIDER
, ListEntry
);
460 for (DllDescriptor
= Provider
->ProviderDlls
; DllDescriptor
&& DllDescriptor
->DllName
; ++DllDescriptor
)
462 for (ThunkDescriptor
= DllDescriptor
->DllThunks
; ThunkDescriptor
&& ThunkDescriptor
->ThunkName
; ++ThunkDescriptor
)
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
);
470 Ptr
= AvrfpFindDuplicateThunk(Entry
, DllDescriptor
->DllName
, ThunkDescriptor
->ThunkName
);
473 if (AVrfpDebug
& RTL_VRF_DBG_SHOWCHAINING
)
474 DbgPrint("AVRF: Chaining (%ws: %s) to %wZ\n", DllDescriptor
->DllName
, ThunkDescriptor
->ThunkName
, &Provider
->DllName
);
476 ThunkDescriptor
->ThunkOldAddress
= Ptr
;
485 AVrfpLoadAndInitializeProvider(PVERIFIER_PROVIDER Provider
)
487 WCHAR StringBuffer
[MAX_PATH
+ 11];
488 UNICODE_STRING DllPath
;
489 PRTL_VERIFIER_PROVIDER_DESCRIPTOR Descriptor
;
490 PIMAGE_NT_HEADERS ImageNtHeader
;
493 RtlInitEmptyUnicodeString(&DllPath
, StringBuffer
, sizeof(StringBuffer
));
494 RtlAppendUnicodeToString(&DllPath
, SharedUserData
->NtSystemRoot
);
495 RtlAppendUnicodeToString(&DllPath
, L
"\\System32\\");
497 if (AVrfpDebug
& RTL_VRF_DBG_SHOWSNAPS
)
498 DbgPrint("AVRF: verifier dll `%wZ'\n", &Provider
->DllName
);
500 Status
= LdrLoadDll(DllPath
.Buffer
, NULL
, &Provider
->DllName
, &Provider
->BaseAddress
);
501 if (!NT_SUCCESS(Status
))
503 DbgPrint("AVRF: %wZ: failed to load provider `%wZ' (status %08X) from %wZ\n",
504 &LdrpImageEntry
->BaseDllName
,
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
))
516 DbgPrint("AVRF: provider %wZ is not a DLL image\n", &Provider
->DllName
);
517 return STATUS_DLL_INIT_FAILED
;
520 Provider
->EntryPoint
= LdrpFetchAddressOfEntryPoint(Provider
->BaseAddress
);
521 if (!Provider
->EntryPoint
)
523 DbgPrint("AVRF: cannot find an entry point for provider %wZ\n", &Provider
->DllName
);
524 return STATUS_PROCEDURE_NOT_FOUND
;
529 if (LdrpCallInitRoutine(Provider
->EntryPoint
,
530 Provider
->BaseAddress
,
531 DLL_PROCESS_VERIFIER
,
534 if (Descriptor
&& Descriptor
->Length
== sizeof(RTL_VERIFIER_PROVIDER_DESCRIPTOR
))
537 Provider
->ProviderDlls
= Descriptor
->ProviderDlls
;
538 Provider
->ProviderDllLoadCallback
= Descriptor
->ProviderDllLoadCallback
;
539 Provider
->ProviderDllUnloadCallback
= Descriptor
->ProviderDllUnloadCallback
;
540 Provider
->ProviderNtdllHeapFreeCallback
= Descriptor
->ProviderNtdllHeapFreeCallback
;
542 /* Update some info for the provider */
543 Descriptor
->VerifierImage
= LdrpImageEntry
->BaseDllName
.Buffer
;
544 Descriptor
->VerifierFlags
= AVrfpVerifierFlags
;
545 Descriptor
->VerifierDebug
= AVrfpDebug
;
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
;
558 DbgPrint("AVRF: provider %wZ passed an invalid descriptor @ %p\n", &Provider
->DllName
, Descriptor
);
559 Status
= STATUS_INVALID_PARAMETER_4
;
564 DbgPrint("AVRF: provider %wZ did not initialize correctly\n", &Provider
->DllName
);
565 Status
= STATUS_DLL_INIT_FAILED
;
568 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
570 Status
= _SEH2_GetExceptionCode();
574 if (!NT_SUCCESS(Status
))
578 if (AVrfpDebug
& RTL_VRF_DBG_LISTPROVIDERS
)
579 DbgPrint("AVRF: initialized provider %wZ (descriptor @ %p)\n", &Provider
->DllName
, Descriptor
);
581 /* Done loading providers, allow dll notifications */
582 AVrfpInitialized
= TRUE
;
584 AVrfpChainDuplicateThunks();
585 AVrfpResnapInitialModules();
587 /* Manually call with DLL_PROCESS_ATTACH, since the process is not done initializing */
590 if (!LdrpCallInitRoutine(Provider
->EntryPoint
,
591 Provider
->BaseAddress
,
595 DbgPrint("AVRF: provider %wZ did not initialize correctly\n", &Provider
->DllName
);
596 Status
= STATUS_DLL_INIT_FAILED
;
600 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
602 Status
= _SEH2_GetExceptionCode();
612 AVrfInitializeVerifier(VOID
)
615 PVERIFIER_PROVIDER Provider
;
619 Status
= RtlInitializeCriticalSection(&AVrfpVerifierLock
);
620 InitializeListHead(&AVrfpVerifierProvidersList
);
622 if (!NT_SUCCESS(Status
))
625 DbgPrint("AVRF: %wZ: pid 0x%X: flags 0x%X: application verifier enabled\n",
626 &LdrpImageEntry
->BaseDllName
, NtCurrentTeb()->ClientId
.UniqueProcess
, AVrfpVerifierFlags
);
628 Provider
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(VERIFIER_PROVIDER
));
630 return STATUS_NO_MEMORY
;
632 RtlInitUnicodeString(&Provider
->DllName
, L
"verifier.dll");
633 InsertTailList(&AVrfpVerifierProvidersList
, &Provider
->ListEntry
);
635 Next
= AVrfpVerifierDllsString
;
639 while (*Next
== L
' ' || *Next
== L
'\t')
644 while (*Next
!= ' ' && *Next
!= '\t' && *Next
)
654 Provider
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(VERIFIER_PROVIDER
));
656 return STATUS_NO_MEMORY
;
657 RtlInitUnicodeString(&Provider
->DllName
, Ptr
);
658 InsertTailList(&AVrfpVerifierProvidersList
, &Provider
->ListEntry
);
662 Entry
= AVrfpVerifierProvidersList
.Flink
;
663 while (Entry
!= &AVrfpVerifierProvidersList
)
665 Provider
= CONTAINING_RECORD(Entry
, VERIFIER_PROVIDER
, ListEntry
);
666 Entry
= Entry
->Flink
;
668 Status
= AVrfpLoadAndInitializeProvider(Provider
);
669 if (!NT_SUCCESS(Status
))
671 RemoveEntryList(&Provider
->ListEntry
);
672 RtlFreeHeap(RtlGetProcessHeap(), 0, Provider
);
676 if (!NT_SUCCESS(Status
))
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
;