STLdoc
STLdocumentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
dloadsup.h
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) 2014 Microsoft Corporation
4 
5 Module Name:
6 
7  dloadsup.h
8 
9 Abstract:
10 
11  This module implements downlevel support for read only delay load import
12  tables. (From nt source: minkernel\dload\helper\dloadsup.h)
13 
14 
15  For the non-explicitly-unloading delay load helper library :
16 
17  DLOAD_UNLOAD is not defined or is defined to 0.
18 
19  If the host OS supports delay load natively in the loader, then
20  the native loader support is invoked. Otherwise, the built-in support for
21  resolving delay load imports is invoked.
22 
23 
24  For the explicitly-unloading delay load helper library (the "VS" version) :
25 
26  DLOAD_UNLOAD is defined to 1.
27 
28  If the image load config directory marks the image as having a protected
29  delay load section, then on each delay load resolution request, the module
30  delay load protection is changed for the duration of the request (and then
31  changed back afterwards). Local support for delay loads is used so as to
32  retain compatibility with programs customizing the behavior of the delay
33  load notification hook (and the ability to perform an explicit module
34  unload).
35 
36 Author:
37 
38  Ken Johnson (kejohns) 4-Jul-2014
39 
40 Revision History:
41 
42 --*/
43 
44 #pragma once
45 
46 #ifndef _DLOAD_DLOADSUP_H
47 #define _DLOAD_DLOADSUP_H
48 
49 #pragma warning(push)
50 #pragma warning(disable:4714) // forceinline function 'YieldProcessor' not inlined
51 #pragma warning(disable:28112) // Disable Prefast warning about variables being accessed through both interlocked and non-interlocked functions
52 
53 #define DLOAD_INLINE __inline
54 
55 #define FAST_FAIL_DLOAD_PROTECTION_FAILURE 25
56 #define IMAGE_GUARD_PROTECT_DELAYLOAD_IAT 0x00001000
57 
58 #if DBG
59 
60 #define DLOAD_ASSERT(_exp) \
61  ((!(_exp)) ? \
62  (__annotation(L"Debug", L"AssertFail", L#_exp), \
63  DbgRaiseAssertionFailure(), FALSE) : \
64  TRUE)
65 
66 #else
67 
68 #define DLOAD_ASSERT(_exp) ((void) 0)
69 
70 #endif
71 
72 #if DLOAD_UNLOAD
73 
74 //++
75 //
76 // ULONG
77 // DLOAD_BYTE_OFFSET (
78 // _In_ PVOID Va,
79 // _In_ SIZE_T PageSize
80 // )
81 //
82 // Routine Description:
83 //
84 // The DLOAD_BYTE_OFFSET macro takes a virtual address and returns the byte offset
85 // of that address within the page.
86 //
87 // Arguments:
88 //
89 // Va - Virtual address.
90 //
91 // PageSize - System page size in bytes.
92 //
93 // Return Value:
94 //
95 // Returns the byte offset portion of the virtual address.
96 //
97 //--
98 
99 #define DLOAD_BYTE_OFFSET(Va, PageSize) ((ULONG)((LONG_PTR)(Va) & (PageSize - 1)))
100 
101 //++
102 //
103 // ULONG
104 // ADDRESS_AND_SIZE_TO_SPAN_PAGES (
105 // _In_ PVOID Va,
106 // _In_ ULONG Size,
107 // _In_ SIZE_T PageSize
108 // )
109 //
110 // Routine Description:
111 //
112 // The ADDRESS_AND_SIZE_TO_SPAN_PAGES macro takes a virtual address and
113 // size and returns the number of pages spanned by the size.
114 //
115 // Arguments:
116 //
117 // Va - Virtual address.
118 //
119 // Size - Size in bytes.
120 //
121 // PageSize - System page size in bytes.
122 //
123 // Return Value:
124 //
125 // Returns the number of pages spanned by the size.
126 //
127 //--
128 
129 #define DLOAD_ADDRESS_AND_SIZE_TO_SPAN_PAGES(Va,Size,PageSize) \
130  ((ULONG)((((ULONG_PTR)(Size)) / PageSize) + ((DLOAD_BYTE_OFFSET (Va, PageSize) + DLOAD_BYTE_OFFSET (Size, PageSize) + PageSize - 1) / PageSize)))
131 
132 #define SRWLOCK_UNINITIALIZED ((HMODULE)0x0)
133 #define SRWLOCK_UNSUPPORTED ((HMODULE)0x1)
134 
135 typedef ULONG_PTR SRWLOCK_TYPE;
136 
137 typedef
138 VOID
139 (NTAPI *
140 AcquireSRWLockExclusiveProc) (
141  _Inout_ _Acquires_exclusive_lock_(*SRWLock) SRWLOCK_TYPE *SRWLock
142  );
143 
144 typedef
145 VOID
146 (NTAPI *
147 ReleaseSRWLockExclusiveProc) (
148  _Inout_ _Releases_exclusive_lock_(*SRWLock) SRWLOCK_TYPE *SRWLock
149  );
150 
151 HMODULE DloadKernel32 = SRWLOCK_UNINITIALIZED;
152 AcquireSRWLockExclusiveProc DloadAcquireSRWLockExclusive;
153 ReleaseSRWLockExclusiveProc DloadReleaseSRWLockExclusive;
154 SRWLOCK_TYPE DloadSrwLock = 0x0;
155 ULONG DloadSectionLockCount;
156 DWORD DloadSectionOldProtection;
157 ULONG DloadSectionCommitPermanent;
158 
159 extern "C" IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used;
160 
161 extern "C" const IMAGE_DOS_HEADER __ImageBase;
162 
163 #else
164 
165 #define DLOAD_UNSUPPORTED ((HMODULE)0x1)
166 
167 typedef
168 PVOID
169 (NTAPI *
170 ResolveDelayLoadedAPIProc) (
171  _In_ PVOID ParentModuleBase,
172  _In_ PCIMAGE_DELAYLOAD_DESCRIPTOR DelayloadDescriptor,
173  _In_opt_ PDELAYLOAD_FAILURE_DLL_CALLBACK FailureDllHook,
174  _In_opt_ PDELAYLOAD_FAILURE_SYSTEM_ROUTINE FailureSystemHook,
175  _Out_ PIMAGE_THUNK_DATA ThunkAddress,
176  _Reserved_ ULONG Flags
177  );
178 
179 typedef
180 NTSTATUS
181 (NTAPI *
182 ResolveDelayLoadsFromDllProc) (
183  _In_ PVOID ParentBase,
185  _Reserved_ ULONG Flags
186  );
187 
189 ResolveDelayLoadedAPIProc DloadResolveDelayLoadedAPI;
190 ResolveDelayLoadsFromDllProc DloadResolveDelayLoadsFromDll;
191 
192 #endif
193 
194 //
195 // The following dload support APIs are used for the explicit-unloading version
196 // of the delay load helper.
197 //
198 
199 #if DLOAD_UNLOAD
200 
202 BOOLEAN
203 DloadGetSRWLockFunctionPointers (
204  VOID
205  )
206 
207 /*++
208 
209 Routine Description:
210 
211  This function obtains pointers to SRWLock Acquire and Release
212  functions.
213 
214 Arguments:
215 
216  None.
217 
218 Return Value:
219 
220  TRUE is returned as the function value if the host OS supports SRW locks
221  and the function pointers have been initialized.
222 
223 --*/
224 
225 {
226 
227  FARPROC FunctionPointer;
228  HMODULE Kernel32;
229  HMODULE OldValue;
230 
231  Kernel32 = (HMODULE)ReadPointerAcquire((PVOID *) &DloadKernel32);
232  if (Kernel32 == SRWLOCK_UNSUPPORTED) {
233  return FALSE;
234  }
235  if (Kernel32 != NULL) {
236  return TRUE;
237  }
238 
239  Kernel32 = GetModuleHandleW(L"KERNEL32.DLL");
240  if (Kernel32 == NULL) {
241  Kernel32 = SRWLOCK_UNSUPPORTED;
242  goto Done;
243  }
244 
245  FunctionPointer = GetProcAddress(Kernel32, "AcquireSRWLockExclusive");
246  if (FunctionPointer == NULL) {
247  Kernel32 = SRWLOCK_UNSUPPORTED;
248  goto Done;
249  }
250 
251  DloadAcquireSRWLockExclusive = (AcquireSRWLockExclusiveProc)FunctionPointer;
252  FunctionPointer = GetProcAddress(Kernel32, "ReleaseSRWLockExclusive");
253  if (FunctionPointer == NULL) {
254  Kernel32 = SRWLOCK_UNSUPPORTED;
255  goto Done;
256  }
257 
258  DloadReleaseSRWLockExclusive = (ReleaseSRWLockExclusiveProc)FunctionPointer;
259 
260 Done:
261  OldValue = (HMODULE)InterlockedCompareExchangePointer((PVOID *)&DloadKernel32,
262  (PVOID)Kernel32,
263  SRWLOCK_UNINITIALIZED);
264 
265  if (((OldValue == SRWLOCK_UNINITIALIZED) &&
266  (Kernel32 == SRWLOCK_UNSUPPORTED)) ||
267  (OldValue == SRWLOCK_UNSUPPORTED)) {
268 
269  return FALSE;
270  }
271 
272  return TRUE;
273 }
274 
275 
277 VOID
278 DloadLock (
279  VOID
280  )
281 
282 /*++
283 
284 Routine Description:
285 
286  This function obtains the delay load unload lock.
287 
288 Arguments:
289 
290  None.
291 
292 Return Value:
293 
294  None.
295 
296 --*/
297 
298 {
299  if (DloadGetSRWLockFunctionPointers() != FALSE) {
300  DloadAcquireSRWLockExclusive(&DloadSrwLock);
301  return;
302  }
303 
304  for ( ; ; ) {
305  while (ReadPointerAcquire((PVOID *)&DloadSrwLock) != 0) {
306  YieldProcessor();
307  }
308 
309  if (InterlockedCompareExchangePointer((PVOID *)&DloadSrwLock, (PVOID)1, 0) == 0) {
310  break;
311  }
312  }
313 
314  return;
315 }
316 
318 VOID
319 DloadUnlock (
320  VOID
321  )
322 
323 /*++
324 
325 Routine Description:
326 
327  This function releases the delay load unload lock.
328 
329 Arguments:
330 
331  None.
332 
333 Return Value:
334 
335  None.
336 
337 --*/
338 
339 {
340  if (DloadGetSRWLockFunctionPointers() != FALSE) {
341  DloadReleaseSRWLockExclusive(&DloadSrwLock);
342 
343  } else {
344 #pragma warning(suppress:6387) // Passing 0 is valid, but WritePointerRelease isn't annotated properly
345  WritePointerRelease((PVOID *)&DloadSrwLock, 0);
346  }
347 
348  return;
349 }
350 
351 _Success_(return != nullptr)
353 PVOID
354 DloadObtainSection (
355  _Out_ PULONG SectionSize,
356  _Out_ PULONG SectionCharacteristics
357  )
358 
359 /*++
360 
361 Routine Description:
362 
363  This function locates the delay load import table section for the current
364  module.
365 
366 Arguments:
367 
368  SectionSize - Receives the size, in bytes, of the delay load import
369  section.
370 
371  SectionCharacteristics - Receives the section characteristics.
372 
373 Return Value:
374 
375  A pointer to the delay load section base is returned, else NULL if the
376  image does not require processing.
377 
378 --*/
379 
380 {
381 
382  PIMAGE_DATA_DIRECTORY DataDir;
383  PCIMAGE_DELAYLOAD_DESCRIPTOR DloadDesc;
384  ULONG Entries;
385  PUCHAR ImageBase;
386  ULONG Index;
387  PIMAGE_NT_HEADERS NtHeaders;
388  ULONG Rva;
389  PIMAGE_SECTION_HEADER SectionHeader;
390 
391  ImageBase = (PUCHAR)&__ImageBase;
392  NtHeaders = (PIMAGE_NT_HEADERS)(ImageBase + __ImageBase.e_lfanew);
393  Entries = NtHeaders->OptionalHeader.NumberOfRvaAndSizes;
394 
395  if (IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT >= Entries) {
396  return NULL;
397  }
398 
399  DataDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT];
400  Rva = DataDir->VirtualAddress;
401  if (Rva == 0) {
402  return NULL;
403  }
404 
405  DloadDesc = (PCIMAGE_DELAYLOAD_DESCRIPTOR)(ImageBase + Rva);
406  SectionHeader = IMAGE_FIRST_SECTION(NtHeaders);
407  Rva = DloadDesc->ImportAddressTableRVA;
408  for (Index = 0;
409  Index < NtHeaders->FileHeader.NumberOfSections;
410  Index += 1, SectionHeader += 1) {
411 
412  if ((Rva >= SectionHeader->VirtualAddress) &&
413  (Rva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize)) {
414 
415  *SectionSize = SectionHeader->Misc.VirtualSize;
416  *SectionCharacteristics = SectionHeader->Characteristics;
417  return ImageBase + SectionHeader->VirtualAddress;
418  }
419  }
420 
421  return NULL;
422 }
423 
424 DECLSPEC_NOINLINE
426 VOID
427 DloadMakePermanentImageCommit (
428  _Inout_updates_ (Length) PVOID BaseAddress,
429  _In_ SIZE_T Length
430  )
431 
432 /*++
433 
434 Routine Description:
435 
436  This routine takes a set of image pages that are protected as writable
437  (i.e. which have commit precharged) and performs a dummy write to each
438  contained page so that the commit currently charged cannot be released by
439  memory management if any pages were not yet dirtied when they are
440  protected to PAGE_READONLY.
441 
442  This avoids a low resources failure path during future reprotections where
443  the region spanned will be repeatedly toggled between PAGE_READWRITE and
444  PAGE_READONLY.
445 
446  N.B. This routine is called with delay load unload lock held and returns
447  with the delay load lock held (i.e., there can be no competing call
448  to change the section protection).
449 
450 Arguments:
451 
452  BaseAddress - Supplies the base of the region of pages.
453 
454  Length - Supplies the length, in bytes, of the region.
455 
456 Return Value:
457 
458  None.
459 
460 --*/
461 
462 {
463 
464  MEMORY_BASIC_INFORMATION MemoryInfo;
465  PUCHAR Page;
466  SIZE_T PageCount;
467  SIZE_T PageSize;
468  SYSTEM_INFO SystemInfo;
469 
470  //
471  // Determine if the delay load section is already read only. If so, i.e.
472  // the loader was not enlightened to support protected delay load
473  // internally, then ensure that commit precharged for the writable section
474  // is made permanent before the section is made read only. Otherwise,
475  // future calls to VirtualProtect from PAGE_READONLY to PAGE_READWRITE
476  // could require memory management to obtain additional commit charges -
477  // which could fail in low resources conditions. In order to maintain
478  // existing contractural behaviors with delay loads it is necessary to not
479  // introduce additional low resources falure paths with protected delay
480  // load support.
481  //
482  // N.B. This call to VirtualQuery cannot fail without an invalid argument
483  // which should not be possible as all arguments are sourced from
484  // the image header which is constant data.
485  //
486 
487  if (VirtualQuery(BaseAddress, &MemoryInfo, sizeof(MemoryInfo)) == 0) {
488  DLOAD_ASSERT(FALSE);
490  }
491 
492  //
493  // If the page is not writeable then the loader has already assumed
494  // responsibility for charging commit. In this case, nothing must be done
495  // to ensure forward progress.
496  //
497 
498  if ((MemoryInfo.Protect & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE)) == 0) {
499  return;
500  }
501 
502  GetSystemInfo(&SystemInfo);
503 
504  PageSize = SystemInfo.dwPageSize;
505 
506  //
507  // The loader is not guaranteed to have charged commit. Access every page
508  // in the delay import section to make the commit already precharged
509  // "permanent", such that it cannot be revoked by memory management once
510  // the pages are transitioned from PAGE_READWRITE to PAGE_READONLY. A
511  // dummy write will dirty each page in succession so that the copy on write
512  // split happens now (which precludes memory management returning the
513  // commit charges when the pages are returned to PAGE_READONLY protection).
514  //
515 
516  PageCount = DLOAD_ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseAddress,
517  Length,
518  PageSize);
519  Page = (PUCHAR)((ULONG_PTR)BaseAddress & ~(PageSize - 1));
520 
521  while (PageCount != 0) {
522  InterlockedOr((PLONG)Page, 0);
523  Page += PageSize;
524  PageCount -= 1;
525  }
526 
527  return;
528 }
529 
531 VOID
532 DloadProtectSection (
533  _In_ ULONG Protection,
534  _Out_ PULONG OldProtection
535  )
536 
537 /*++
538 
539 Routine Description:
540 
541  This function changes the protection of the delay load section for this
542  module.
543 
544  N.B. This function is called with the dload protection lock held and
545  returns with the dload protection lock held.
546 
547 Arguments:
548 
549  Protection - Supplies the new section protection.
550 
551  OldProtection - Receives the old section protection.
552 
553 Return Value:
554 
555  None. This function does not fail.
556 
557 --*/
558 
559 {
560 
561  ULONG Characteristics;
562  PVOID Section;
563  ULONG Size;
564 
565  Section = DloadObtainSection(&Size, &Characteristics);
566 
567  if (Section == NULL) {
568  *OldProtection = PAGE_READWRITE;
569  return;
570  }
571 
572  //
573  // Ensure that commit obtained by memory management for the read/write
574  // state of the delay load import section cannot be released by a
575  // VirtualProtect to a read only protection, before the first transition to
576  // read only. This is required in order to ensure that future calls to
577  // VirtualProtect are guaranteed to support forward progress under low
578  // resources.
579  //
580 
581  if (DloadSectionCommitPermanent == 0) {
582  DloadSectionCommitPermanent = 1;
583 
584  if ((Characteristics & IMAGE_SCN_MEM_WRITE) == 0) {
585 
586  //
587  // This delay load helper module does not support merging the delay
588  // load section to a read only section because memory management
589  // would not guarantee that there is commit available - and thus a
590  // low memory failure path where the delay load failure hook could
591  // not be safely invoked (the delay load section would still be
592  // read only) might be encountered.
593  //
594  // It is a build time configuration problem to produce such a
595  // binary so abort here and now so that the problem can be
596  // identified & fixed.
597  //
598 
600  }
601 
602  DloadMakePermanentImageCommit(Section, Size);
603  }
604 
605  //
606  // Protect the delay load import section.
607  //
608  // N.B. This call cannot fail unless an argument is invalid and all
609  // arguments come from the image header.
610  //
611 
612  if (VirtualProtect(Section, Size, Protection, OldProtection) == FALSE) {
613  DLOAD_ASSERT(FALSE);
615  }
616 
617  return;
618 }
619 
621 VOID
622 DloadAcquireSectionWriteAccess (
623  VOID
624  )
625 
626 /*++
627 
628 Routine Description:
629 
630  This function obtains write access to the delay load section. Until a
631  matched call to DloadReleaseSectionAccess is made the section is still
632  considered writeable.
633 
634 Arguments:
635 
636  None.
637 
638 Return Value:
639 
640  None.
641 
642 --*/
643 
644 {
645 
646  //
647  // If protected delay load is not in use, there is nothing to do.
648  //
649 
650  if ((_load_config_used.GuardFlags & IMAGE_GUARD_PROTECT_DELAYLOAD_IAT) == 0) {
651  return;
652  }
653 
654  //
655  // Acquire the Dload protection lock for this module and change protection.
656  //
657 
658  DloadLock();
659 
660  DloadSectionLockCount += 1;
661  if (DloadSectionLockCount == 1) {
662  DloadProtectSection(PAGE_READWRITE, &DloadSectionOldProtection);
663  }
664 
665  DloadUnlock();
666 
667  return;
668 }
669 
671 VOID
672 DloadReleaseSectionWriteAccess (
673  VOID
674  )
675 
676 /*++
677 
678 Routine Description:
679 
680  This function relinquishes write access to the delay load section.
681 
682 Arguments:
683 
684  None.
685 
686 Return Value:
687 
688  None.
689 
690 --*/
691 
692 {
693 
694  ULONG OldProtect;
695 
696  //
697  // If protected delay load is not in use, there is nothing to do.
698  //
699 
700  if ((_load_config_used.GuardFlags & IMAGE_GUARD_PROTECT_DELAYLOAD_IAT) == 0) {
701  return;
702  }
703 
704  //
705  // Acquire the Dload protection lock for this module and change protection.
706  //
707 
708  DloadLock();
709 
710  DloadSectionLockCount -= 1;
711  if (DloadSectionLockCount == 0) {
712  DloadProtectSection(DloadSectionOldProtection, &OldProtect);
713  }
714 
715  DloadUnlock();
716 
717  return;
718 }
719 
720 #else
721 
722 //
723 // The following dload support APIs are used for the non-explicit-unloading
724 // version of the delay load helper.
725 //
726 
728 BOOLEAN
730  VOID
731  )
732 
733 /*++
734 
735 Routine Description:
736 
737  This function resolves support for native loader-based delay load handling.
738 
739 Arguments:
740 
741  None.
742 
743 Return Value:
744 
745  TRUE is returned as the function value if the host OS supports delay load
746  in the loader (in which case all linkage to the host OS native support has
747  been initialized).
748 
749 --*/
750 
751 {
752 
753  HMODULE Kernel32;
754 
755  Kernel32 = (HMODULE)ReadPointerAcquire((PVOID *) &DloadKernel32);
756  if (Kernel32 == DLOAD_UNSUPPORTED) {
757  return FALSE;
758  }
759  if (Kernel32 != NULL) {
760  return TRUE;
761  }
762 
763  Kernel32 = GetModuleHandleW(L"api-ms-win-core-delayload-l1-1-1.dll");
764  if (Kernel32 == NULL) {
765  Kernel32 = GetModuleHandleW(L"KERNEL32.DLL");
766  if (Kernel32 == NULL) {
767  Kernel32 = DLOAD_UNSUPPORTED;
768  goto Done;
769  }
770  }
771 
772  DloadResolveDelayLoadedAPI =
773  (ResolveDelayLoadedAPIProc)GetProcAddress(Kernel32,
774  "ResolveDelayLoadedAPI");
775 
776  if (DloadResolveDelayLoadedAPI == NULL) {
777  Kernel32 = DLOAD_UNSUPPORTED;
778  goto Done;
779  }
780 
781  DloadResolveDelayLoadsFromDll =
782  (ResolveDelayLoadsFromDllProc)GetProcAddress(Kernel32,
783  "ResolveDelayLoadsFromDll");
784 
785  if (DloadResolveDelayLoadsFromDll == NULL) {
786  Kernel32 = DLOAD_UNSUPPORTED;
787  goto Done;
788  }
789 
790 Done:
791  WritePointerRelease((PVOID *)&DloadKernel32, Kernel32);
792  return (Kernel32 != DLOAD_UNSUPPORTED);
793 }
794 
796 PVOID
797 WINAPI
799  _In_ PCIMAGE_DELAYLOAD_DESCRIPTOR DelayloadDescriptor,
800  _Out_ PIMAGE_THUNK_DATA ThunkAddress,
801  _Out_ PBOOLEAN NativeHandled
802  )
803 
804 /*++
805 
806 Routine Description:
807 
808  This function is a thin wrapper around the loader functionality in ntdll to
809  resolve a particular delayload thunk from a delayload descriptor.
810 
811 Arguments:
812 
813  DelayloadDescriptor - Supplies a pointer to a structure that describes the
814  module to be loaded in order to satisfy the delayed load.
815 
816  ThunkAddress - Supplies a pointer to the thunk to be filled in with the
817  appropriate target function. This thunk pointer is used to find
818  the specific name table entry of the function to be imported.
819 
820  NativeHandled - Receives TRUE if the implementation was handled by the
821  native loader, else FALSE if it was not handled by the
822  native loader and the caller must satisfy the request.
823 
824 Return Value:
825 
826  Address of the import, or the failure stub for it.
827 
828 --*/
829 
830 {
831 
832  PVOID Symbol;
833 
834  if (DloadResolve() == FALSE) {
835  *NativeHandled = FALSE;
836  return NULL;
837  }
838 
839  *NativeHandled = TRUE;
840 
841  Symbol = DloadResolveDelayLoadedAPI((PVOID)&__ImageBase,
842  DelayloadDescriptor,
843  (PDELAYLOAD_FAILURE_DLL_CALLBACK)__pfnDliFailureHook2,
844  DelayLoadFailureHook,
845  ThunkAddress,
846  0);
847 
848  return Symbol;
849 }
850 
852 HRESULT
853 WINAPI
855  _In_ LPCSTR DllName,
856  _Out_ PBOOLEAN NativeHandled
857  )
858 
859 /*++
860 
861 Routine Description:
862 
863  This function is a thin wrapper around the loader functionality in ntdll to
864  resolve all delayload thunks in the current binary from a target
865  module.
866 
867 Arguments:
868 
869  DllName - Supplies the case-insensitive name of the delayloaded target
870  module whose imports are to be resolved.
871 
872  NativeHandled - Receives TRUE if the implementation was handled by the
873  native loader, else FALSE if it was not handled by the
874  native loader and the caller must satisfy the request.
875 
876 Return Value:
877 
878  HRESULT
879 
880 --*/
881 
882 {
883 
884  NTSTATUS Status;
885 
886  if (DloadResolve() == FALSE) {
887  *NativeHandled = FALSE;
888  return HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND);
889  }
890 
891  *NativeHandled = TRUE;
892 
893  Status = DloadResolveDelayLoadsFromDll((PVOID)&__ImageBase,
894  DllName,
895  0);
896 
897  if (Status == STATUS_DLL_NOT_FOUND) {
898  return HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND);
899 
900  } else {
901  return S_OK;
902  }
903 }
904 
905 #endif
906 
907 #pragma warning(pop)
908 
909 #endif
910 
#define _Out_
Definition: sal.h:342
#define FAST_FAIL_DLOAD_PROTECTION_FAILURE
Definition: dloadsup.h:55
#define NULL
Definition: vcruntime.h:236
#define S_OK
Definition: comutil.h:62
_In_ PCIMAGE_DELAYLOAD_DESCRIPTOR _In_opt_ PDELAYLOAD_FAILURE_DLL_CALLBACK _In_opt_ PDELAYLOAD_FAILURE_SYSTEM_ROUTINE _Out_ PIMAGE_THUNK_DATA _Reserved_ ULONG Flags
Definition: dloadsup.h:172
#define _Inout_updates_(size)
Definition: sal.h:384
typedef NTSTATUS(NTAPI *ResolveDelayLoadsFromDllProc)(_In_ PVOID ParentBase
#define DLOAD_ASSERT(_exp)
Definition: dloadsup.h:68
_In_ PCIMAGE_DELAYLOAD_DESCRIPTOR _In_opt_ PDELAYLOAD_FAILURE_DLL_CALLBACK _In_opt_ PDELAYLOAD_FAILURE_SYSTEM_ROUTINE FailureSystemHook
Definition: dloadsup.h:172
DLOAD_INLINE BOOLEAN DloadResolve(VOID)
Definition: dloadsup.h:729
typedef PVOID(NTAPI *ResolveDelayLoadedAPIProc)(_In_ PVOID ParentModuleBase
#define _Releases_exclusive_lock_(lock)
Definition: ConcurrencySal.h:282
DLOAD_INLINE HRESULT WINAPI Dload__HrLoadAllImportsForDll(_In_ LPCSTR DllName, _Out_ PBOOLEAN NativeHandled)
Definition: dloadsup.h:854
#define _In_
Definition: sal.h:305
#define _In_opt_
Definition: sal.h:306
#define IMAGE_GUARD_PROTECT_DELAYLOAD_IAT
Definition: dloadsup.h:56
#define DLOAD_INLINE
Definition: dloadsup.h:53
ResolveDelayLoadedAPIProc DloadResolveDelayLoadedAPI
Definition: dloadsup.h:189
_In_ PCIMAGE_DELAYLOAD_DESCRIPTOR _In_opt_ PDELAYLOAD_FAILURE_DLL_CALLBACK _In_opt_ PDELAYLOAD_FAILURE_SYSTEM_ROUTINE _Out_ PIMAGE_THUNK_DATA ThunkAddress
Definition: dloadsup.h:172
#define DLOAD_UNSUPPORTED
Definition: dloadsup.h:165
unsigned long DWORD
Definition: concrt.h:63
_In_ PCIMAGE_DELAYLOAD_DESCRIPTOR _In_opt_ PDELAYLOAD_FAILURE_DLL_CALLBACK FailureDllHook
Definition: dloadsup.h:172
ResolveDelayLoadsFromDllProc DloadResolveDelayLoadsFromDll
Definition: dloadsup.h:190
const IMAGE_DOS_HEADER __ImageBase
Definition: delayhlp.cpp:95
_In_ PCIMAGE_DELAYLOAD_DESCRIPTOR DelayloadDescriptor
Definition: dloadsup.h:172
ExternC const PfnDliHook __pfnDliFailureHook2
Definition: delayimp.h:141
#define _Acquires_exclusive_lock_(lock)
Definition: ConcurrencySal.h:279
DLOAD_INLINE PVOID WINAPI Dload__delayLoadHelper2(_In_ PCIMAGE_DELAYLOAD_DESCRIPTOR DelayloadDescriptor, _Out_ PIMAGE_THUNK_DATA ThunkAddress, _Out_ PBOOLEAN NativeHandled)
Definition: dloadsup.h:798
#define _Inout_
Definition: sal.h:375
#define _Success_(expr)
Definition: sal.h:256
#define _Reserved_
Definition: sal.h:292
_In_ LPCSTR TargetDllName
Definition: dloadsup.h:184
HMODULE DloadKernel32
Definition: dloadsup.h:188