ReactOS 0.4.16-dev-974-g5022a45
ldrutils.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NT User-Mode Library
4 * FILE: dll/ntdll/ldr/ldrutils.c
5 * PURPOSE: Internal Loader Utility Functions
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * Aleksey Bragin (aleksey@reactos.org)
8 */
9
10/* INCLUDES *****************************************************************/
11
12#include <ntdll.h>
13
14#define NDEBUG
15#include <debug.h>
16
17/* GLOBALS *******************************************************************/
18
20
28
29/* FUNCTIONS *****************************************************************/
30
35{
36 /* Sanity checks */
39
40 /* Assume failure */
41 StringOut->Length = 0;
42
43 /* Make sure it's not mis-aligned */
44 if (Length & 1)
45 {
46 /* Fail */
47 StringOut->Buffer = NULL;
48 StringOut->MaximumLength = 0;
50 }
51
52 /* Allocate the string*/
54 0,
55 Length + sizeof(WCHAR));
56 if (!StringOut->Buffer)
57 {
58 /* Fail */
59 StringOut->MaximumLength = 0;
60 return STATUS_NO_MEMORY;
61 }
62
63 /* Null-terminate it */
64 StringOut->Buffer[Length / sizeof(WCHAR)] = UNICODE_NULL;
65
66 /* Check if this is a maximum-sized string */
68 {
69 /* It's not, so set the maximum length to be one char more */
70 StringOut->MaximumLength = (USHORT)Length + sizeof(UNICODE_NULL);
71 }
72 else
73 {
74 /* The length is already the maximum possible */
75 StringOut->MaximumLength = UNICODE_STRING_MAX_BYTES;
76 }
77
78 /* Return success */
79 return STATUS_SUCCESS;
80}
81
82VOID
85{
86 ASSERT(StringIn != NULL);
87
88 /* If Buffer is not NULL - free it */
89 if (StringIn->Buffer)
90 {
91 RtlFreeHeap(LdrpHeap, 0, StringIn->Buffer);
92 }
93
94 /* Zero it out */
95 RtlInitEmptyUnicodeString(StringIn, NULL, 0);
96}
97
104{
105 /* Call the entry */
106 return EntryPoint(BaseAddress, Reason, Context);
107}
108
109/* NOTE: This function is broken */
110VOID
111NTAPI
113 IN ULONG Flags,
114 OUT PUNICODE_STRING UpdateString)
115{
116 PIMAGE_BOUND_FORWARDER_REF NewImportForwarder;
119 PIMAGE_IMPORT_DESCRIPTOR ImportEntry;
120 PIMAGE_THUNK_DATA FirstThunk;
122 PUNICODE_STRING ImportNameUnic, RedirectedImportName;
123 ANSI_STRING ImportNameAnsi;
124 LPSTR ImportName;
125 ULONG ImportSize;
127 ULONG i;
128 BOOLEAN RedirectedDll;
129 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
130
131 /* Set up the Act Ctx */
132 ActCtx.Size = sizeof(ActCtx);
135
136 /* Activate the ActCtx */
137 RtlActivateActivationContextUnsafeFast(&ActCtx,
138 LdrEntry->EntryPointActivationContext);
139
140 /* Check the action we need to perform */
142 {
143 /* Make sure entry is not being loaded already */
144 if (LdrEntry->Flags & LDRP_LOAD_IN_PROGRESS)
145 goto done;
146
147 LdrEntry->Flags |= LDRP_LOAD_IN_PROGRESS;
148 }
149 else if (Flags == LDRP_UPDATE_DEREFCOUNT)
150 {
151 /* Make sure the entry is not being unloaded already */
152 if (LdrEntry->Flags & LDRP_UNLOAD_IN_PROGRESS)
153 goto done;
154
155 LdrEntry->Flags |= LDRP_UNLOAD_IN_PROGRESS;
156 }
157
158 /* Go through all bound DLLs and dereference them */
159 ImportNameUnic = &NtCurrentTeb()->StaticUnicodeString;
160
161 /* Try to get the new import entry */
162 FirstEntry = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
163 TRUE,
165 &ImportSize);
166
167 if (FirstEntry)
168 {
169 /* Set entry flags if refing/derefing */
171 LdrEntry->Flags |= LDRP_LOAD_IN_PROGRESS;
172 else if (Flags == LDRP_UPDATE_DEREFCOUNT)
173 LdrEntry->Flags |= LDRP_UNLOAD_IN_PROGRESS;
174
175 BoundEntry = FirstEntry;
176 while (BoundEntry->OffsetModuleName)
177 {
178 /* Get pointer to the current import name */
179 ImportName = (LPSTR)FirstEntry + BoundEntry->OffsetModuleName;
180
181 RtlInitAnsiString(&ImportNameAnsi, ImportName);
182 Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE);
183
184 if (NT_SUCCESS(Status))
185 {
186 RedirectedDll = FALSE;
187 RedirectedImportName = ImportNameUnic;
188
189 /* Check if the SxS Assemblies specify another file */
191 ImportNameUnic, &LdrApiDefaultExtension, UpdateString, NULL, &RedirectedImportName,
192 &RedirectedDll);
193
194 /* Check success */
195 if (NT_SUCCESS(Status) && RedirectedDll)
196 {
197 if (ShowSnaps)
198 {
199 DPRINT1("LDR: %Z got redirected to %wZ\n", &ImportNameAnsi, RedirectedImportName);
200 }
201 }
202
203 if (NT_SUCCESS(Status))
204 {
206 RedirectedImportName,
207 TRUE,
208 RedirectedDll,
209 &Entry))
210 {
211 if (Entry->LoadCount != 0xFFFF)
212 {
213 /* Perform the required action */
214 switch (Flags)
215 {
217 Entry->LoadCount++;
218 break;
220 Entry->LoadCount--;
221 break;
222 case LDRP_UPDATE_PIN:
223 Entry->LoadCount = 0xFFFF;
224 break;
225 }
226
227 /* Show snaps */
228 if (ShowSnaps)
229 {
230 DPRINT1("LDR: Flags %lu %wZ (%lx)\n", Flags, RedirectedImportName, Entry->LoadCount);
231 }
232 }
233
234 /* Recurse into this entry */
235 LdrpUpdateLoadCount3(Entry, Flags, UpdateString);
236 }
237 else if (RedirectedDll)
238 {
239 DPRINT1("LDR: LdrpCheckForLoadedDll failed for redirected dll %wZ\n", RedirectedImportName);
240 }
241 }
242 else
243 {
244 /* Unrecoverable SxS failure */
245 DPRINT1("LDR: LdrpApplyFileNameRedirection failed with status %x for dll %wZ\n", Status, ImportNameUnic);
246 }
247
248 }
249
250 /* Go through forwarders */
251 NewImportForwarder = (PIMAGE_BOUND_FORWARDER_REF)(BoundEntry + 1);
252 for (i = 0; i < BoundEntry->NumberOfModuleForwarderRefs; i++)
253 {
254 ImportName = (LPSTR)FirstEntry + NewImportForwarder->OffsetModuleName;
255
256 RtlInitAnsiString(&ImportNameAnsi, ImportName);
257 Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE);
258 if (NT_SUCCESS(Status))
259 {
260 RedirectedDll = FALSE;
261 RedirectedImportName = ImportNameUnic;
262
263 /* Check if the SxS Assemblies specify another file */
265 ImportNameUnic, &LdrApiDefaultExtension, UpdateString, NULL, &RedirectedImportName,
266 &RedirectedDll);
267
268 /* Check success */
269 if (NT_SUCCESS(Status) && RedirectedDll)
270 {
271 if (ShowSnaps)
272 {
273 DPRINT1("LDR: %Z got redirected to %wZ\n", &ImportNameAnsi, RedirectedImportName);
274 }
275 }
276
277 if (NT_SUCCESS(Status))
278 {
280 RedirectedImportName,
281 TRUE,
282 RedirectedDll,
283 &Entry))
284 {
285 if (Entry->LoadCount != 0xFFFF)
286 {
287 /* Perform the required action */
288 switch (Flags)
289 {
291 Entry->LoadCount++;
292 break;
294 Entry->LoadCount--;
295 break;
296 case LDRP_UPDATE_PIN:
297 Entry->LoadCount = 0xFFFF;
298 break;
299 }
300
301 /* Show snaps */
302 if (ShowSnaps)
303 {
304 DPRINT1("LDR: Flags %lu %wZ (%lx)\n", Flags, RedirectedImportName, Entry->LoadCount);
305 }
306 }
307
308 /* Recurse into this entry */
309 LdrpUpdateLoadCount3(Entry, Flags, UpdateString);
310 }
311 else if (RedirectedDll)
312 {
313 DPRINT1("LDR: LdrpCheckForLoadedDll failed with status %x for redirected dll %wZ\n", Status, RedirectedImportName);
314 }
315 }
316 else
317 {
318 /* Unrecoverable SxS failure */
319 DPRINT1("LDR: LdrpApplyFileNameRedirection failed with status %x for dll %wZ\n", Status, ImportNameUnic);
320 }
321
322 }
323
324 NewImportForwarder++;
325 }
326
327 BoundEntry = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)NewImportForwarder;
328 }
329
330 /* We're done */
331 goto done;
332 }
333
334 /* Check oldstyle import descriptor */
335 ImportEntry = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(LdrEntry->DllBase,
336 TRUE,
338 &ImportSize);
339 if (ImportEntry)
340 {
341 /* There is old one, so go through its entries */
342 while (ImportEntry->Name && ImportEntry->FirstThunk)
343 {
344 FirstThunk = (PIMAGE_THUNK_DATA)((ULONG_PTR)LdrEntry->DllBase + ImportEntry->FirstThunk);
345
346 /* Skip this entry if needed */
347 if (!FirstThunk->u1.Function)
348 {
349 ImportEntry++;
350 continue;
351 }
352
353 ImportName = (PSZ)((ULONG_PTR)LdrEntry->DllBase + ImportEntry->Name);
354
355 RtlInitAnsiString(&ImportNameAnsi, ImportName);
356 Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE);
357 if (NT_SUCCESS(Status))
358 {
359 RedirectedDll = FALSE;
360 RedirectedImportName = ImportNameUnic;
361
362 /* Check if the SxS Assemblies specify another file */
364 ImportNameUnic, &LdrApiDefaultExtension, UpdateString, NULL, &RedirectedImportName, &RedirectedDll);
365
366 /* Check success */
367 if (NT_SUCCESS(Status) && RedirectedDll)
368 {
369 if (ShowSnaps)
370 {
371 DPRINT1("LDR: %Z got redirected to %wZ\n", &ImportNameAnsi, RedirectedImportName);
372 }
373 }
374
375 if (NT_SUCCESS(Status))
376 {
378 RedirectedImportName,
379 TRUE,
380 RedirectedDll,
381 &Entry))
382 {
383 if (Entry->LoadCount != 0xFFFF)
384 {
385 /* Perform the required action */
386 switch (Flags)
387 {
389 Entry->LoadCount++;
390 break;
392 Entry->LoadCount--;
393 break;
394 case LDRP_UPDATE_PIN:
395 Entry->LoadCount = 0xFFFF;
396 break;
397 }
398
399 /* Show snaps */
400 if (ShowSnaps)
401 {
402 DPRINT1("LDR: Flags %lu %wZ (%lx)\n", Flags, RedirectedImportName, Entry->LoadCount);
403 }
404 }
405
406 /* Recurse */
407 LdrpUpdateLoadCount3(Entry, Flags, UpdateString);
408 }
409 else if (RedirectedDll)
410 {
411 DPRINT1("LDR: LdrpCheckForLoadedDll failed for redirected dll %wZ\n", RedirectedImportName);
412 }
413
414 }
415 else
416 {
417 /* Unrecoverable SxS failure */
418 DPRINT1("LDR: LdrpApplyFileNameRedirection failed for dll %wZ\n", ImportNameUnic);
419 }
420 }
421
422 /* Go to the next entry */
423 ImportEntry++;
424 }
425 }
426
427done:
428 /* Release the context */
429 RtlDeactivateActivationContextUnsafeFast(&ActCtx);
430}
431
432VOID
433NTAPI
435 IN ULONG Flags)
436{
438 UNICODE_STRING UpdateString;
439
440 /* Setup the string and call the extended API */
441 RtlInitEmptyUnicodeString(&UpdateString, Buffer, sizeof(Buffer));
442 LdrpUpdateLoadCount3(LdrEntry, Flags, &UpdateString);
443}
444
445VOID
446NTAPI
449{
450 PIMAGE_TLS_DIRECTORY TlsDirectory;
452 ULONG Size;
453
454 /* Get the TLS Directory */
455 TlsDirectory = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
456 TRUE,
458 &Size);
459
460 /* Protect against invalid pointers */
462 {
463 /* Make sure it's valid */
464 if (TlsDirectory)
465 {
466 /* Get the array */
467 Array = (PIMAGE_TLS_CALLBACK *)TlsDirectory->AddressOfCallBacks;
468 if (Array)
469 {
470 /* Display debug */
471 if (ShowSnaps)
472 {
473 DPRINT1("LDR: Tls Callbacks Found. Imagebase %p Tls %p CallBacks %p\n",
474 LdrEntry->DllBase, TlsDirectory, Array);
475 }
476
477 /* Loop the array */
478 while (*Array)
479 {
480 /* Get the TLS Entrypoint */
481 Callback = *Array++;
482
483 /* Display debug */
484 if (ShowSnaps)
485 {
486 DPRINT1("LDR: Calling Tls Callback Imagebase %p Function %p\n",
487 LdrEntry->DllBase, Callback);
488 }
489
490 /* Call it */
492 LdrEntry->DllBase,
493 Reason,
494 NULL);
495 }
496 }
497 }
498 }
500 {
501 DPRINT1("LDR: Exception 0x%x during Tls Callback(%u) for %wZ\n",
502 _SEH2_GetExceptionCode(), Reason, &LdrEntry->BaseDllName);
503 }
504 _SEH2_END;
505}
506
508NTAPI
510 IN HANDLE DllHandle)
511{
512 /* Not implemented */
513 return STATUS_SUCCESS;
514}
515
517NTAPI
519 IN HANDLE DllHandle,
520 IN PULONG DllCharacteristics OPTIONAL,
521 OUT PHANDLE SectionHandle)
522{
527 ULONG_PTR HardErrorParameters[1];
529 SECTION_IMAGE_INFORMATION SectionImageInfo;
530
531 /* Check if we don't already have a handle */
532 if (!DllHandle)
533 {
534 /* Create the object attributes */
536 FullName,
538 NULL,
539 NULL);
540
541 /* Open the DLL */
548
549 /* Check if we failed */
550 if (!NT_SUCCESS(Status))
551 {
552 /* Attempt to open for execute only */
559
560 /* Check if this failed too */
561 if (!NT_SUCCESS(Status))
562 {
563 /* Show debug message */
564 if (ShowSnaps)
565 {
566 DPRINT1("LDR: LdrpCreateDllSection - NtOpenFile failed; status = %x\n",
567 Status);
568 }
569
570 /* Make sure to return an expected status code */
572 {
573 /* Callers expect this instead */
575 }
576
577 /* Return an empty section handle */
578 *SectionHandle = NULL;
579 return Status;
580 }
581 }
582 }
583 else
584 {
585 /* Use the handle we already have */
586 FileHandle = DllHandle;
587 }
588
589 /* Create a section for the DLL */
590 Status = NtCreateSection(SectionHandle,
593 NULL,
594 NULL,
596 SEC_IMAGE,
597 FileHandle);
598
599 /* If mapping failed, raise a hard error */
600 if (!NT_SUCCESS(Status))
601 {
602 /* Forget the handle */
603 *SectionHandle = NULL;
604
605 /* Give the DLL name */
606 HardErrorParameters[0] = (ULONG_PTR)FullName;
607
608 /* Raise the error */
610 1,
611 1,
612 HardErrorParameters,
613 OptionOk,
614 &Response);
615
616 /* Increment the error count */
618
619 goto Exit;
620 }
621
622 /* Check for Safer restrictions */
623 if (!DllCharacteristics ||
624 !(*DllCharacteristics & IMAGE_FILE_SYSTEM))
625 {
626 /* Make sure it's executable */
627 Status = ZwQuerySection(*SectionHandle,
629 &SectionImageInfo,
631 NULL);
632 if (NT_SUCCESS(Status))
633 {
634 /* Bypass the check for .NET images */
635 if (!(SectionImageInfo.LoaderFlags & IMAGE_LOADER_FLAGS_COMPLUS))
636 {
637 /* Check with Safer */
640 {
641 /* Show debug message */
642 if (ShowSnaps)
643 {
644 DPRINT1("LDR: Loading of (%wZ) blocked by Winsafer\n",
645 &FullName);
646 }
647
648 /* Failure case, close section handle */
649 NtClose(*SectionHandle);
650 *SectionHandle = NULL;
651 }
652 }
653 }
654 else
655 {
656 /* Failure case, close section handle */
657 NtClose(*SectionHandle);
658 *SectionHandle = NULL;
659 }
660 }
661
662Exit:
663 /* Close the file handle, we don't need it */
665
666 /* Return status */
667 return Status;
668}
669
670/* NOTE: This function is totally b0rked and doesn't handle the parameters/functionality it should */
672NTAPI
674 PWSTR DllName,
676 PUNICODE_STRING BaseDllName)
677{
678 PWCHAR NameBuffer, p1, p2 = 0;
680 ULONG BufSize = 500;
681
682 /* Allocate space for full DLL name */
684 if (!FullDllName->Buffer) return FALSE;
685
687 DllName,
688 NULL,
689 BufSize,
690 FullDllName->Buffer,
691 &BaseDllName->Buffer);
692
693 if (!Length || Length > BufSize)
694 {
695 if (ShowSnaps)
696 {
697 DPRINT1("LDR: LdrResolveDllName - Unable to find ");
698 DPRINT1("%ws from %ws\n", DllName, DllPath ? DllPath : LdrpDefaultPath.Buffer);
699 }
700
702 return FALSE;
703 }
704
705 /* Construct full DLL name */
706 FullDllName->Length = Length;
707 FullDllName->MaximumLength = FullDllName->Length + sizeof(UNICODE_NULL);
708
709 /* Allocate a new buffer */
710 NameBuffer = RtlAllocateHeap(LdrpHeap, 0, FullDllName->MaximumLength);
711 if (!NameBuffer)
712 {
713 RtlFreeHeap(LdrpHeap, 0, FullDllName->Buffer);
714 return FALSE;
715 }
716
717 /* Copy over the contents from the previous one and free it */
718 RtlCopyMemory(NameBuffer, FullDllName->Buffer, FullDllName->MaximumLength);
719 RtlFreeHeap(LdrpHeap, 0, FullDllName->Buffer);
720 FullDllName->Buffer = NameBuffer;
721
722 /* Find last backslash */
723 p1 = FullDllName->Buffer;
724 while (*p1)
725 {
726 if (*p1++ == L'\\')
727 {
728 p2 = p1;
729 }
730 }
731
732 /* If found, set p1 to it, otherwise p1 points to the beginning of DllName */
733 if (p2)
734 p1 = p2;
735 else
736 p1 = DllName;
737
738 p2 = p1;
739
740 /* Calculate remaining length */
741 while (*p1) ++p1;
742
743 /* Construct base DLL name */
744 BaseDllName->Length = (ULONG_PTR)p1 - (ULONG_PTR)p2;
745 BaseDllName->MaximumLength = BaseDllName->Length + sizeof(UNICODE_NULL);
746 BaseDllName->Buffer = RtlAllocateHeap(LdrpHeap, 0, BaseDllName->MaximumLength);
747
748 if (!BaseDllName->Buffer)
749 {
750 RtlFreeHeap(LdrpHeap, 0, NameBuffer);
751 return FALSE;
752 }
753
754 /* Copy base dll name to the new buffer */
755 RtlMoveMemory(BaseDllName->Buffer,
756 p2,
757 BaseDllName->Length);
758
759 /* Null-terminate the string */
760 BaseDllName->Buffer[BaseDllName->Length / sizeof(WCHAR)] = 0;
761
762 return TRUE;
763}
764
765PVOID
766NTAPI
768{
769 PIMAGE_NT_HEADERS NtHeaders;
770 ULONG_PTR EntryPoint = 0;
771
772 /* Get entry point offset from NT headers */
773 NtHeaders = RtlImageNtHeader(ImageBase);
774 if (NtHeaders)
775 {
776 /* Add image base */
777 EntryPoint = NtHeaders->OptionalHeader.AddressOfEntryPoint;
778 if (EntryPoint) EntryPoint += (ULONG_PTR)ImageBase;
779 }
780
781 /* Return calculated pointer (or zero in case of failure) */
782 return (PVOID)EntryPoint;
783}
784
785/* NOTE: This function is partially missing SxS */
787NTAPI
790 PUNICODE_STRING BaseDllName,
791 HANDLE *SectionHandle)
792{
794 HANDLE Section = NULL;
795 UNICODE_STRING DllNameUnic;
797 PCHAR p1;
798 PWCHAR p2;
799
800 /* Zero initialize provided parameters */
801 if (SectionHandle) *SectionHandle = 0;
802
803 if (FullDllName)
804 {
805 FullDllName->Length = 0;
806 FullDllName->MaximumLength = 0;
807 FullDllName->Buffer = NULL;
808 }
809
810 if (BaseDllName)
811 {
812 BaseDllName->Length = 0;
813 BaseDllName->MaximumLength = 0;
814 BaseDllName->Buffer = NULL;
815 }
816
817 /* If any of these three params are missing then fail */
818 if (!SectionHandle || !FullDllName || !BaseDllName)
820
821 /* Check the Loader Lock */
823
824 /* Upgrade DllName to a unicode string */
825 RtlInitUnicodeString(&DllNameUnic, DllName);
826
827 /* FIXME: Missing RtlComputePrivatizedDllName_U related functionality */
828
829 /* Get the activation context */
831 NULL,
832 ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
833 &DllNameUnic,
834 NULL);
835
836 /* Check if it's a SxS or not */
839 {
840 /* NOTE: Here it's beneficial to allocate one big unicode string
841 using LdrpAllocateUnicodeString instead of fragmenting the heap
842 with two allocations as it's done now. */
843
844 /* Set up BaseDllName */
845 BaseDllName->Length = DllNameUnic.Length;
846 BaseDllName->MaximumLength = DllNameUnic.MaximumLength;
847 BaseDllName->Buffer = RtlAllocateHeap(LdrpHeap,
848 0,
849 DllNameUnic.MaximumLength);
850 if (!BaseDllName->Buffer)
851 {
853 goto Failure;
854 }
855
856 /* Copy the contents there */
857 RtlMoveMemory(BaseDllName->Buffer, DllNameUnic.Buffer, DllNameUnic.MaximumLength);
858
859 /* Set up FullDllName */
860 FullDllName->Length = LdrpKnownDllPath.Length + BaseDllName->Length + sizeof(WCHAR);
861 FullDllName->MaximumLength = FullDllName->Length + sizeof(UNICODE_NULL);
862 FullDllName->Buffer = RtlAllocateHeap(LdrpHeap, 0, FullDllName->MaximumLength);
863 if (!FullDllName->Buffer)
864 {
866 goto Failure;
867 }
868
870
871 /* Put a slash there */
873 p2 = (PWCHAR)p1;
874 *p2++ = (WCHAR)'\\';
875 p1 = (PCHAR)p2;
876
877 /* Set up DllNameUnic for a relative path */
878 DllNameUnic.Buffer = (PWSTR)p1;
879 DllNameUnic.Length = BaseDllName->Length;
880 DllNameUnic.MaximumLength = DllNameUnic.Length + sizeof(UNICODE_NULL);
881
882 /* Copy the contents */
883 RtlMoveMemory(p1, BaseDllName->Buffer, BaseDllName->MaximumLength);
884
885 /* There are all names, init attributes and open the section */
887 &DllNameUnic,
890 NULL);
891
892 Status = NtOpenSection(&Section,
895 if (!NT_SUCCESS(Status))
896 {
897 /* Clear status in case it was just not found */
899 goto Failure;
900 }
901
902 /* Pass section handle to the caller and return success */
903 *SectionHandle = Section;
904 return STATUS_SUCCESS;
905 }
906
907Failure:
908 /* Close section object if it was opened */
909 if (Section) NtClose(Section);
910
911 /* Free string resources */
912 if (BaseDllName->Buffer) RtlFreeHeap(LdrpHeap, 0, BaseDllName->Buffer);
913 if (FullDllName->Buffer) RtlFreeHeap(LdrpHeap, 0, FullDllName->Buffer);
914
915 /* Return status */
916 return Status;
917}
918
920NTAPI
922 BOOLEAN Restore)
923{
924 PIMAGE_NT_HEADERS NtHeaders;
925 PIMAGE_SECTION_HEADER Section;
927 PVOID SectionBase;
928 SIZE_T SectionSize;
929 ULONG NewProtection, OldProtection, i;
930
931 /* Get the NT headers */
932 NtHeaders = RtlImageNtHeader(ViewBase);
933 if (!NtHeaders) return STATUS_INVALID_IMAGE_FORMAT;
934
935 /* Compute address of the first section header */
936 Section = IMAGE_FIRST_SECTION(NtHeaders);
937
938 /* Go through all sections */
939 for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++)
940 {
941 /* Check for read-only non-zero section */
942 if ((Section->SizeOfRawData) &&
944 {
945 /* Check if we are setting or restoring protection */
946 if (Restore)
947 {
948 /* Set it to either EXECUTE or READONLY */
950 {
951 NewProtection = PAGE_EXECUTE;
952 }
953 else
954 {
955 NewProtection = PAGE_READONLY;
956 }
957
958 /* Add PAGE_NOCACHE if needed */
960 {
961 NewProtection |= PAGE_NOCACHE;
962 }
963 }
964 else
965 {
966 /* Enable write access */
967 NewProtection = PAGE_READWRITE;
968 }
969
970 /* Get the section VA */
971 SectionBase = (PVOID)((ULONG_PTR)ViewBase + Section->VirtualAddress);
972 SectionSize = Section->SizeOfRawData;
973 if (SectionSize)
974 {
975 /* Set protection */
977 &SectionBase,
978 &SectionSize,
979 NewProtection,
980 &OldProtection);
981 if (!NT_SUCCESS(Status)) return Status;
982 }
983 }
984
985 /* Move to the next section */
986 Section++;
987 }
988
989 /* Flush instruction cache if necessary */
991 return STATUS_SUCCESS;
992}
993
994/* NOTE: Not yet reviewed */
996NTAPI
998 IN PWSTR DllPath2,
999 IN PWSTR DllName OPTIONAL,
1000 IN PULONG DllCharacteristics,
1002 IN BOOLEAN Redirect,
1003 OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry)
1004{
1005 PTEB Teb = NtCurrentTeb();
1006 PPEB Peb = NtCurrentPeb();
1007 PWCHAR p1 = DllName;
1008 WCHAR TempChar;
1009 BOOLEAN KnownDll = FALSE;
1010 UNICODE_STRING FullDllName, BaseDllName;
1011 HANDLE SectionHandle = NULL, DllHandle = 0;
1012 UNICODE_STRING NtPathDllName;
1013 ULONG_PTR HardErrorParameters[2];
1014 UNICODE_STRING HardErrorDllName, HardErrorDllPath;
1016 SIZE_T ViewSize = 0;
1017 PVOID ViewBase = NULL;
1018 PVOID ArbitraryUserPointer;
1019 PIMAGE_NT_HEADERS NtHeaders;
1020 NTSTATUS HardErrorStatus, Status;
1021 BOOLEAN OverlapDllFound = FALSE;
1022 ULONG_PTR ImageBase, ImageEnd;
1023 PLIST_ENTRY ListHead, NextEntry;
1024 PLDR_DATA_TABLE_ENTRY CandidateEntry, LdrEntry;
1025 ULONG_PTR CandidateBase, CandidateEnd;
1026 UNICODE_STRING OverlapDll;
1027 BOOLEAN RelocatableDll = TRUE;
1028 UNICODE_STRING IllegalDll;
1029 PVOID RelocData;
1030 ULONG RelocDataSize = 0;
1031
1032 // FIXME: AppCompat stuff is missing
1033
1034 if (ShowSnaps)
1035 {
1036 DPRINT1("LDR: LdrpMapDll: Image Name %ws, Search Path %ws\n",
1037 DllName,
1038 SearchPath ? SearchPath : L"");
1039 }
1040
1041 /* Check if we have a known dll directory */
1042 if (LdrpKnownDllObjectDirectory && Redirect == FALSE)
1043 {
1044 /* Check if the path is full */
1045 while (*p1)
1046 {
1047 TempChar = *p1++;
1048 if (TempChar == '\\' || TempChar == '/' )
1049 {
1050 /* Complete path, don't do Known Dll lookup */
1051 goto SkipCheck;
1052 }
1053 }
1054
1055 /* Try to find a Known DLL */
1056 Status = LdrpCheckForKnownDll(DllName,
1057 &FullDllName,
1058 &BaseDllName,
1059 &SectionHandle);
1060
1062 {
1063 /* Failure */
1066 "LDR: %s - call to LdrpCheckForKnownDll(\"%ws\", ...) failed with status %x\n",
1068 DllName,
1069 Status);
1070
1071 return Status;
1072 }
1073 }
1074
1075SkipCheck:
1076
1077 /* Check if the Known DLL Check returned something */
1078 if (!SectionHandle)
1079 {
1080 /* It didn't, so try to resolve the name now */
1082 DllName,
1083 &FullDllName,
1084 &BaseDllName))
1085 {
1086 /* Got a name, display a message */
1087 if (ShowSnaps)
1088 {
1089 DPRINT1("LDR: Loading (%s) %wZ\n",
1090 Static ? "STATIC" : "DYNAMIC",
1091 &FullDllName);
1092 }
1093
1094 /* Convert to NT Name */
1096 &NtPathDllName,
1097 NULL,
1098 NULL))
1099 {
1100 /* Path was invalid */
1102 }
1103
1104 /* Create a section for this dLL */
1105 Status = LdrpCreateDllSection(&NtPathDllName,
1106 DllHandle,
1107 DllCharacteristics,
1108 &SectionHandle);
1109
1110 /* Free the NT Name */
1111 RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathDllName.Buffer);
1112
1113 /* If we failed */
1114 if (!NT_SUCCESS(Status))
1115 {
1116 /* Free the name strings and return */
1118 LdrpFreeUnicodeString(&BaseDllName);
1119 return Status;
1120 }
1121 }
1122 else
1123 {
1124 /* We couldn't resolve the name, is this a static load? */
1125 if (Static)
1126 {
1127 /*
1128 * This is BAD! Static loads are CRITICAL. Bugcheck!
1129 * Initialize the strings for the error
1130 */
1131 RtlInitUnicodeString(&HardErrorDllName, DllName);
1132 RtlInitUnicodeString(&HardErrorDllPath,
1133 DllPath2 ? DllPath2 : LdrpDefaultPath.Buffer);
1134
1135 /* Set them as error parameters */
1136 HardErrorParameters[0] = (ULONG_PTR)&HardErrorDllName;
1137 HardErrorParameters[1] = (ULONG_PTR)&HardErrorDllPath;
1138
1139 /* Raise the hard error */
1141 2,
1142 0x00000003,
1143 HardErrorParameters,
1144 OptionOk,
1145 &Response);
1146
1147 /* We're back, where we initializing? */
1149 }
1150
1151 /* Return failure */
1152 return STATUS_DLL_NOT_FOUND;
1153 }
1154 }
1155 else
1156 {
1157 /* We have a section handle, so this is a known dll */
1158 KnownDll = TRUE;
1159 }
1160
1161 /* Stuff the image name in the TIB, for the debugger */
1162 ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
1164
1165 /* Map the DLL */
1166 ViewBase = NULL;
1167 ViewSize = 0;
1168 Status = NtMapViewOfSection(SectionHandle,
1170 &ViewBase,
1171 0,
1172 0,
1173 NULL,
1174 &ViewSize,
1175 ViewShare,
1176 0,
1178
1179 /* Restore */
1180 Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
1181
1182 /* Fail if we couldn't map it */
1183 if (!NT_SUCCESS(Status))
1184 {
1185 /* Close and return */
1186 NtClose(SectionHandle);
1187 return Status;
1188 }
1189
1190 /* Get the NT Header */
1191 if (!(NtHeaders = RtlImageNtHeader(ViewBase)))
1192 {
1193 /* Invalid image, unmap, close handle and fail */
1195 NtClose(SectionHandle);
1197 }
1198
1199 // FIXME: .NET support is missing
1200
1201 /* Allocate an entry */
1202 if (!(LdrEntry = LdrpAllocateDataTableEntry(ViewBase)))
1203 {
1204 /* Invalid image, unmap, close handle and fail */
1206 NtClose(SectionHandle);
1207 return STATUS_NO_MEMORY;
1208 }
1209
1210 /* Setup the entry */
1211 LdrEntry->Flags = Static ? LDRP_STATIC_LINK : 0;
1212 if (Redirect) LdrEntry->Flags |= LDRP_REDIRECTED;
1213 LdrEntry->LoadCount = 0;
1214 LdrEntry->FullDllName = FullDllName;
1215 LdrEntry->BaseDllName = BaseDllName;
1216 LdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(LdrEntry->DllBase);
1217
1218 /* Show debug message */
1219 if (ShowSnaps)
1220 {
1221 DPRINT1("LDR: LdrpMapDll: Full Name %wZ, Base Name %wZ\n",
1222 &FullDllName,
1223 &BaseDllName);
1224 }
1225
1226 /* Insert this entry */
1228
1229#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA) || (DLL_EXPORT_VERSION >= _WIN32_WINNT_VISTA)
1231#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
1232 LdrEntry->Flags |= LDRP_LOAD_NOTIFICATIONS_SENT; /* LdrEntry->LoadNotificationsSent = TRUE; */
1233#endif
1234#endif
1235
1236 /* Check for invalid CPU Image */
1238 {
1239 /* Load our header */
1241
1242 /* Assume defaults if we don't have to run the Hard Error path */
1243 HardErrorStatus = STATUS_SUCCESS;
1245
1246 /* Are we an NT 3.0 image? [Do these still exist? LOL -- IAI] */
1248 {
1249 /* Reset the entrypoint, save our Dll Name */
1250 LdrEntry->EntryPoint = 0;
1251 HardErrorParameters[0] = (ULONG_PTR)&FullDllName;
1252
1253 /* Raise the error */
1255 1,
1256 1,
1257 HardErrorParameters,
1259 &Response);
1260 }
1261
1262 /* Check if the user pressed cancel */
1263 if (NT_SUCCESS(HardErrorStatus) && Response == ResponseCancel)
1264 {
1265 /* Remove the DLL from the lists */
1268 RemoveEntryList(&LdrEntry->HashLinks);
1269
1270 /* Remove the LDR Entry */
1271 RtlFreeHeap(LdrpHeap, 0, LdrEntry );
1272
1273 /* Unmap and close section */
1275 NtClose(SectionHandle);
1276
1277 /* Did we do a hard error? */
1279 {
1280 /* Yup, so increase fatal error count if we are initializing */
1282 }
1283
1284 /* Return failure */
1286 }
1287 }
1288 else
1289 {
1290 /* The image was valid. Is it a DLL? */
1291 if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
1292 {
1293 /* Set the DLL Flag */
1294 LdrEntry->Flags |= LDRP_IMAGE_DLL;
1295 }
1296
1297 /* If we're not a DLL, clear the entrypoint */
1298 if (!(LdrEntry->Flags & LDRP_IMAGE_DLL))
1299 {
1300 LdrEntry->EntryPoint = 0;
1301 }
1302 }
1303
1304 /* Return it for the caller */
1305 *DataTableEntry = LdrEntry;
1306
1307 /* Check if we loaded somewhere else */
1309 {
1310 /* Write the flag */
1311 LdrEntry->Flags |= LDRP_IMAGE_NOT_AT_BASE;
1312
1313 /* Find our region */
1314 ImageBase = (ULONG_PTR)NtHeaders->OptionalHeader.ImageBase;
1315 ImageEnd = ImageBase + ViewSize;
1316
1317 DPRINT("LDR: LdrpMapDll Relocating Image Name %ws (%p-%p -> %p)\n", DllName, (PVOID)ImageBase, (PVOID)ImageEnd, ViewBase);
1318
1319 /* Scan all the modules */
1320 ListHead = &Peb->Ldr->InLoadOrderModuleList;
1321 NextEntry = ListHead->Flink;
1322 while (NextEntry != ListHead)
1323 {
1324 /* Get the entry */
1325 CandidateEntry = CONTAINING_RECORD(NextEntry,
1327 InLoadOrderLinks);
1328 NextEntry = NextEntry->Flink;
1329
1330 /* Get the entry's bounds */
1331 CandidateBase = (ULONG_PTR)CandidateEntry->DllBase;
1332 CandidateEnd = CandidateBase + CandidateEntry->SizeOfImage;
1333
1334 /* Make sure this entry isn't unloading */
1335 if (!CandidateEntry->InMemoryOrderLinks.Flink) continue;
1336
1337 /* Check if our regions are colliding */
1338 if ((ImageBase >= CandidateBase && ImageBase <= CandidateEnd) ||
1339 (ImageEnd >= CandidateBase && ImageEnd <= CandidateEnd) ||
1340 (CandidateBase >= ImageBase && CandidateBase <= ImageEnd))
1341 {
1342 /* Found who is overlapping */
1343 OverlapDllFound = TRUE;
1344 OverlapDll = CandidateEntry->FullDllName;
1345 break;
1346 }
1347 }
1348
1349 /* Check if we found the DLL overlapping with us */
1350 if (!OverlapDllFound)
1351 {
1352 /* It's not another DLL, it's memory already here */
1353 RtlInitUnicodeString(&OverlapDll, L"Dynamically Allocated Memory");
1354 }
1355
1356 DPRINT("Overlapping DLL: %wZ\n", &OverlapDll);
1357
1358 /* Are we dealing with a DLL? */
1359 if (LdrEntry->Flags & LDRP_IMAGE_DLL)
1360 {
1361 /* Check if relocs were stripped */
1363 {
1364 /* Get the relocation data */
1365 RelocData = RtlImageDirectoryEntryToData(ViewBase,
1366 TRUE,
1368 &RelocDataSize);
1369
1370 /* Does the DLL not have any? */
1371 if (!RelocData && !RelocDataSize)
1372 {
1373 /* We'll allow this and simply continue */
1374 goto NoRelocNeeded;
1375 }
1376 }
1377
1378 /* See if this is an Illegal DLL - IE: user32 and kernel32 */
1379 RtlInitUnicodeString(&IllegalDll,L"user32.dll");
1380 if (RtlEqualUnicodeString(&BaseDllName, &IllegalDll, TRUE))
1381 {
1382 /* Can't relocate user32 */
1383 RelocatableDll = FALSE;
1384 }
1385 else
1386 {
1387 RtlInitUnicodeString(&IllegalDll, L"kernel32.dll");
1388 if (RtlEqualUnicodeString(&BaseDllName, &IllegalDll, TRUE))
1389 {
1390 /* Can't relocate kernel32 */
1391 RelocatableDll = FALSE;
1392 }
1393 }
1394
1395 /* Known DLLs are not allowed to be relocated */
1396 if (KnownDll && !RelocatableDll)
1397 {
1398 /* Setup for hard error */
1399 HardErrorParameters[0] = (ULONG_PTR)&IllegalDll;
1400 HardErrorParameters[1] = (ULONG_PTR)&OverlapDll;
1401
1402 DPRINT1("Illegal DLL relocation! %wZ overlaps %wZ\n", &OverlapDll, &IllegalDll);
1403
1404 /* Raise the error */
1406 2,
1407 3,
1408 HardErrorParameters,
1409 OptionOk,
1410 &Response);
1411
1412 /* If initializing, increase the error count */
1414
1415 /* Don't do relocation */
1417 goto FailRelocate;
1418 }
1419
1420 /* Change the protection to prepare for relocation */
1421 Status = LdrpSetProtection(ViewBase, FALSE);
1422
1423 /* Make sure we changed the protection */
1424 if (NT_SUCCESS(Status))
1425 {
1426 /* Do the relocation */
1429
1430 if (NT_SUCCESS(Status))
1431 {
1432 /* Stuff the image name in the TIB, for the debugger */
1433 ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
1435#if 0
1436 /* Map the DLL */
1437 Status = NtMapViewOfSection(SectionHandle,
1439 &ViewBase,
1440 0,
1441 0,
1442 NULL,
1443 &ViewSize,
1444 ViewShare,
1445 0,
1447#endif
1448 /* Restore */
1449 Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
1450
1451 /* Return the protection */
1452 Status = LdrpSetProtection(ViewBase, TRUE);
1453 }
1454 }
1455FailRelocate:
1456 /* Handle any kind of failure */
1457 if (!NT_SUCCESS(Status))
1458 {
1459 /* Remove it from the lists */
1462 RemoveEntryList(&LdrEntry->HashLinks);
1463
1464 /* Unmap it, clear the entry */
1466 LdrEntry = NULL;
1467 }
1468
1469 /* Show debug message */
1470 if (ShowSnaps)
1471 {
1472 DPRINT1("LDR: Fixups %successfully re-applied @ %p\n",
1473 NT_SUCCESS(Status) ? "s" : "uns", ViewBase);
1474 }
1475 }
1476 else
1477 {
1478NoRelocNeeded:
1479 /* Not a DLL, or no relocation needed */
1481
1482 /* Stuff the image name in the TIB, for the debugger */
1483 ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
1485#if 0
1486 /* Map the DLL */
1487 Status = NtMapViewOfSection(SectionHandle,
1489 &ViewBase,
1490 0,
1491 0,
1492 NULL,
1493 &ViewSize,
1494 ViewShare,
1495 0,
1497#endif
1498 /* Restore */
1499 Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
1500
1501 /* Show debug message */
1502 if (ShowSnaps)
1503 {
1504 DPRINT1("LDR: Fixups won't be re-applied to non-Dll @ %p\n", ViewBase);
1505 }
1506 }
1507 }
1508
1509 // FIXME: LdrpCheckCorImage() is missing
1510
1511 /* Check if this is an SMP Machine and a DLL */
1512 if ((LdrpNumberOfProcessors > 1) &&
1513 (LdrEntry && (LdrEntry->Flags & LDRP_IMAGE_DLL)))
1514 {
1515 /* Validate the image for MP */
1516 LdrpValidateImageForMp(LdrEntry);
1517 }
1518
1519 // FIXME: LdrpCorUnloadImage() is missing
1520
1521 /* Close section and return status */
1522 NtClose(SectionHandle);
1523 return Status;
1524}
1525
1527NTAPI
1529{
1530 PLDR_DATA_TABLE_ENTRY LdrEntry = NULL;
1531 PIMAGE_NT_HEADERS NtHeader;
1532
1533 /* Make sure the header is valid */
1534 NtHeader = RtlImageNtHeader(BaseAddress);
1535 DPRINT("LdrpAllocateDataTableEntry(%p), NtHeader %p\n", BaseAddress, NtHeader);
1536
1537 if (NtHeader)
1538 {
1539 /* Allocate an entry */
1540 LdrEntry = RtlAllocateHeap(LdrpHeap,
1542 sizeof(LDR_DATA_TABLE_ENTRY));
1543
1544 /* Make sure we got one */
1545 if (LdrEntry)
1546 {
1547 /* Set it up */
1548 LdrEntry->DllBase = BaseAddress;
1549 LdrEntry->SizeOfImage = NtHeader->OptionalHeader.SizeOfImage;
1550 LdrEntry->TimeDateStamp = NtHeader->FileHeader.TimeDateStamp;
1551 LdrEntry->PatchInformation = NULL;
1552 }
1553 }
1554
1555 /* Return the entry */
1556 return LdrEntry;
1557}
1558
1559VOID
1560NTAPI
1562{
1563 PPEB_LDR_DATA PebData = NtCurrentPeb()->Ldr;
1564 ULONG i;
1565
1566 /* Insert into hash table */
1567 i = LDR_GET_HASH_ENTRY(LdrEntry->BaseDllName.Buffer[0]);
1568 InsertTailList(&LdrpHashTable[i], &LdrEntry->HashLinks);
1569
1570 /* Insert into other lists */
1571 InsertTailList(&PebData->InLoadOrderModuleList, &LdrEntry->InLoadOrderLinks);
1572 InsertTailList(&PebData->InMemoryOrderModuleList, &LdrEntry->InMemoryOrderLinks);
1573}
1574
1575VOID
1576NTAPI
1578{
1579 /* Sanity check */
1580 ASSERT(Entry != NULL);
1581
1582 /* Release the activation context if it exists and wasn't already released */
1583 if ((Entry->EntryPointActivationContext) &&
1584 (Entry->EntryPointActivationContext != INVALID_HANDLE_VALUE))
1585 {
1586 /* Mark it as invalid */
1587 RtlReleaseActivationContext(Entry->EntryPointActivationContext);
1588 Entry->EntryPointActivationContext = INVALID_HANDLE_VALUE;
1589 }
1590
1591 /* Release the full dll name string */
1592 if (Entry->FullDllName.Buffer) LdrpFreeUnicodeString(&Entry->FullDllName);
1593
1594 /* Finally free the entry's memory */
1596}
1597
1598BOOLEAN
1599NTAPI
1601 OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
1602{
1603 PLDR_DATA_TABLE_ENTRY Current;
1604 PLIST_ENTRY ListHead, Next;
1605
1606 /* Check the cache first */
1609 {
1610 /* We got lucky, return the cached entry */
1611 *LdrEntry = LdrpLoadedDllHandleCache;
1612 return TRUE;
1613 }
1614
1615 /* Time for a lookup */
1616 ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
1617 Next = ListHead->Flink;
1618 while (Next != ListHead)
1619 {
1620 /* Get the current entry */
1621 Current = CONTAINING_RECORD(Next,
1623 InLoadOrderLinks);
1624
1625 /* Make sure it's not unloading and check for a match */
1626 if ((Current->InMemoryOrderLinks.Flink) && (Base == Current->DllBase))
1627 {
1628 /* Save in cache */
1629 LdrpLoadedDllHandleCache = Current;
1630
1631 /* Return it */
1632 *LdrEntry = Current;
1633 return TRUE;
1634 }
1635
1636 /* Move to the next one */
1637 Next = Next->Flink;
1638 }
1639
1640 /* Nothing found */
1641 return FALSE;
1642}
1643
1645NTAPI
1647 IN PUNICODE_STRING PathName,
1648 IN PUNICODE_STRING FullPathName,
1649 IN PUNICODE_STRING *ExpandedName)
1650{
1652// RTL_PATH_TYPE PathType;
1653// BOOLEAN InvalidName;
1654 ULONG Length;
1655
1656 /* Display debug output if snaps are on */
1657 if (ShowSnaps)
1658 {
1661 "LDR: %s - Expanding full name of %wZ\n",
1663 OriginalName);
1664 }
1665
1666 /* FIXME: Lock the PEB */
1667 //RtlEnterCriticalSection(&FastPebLock);
1668#if 0
1669 /* Get the path name */
1670 Length = RtlGetFullPathName_Ustr(OriginalName,
1671 PathName->Length,
1672 PathName->Buffer,
1673 NULL,
1674 &InvalidName,
1675 &PathType);
1676#else
1677 Length = 0;
1678#endif
1680 {
1681 /* Fail */
1683 goto Quickie;
1684 }
1685
1686 /* Check if the length hasn't changed */
1687 if (Length <= PathName->Length)
1688 {
1689 /* Return the same thing */
1690 *ExpandedName = PathName;
1691 PathName->Length = (USHORT)Length;
1692 goto Quickie;
1693 }
1694
1695 /* Sanity check */
1696 ASSERT(Length >= sizeof(WCHAR));
1697
1698 /* Allocate a string */
1699 Status = LdrpAllocateUnicodeString(FullPathName, Length - sizeof(WCHAR));
1700 if (!NT_SUCCESS(Status)) goto Quickie;
1701
1702 /* Now get the full path again */
1703#if 0
1704 Length = RtlGetFullPathName_Ustr(OriginalName,
1705 FullPathName->Length,
1706 FullPathName->Buffer,
1707 NULL,
1708 &InvalidName,
1709 &PathType);
1710#else
1711 Length = 0;
1712#endif
1713 if (!(Length) || (Length > FullPathName->Length))
1714 {
1715 /* Fail */
1716 LdrpFreeUnicodeString(FullPathName);
1718 }
1719 else
1720 {
1721 /* Return the expanded name */
1722 *ExpandedName = FullPathName;
1723 FullPathName->Length = (USHORT)Length;
1724 }
1725
1726Quickie:
1727 /* FIXME: Unlock the PEB */
1728 //RtlLeaveCriticalSection(&FastPebLock);
1729
1730 /* Display debug output if snaps are on */
1731 if (ShowSnaps)
1732 {
1733 /* Check which output to use -- failure or success */
1734 if (NT_SUCCESS(Status))
1735 {
1738 "LDR: %s - Expanded to %wZ\n",
1740 *ExpandedName);
1741 }
1742 else
1743 {
1746 "LDR: %s - Failed to expand %wZ; 0x%08x\n",
1748 OriginalName,
1749 Status);
1750 }
1751 }
1752
1753 /* If we failed, return NULL */
1754 if (!NT_SUCCESS(Status)) *ExpandedName = NULL;
1755
1756 /* Return status */
1757 return Status;
1758}
1759
1761NTAPI
1763 IN PWCHAR DllName,
1764 IN PUNICODE_STRING PathName,
1765 IN PUNICODE_STRING FullPathName,
1766 IN PUNICODE_STRING *ExpandedName)
1767{
1769 PWCHAR ActualSearchPath = *SearchPath;
1772 PWCHAR Buffer, BufEnd = NULL;
1773 ULONG Length = 0;
1774 WCHAR p;
1775 //PWCHAR pp;
1776
1777 /* Check if we don't have a search path */
1778 if (!ActualSearchPath) *SearchPath = LdrpDefaultPath.Buffer;
1779
1780 /* Display debug output if snaps are on */
1781 if (ShowSnaps)
1782 {
1785 "LDR: %s - Looking for %ws in %ws\n",
1787 DllName,
1788 *SearchPath);
1789 }
1790
1791 /* Check if we're dealing with a relative path */
1793 {
1794 /* Good, we're not. Create the name string */
1796 if (!NT_SUCCESS(Status)) goto Quickie;
1797
1798 /* Make sure it exists */
1799 #if 0
1801 {
1802 /* It doesn't, fail */
1804 goto Quickie;
1805 }
1806 #endif
1807
1808 /* Resolve the full name */
1810 PathName,
1811 FullPathName,
1812 ExpandedName);
1813 goto Quickie;
1814 }
1815
1816 /* FIXME: Handle relative case semicolon-lookup here */
1817
1818 /* Calculate length */
1819 Length += (ULONG)wcslen(DllName) + 1;
1821 {
1822 /* Too long, fail */
1824 goto Quickie;
1825 }
1826
1827 /* Allocate buffer */
1828 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR));
1829 if (!Buffer)
1830 {
1831 /* Fail */
1833 goto Quickie;
1834 }
1835
1836 /* FIXME: Setup TestName here */
1838 BufEnd = Buffer;
1839
1840 /* Start loop */
1841 do
1842 {
1843 /* Get character */
1844 p = *ActualSearchPath;
1845 if (!(p) || (p == ';'))
1846 {
1847 /* FIXME: We don't have a character, or is a semicolon.*/
1848
1849 /* Display debug output if snaps are on */
1850 if (ShowSnaps)
1851 {
1854 "LDR: %s - Looking for %ws\n",
1856 Buffer);
1857 }
1858
1859 /* Sanity check */
1860 TestName.Length = (USHORT)ALIGN_DOWN((BufEnd - Buffer), WCHAR);
1861#if 0
1862 ASSERT(TestName.Length < TestName.MaximumLength);
1863#endif
1864
1865 /* Check if the file exists */
1866 #if 0
1868 #endif
1869 {
1870 /* It does. Reallocate the buffer */
1871 TestName.MaximumLength = (USHORT)ALIGN_DOWN((BufEnd - Buffer), WCHAR) + sizeof(WCHAR);
1872 TestName.Buffer = RtlReAllocateHeap(RtlGetProcessHeap(),
1873 0,
1874 Buffer,
1875 TestName.MaximumLength);
1876 if (!TestName.Buffer)
1877 {
1878 /* Keep the old one */
1879 TestName.Buffer = Buffer;
1880 }
1881 else
1882 {
1883 /* Update buffer */
1884 Buffer = TestName.Buffer;
1885 }
1886
1887 /* Make sure we have a buffer at least */
1888 ASSERT(TestName.Buffer);
1889
1890 /* Resolve the name */
1891 *SearchPath = ActualSearchPath++;
1893 PathName,
1894 FullPathName,
1895 ExpandedName);
1896 break;
1897 }
1898
1899 /* Update buffer end */
1900 BufEnd = Buffer;
1901
1902 /* Update string position */
1903 //pp = ActualSearchPath++;
1904 }
1905 else
1906 {
1907 /* Otherwise, write the character */
1908 *BufEnd = p;
1909 BufEnd++;
1910 }
1911
1912 /* Check if the string is empty, meaning we're done */
1913 if (!(*ActualSearchPath)) TryAgain = TRUE;
1914
1915 /* Advance in the string */
1916 ActualSearchPath++;
1917 } while (!TryAgain);
1918
1919 /* Check if we had a buffer and free it */
1920 if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1921
1922Quickie:
1923 /* Check if we got here through failure */
1924 if (!NT_SUCCESS(Status)) *ExpandedName = NULL;
1925
1926 /* Display debug output if snaps are on */
1927 if (ShowSnaps)
1928 {
1929 /* Check which output to use -- failure or success */
1930 if (NT_SUCCESS(Status))
1931 {
1934 "LDR: %s - Returning %wZ\n",
1936 *ExpandedName);
1937 }
1938 else
1939 {
1942 "LDR: %s - Unable to locate %ws in %ws: 0x%08x\n",
1944 DllName,
1945 ActualSearchPath,
1946 Status);
1947 }
1948 }
1949
1950 /* Return status */
1951 return Status;
1952}
1953
1954
1955/* NOTE: This function is b0rked and in the process of being slowly unf*cked */
1956BOOLEAN
1957NTAPI
1959 IN PUNICODE_STRING DllName,
1960 IN BOOLEAN Flag,
1961 IN BOOLEAN RedirectedDll,
1962 OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
1963{
1964 ULONG HashIndex;
1965 PLIST_ENTRY ListHead, ListEntry;
1966 PLDR_DATA_TABLE_ENTRY CurEntry;
1967 BOOLEAN FullPath = FALSE;
1968 PWCHAR wc;
1969 WCHAR NameBuf[266];
1970 UNICODE_STRING FullDllName, NtPathName;
1971 ULONG Length;
1974 HANDLE FileHandle, SectionHandle;
1976 PVOID ViewBase = NULL;
1977 SIZE_T ViewSize = 0;
1978 PIMAGE_NT_HEADERS NtHeader, NtHeader2;
1979 DPRINT("LdrpCheckForLoadedDll('%S' '%wZ' %u %u %p)\n", DllPath ? ((ULONG_PTR)DllPath == 1 ? L"" : DllPath) : L"", DllName, Flag, RedirectedDll, LdrEntry);
1980
1981 /* Check if a dll name was provided */
1982 if (!(DllName->Buffer) || !(DllName->Buffer[0])) return FALSE;
1983
1984 /* FIXME: Warning, "Flag" is used as magic instead of "Static" */
1985 /* FIXME: Warning, code does not support redirection at all */
1986
1987 /* Look in the hash table if flag was set */
1988lookinhash:
1989 if (Flag /* the second check is a hack */ && !RedirectedDll)
1990 {
1991 /* FIXME: if we get redirected dll it means that we also get a full path so we need to find its filename for the hash lookup */
1992
1993 /* Get hash index */
1994 HashIndex = LDR_GET_HASH_ENTRY(DllName->Buffer[0]);
1995
1996 /* Traverse that list */
1997 ListHead = &LdrpHashTable[HashIndex];
1998 ListEntry = ListHead->Flink;
1999 while (ListEntry != ListHead)
2000 {
2001 /* Get the current entry */
2002 CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, HashLinks);
2003
2004 /* Check base name of that module */
2005 if (RtlEqualUnicodeString(DllName, &CurEntry->BaseDllName, TRUE))
2006 {
2007 /* It matches, return it */
2008 *LdrEntry = CurEntry;
2009 return TRUE;
2010 }
2011
2012 /* Advance to the next entry */
2013 ListEntry = ListEntry->Flink;
2014 }
2015
2016 /* Module was not found, return failure */
2017 return FALSE;
2018 }
2019
2020 /* Check if this is a redirected DLL */
2021 if (RedirectedDll)
2022 {
2023 /* Redirected dlls already have a full path */
2024 FullPath = TRUE;
2025 FullDllName = *DllName;
2026 }
2027 else
2028 {
2029 /* Check if there is a full path in this DLL */
2030 wc = DllName->Buffer;
2031 while (*wc)
2032 {
2033 /* Check for a slash in the current position*/
2034 if ((*wc == L'\\') || (*wc == L'/'))
2035 {
2036 /* Found the slash, so dll name contains path */
2037 FullPath = TRUE;
2038
2039 /* Setup full dll name string */
2040 FullDllName.Buffer = NameBuf;
2041
2042 /* FIXME: This is from the Windows 2000 loader, not XP/2003, we should call LdrpSearchPath */
2044 DllName->Buffer,
2045 NULL,
2046 sizeof(NameBuf) - sizeof(UNICODE_NULL),
2047 FullDllName.Buffer,
2048 NULL);
2049
2050 /* Check if that was successful */
2051 if (!(Length) || (Length > (sizeof(NameBuf) - sizeof(UNICODE_NULL))))
2052 {
2053 if (ShowSnaps)
2054 {
2055 DPRINT1("LDR: LdrpCheckForLoadedDll - Unable To Locate %wZ: 0x%08x\n",
2056 &DllName, Length);
2057 }
2058 }
2059
2060 /* Full dll name is found */
2061 FullDllName.Length = Length;
2062 FullDllName.MaximumLength = FullDllName.Length + sizeof(UNICODE_NULL);
2063 break;
2064 }
2065
2066 wc++;
2067 }
2068 }
2069
2070 /* Go check the hash table */
2071 if (!FullPath)
2072 {
2073 Flag = TRUE;
2074 goto lookinhash;
2075 }
2076
2077 /* FIXME: Warning, activation context missing */
2078 DPRINT("Warning, activation context missing\n");
2079
2080 /* NOTE: From here on down, everything looks good */
2081
2082 /* Loop the module list */
2083 ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
2084 ListEntry = ListHead->Flink;
2085 while (ListEntry != ListHead)
2086 {
2087 /* Get the current entry and advance to the next one */
2088 CurEntry = CONTAINING_RECORD(ListEntry,
2090 InLoadOrderLinks);
2091 ListEntry = ListEntry->Flink;
2092
2093 /* Check if it's being unloaded */
2094 if (!CurEntry->InMemoryOrderLinks.Flink) continue;
2095
2096 /* Check if name matches */
2098 &CurEntry->FullDllName,
2099 TRUE))
2100 {
2101 /* Found it */
2102 *LdrEntry = CurEntry;
2103 return TRUE;
2104 }
2105 }
2106
2107 /* Convert given path to NT path */
2109 &NtPathName,
2110 NULL,
2111 NULL))
2112 {
2113 /* Fail if conversion failed */
2114 return FALSE;
2115 }
2116
2117 /* Initialize object attributes and open it */
2119 &NtPathName,
2121 NULL,
2122 NULL);
2126 &Iosb,
2129
2130 /* Free NT path name */
2131 RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
2132
2133 /* If opening the file failed - return failure */
2134 if (!NT_SUCCESS(Status)) return FALSE;
2135
2136 /* Create a section for this file */
2137 Status = NtCreateSection(&SectionHandle,
2141 NULL,
2142 NULL,
2144 SEC_COMMIT,
2145 FileHandle);
2146
2147 /* Close file handle */
2149
2150 /* If creating section failed - return failure */
2151 if (!NT_SUCCESS(Status)) return FALSE;
2152
2153 /* Map view of this section */
2154 Status = ZwMapViewOfSection(SectionHandle,
2156 &ViewBase,
2157 0,
2158 0,
2159 NULL,
2160 &ViewSize,
2161 ViewShare,
2162 0,
2163 PAGE_EXECUTE);
2164
2165 /* Close section handle */
2166 NtClose(SectionHandle);
2167
2168 /* If section mapping failed - return failure */
2169 if (!NT_SUCCESS(Status)) return FALSE;
2170
2171 /* Get pointer to the NT header of this section */
2172 Status = RtlImageNtHeaderEx(0, ViewBase, ViewSize, &NtHeader);
2173 if (!(NT_SUCCESS(Status)) || !(NtHeader))
2174 {
2175 /* Unmap the section and fail */
2177 return FALSE;
2178 }
2179
2180 /* Go through the list of modules again */
2181 ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
2182 ListEntry = ListHead->Flink;
2183 while (ListEntry != ListHead)
2184 {
2185 /* Get the current entry and advance to the next one */
2186 CurEntry = CONTAINING_RECORD(ListEntry,
2188 InLoadOrderLinks);
2189 ListEntry = ListEntry->Flink;
2190
2191 /* Check if it's in the process of being unloaded */
2192 if (!CurEntry->InMemoryOrderLinks.Flink) continue;
2193
2194 /* The header is untrusted, use SEH */
2195 _SEH2_TRY
2196 {
2197 /* Check if timedate stamp and sizes match */
2198 if ((CurEntry->TimeDateStamp == NtHeader->FileHeader.TimeDateStamp) &&
2199 (CurEntry->SizeOfImage == NtHeader->OptionalHeader.SizeOfImage))
2200 {
2201 /* Time, date and size match. Let's compare their headers */
2202 NtHeader2 = RtlImageNtHeader(CurEntry->DllBase);
2203 if (RtlCompareMemory(NtHeader2, NtHeader, sizeof(IMAGE_NT_HEADERS)))
2204 {
2205 /* Headers match too! Finally ask the kernel to compare mapped files */
2206 Status = ZwAreMappedFilesTheSame(CurEntry->DllBase, ViewBase);
2207 if (NT_SUCCESS(Status))
2208 {
2209 /* This is our entry!, unmap and return success */
2210 *LdrEntry = CurEntry;
2212 _SEH2_YIELD(return TRUE;)
2213 }
2214 }
2215 }
2216 }
2218 {
2219 _SEH2_YIELD(break;)
2220 }
2221 _SEH2_END;
2222 }
2223
2224 /* Unmap the section and fail */
2226 return FALSE;
2227}
2228
2230NTAPI
2233 _In_opt_ _When_(Ordinal == 0, _Notnull_) PANSI_STRING Name,
2234 _In_opt_ _When_(Name == NULL, _In_range_(>, 0)) ULONG Ordinal,
2235 _Out_ PVOID *ProcedureAddress,
2236 _In_ BOOLEAN ExecuteInit)
2237{
2239 UCHAR ImportBuffer[64]; // 128 since NT6.2
2240 PLDR_DATA_TABLE_ENTRY LdrEntry;
2241 IMAGE_THUNK_DATA Thunk;
2242 PVOID ImageBase;
2243 PIMAGE_IMPORT_BY_NAME ImportName = NULL;
2244 PIMAGE_EXPORT_DIRECTORY ExportDir;
2245 ULONG ExportDirSize, Length;
2247
2248 /* Show debug message */
2249 if (ShowSnaps) DPRINT1("LDR: LdrGetProcedureAddress by ");
2250
2251 /* Check if we got a name */
2252 if (Name)
2253 {
2254 /* Show debug message */
2255 if (ShowSnaps) DbgPrint("NAME - %s\n", Name->Buffer);
2256
2257 /* Make sure it's not too long */
2258 Length = Name->Length +
2259 sizeof(CHAR) +
2262 {
2263 /* Won't have enough space to add the hint */
2264 return STATUS_NAME_TOO_LONG;
2265 }
2266
2267 /* Check if our buffer is large enough */
2268 if (Length > sizeof(ImportBuffer))
2269 {
2270 /* Allocate from heap, plus 2 bytes for the Hint */
2271 ImportName = RtlAllocateHeap(RtlGetProcessHeap(),
2272 0,
2273 Length);
2274 if (!ImportName)
2275 {
2276 /* Return STATUS_INSUFFICIENT_RESOURCES since NT6.2 */
2278 }
2279 }
2280 else
2281 {
2282 /* Use our internal buffer */
2283 ImportName = (PIMAGE_IMPORT_BY_NAME)ImportBuffer;
2284 }
2285
2286 /* Clear the hint */
2287 ImportName->Hint = 0;
2288
2289 /* Copy the name and null-terminate it */
2290 RtlCopyMemory(ImportName->Name, Name->Buffer, Name->Length);
2291 ImportName->Name[Name->Length] = ANSI_NULL;
2292
2293 /* Clear the high bit */
2294 ImageBase = ImportName;
2295 Thunk.u1.AddressOfData = 0;
2296 }
2297 else
2298 {
2299 /* Do it by ordinal */
2300 ImageBase = NULL;
2301
2302 /* Show debug message */
2303 if (ShowSnaps) DbgPrint("ORDINAL - %lx\n", Ordinal);
2304
2305 /* Make sure an ordinal was given */
2306 if (!Ordinal)
2307 {
2308 /* No ordinal */
2309 DPRINT1("No ordinal and no name\n");
2311 }
2312
2313 /* Set the original flag in the thunk */
2314 Thunk.u1.Ordinal = Ordinal | IMAGE_ORDINAL_FLAG;
2315 }
2316
2317 /* Acquire lock unless we are initting */
2319
2320 _SEH2_TRY
2321 {
2322 /* Try to find the loaded DLL */
2324 {
2325 /* Invalid base */
2326 DPRINT1("Invalid base address %p\n", BaseAddress);
2328 _SEH2_YIELD(goto Quickie;)
2329 }
2330
2331 /* Get the pointer to the export directory */
2332 ExportDir = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
2333 TRUE,
2335 &ExportDirSize);
2336
2337 if (!ExportDir)
2338 {
2339 DPRINT1("Image %wZ has no exports, but were trying to get procedure %Z. BaseAddress asked 0x%p, got entry BA 0x%p\n",
2340 &LdrEntry->BaseDllName, Name, BaseAddress, LdrEntry->DllBase);
2342 _SEH2_YIELD(goto Quickie;)
2343 }
2344
2345 /* Now get the thunk */
2346 Status = LdrpSnapThunk(LdrEntry->DllBase,
2347 ImageBase,
2348 &Thunk,
2349 &Thunk,
2350 ExportDir,
2351 ExportDirSize,
2352 FALSE,
2353 NULL);
2354
2355 /* Finally, see if we're supposed to run the init routines */
2356 if ((NT_SUCCESS(Status)) && (ExecuteInit))
2357 {
2358 /*
2359 * It's possible a forwarded entry had us load the DLL. In that case,
2360 * then we will call its DllMain. Use the last loaded DLL for this.
2361 */
2362 Entry = NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Blink;
2363 LdrEntry = CONTAINING_RECORD(Entry,
2365 InInitializationOrderLinks);
2366
2367 /* Make sure we didn't process it yet*/
2368 if (!(LdrEntry->Flags & LDRP_ENTRY_PROCESSED))
2369 {
2370 /* Call the init routine */
2371 _SEH2_TRY
2372 {
2374 }
2376 {
2377 /* Get the exception code */
2379 }
2380 _SEH2_END;
2381 }
2382 }
2383
2384 /* Make sure we're OK till here */
2385 if (NT_SUCCESS(Status))
2386 {
2387 /* Return the address */
2388 *ProcedureAddress = (PVOID)Thunk.u1.Function;
2389 }
2390 }
2392 {
2393 /* Just ignore exceptions */
2394 }
2395 _SEH2_END;
2396
2397Quickie:
2398 /* Cleanup */
2399 if (ImportName && (ImportName != (PIMAGE_IMPORT_BY_NAME)ImportBuffer))
2400 {
2401 /* We allocated from heap, free it */
2402 RtlFreeHeap(RtlGetProcessHeap(), 0, ImportName);
2403 }
2404
2405 /* Release the CS if we entered it */
2407
2408 /* We're done */
2409 return Status;
2410}
2411
2413NTAPI
2416 IN PULONG DllCharacteristics OPTIONAL,
2417 IN PUNICODE_STRING DllName,
2419 IN BOOLEAN CallInit)
2420{
2421 PPEB Peb = NtCurrentPeb();
2423 const WCHAR *p;
2424 BOOLEAN GotExtension;
2425 WCHAR c;
2426 WCHAR NameBuffer[MAX_PATH + 6];
2427 UNICODE_STRING RawDllName;
2428 PLDR_DATA_TABLE_ENTRY LdrEntry;
2429 BOOLEAN InInit = LdrpInLdrInit;
2430
2431 /* Save the Raw DLL Name */
2432 if (DllName->Length >= sizeof(NameBuffer)) return STATUS_NAME_TOO_LONG;
2433 RtlInitEmptyUnicodeString(&RawDllName, NameBuffer, sizeof(NameBuffer));
2434 RtlCopyUnicodeString(&RawDllName, DllName);
2435
2436 /* Find the extension, if present */
2437 /* NOTE: Access violation is expected here in some cases (Buffer[-1]) */
2438 p = DllName->Buffer + DllName->Length / sizeof(WCHAR) - 1;
2439 GotExtension = FALSE;
2440 while (p >= DllName->Buffer)
2441 {
2442 c = *p--;
2443 if (c == L'.')
2444 {
2445 GotExtension = TRUE;
2446 break;
2447 }
2448 else if (c == L'\\')
2449 {
2450 break;
2451 }
2452 }
2453
2454 /* If no extension was found, add the default extension */
2455 if (!GotExtension)
2456 {
2457 /* Check that we have space to add one */
2458 if ((DllName->Length + LdrApiDefaultExtension.Length + sizeof(UNICODE_NULL)) >=
2459 sizeof(NameBuffer))
2460 {
2461 /* No space to add the extension */
2464 "LDR: %s - Dll name missing extension; with extension "
2465 "added the name is too long\n"
2466 " DllName: (@ %p) \"%wZ\"\n"
2467 " DllName->Length: %u\n",
2469 DllName,
2470 DllName,
2471 DllName->Length);
2472 return STATUS_NAME_TOO_LONG;
2473 }
2474
2475 /* Add it. Needs to be null terminated, thus the length check above */
2478 }
2479
2480 /* Check for init flag and acquire lock */
2482
2483 _SEH2_TRY
2484 {
2485 /* Show debug message */
2486 if (ShowSnaps)
2487 {
2488 DPRINT1("LDR: LdrLoadDll, loading %wZ from %ws\n",
2489 &RawDllName,
2490 DllPath ? DllPath : L"");
2491 }
2492
2493 /* Check if the DLL is already loaded */
2495 &RawDllName,
2496 FALSE,
2497 Redirected,
2498 &LdrEntry))
2499 {
2500 /* Map it */
2502 DllPath,
2503 NameBuffer,
2504 DllCharacteristics,
2505 FALSE,
2506 Redirected,
2507 &LdrEntry);
2508 if (!NT_SUCCESS(Status))
2510
2511 /* FIXME: Need to mark the DLL range for the stack DB */
2512 //RtlpStkMarkDllRange(LdrEntry);
2513
2514 /* Check if IMAGE_FILE_EXECUTABLE_IMAGE was provided */
2515 if ((DllCharacteristics) &&
2516 (*DllCharacteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
2517 {
2518 /* This is not a DLL, so remove such data */
2519 LdrEntry->EntryPoint = NULL;
2520 LdrEntry->Flags &= ~LDRP_IMAGE_DLL;
2521 }
2522
2523 /* Make sure it's a DLL */
2524 if (LdrEntry->Flags & LDRP_IMAGE_DLL)
2525 {
2526 /* Check if this is a .NET Image */
2527 if (!(LdrEntry->Flags & LDRP_COR_IMAGE))
2528 {
2529 /* Walk the Import Descriptor */
2531 }
2532
2533 /* Update load count, unless it's locked */
2534 if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
2536
2537 /* Check if we failed */
2538 if (!NT_SUCCESS(Status))
2539 {
2540 /* Clear entrypoint, and insert into list */
2541 LdrEntry->EntryPoint = NULL;
2543 &LdrEntry->InInitializationOrderLinks);
2544
2545 /* Cancel the load */
2547
2548 /* Unload the DLL */
2549 if (ShowSnaps)
2550 {
2551 DbgPrint("LDR: Unloading %wZ due to error %x walking "
2552 "import descriptors\n",
2553 DllName,
2554 Status);
2555 }
2556 LdrUnloadDll(LdrEntry->DllBase);
2557
2558 /* Return the error */
2560 }
2561 }
2562 else if (LdrEntry->LoadCount != 0xFFFF)
2563 {
2564 /* Increase load count */
2565 LdrEntry->LoadCount++;
2566 }
2567
2568 /* Insert it into the list */
2570 &LdrEntry->InInitializationOrderLinks);
2571
2572 /* If we have to run the entrypoint, make sure the DB is ready */
2573 if (CallInit && LdrpLdrDatabaseIsSetup)
2574 {
2575 /* Notify Shim Engine */
2576 if (g_ShimsEnabled)
2577 {
2579 SE_DllLoaded(LdrEntry);
2580 }
2581
2582 /* Run the init routine */
2584 if (!NT_SUCCESS(Status))
2585 {
2586 /* Failed, unload the DLL */
2587 if (ShowSnaps)
2588 {
2589 DbgPrint("LDR: Unloading %wZ because either its init "
2590 "routine or one of its static imports failed; "
2591 "status = 0x%08lx\n",
2592 DllName,
2593 Status);
2594 }
2595 LdrUnloadDll(LdrEntry->DllBase);
2596 }
2597 }
2598 else
2599 {
2600 /* The DB isn't ready, which means we were loaded because of a forwarder */
2602 }
2603 }
2604 else
2605 {
2606 /* We were already loaded. Are we a DLL? */
2607 if ((LdrEntry->Flags & LDRP_IMAGE_DLL) && (LdrEntry->LoadCount != 0xFFFF))
2608 {
2609 /* Increase load count */
2610 LdrEntry->LoadCount++;
2612
2613 /* Clear the load in progress */
2615 }
2616 else
2617 {
2618 /* Not a DLL, just increase the load count */
2619 if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
2620 }
2621 }
2622
2623 }
2625 {
2626 /* Release the lock */
2628 }
2629 _SEH2_END;
2630
2631 /* Check for success */
2632 if (NT_SUCCESS(Status))
2633 {
2634 /* Return the base address */
2635 *BaseAddress = LdrEntry->DllBase;
2636 }
2637 else
2638 {
2639 /* Nothing found */
2640 *BaseAddress = NULL;
2641 }
2642
2643 /* Return status */
2644 return Status;
2645}
2646
2647ULONG
2648NTAPI
2650{
2651 PLIST_ENTRY ListHead, Entry;
2652 PLDR_DATA_TABLE_ENTRY LdrEntry;
2653 ULONG ModulesCount = 0;
2654
2655 /* Traverse the init list */
2656 ListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
2657 Entry = ListHead->Flink;
2658 while (Entry != ListHead)
2659 {
2660 /* Get the loader entry */
2661 LdrEntry = CONTAINING_RECORD(Entry,
2663 InInitializationOrderLinks);
2664
2665 /* Clear load in progress flag */
2666 LdrEntry->Flags &= ~LDRP_LOAD_IN_PROGRESS;
2667
2668 /* Check for modules with entry point count but not processed yet */
2669 if ((LdrEntry->EntryPoint) &&
2670 !(LdrEntry->Flags & LDRP_ENTRY_PROCESSED))
2671 {
2672 /* Increase counter */
2673 ModulesCount++;
2674 }
2675
2676 /* Advance to the next entry */
2677 Entry = Entry->Flink;
2678 }
2679
2680 /* Return final count */
2681 return ModulesCount;
2682}
2683
2685{
2688 PVOID Address;
2690 /* Skip Dll init */
2692 return NT_SUCCESS(Status) ? Address : NULL;
2693}
2694
2695VOID
2696NTAPI
2698{
2701 PVOID SE_InstallBeforeInit = LdrpGetShimEngineFunction("SE_InstallBeforeInit");
2702 PVOID SE_InstallAfterInit = LdrpGetShimEngineFunction("SE_InstallAfterInit");
2703 PVOID SE_ProcessDying = LdrpGetShimEngineFunction("SE_ProcessDying");
2704
2706 {
2713 }
2714 else
2715 {
2717 }
2718}
2719
2720VOID
2721NTAPI
2723{
2724 PLIST_ENTRY ListHead, Next;
2725 PLDR_DATA_TABLE_ENTRY LdrEntry;
2726
2727 ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
2728 Next = ListHead->Flink;
2729 while (Next != ListHead)
2730 {
2731 LdrEntry = CONTAINING_RECORD(Next, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
2732
2733 if (g_pShimEngineModule == LdrEntry->DllBase)
2734 {
2735 if (LdrEntry->EntryPoint)
2736 {
2737 _SEH2_TRY
2738 {
2739 LdrpCallInitRoutine(LdrEntry->EntryPoint, LdrEntry->DllBase, Reason, NULL);
2740 }
2742 {
2743 DPRINT1("WARNING: Exception 0x%x during LdrpRunShimEngineInitRoutine(%u)\n",
2745 }
2746 _SEH2_END;
2747 }
2748 return;
2749 }
2750
2751 Next = Next->Flink;
2752 }
2753}
2754
2755VOID
2756NTAPI
2758{
2759 UNICODE_STRING ShimLibraryName;
2760 PVOID ShimLibrary;
2762 RtlInitUnicodeString(&ShimLibraryName, ImageName);
2763 /* We should NOT pass CallInit = TRUE!
2764 If we do this, other init routines will be called before we get a chance to shim stuff.. */
2765 Status = LdrpLoadDll(FALSE, NULL, NULL, &ShimLibraryName, &ShimLibrary, FALSE);
2766 if (NT_SUCCESS(Status))
2767 {
2768 g_pShimEngineModule = ShimLibrary;
2771 if (g_ShimsEnabled)
2772 {
2775 SE_InstallBeforeInit(ProcessImage, pShimData);
2776 }
2777 }
2778}
2779
2780VOID
2781NTAPI
2783{
2784 /* Make sure we do not call into the shim engine anymore */
2789}
2790
2791/* EOF */
NTSTATUS NTAPI NtUnmapViewOfSection(IN HANDLE ProcessHandle, IN PVOID BaseAddress)
Definition: section.c:3481
NTSTATUS NTAPI NtCreateSection(OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize OPTIONAL, IN ULONG SectionPageProtection OPTIONAL, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL)
Definition: section.c:3074
NTSTATUS NTAPI NtOpenSection(OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: section.c:3202
NTSTATUS NTAPI NtMapViewOfSection(IN HANDLE SectionHandle, IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect)
Definition: section.c:3255
#define NtCurrentPeb()
Definition: FLS.c:22
#define BufSize
Definition: FsRtlTunnel.c:28
unsigned char BOOLEAN
static IN ULONG IN PWSTR OUT PCWSTR OUT PBOOLEAN OUT PATH_TYPE_AND_UNKNOWN * PathType
static IN ULONG IN PWSTR OUT PCWSTR OUT PBOOLEAN InvalidName
#define VOID
Definition: acefi.h:82
ACPI_BUFFER *RetBuffer ACPI_BUFFER *RetBuffer char ACPI_WALK_RESOURCE_CALLBACK void *Context ACPI_BUFFER *RetBuffer UINT16 ACPI_RESOURCE **ResourcePtr ACPI_GENERIC_ADDRESS *Reg UINT32 *ReturnValue UINT8 UINT8 *Slp_TypB ACPI_PHYSICAL_ADDRESS PhysicalAddress64 UINT32 UINT32 *TimeElapsed UINT32 ACPI_STATUS const char UINT32 ACPI_STATUS const char UINT32 const char * FunctionName
Definition: acpixf.h:1279
#define DPFLTR_ERROR_LEVEL
Definition: main.cpp:32
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define DPRINT1
Definition: precomp.h:8
#define CHAR(Char)
@ TryAgain
Definition: bl.h:896
NTSTATUS NTAPI RtlImageNtHeaderEx(_In_ ULONG Flags, _In_ PVOID Base, _In_ ULONG64 Size, _Out_ PIMAGE_NT_HEADERS *OutHeaders)
Definition: libsupp.c:32
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:616
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:634
struct _LDR_DATA_TABLE_ENTRY * PLDR_DATA_TABLE_ENTRY
_In_ CDROM_SCAN_FOR_SPECIAL_INFO _In_ PCDROM_SCAN_FOR_SPECIAL_HANDLER Function
Definition: cdrom.h:1156
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
PIMAGE_NT_HEADERS WINAPI ImageNtHeader(_In_ PVOID)
LPWSTR Name
Definition: desk.c:124
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define IMAGE_DIRECTORY_ENTRY_EXPORT
Definition: compat.h:151
#define PAGE_READONLY
Definition: compat.h:138
#define SECTION_MAP_READ
Definition: compat.h:139
#define DLL_PROCESS_ATTACH
Definition: compat.h:131
#define DLL_PROCESS_DETACH
Definition: compat.h:130
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define RtlImageDirectoryEntryToData
Definition: compat.h:809
#define RtlImageNtHeader
Definition: compat.h:806
#define MAX_PATH
Definition: compat.h:34
#define FILE_SHARE_READ
Definition: compat.h:136
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
PPEB Peb
Definition: dllmain.c:27
@ DPFLTR_LDR_ID
Definition: dpfilter.h:113
#define __FUNCTION__
Definition: types.h:116
return Iosb
Definition: create.c:4403
#define ULONG_PTR
Definition: config.h:101
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
UNICODE_STRING * PUNICODE_STRING
Definition: env_spec_w32.h:373
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
Status
Definition: gdiplustypes.h:25
const GLubyte * c
Definition: glext.h:8905
GLfloat GLfloat p
Definition: glext.h:8902
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define DbgPrint
Definition: hal.h:12
NTSTATUS NTAPI NtRaiseHardError(IN NTSTATUS ErrorStatus, IN ULONG NumberOfParameters, IN ULONG UnicodeStringParameterMask, IN PULONG_PTR Parameters, IN ULONG ValidResponseOptions, OUT PULONG Response)
Definition: harderr.c:551
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI NTSTATUS WINAPI RtlFindActivationContextSectionString(ULONG, const GUID *, ULONG, const UNICODE_STRING *, PVOID)
Definition: actctx.c:5874
NTSYSAPI PVOID WINAPI RtlReAllocateHeap(HANDLE, ULONG, PVOID, SIZE_T)
Definition: heap.c:2686
NTSYSAPI NTSTATUS WINAPI RtlInitUnicodeStringEx(PUNICODE_STRING, PCWSTR)
NTSYSAPI void WINAPI RtlReleaseActivationContext(HANDLE)
Definition: actctx.c:5384
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define NtCurrentTeb
#define DbgPrintEx(cmpid, lvl, fmt,...)
Definition: kdinit.c:24
#define c
Definition: ke_i.h:80
NTSTATUS NTAPI LdrUnloadDll(_In_ PVOID BaseAddress)
Definition: ldrapi.c:1291
#define LDRP_UNLOAD_IN_PROGRESS
Definition: ldrtypes.h:47
#define LDRP_REDIRECTED
Definition: ldrtypes.h:62
#define LDRP_ENTRY_PROCESSED
Definition: ldrtypes.h:48
BOOLEAN(NTAPI * PDLL_INIT_ROUTINE)(_In_ PVOID DllHandle, _In_ ULONG Reason, _In_opt_ PCONTEXT Context)
Definition: ldrtypes.h:271
#define LDR_DLL_NOTIFICATION_REASON_LOADED
Definition: ldrtypes.h:203
_In_ PCWSTR _Out_ PVOID * ActCtx
Definition: ldrtypes.h:264
#define LDRP_LOAD_NOTIFICATIONS_SENT
Definition: ldrtypes.h:43
#define LDRP_IMAGE_NOT_AT_BASE
Definition: ldrtypes.h:55
#define LDRP_STATIC_LINK
Definition: ldrtypes.h:38
#define LDRP_COR_IMAGE
Definition: ldrtypes.h:56
_In_ PCWSTR FullDllName
Definition: ldrtypes.h:264
#define LDRP_IMAGE_DLL
Definition: ldrtypes.h:39
#define LDRP_LOAD_IN_PROGRESS
Definition: ldrtypes.h:46
VOID NTAPI LdrpCallTlsInitializers(IN PLDR_DATA_TABLE_ENTRY LdrEntry, IN ULONG Reason)
Definition: ldrutils.c:447
BOOLEAN NTAPI LdrpResolveDllName(PWSTR DllPath, PWSTR DllName, PUNICODE_STRING FullDllName, PUNICODE_STRING BaseDllName)
Definition: ldrutils.c:673
VOID NTAPI LdrpUnloadShimEngine()
Definition: ldrutils.c:2782
PVOID g_pfnSE_InstallBeforeInit
Definition: ldrutils.c:25
NTSTATUS NTAPI LdrpMapDll(IN PWSTR SearchPath OPTIONAL, IN PWSTR DllPath2, IN PWSTR DllName OPTIONAL, IN PULONG DllCharacteristics, IN BOOLEAN Static, IN BOOLEAN Redirect, OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry)
Definition: ldrutils.c:997
NTSTATUS NTAPI LdrpAllocateUnicodeString(IN OUT PUNICODE_STRING StringOut, IN ULONG Length)
Definition: ldrutils.c:33
PVOID g_pfnSE_InstallAfterInit
Definition: ldrutils.c:26
VOID NTAPI LdrpLoadShimEngine(IN PWSTR ImageName, IN PUNICODE_STRING ProcessImage, IN PVOID pShimData)
Definition: ldrutils.c:2757
BOOLEAN NTAPI LdrpCheckForLoadedDllHandle(IN PVOID Base, OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
Definition: ldrutils.c:1600
NTSTATUS NTAPI LdrpLoadDll(IN BOOLEAN Redirected, IN PWSTR DllPath OPTIONAL, IN PULONG DllCharacteristics OPTIONAL, IN PUNICODE_STRING DllName, OUT PVOID *BaseAddress, IN BOOLEAN CallInit)
Definition: ldrutils.c:2414
PVOID g_pShimEngineModule
Definition: ldrutils.c:22
PVOID g_pfnSE_ProcessDying
Definition: ldrutils.c:27
NTSTATUS NTAPI LdrpSearchPath(IN PWCHAR *SearchPath, IN PWCHAR DllName, IN PUNICODE_STRING PathName, IN PUNICODE_STRING FullPathName, IN PUNICODE_STRING *ExpandedName)
Definition: ldrutils.c:1762
PVOID NTAPI LdrpFetchAddressOfEntryPoint(IN PVOID ImageBase)
Definition: ldrutils.c:767
VOID NTAPI LdrpUpdateLoadCount2(IN PLDR_DATA_TABLE_ENTRY LdrEntry, IN ULONG Flags)
Definition: ldrutils.c:434
VOID NTAPI LdrpRunShimEngineInitRoutine(IN ULONG Reason)
Definition: ldrutils.c:2722
VOID NTAPI LdrpFinalizeAndDeallocateDataTableEntry(IN PLDR_DATA_TABLE_ENTRY Entry)
Definition: ldrutils.c:1577
NTSTATUS NTAPI LdrpCheckForKnownDll(PWSTR DllName, PUNICODE_STRING FullDllName, PUNICODE_STRING BaseDllName, HANDLE *SectionHandle)
Definition: ldrutils.c:788
PLDR_DATA_TABLE_ENTRY LdrpGetModuleHandleCache
Definition: ldrutils.c:19
NTSTATUS NTAPI LdrpGetProcedureAddress(_In_ PVOID BaseAddress, _In_opt_ _When_(Ordinal==0, _Notnull_) PANSI_STRING Name, _In_opt_ _When_(Name==NULL, _In_range_(>, 0)) ULONG Ordinal, _Out_ PVOID *ProcedureAddress, _In_ BOOLEAN ExecuteInit)
Definition: ldrutils.c:2231
VOID NTAPI LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry, IN ULONG Flags, OUT PUNICODE_STRING UpdateString)
Definition: ldrutils.c:112
VOID NTAPI LdrpInsertMemoryTableEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: ldrutils.c:1561
NTSTATUS NTAPI LdrpSetProtection(PVOID ViewBase, BOOLEAN Restore)
Definition: ldrutils.c:921
BOOLEAN NTAPI LdrpCheckForLoadedDll(IN PWSTR DllPath, IN PUNICODE_STRING DllName, IN BOOLEAN Flag, IN BOOLEAN RedirectedDll, OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
Definition: ldrutils.c:1958
BOOLEAN NTAPI LdrpCallInitRoutine(IN PDLL_INIT_ROUTINE EntryPoint, IN PVOID BaseAddress, IN ULONG Reason, IN PVOID Context)
Definition: ldrutils.c:100
NTSTATUS NTAPI LdrpCodeAuthzCheckDllAllowed(IN PUNICODE_STRING FullName, IN HANDLE DllHandle)
Definition: ldrutils.c:509
PLDR_DATA_TABLE_ENTRY NTAPI LdrpAllocateDataTableEntry(IN PVOID BaseAddress)
Definition: ldrutils.c:1528
NTSTATUS NTAPI LdrpCreateDllSection(IN PUNICODE_STRING FullName, IN HANDLE DllHandle, IN PULONG DllCharacteristics OPTIONAL, OUT PHANDLE SectionHandle)
Definition: ldrutils.c:518
BOOLEAN g_ShimsEnabled
Definition: ldrutils.c:21
NTSTATUS NTAPI LdrpResolveFullName(IN PUNICODE_STRING OriginalName, IN PUNICODE_STRING PathName, IN PUNICODE_STRING FullPathName, IN PUNICODE_STRING *ExpandedName)
Definition: ldrutils.c:1646
ULONG NTAPI LdrpClearLoadInProgress(VOID)
Definition: ldrutils.c:2649
PVOID LdrpGetShimEngineFunction(PCSZ FunctionName)
Definition: ldrutils.c:2684
PVOID g_pfnSE_DllUnloaded
Definition: ldrutils.c:24
PLDR_DATA_TABLE_ENTRY LdrpLoadedDllHandleCache
Definition: ldrutils.c:19
PVOID g_pfnSE_DllLoaded
Definition: ldrutils.c:23
VOID NTAPI LdrpFreeUnicodeString(IN PUNICODE_STRING StringIn)
Definition: ldrutils.c:84
VOID NTAPI LdrpGetShimEngineInterface()
Definition: ldrutils.c:2697
if(dx< 0)
Definition: linetemp.h:194
#define PCHAR
Definition: match.c:90
#define ASSERT(a)
Definition: mode.c:44
PVOID PVOID PWCHAR PVOID USHORT PULONG Reason
Definition: env.c:47
WCHAR TestName[MAX_PATH]
Definition: main.cpp:13
string StringOut(const string &String, bool forcePrint=true)
Definition: tools.cpp:96
static const char const char * DllPath
Definition: image.c:34
static const char * ImageName
Definition: image.c:34
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSYSAPI NTSTATUS NTAPI ZwRaiseHardError(_In_ NTSTATUS ErrorStatus, _In_ ULONG NumberOfParameters, _In_ ULONG UnicodeStringParameterMask, _In_ PULONG_PTR Parameters, _In_ ULONG ValidResponseOptions, _Out_ PULONG Response)
@ OptionOkCancel
Definition: extypes.h:188
@ OptionOk
Definition: extypes.h:187
@ ResponseCancel
Definition: extypes.h:202
NTSYSAPI NTSTATUS NTAPI ZwFlushInstructionCache(_In_ HANDLE ProcessHandle, _In_ PVOID BaseAddress, _In_ ULONG NumberOfBytesToFlush)
NTSYSAPI NTSTATUS NTAPI ZwQuerySection(_In_ HANDLE SectionHandle, _In_ SECTION_INFORMATION_CLASS SectionInformationClass, _Out_ PVOID SectionInformation, _In_ SIZE_T Length, _Out_opt_ PSIZE_T ResultLength)
NTSYSAPI NTSTATUS NTAPI ZwAreMappedFilesTheSame(_In_ PVOID File1MappedAsAnImage, _In_ PVOID File2MappedAsFile)
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:408
NTSYSAPI NTSTATUS NTAPI ZwProtectVirtualMemory(_In_ HANDLE ProcessHandle, _In_ PVOID *BaseAddress, _In_ SIZE_T *NumberOfBytesToProtect, _In_ ULONG NewAccessProtection, _Out_ PULONG OldAccessProtection)
#define SEC_COMMIT
Definition: mmtypes.h:100
#define SEC_IMAGE
Definition: mmtypes.h:97
@ SectionImageInformation
Definition: mmtypes.h:196
NTSYSAPI RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_U(_In_ PCWSTR Path)
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2478
ULONG NTAPI LdrRelocateImageWithBias(_In_ PVOID BaseAddress, _In_ LONGLONG AdditionalBias, _In_opt_ PCSTR LoaderName, _In_ ULONG Success, _In_ ULONG Conflict, _In_ ULONG Invalid)
Definition: image.c:474
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI ULONG NTAPI RtlDosSearchPath_U(_In_ PCWSTR Path, _In_ PCWSTR FileName, _In_ PCWSTR Extension, _In_ ULONG BufferSize, _Out_ PWSTR Buffer, _Out_ PWSTR *PartName)
NTSYSAPI BOOLEAN NTAPI RtlDosPathNameToNtPathName_U(_In_opt_z_ PCWSTR DosPathName, _Out_ PUNICODE_STRING NtPathName, _Out_opt_ PCWSTR *NtFileNamePart, _Out_opt_ PRTL_RELATIVE_NAME_U DirectoryInfo)
#define RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER
Definition: rtltypes.h:101
@ RtlPathTypeRelative
Definition: rtltypes.h:470
#define _Notnull_
Definition: no_sal2.h:54
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define _In_range_(l, h)
Definition: no_sal2.h:368
#define _When_(c, a)
Definition: no_sal2.h:38
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
#define SECTION_MAP_EXECUTE
Definition: nt_native.h:1290
NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT PHANDLE phFile, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG ShareMode, IN ULONG OpenMode)
Definition: file.c:3953
#define SYNCHRONIZE
Definition: nt_native.h:61
#define SECTION_MAP_WRITE
Definition: nt_native.h:1288
#define FILE_READ_DATA
Definition: nt_native.h:628
#define PAGE_NOCACHE
Definition: nt_native.h:1311
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define SECTION_QUERY
Definition: nt_native.h:1287
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
#define PAGE_EXECUTE
Definition: nt_native.h:1306
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define FILE_EXECUTE
Definition: nt_native.h:642
@ ViewShare
Definition: nt_native.h:1278
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
#define UNICODE_NULL
#define UNICODE_STRING_MAX_CHARS
#define UNICODE_STRING_MAX_BYTES
#define ANSI_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
BOOLEAN LdrpInLdrInit
Definition: ldrinit.c:30
NTSYSAPI NTSTATUS NTAPI LdrpApplyFileNameRedirection(_In_ PUNICODE_STRING OriginalName, _In_ PUNICODE_STRING Extension, _Inout_opt_ PUNICODE_STRING StaticString, _Inout_opt_ PUNICODE_STRING DynamicString, _Inout_ PUNICODE_STRING *NewName, _Inout_ PBOOLEAN RedirectedDll)
UNICODE_STRING LdrpDefaultPath
Definition: ldrinit.c:63
NTSTATUS NTAPI LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL, IN PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: ldrpe.c:670
ULONG LdrpNumberOfProcessors
Definition: ldrinit.c:55
PVOID LdrpHeap
Definition: ldrinit.c:3
#define LDRP_UPDATE_DEREFCOUNT
Definition: ntdllp.h:16
UNICODE_STRING LdrApiDefaultExtension
Definition: ldrapi.c:22
#define LDR_GET_HASH_ENTRY(x)
Definition: ntdllp.h:12
ULONG LdrpFatalHardErrorCount
Definition: ldrinit.c:81
VOID NTAPI LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry)
Definition: ldrinit.c:1546
LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES]
Definition: ldrinit.c:59
UNICODE_STRING LdrpKnownDllPath
Definition: ldrinit.c:61
#define IMAGE_LOADER_FLAGS_COMPLUS
Definition: ntdllp.h:20
NTSTATUS NTAPI LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
Definition: ldrinit.c:648
BOOLEAN LdrpLdrDatabaseIsSetup
Definition: ldrinit.c:33
BOOLEAN ShowSnaps
Definition: ldrinit.c:79
HANDLE LdrpKnownDllObjectDirectory
Definition: ldrinit.c:60
#define LDRP_UPDATE_PIN
Definition: ntdllp.h:17
VOID NTAPI LdrpSendDllNotifications(_In_ PLDR_DATA_TABLE_ENTRY DllEntry, _In_ ULONG NotificationReason)
Definition: ldrnotify.c:104
RTL_CRITICAL_SECTION LdrpLoaderLock
Definition: ldrinit.c:68
#define LDRP_UPDATE_REFCOUNT
Definition: ntdllp.h:15
VOID NTAPI LdrpEnsureLoaderLockIsHeld(VOID)
Definition: ldrinit.c:408
NTSTATUS NTAPI LdrpSnapThunk(IN PVOID ExportBase, IN PVOID ImportBase, IN PIMAGE_THUNK_DATA OriginalThunk, IN OUT PIMAGE_THUNK_DATA Thunk, IN PIMAGE_EXPORT_DIRECTORY ExportEntry, IN ULONG ExportSize, IN BOOLEAN Static, IN LPSTR DllName)
Definition: ldrpe.c:937
#define IMAGE_SCN_MEM_NOT_CACHED
Definition: ntimage.h:236
#define IMAGE_SCN_MEM_WRITE
Definition: ntimage.h:241
struct _IMAGE_IMPORT_DESCRIPTOR * PIMAGE_IMPORT_DESCRIPTOR
#define IMAGE_SCN_MEM_EXECUTE
Definition: ntimage.h:239
#define IMAGE_FIRST_SECTION(NtHeader)
Definition: ntimage.h:427
PIMAGE_THUNK_DATA32 PIMAGE_THUNK_DATA
Definition: ntimage.h:566
VOID(NTAPI * PIMAGE_TLS_CALLBACK)(PVOID DllHandle, ULONG Reason, PVOID Reserved)
Definition: ntimage.h:531
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_INVALID_IMAGE_FORMAT
Definition: ntstatus.h:359
#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH
Definition: ntstatus.h:128
#define STATUS_DLL_NOT_FOUND
Definition: ntstatus.h:545
#define STATUS_OBJECT_PATH_SYNTAX_BAD
Definition: ntstatus.h:295
#define STATUS_ILLEGAL_DLL_RELOCATION
Definition: ntstatus.h:742
#define STATUS_PROCEDURE_NOT_FOUND
Definition: ntstatus.h:358
#define STATUS_CONFLICTING_ADDRESSES
Definition: ntstatus.h:261
#define STATUS_SXS_SECTION_NOT_FOUND
Definition: ntstatus.h:1382
#define STATUS_SXS_KEY_NOT_FOUND
Definition: ntstatus.h:1389
#define STATUS_IMAGE_NOT_AT_BASE
Definition: ntstatus.h:117
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:498
#define L(x)
Definition: ntvdm.h:50
#define IMAGE_FILE_EXECUTABLE_IMAGE
Definition: pedump.c:160
#define IMAGE_DIRECTORY_ENTRY_IMPORT
Definition: pedump.c:260
#define IMAGE_ORDINAL_FLAG
Definition: pedump.c:336
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
Definition: pedump.c:270
#define IMAGE_DIRECTORY_ENTRY_BASERELOC
Definition: pedump.c:264
#define IMAGE_FILE_DLL
Definition: pedump.c:169
#define IMAGE_DIRECTORY_ENTRY_TLS
Definition: pedump.c:268
#define IMAGE_FILE_SYSTEM
Definition: pedump.c:168
struct _IMAGE_IMPORT_BY_NAME * PIMAGE_IMPORT_BY_NAME
unsigned short USHORT
Definition: pedump.c:61
#define IMAGE_FILE_RELOCS_STRIPPED
Definition: pedump.c:159
static WCHAR Address[46]
Definition: ping.c:68
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:181
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:82
#define _SEH2_FINALLY
Definition: pseh2_64.h:130
#define _SEH2_END
Definition: pseh2_64.h:171
#define _SEH2_TRY
Definition: pseh2_64.h:71
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:184
#define _SEH2_LEAVE
Definition: pseh2_64.h:183
BOOLEAN NTAPI RtlDoesFileExists_UstrEx(IN PCUNICODE_STRING FileName, IN BOOLEAN SucceedIfBusy)
Definition: path.c:1430
ULONG NTAPI RtlGetFullPathName_Ustr(_In_ PUNICODE_STRING FileName, _In_ ULONG Size, _Out_z_bytecap_(Size) PWSTR Buffer, _Out_opt_ PCWSTR *ShortName, _Out_opt_ PBOOLEAN InvalidName, _Out_ RTL_PATH_TYPE *PathType)
Definition: path.c:734
PVOID NTAPI RtlEncodeSystemPointer(IN PVOID Pointer)
Definition: process.c:429
PVOID NTAPI RtlDecodeSystemPointer(IN PVOID Pointer)
Definition: process.c:439
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
VOID NTAPI SE_InstallAfterInit(PUNICODE_STRING ProcessImage, PVOID pShimData)
Definition: shimeng.c:1436
VOID NTAPI SE_InstallBeforeInit(PUNICODE_STRING ProcessImage, PVOID pShimData)
Definition: shimeng.c:1417
VOID NTAPI SE_ProcessDying(VOID)
Definition: shimeng.c:1441
VOID WINAPI SE_DllLoaded(PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: shimeng.c:1447
VOID WINAPI SE_DllUnloaded(PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: shimeng.c:1465
STDMETHOD() Next(THIS_ ULONG celt, IAssociationElement *pElement, ULONG *pceltFetched) PURE
#define DPRINT
Definition: sndvol32.h:73
static void Exit(void)
Definition: sock.c:1330
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
base of all file and directory entries
Definition: entries.h:83
Definition: xml2sdb.h:80
Definition: ncftp.h:89
Definition: window.h:585
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
IMAGE_FILE_HEADER FileHeader
Definition: ntddk_ex.h:183
union _IMAGE_THUNK_DATA32::@2218 u1
Definition: btrfs_drv.h:1876
USHORT LoadCount
Definition: ntddk_ex.h:208
PVOID EntryPoint
Definition: ntddk_ex.h:203
UNICODE_STRING FullDllName
Definition: btrfs_drv.h:1882
ULONG SizeOfImage
Definition: ldrtypes.h:147
LIST_ENTRY InLoadOrderLinks
Definition: ldrtypes.h:142
LIST_ENTRY InInitializationOrderLinks
Definition: ldrtypes.h:144
PVOID DllBase
Definition: btrfs_drv.h:1880
LIST_ENTRY InMemoryOrderLinks
Definition: btrfs_drv.h:1878
ULONG Flags
Definition: ntddk_ex.h:207
ULONG TimeDateStamp
Definition: btrfs_drv.h:1889
LIST_ENTRY HashLinks
Definition: ldrtypes.h:155
UNICODE_STRING BaseDllName
Definition: ldrtypes.h:149
PVOID PatchInformation
Definition: ldrtypes.h:168
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PVOID ArbitraryUserPointer
Definition: compat.h:719
LIST_ENTRY InInitializationOrderModuleList
Definition: ldrtypes.h:126
LIST_ENTRY InMemoryOrderModuleList
Definition: btrfs_drv.h:1895
LIST_ENTRY InLoadOrderModuleList
Definition: ldrtypes.h:124
PPEB_LDR_DATA Ldr
Definition: btrfs_drv.h:1912
PVOID ImageBaseAddress
Definition: ntddk_ex.h:245
Definition: compat.h:836
NT_TIB NtTib
Definition: ntddk_ex.h:332
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define LL
Definition: tui.h:166
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
uint16_t * PWCHAR
Definition: typedefs.h:56
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
CONST char * PCSZ
Definition: umtypes.h:125
#define ALIGN_DOWN(size, type)
Definition: umtypes.h:88
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_In_ WDFINTERRUPT _In_ PFN_WDF_INTERRUPT_SYNCHRONIZE Callback
Definition: wdfinterrupt.h:458
#define SearchPath
Definition: winbase.h:3931
char * PSZ
Definition: windef.h:57
struct _IMAGE_BOUND_FORWARDER_REF * PIMAGE_BOUND_FORWARDER_REF
struct _IMAGE_BOUND_IMPORT_DESCRIPTOR * PIMAGE_BOUND_IMPORT_DESCRIPTOR
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_In_ PSTRING FullName
Definition: rtlfuncs.h:1665
char * LPSTR
Definition: xmlstorage.h:182
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180