ReactOS 0.4.15-dev-8145-ga541a46
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 // LdrpSendDllNotifications(LdrEntry, TRUE, Status == STATUS_IMAGE_NOT_AT_BASE)
1230
1231 /* Check for invalid CPU Image */
1233 {
1234 /* Load our header */
1236
1237 /* Assume defaults if we don't have to run the Hard Error path */
1238 HardErrorStatus = STATUS_SUCCESS;
1240
1241 /* Are we an NT 3.0 image? [Do these still exist? LOL -- IAI] */
1243 {
1244 /* Reset the entrypoint, save our Dll Name */
1245 LdrEntry->EntryPoint = 0;
1246 HardErrorParameters[0] = (ULONG_PTR)&FullDllName;
1247
1248 /* Raise the error */
1250 1,
1251 1,
1252 HardErrorParameters,
1254 &Response);
1255 }
1256
1257 /* Check if the user pressed cancel */
1258 if (NT_SUCCESS(HardErrorStatus) && Response == ResponseCancel)
1259 {
1260 /* Remove the DLL from the lists */
1263 RemoveEntryList(&LdrEntry->HashLinks);
1264
1265 /* Remove the LDR Entry */
1266 RtlFreeHeap(LdrpHeap, 0, LdrEntry );
1267
1268 /* Unmap and close section */
1270 NtClose(SectionHandle);
1271
1272 /* Did we do a hard error? */
1274 {
1275 /* Yup, so increase fatal error count if we are initializing */
1277 }
1278
1279 /* Return failure */
1281 }
1282 }
1283 else
1284 {
1285 /* The image was valid. Is it a DLL? */
1286 if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
1287 {
1288 /* Set the DLL Flag */
1289 LdrEntry->Flags |= LDRP_IMAGE_DLL;
1290 }
1291
1292 /* If we're not a DLL, clear the entrypoint */
1293 if (!(LdrEntry->Flags & LDRP_IMAGE_DLL))
1294 {
1295 LdrEntry->EntryPoint = 0;
1296 }
1297 }
1298
1299 /* Return it for the caller */
1300 *DataTableEntry = LdrEntry;
1301
1302 /* Check if we loaded somewhere else */
1304 {
1305 /* Write the flag */
1306 LdrEntry->Flags |= LDRP_IMAGE_NOT_AT_BASE;
1307
1308 /* Find our region */
1309 ImageBase = (ULONG_PTR)NtHeaders->OptionalHeader.ImageBase;
1310 ImageEnd = ImageBase + ViewSize;
1311
1312 DPRINT("LDR: LdrpMapDll Relocating Image Name %ws (%p-%p -> %p)\n", DllName, (PVOID)ImageBase, (PVOID)ImageEnd, ViewBase);
1313
1314 /* Scan all the modules */
1315 ListHead = &Peb->Ldr->InLoadOrderModuleList;
1316 NextEntry = ListHead->Flink;
1317 while (NextEntry != ListHead)
1318 {
1319 /* Get the entry */
1320 CandidateEntry = CONTAINING_RECORD(NextEntry,
1322 InLoadOrderLinks);
1323 NextEntry = NextEntry->Flink;
1324
1325 /* Get the entry's bounds */
1326 CandidateBase = (ULONG_PTR)CandidateEntry->DllBase;
1327 CandidateEnd = CandidateBase + CandidateEntry->SizeOfImage;
1328
1329 /* Make sure this entry isn't unloading */
1330 if (!CandidateEntry->InMemoryOrderLinks.Flink) continue;
1331
1332 /* Check if our regions are colliding */
1333 if ((ImageBase >= CandidateBase && ImageBase <= CandidateEnd) ||
1334 (ImageEnd >= CandidateBase && ImageEnd <= CandidateEnd) ||
1335 (CandidateBase >= ImageBase && CandidateBase <= ImageEnd))
1336 {
1337 /* Found who is overlapping */
1338 OverlapDllFound = TRUE;
1339 OverlapDll = CandidateEntry->FullDllName;
1340 break;
1341 }
1342 }
1343
1344 /* Check if we found the DLL overlapping with us */
1345 if (!OverlapDllFound)
1346 {
1347 /* It's not another DLL, it's memory already here */
1348 RtlInitUnicodeString(&OverlapDll, L"Dynamically Allocated Memory");
1349 }
1350
1351 DPRINT("Overlapping DLL: %wZ\n", &OverlapDll);
1352
1353 /* Are we dealing with a DLL? */
1354 if (LdrEntry->Flags & LDRP_IMAGE_DLL)
1355 {
1356 /* Check if relocs were stripped */
1358 {
1359 /* Get the relocation data */
1360 RelocData = RtlImageDirectoryEntryToData(ViewBase,
1361 TRUE,
1363 &RelocDataSize);
1364
1365 /* Does the DLL not have any? */
1366 if (!RelocData && !RelocDataSize)
1367 {
1368 /* We'll allow this and simply continue */
1369 goto NoRelocNeeded;
1370 }
1371 }
1372
1373 /* See if this is an Illegal DLL - IE: user32 and kernel32 */
1374 RtlInitUnicodeString(&IllegalDll,L"user32.dll");
1375 if (RtlEqualUnicodeString(&BaseDllName, &IllegalDll, TRUE))
1376 {
1377 /* Can't relocate user32 */
1378 RelocatableDll = FALSE;
1379 }
1380 else
1381 {
1382 RtlInitUnicodeString(&IllegalDll, L"kernel32.dll");
1383 if (RtlEqualUnicodeString(&BaseDllName, &IllegalDll, TRUE))
1384 {
1385 /* Can't relocate kernel32 */
1386 RelocatableDll = FALSE;
1387 }
1388 }
1389
1390 /* Known DLLs are not allowed to be relocated */
1391 if (KnownDll && !RelocatableDll)
1392 {
1393 /* Setup for hard error */
1394 HardErrorParameters[0] = (ULONG_PTR)&IllegalDll;
1395 HardErrorParameters[1] = (ULONG_PTR)&OverlapDll;
1396
1397 DPRINT1("Illegal DLL relocation! %wZ overlaps %wZ\n", &OverlapDll, &IllegalDll);
1398
1399 /* Raise the error */
1401 2,
1402 3,
1403 HardErrorParameters,
1404 OptionOk,
1405 &Response);
1406
1407 /* If initializing, increase the error count */
1409
1410 /* Don't do relocation */
1412 goto FailRelocate;
1413 }
1414
1415 /* Change the protection to prepare for relocation */
1416 Status = LdrpSetProtection(ViewBase, FALSE);
1417
1418 /* Make sure we changed the protection */
1419 if (NT_SUCCESS(Status))
1420 {
1421 /* Do the relocation */
1424
1425 if (NT_SUCCESS(Status))
1426 {
1427 /* Stuff the image name in the TIB, for the debugger */
1428 ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
1430#if 0
1431 /* Map the DLL */
1432 Status = NtMapViewOfSection(SectionHandle,
1434 &ViewBase,
1435 0,
1436 0,
1437 NULL,
1438 &ViewSize,
1439 ViewShare,
1440 0,
1442#endif
1443 /* Restore */
1444 Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
1445
1446 /* Return the protection */
1447 Status = LdrpSetProtection(ViewBase, TRUE);
1448 }
1449 }
1450FailRelocate:
1451 /* Handle any kind of failure */
1452 if (!NT_SUCCESS(Status))
1453 {
1454 /* Remove it from the lists */
1457 RemoveEntryList(&LdrEntry->HashLinks);
1458
1459 /* Unmap it, clear the entry */
1461 LdrEntry = NULL;
1462 }
1463
1464 /* Show debug message */
1465 if (ShowSnaps)
1466 {
1467 DPRINT1("LDR: Fixups %successfully re-applied @ %p\n",
1468 NT_SUCCESS(Status) ? "s" : "uns", ViewBase);
1469 }
1470 }
1471 else
1472 {
1473NoRelocNeeded:
1474 /* Not a DLL, or no relocation needed */
1476
1477 /* Stuff the image name in the TIB, for the debugger */
1478 ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
1480#if 0
1481 /* Map the DLL */
1482 Status = NtMapViewOfSection(SectionHandle,
1484 &ViewBase,
1485 0,
1486 0,
1487 NULL,
1488 &ViewSize,
1489 ViewShare,
1490 0,
1492#endif
1493 /* Restore */
1494 Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
1495
1496 /* Show debug message */
1497 if (ShowSnaps)
1498 {
1499 DPRINT1("LDR: Fixups won't be re-applied to non-Dll @ %p\n", ViewBase);
1500 }
1501 }
1502 }
1503
1504 // FIXME: LdrpCheckCorImage() is missing
1505
1506 /* Check if this is an SMP Machine and a DLL */
1507 if ((LdrpNumberOfProcessors > 1) &&
1508 (LdrEntry && (LdrEntry->Flags & LDRP_IMAGE_DLL)))
1509 {
1510 /* Validate the image for MP */
1511 LdrpValidateImageForMp(LdrEntry);
1512 }
1513
1514 // FIXME: LdrpCorUnloadImage() is missing
1515
1516 /* Close section and return status */
1517 NtClose(SectionHandle);
1518 return Status;
1519}
1520
1522NTAPI
1524{
1525 PLDR_DATA_TABLE_ENTRY LdrEntry = NULL;
1526 PIMAGE_NT_HEADERS NtHeader;
1527
1528 /* Make sure the header is valid */
1529 NtHeader = RtlImageNtHeader(BaseAddress);
1530 DPRINT("LdrpAllocateDataTableEntry(%p), NtHeader %p\n", BaseAddress, NtHeader);
1531
1532 if (NtHeader)
1533 {
1534 /* Allocate an entry */
1535 LdrEntry = RtlAllocateHeap(LdrpHeap,
1537 sizeof(LDR_DATA_TABLE_ENTRY));
1538
1539 /* Make sure we got one */
1540 if (LdrEntry)
1541 {
1542 /* Set it up */
1543 LdrEntry->DllBase = BaseAddress;
1544 LdrEntry->SizeOfImage = NtHeader->OptionalHeader.SizeOfImage;
1545 LdrEntry->TimeDateStamp = NtHeader->FileHeader.TimeDateStamp;
1546 LdrEntry->PatchInformation = NULL;
1547 }
1548 }
1549
1550 /* Return the entry */
1551 return LdrEntry;
1552}
1553
1554VOID
1555NTAPI
1557{
1558 PPEB_LDR_DATA PebData = NtCurrentPeb()->Ldr;
1559 ULONG i;
1560
1561 /* Insert into hash table */
1562 i = LDR_GET_HASH_ENTRY(LdrEntry->BaseDllName.Buffer[0]);
1563 InsertTailList(&LdrpHashTable[i], &LdrEntry->HashLinks);
1564
1565 /* Insert into other lists */
1566 InsertTailList(&PebData->InLoadOrderModuleList, &LdrEntry->InLoadOrderLinks);
1567 InsertTailList(&PebData->InMemoryOrderModuleList, &LdrEntry->InMemoryOrderLinks);
1568}
1569
1570VOID
1571NTAPI
1573{
1574 /* Sanity check */
1575 ASSERT(Entry != NULL);
1576
1577 /* Release the activation context if it exists and wasn't already released */
1578 if ((Entry->EntryPointActivationContext) &&
1579 (Entry->EntryPointActivationContext != INVALID_HANDLE_VALUE))
1580 {
1581 /* Mark it as invalid */
1582 RtlReleaseActivationContext(Entry->EntryPointActivationContext);
1583 Entry->EntryPointActivationContext = INVALID_HANDLE_VALUE;
1584 }
1585
1586 /* Release the full dll name string */
1587 if (Entry->FullDllName.Buffer) LdrpFreeUnicodeString(&Entry->FullDllName);
1588
1589 /* Finally free the entry's memory */
1591}
1592
1593BOOLEAN
1594NTAPI
1596 OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
1597{
1598 PLDR_DATA_TABLE_ENTRY Current;
1599 PLIST_ENTRY ListHead, Next;
1600
1601 /* Check the cache first */
1604 {
1605 /* We got lucky, return the cached entry */
1606 *LdrEntry = LdrpLoadedDllHandleCache;
1607 return TRUE;
1608 }
1609
1610 /* Time for a lookup */
1611 ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
1612 Next = ListHead->Flink;
1613 while (Next != ListHead)
1614 {
1615 /* Get the current entry */
1616 Current = CONTAINING_RECORD(Next,
1618 InLoadOrderLinks);
1619
1620 /* Make sure it's not unloading and check for a match */
1621 if ((Current->InMemoryOrderLinks.Flink) && (Base == Current->DllBase))
1622 {
1623 /* Save in cache */
1624 LdrpLoadedDllHandleCache = Current;
1625
1626 /* Return it */
1627 *LdrEntry = Current;
1628 return TRUE;
1629 }
1630
1631 /* Move to the next one */
1632 Next = Next->Flink;
1633 }
1634
1635 /* Nothing found */
1636 return FALSE;
1637}
1638
1640NTAPI
1642 IN PUNICODE_STRING PathName,
1643 IN PUNICODE_STRING FullPathName,
1644 IN PUNICODE_STRING *ExpandedName)
1645{
1647// RTL_PATH_TYPE PathType;
1648// BOOLEAN InvalidName;
1649 ULONG Length;
1650
1651 /* Display debug output if snaps are on */
1652 if (ShowSnaps)
1653 {
1656 "LDR: %s - Expanding full name of %wZ\n",
1658 OriginalName);
1659 }
1660
1661 /* FIXME: Lock the PEB */
1662 //RtlEnterCriticalSection(&FastPebLock);
1663#if 0
1664 /* Get the path name */
1665 Length = RtlGetFullPathName_Ustr(OriginalName,
1666 PathName->Length,
1667 PathName->Buffer,
1668 NULL,
1669 &InvalidName,
1670 &PathType);
1671#else
1672 Length = 0;
1673#endif
1675 {
1676 /* Fail */
1678 goto Quickie;
1679 }
1680
1681 /* Check if the length hasn't changed */
1682 if (Length <= PathName->Length)
1683 {
1684 /* Return the same thing */
1685 *ExpandedName = PathName;
1686 PathName->Length = (USHORT)Length;
1687 goto Quickie;
1688 }
1689
1690 /* Sanity check */
1691 ASSERT(Length >= sizeof(WCHAR));
1692
1693 /* Allocate a string */
1694 Status = LdrpAllocateUnicodeString(FullPathName, Length - sizeof(WCHAR));
1695 if (!NT_SUCCESS(Status)) goto Quickie;
1696
1697 /* Now get the full path again */
1698#if 0
1699 Length = RtlGetFullPathName_Ustr(OriginalName,
1700 FullPathName->Length,
1701 FullPathName->Buffer,
1702 NULL,
1703 &InvalidName,
1704 &PathType);
1705#else
1706 Length = 0;
1707#endif
1708 if (!(Length) || (Length > FullPathName->Length))
1709 {
1710 /* Fail */
1711 LdrpFreeUnicodeString(FullPathName);
1713 }
1714 else
1715 {
1716 /* Return the expanded name */
1717 *ExpandedName = FullPathName;
1718 FullPathName->Length = (USHORT)Length;
1719 }
1720
1721Quickie:
1722 /* FIXME: Unlock the PEB */
1723 //RtlLeaveCriticalSection(&FastPebLock);
1724
1725 /* Display debug output if snaps are on */
1726 if (ShowSnaps)
1727 {
1728 /* Check which output to use -- failure or success */
1729 if (NT_SUCCESS(Status))
1730 {
1733 "LDR: %s - Expanded to %wZ\n",
1735 *ExpandedName);
1736 }
1737 else
1738 {
1741 "LDR: %s - Failed to expand %wZ; 0x%08x\n",
1743 OriginalName,
1744 Status);
1745 }
1746 }
1747
1748 /* If we failed, return NULL */
1749 if (!NT_SUCCESS(Status)) *ExpandedName = NULL;
1750
1751 /* Return status */
1752 return Status;
1753}
1754
1756NTAPI
1758 IN PWCHAR DllName,
1759 IN PUNICODE_STRING PathName,
1760 IN PUNICODE_STRING FullPathName,
1761 IN PUNICODE_STRING *ExpandedName)
1762{
1764 PWCHAR ActualSearchPath = *SearchPath;
1765 UNICODE_STRING TestName;
1767 PWCHAR Buffer, BufEnd = NULL;
1768 ULONG Length = 0;
1769 WCHAR p;
1770 //PWCHAR pp;
1771
1772 /* Check if we don't have a search path */
1773 if (!ActualSearchPath) *SearchPath = LdrpDefaultPath.Buffer;
1774
1775 /* Display debug output if snaps are on */
1776 if (ShowSnaps)
1777 {
1780 "LDR: %s - Looking for %ws in %ws\n",
1782 DllName,
1783 *SearchPath);
1784 }
1785
1786 /* Check if we're dealing with a relative path */
1788 {
1789 /* Good, we're not. Create the name string */
1790 Status = RtlInitUnicodeStringEx(&TestName, DllName);
1791 if (!NT_SUCCESS(Status)) goto Quickie;
1792
1793 /* Make sure it exists */
1794 #if 0
1795 if (!RtlDoesFileExists_UstrEx(&TestName, TRUE))
1796 {
1797 /* It doesn't, fail */
1799 goto Quickie;
1800 }
1801 #endif
1802
1803 /* Resolve the full name */
1804 Status = LdrpResolveFullName(&TestName,
1805 PathName,
1806 FullPathName,
1807 ExpandedName);
1808 goto Quickie;
1809 }
1810
1811 /* FIXME: Handle relative case semicolon-lookup here */
1812
1813 /* Calculate length */
1814 Length += (ULONG)wcslen(DllName) + 1;
1816 {
1817 /* Too long, fail */
1819 goto Quickie;
1820 }
1821
1822 /* Allocate buffer */
1823 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR));
1824 if (!Buffer)
1825 {
1826 /* Fail */
1828 goto Quickie;
1829 }
1830
1831 /* FIXME: Setup TestName here */
1833 BufEnd = Buffer;
1834
1835 /* Start loop */
1836 do
1837 {
1838 /* Get character */
1839 p = *ActualSearchPath;
1840 if (!(p) || (p == ';'))
1841 {
1842 /* FIXME: We don't have a character, or is a semicolon.*/
1843
1844 /* Display debug output if snaps are on */
1845 if (ShowSnaps)
1846 {
1849 "LDR: %s - Looking for %ws\n",
1851 Buffer);
1852 }
1853
1854 /* Sanity check */
1855 TestName.Length = (USHORT)ALIGN_DOWN((BufEnd - Buffer), WCHAR);
1856#if 0
1857 ASSERT(TestName.Length < TestName.MaximumLength);
1858#endif
1859
1860 /* Check if the file exists */
1861 #if 0
1862 if (RtlDoesFileExists_UstrEx(&TestName, FALSE))
1863 #endif
1864 {
1865 /* It does. Reallocate the buffer */
1866 TestName.MaximumLength = (USHORT)ALIGN_DOWN((BufEnd - Buffer), WCHAR) + sizeof(WCHAR);
1867 TestName.Buffer = RtlReAllocateHeap(RtlGetProcessHeap(),
1868 0,
1869 Buffer,
1870 TestName.MaximumLength);
1871 if (!TestName.Buffer)
1872 {
1873 /* Keep the old one */
1874 TestName.Buffer = Buffer;
1875 }
1876 else
1877 {
1878 /* Update buffer */
1879 Buffer = TestName.Buffer;
1880 }
1881
1882 /* Make sure we have a buffer at least */
1883 ASSERT(TestName.Buffer);
1884
1885 /* Resolve the name */
1886 *SearchPath = ActualSearchPath++;
1887 Status = LdrpResolveFullName(&TestName,
1888 PathName,
1889 FullPathName,
1890 ExpandedName);
1891 break;
1892 }
1893
1894 /* Update buffer end */
1895 BufEnd = Buffer;
1896
1897 /* Update string position */
1898 //pp = ActualSearchPath++;
1899 }
1900 else
1901 {
1902 /* Otherwise, write the character */
1903 *BufEnd = p;
1904 BufEnd++;
1905 }
1906
1907 /* Check if the string is empty, meaning we're done */
1908 if (!(*ActualSearchPath)) TryAgain = TRUE;
1909
1910 /* Advance in the string */
1911 ActualSearchPath++;
1912 } while (!TryAgain);
1913
1914 /* Check if we had a buffer and free it */
1915 if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1916
1917Quickie:
1918 /* Check if we got here through failure */
1919 if (!NT_SUCCESS(Status)) *ExpandedName = NULL;
1920
1921 /* Display debug output if snaps are on */
1922 if (ShowSnaps)
1923 {
1924 /* Check which output to use -- failure or success */
1925 if (NT_SUCCESS(Status))
1926 {
1929 "LDR: %s - Returning %wZ\n",
1931 *ExpandedName);
1932 }
1933 else
1934 {
1937 "LDR: %s - Unable to locate %ws in %ws: 0x%08x\n",
1939 DllName,
1940 ActualSearchPath,
1941 Status);
1942 }
1943 }
1944
1945 /* Return status */
1946 return Status;
1947}
1948
1949
1950/* NOTE: This function is b0rked and in the process of being slowly unf*cked */
1951BOOLEAN
1952NTAPI
1954 IN PUNICODE_STRING DllName,
1955 IN BOOLEAN Flag,
1956 IN BOOLEAN RedirectedDll,
1957 OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
1958{
1959 ULONG HashIndex;
1960 PLIST_ENTRY ListHead, ListEntry;
1961 PLDR_DATA_TABLE_ENTRY CurEntry;
1962 BOOLEAN FullPath = FALSE;
1963 PWCHAR wc;
1964 WCHAR NameBuf[266];
1965 UNICODE_STRING FullDllName, NtPathName;
1966 ULONG Length;
1969 HANDLE FileHandle, SectionHandle;
1971 PVOID ViewBase = NULL;
1972 SIZE_T ViewSize = 0;
1973 PIMAGE_NT_HEADERS NtHeader, NtHeader2;
1974 DPRINT("LdrpCheckForLoadedDll('%S' '%wZ' %u %u %p)\n", DllPath ? ((ULONG_PTR)DllPath == 1 ? L"" : DllPath) : L"", DllName, Flag, RedirectedDll, LdrEntry);
1975
1976 /* Check if a dll name was provided */
1977 if (!(DllName->Buffer) || !(DllName->Buffer[0])) return FALSE;
1978
1979 /* FIXME: Warning, "Flag" is used as magic instead of "Static" */
1980 /* FIXME: Warning, code does not support redirection at all */
1981
1982 /* Look in the hash table if flag was set */
1983lookinhash:
1984 if (Flag /* the second check is a hack */ && !RedirectedDll)
1985 {
1986 /* 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 */
1987
1988 /* Get hash index */
1989 HashIndex = LDR_GET_HASH_ENTRY(DllName->Buffer[0]);
1990
1991 /* Traverse that list */
1992 ListHead = &LdrpHashTable[HashIndex];
1993 ListEntry = ListHead->Flink;
1994 while (ListEntry != ListHead)
1995 {
1996 /* Get the current entry */
1997 CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, HashLinks);
1998
1999 /* Check base name of that module */
2000 if (RtlEqualUnicodeString(DllName, &CurEntry->BaseDllName, TRUE))
2001 {
2002 /* It matches, return it */
2003 *LdrEntry = CurEntry;
2004 return TRUE;
2005 }
2006
2007 /* Advance to the next entry */
2008 ListEntry = ListEntry->Flink;
2009 }
2010
2011 /* Module was not found, return failure */
2012 return FALSE;
2013 }
2014
2015 /* Check if this is a redirected DLL */
2016 if (RedirectedDll)
2017 {
2018 /* Redirected dlls already have a full path */
2019 FullPath = TRUE;
2020 FullDllName = *DllName;
2021 }
2022 else
2023 {
2024 /* Check if there is a full path in this DLL */
2025 wc = DllName->Buffer;
2026 while (*wc)
2027 {
2028 /* Check for a slash in the current position*/
2029 if ((*wc == L'\\') || (*wc == L'/'))
2030 {
2031 /* Found the slash, so dll name contains path */
2032 FullPath = TRUE;
2033
2034 /* Setup full dll name string */
2035 FullDllName.Buffer = NameBuf;
2036
2037 /* FIXME: This is from the Windows 2000 loader, not XP/2003, we should call LdrpSearchPath */
2039 DllName->Buffer,
2040 NULL,
2041 sizeof(NameBuf) - sizeof(UNICODE_NULL),
2042 FullDllName.Buffer,
2043 NULL);
2044
2045 /* Check if that was successful */
2046 if (!(Length) || (Length > (sizeof(NameBuf) - sizeof(UNICODE_NULL))))
2047 {
2048 if (ShowSnaps)
2049 {
2050 DPRINT1("LDR: LdrpCheckForLoadedDll - Unable To Locate %wZ: 0x%08x\n",
2051 &DllName, Length);
2052 }
2053 }
2054
2055 /* Full dll name is found */
2056 FullDllName.Length = Length;
2057 FullDllName.MaximumLength = FullDllName.Length + sizeof(UNICODE_NULL);
2058 break;
2059 }
2060
2061 wc++;
2062 }
2063 }
2064
2065 /* Go check the hash table */
2066 if (!FullPath)
2067 {
2068 Flag = TRUE;
2069 goto lookinhash;
2070 }
2071
2072 /* FIXME: Warning, activation context missing */
2073 DPRINT("Warning, activation context missing\n");
2074
2075 /* NOTE: From here on down, everything looks good */
2076
2077 /* Loop the module list */
2078 ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
2079 ListEntry = ListHead->Flink;
2080 while (ListEntry != ListHead)
2081 {
2082 /* Get the current entry and advance to the next one */
2083 CurEntry = CONTAINING_RECORD(ListEntry,
2085 InLoadOrderLinks);
2086 ListEntry = ListEntry->Flink;
2087
2088 /* Check if it's being unloaded */
2089 if (!CurEntry->InMemoryOrderLinks.Flink) continue;
2090
2091 /* Check if name matches */
2093 &CurEntry->FullDllName,
2094 TRUE))
2095 {
2096 /* Found it */
2097 *LdrEntry = CurEntry;
2098 return TRUE;
2099 }
2100 }
2101
2102 /* Convert given path to NT path */
2104 &NtPathName,
2105 NULL,
2106 NULL))
2107 {
2108 /* Fail if conversion failed */
2109 return FALSE;
2110 }
2111
2112 /* Initialize object attributes and open it */
2114 &NtPathName,
2116 NULL,
2117 NULL);
2121 &Iosb,
2124
2125 /* Free NT path name */
2126 RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
2127
2128 /* If opening the file failed - return failure */
2129 if (!NT_SUCCESS(Status)) return FALSE;
2130
2131 /* Create a section for this file */
2132 Status = NtCreateSection(&SectionHandle,
2136 NULL,
2137 NULL,
2139 SEC_COMMIT,
2140 FileHandle);
2141
2142 /* Close file handle */
2144
2145 /* If creating section failed - return failure */
2146 if (!NT_SUCCESS(Status)) return FALSE;
2147
2148 /* Map view of this section */
2149 Status = ZwMapViewOfSection(SectionHandle,
2151 &ViewBase,
2152 0,
2153 0,
2154 NULL,
2155 &ViewSize,
2156 ViewShare,
2157 0,
2158 PAGE_EXECUTE);
2159
2160 /* Close section handle */
2161 NtClose(SectionHandle);
2162
2163 /* If section mapping failed - return failure */
2164 if (!NT_SUCCESS(Status)) return FALSE;
2165
2166 /* Get pointer to the NT header of this section */
2167 Status = RtlImageNtHeaderEx(0, ViewBase, ViewSize, &NtHeader);
2168 if (!(NT_SUCCESS(Status)) || !(NtHeader))
2169 {
2170 /* Unmap the section and fail */
2172 return FALSE;
2173 }
2174
2175 /* Go through the list of modules again */
2176 ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
2177 ListEntry = ListHead->Flink;
2178 while (ListEntry != ListHead)
2179 {
2180 /* Get the current entry and advance to the next one */
2181 CurEntry = CONTAINING_RECORD(ListEntry,
2183 InLoadOrderLinks);
2184 ListEntry = ListEntry->Flink;
2185
2186 /* Check if it's in the process of being unloaded */
2187 if (!CurEntry->InMemoryOrderLinks.Flink) continue;
2188
2189 /* The header is untrusted, use SEH */
2190 _SEH2_TRY
2191 {
2192 /* Check if timedate stamp and sizes match */
2193 if ((CurEntry->TimeDateStamp == NtHeader->FileHeader.TimeDateStamp) &&
2194 (CurEntry->SizeOfImage == NtHeader->OptionalHeader.SizeOfImage))
2195 {
2196 /* Time, date and size match. Let's compare their headers */
2197 NtHeader2 = RtlImageNtHeader(CurEntry->DllBase);
2198 if (RtlCompareMemory(NtHeader2, NtHeader, sizeof(IMAGE_NT_HEADERS)))
2199 {
2200 /* Headers match too! Finally ask the kernel to compare mapped files */
2201 Status = ZwAreMappedFilesTheSame(CurEntry->DllBase, ViewBase);
2202 if (NT_SUCCESS(Status))
2203 {
2204 /* This is our entry!, unmap and return success */
2205 *LdrEntry = CurEntry;
2207 _SEH2_YIELD(return TRUE;)
2208 }
2209 }
2210 }
2211 }
2213 {
2214 _SEH2_YIELD(break;)
2215 }
2216 _SEH2_END;
2217 }
2218
2219 /* Unmap the section and fail */
2221 return FALSE;
2222}
2223
2225NTAPI
2228 _In_opt_ _When_(Ordinal == 0, _Notnull_) PANSI_STRING Name,
2229 _In_opt_ _When_(Name == NULL, _In_range_(>, 0)) ULONG Ordinal,
2230 _Out_ PVOID *ProcedureAddress,
2231 _In_ BOOLEAN ExecuteInit)
2232{
2234 UCHAR ImportBuffer[64]; // 128 since NT6.2
2235 PLDR_DATA_TABLE_ENTRY LdrEntry;
2236 IMAGE_THUNK_DATA Thunk;
2237 PVOID ImageBase;
2238 PIMAGE_IMPORT_BY_NAME ImportName = NULL;
2239 PIMAGE_EXPORT_DIRECTORY ExportDir;
2240 ULONG ExportDirSize, Length;
2242
2243 /* Show debug message */
2244 if (ShowSnaps) DPRINT1("LDR: LdrGetProcedureAddress by ");
2245
2246 /* Check if we got a name */
2247 if (Name)
2248 {
2249 /* Show debug message */
2250 if (ShowSnaps) DbgPrint("NAME - %s\n", Name->Buffer);
2251
2252 /* Make sure it's not too long */
2253 Length = Name->Length +
2254 sizeof(CHAR) +
2257 {
2258 /* Won't have enough space to add the hint */
2259 return STATUS_NAME_TOO_LONG;
2260 }
2261
2262 /* Check if our buffer is large enough */
2263 if (Length > sizeof(ImportBuffer))
2264 {
2265 /* Allocate from heap, plus 2 bytes for the Hint */
2266 ImportName = RtlAllocateHeap(RtlGetProcessHeap(),
2267 0,
2268 Length);
2269 if (!ImportName)
2270 {
2271 /* Return STATUS_INSUFFICIENT_RESOURCES since NT6.2 */
2273 }
2274 }
2275 else
2276 {
2277 /* Use our internal buffer */
2278 ImportName = (PIMAGE_IMPORT_BY_NAME)ImportBuffer;
2279 }
2280
2281 /* Clear the hint */
2282 ImportName->Hint = 0;
2283
2284 /* Copy the name and null-terminate it */
2285 RtlCopyMemory(ImportName->Name, Name->Buffer, Name->Length);
2286 ImportName->Name[Name->Length] = ANSI_NULL;
2287
2288 /* Clear the high bit */
2289 ImageBase = ImportName;
2290 Thunk.u1.AddressOfData = 0;
2291 }
2292 else
2293 {
2294 /* Do it by ordinal */
2295 ImageBase = NULL;
2296
2297 /* Show debug message */
2298 if (ShowSnaps) DbgPrint("ORDINAL - %lx\n", Ordinal);
2299
2300 /* Make sure an ordinal was given */
2301 if (!Ordinal)
2302 {
2303 /* No ordinal */
2304 DPRINT1("No ordinal and no name\n");
2306 }
2307
2308 /* Set the original flag in the thunk */
2309 Thunk.u1.Ordinal = Ordinal | IMAGE_ORDINAL_FLAG;
2310 }
2311
2312 /* Acquire lock unless we are initting */
2314
2315 _SEH2_TRY
2316 {
2317 /* Try to find the loaded DLL */
2319 {
2320 /* Invalid base */
2321 DPRINT1("Invalid base address %p\n", BaseAddress);
2323 _SEH2_YIELD(goto Quickie;)
2324 }
2325
2326 /* Get the pointer to the export directory */
2327 ExportDir = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
2328 TRUE,
2330 &ExportDirSize);
2331
2332 if (!ExportDir)
2333 {
2334 DPRINT1("Image %wZ has no exports, but were trying to get procedure %Z. BaseAddress asked 0x%p, got entry BA 0x%p\n",
2335 &LdrEntry->BaseDllName, Name, BaseAddress, LdrEntry->DllBase);
2337 _SEH2_YIELD(goto Quickie;)
2338 }
2339
2340 /* Now get the thunk */
2341 Status = LdrpSnapThunk(LdrEntry->DllBase,
2342 ImageBase,
2343 &Thunk,
2344 &Thunk,
2345 ExportDir,
2346 ExportDirSize,
2347 FALSE,
2348 NULL);
2349
2350 /* Finally, see if we're supposed to run the init routines */
2351 if ((NT_SUCCESS(Status)) && (ExecuteInit))
2352 {
2353 /*
2354 * It's possible a forwarded entry had us load the DLL. In that case,
2355 * then we will call its DllMain. Use the last loaded DLL for this.
2356 */
2357 Entry = NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Blink;
2358 LdrEntry = CONTAINING_RECORD(Entry,
2360 InInitializationOrderLinks);
2361
2362 /* Make sure we didn't process it yet*/
2363 if (!(LdrEntry->Flags & LDRP_ENTRY_PROCESSED))
2364 {
2365 /* Call the init routine */
2366 _SEH2_TRY
2367 {
2369 }
2371 {
2372 /* Get the exception code */
2374 }
2375 _SEH2_END;
2376 }
2377 }
2378
2379 /* Make sure we're OK till here */
2380 if (NT_SUCCESS(Status))
2381 {
2382 /* Return the address */
2383 *ProcedureAddress = (PVOID)Thunk.u1.Function;
2384 }
2385 }
2387 {
2388 /* Just ignore exceptions */
2389 }
2390 _SEH2_END;
2391
2392Quickie:
2393 /* Cleanup */
2394 if (ImportName && (ImportName != (PIMAGE_IMPORT_BY_NAME)ImportBuffer))
2395 {
2396 /* We allocated from heap, free it */
2397 RtlFreeHeap(RtlGetProcessHeap(), 0, ImportName);
2398 }
2399
2400 /* Release the CS if we entered it */
2402
2403 /* We're done */
2404 return Status;
2405}
2406
2408NTAPI
2411 IN PULONG DllCharacteristics OPTIONAL,
2412 IN PUNICODE_STRING DllName,
2414 IN BOOLEAN CallInit)
2415{
2416 PPEB Peb = NtCurrentPeb();
2418 const WCHAR *p;
2419 BOOLEAN GotExtension;
2420 WCHAR c;
2421 WCHAR NameBuffer[MAX_PATH + 6];
2422 UNICODE_STRING RawDllName;
2423 PLDR_DATA_TABLE_ENTRY LdrEntry;
2424 BOOLEAN InInit = LdrpInLdrInit;
2425
2426 /* Save the Raw DLL Name */
2427 if (DllName->Length >= sizeof(NameBuffer)) return STATUS_NAME_TOO_LONG;
2428 RtlInitEmptyUnicodeString(&RawDllName, NameBuffer, sizeof(NameBuffer));
2429 RtlCopyUnicodeString(&RawDllName, DllName);
2430
2431 /* Find the extension, if present */
2432 /* NOTE: Access violation is expected here in some cases (Buffer[-1]) */
2433 p = DllName->Buffer + DllName->Length / sizeof(WCHAR) - 1;
2434 GotExtension = FALSE;
2435 while (p >= DllName->Buffer)
2436 {
2437 c = *p--;
2438 if (c == L'.')
2439 {
2440 GotExtension = TRUE;
2441 break;
2442 }
2443 else if (c == L'\\')
2444 {
2445 break;
2446 }
2447 }
2448
2449 /* If no extension was found, add the default extension */
2450 if (!GotExtension)
2451 {
2452 /* Check that we have space to add one */
2453 if ((DllName->Length + LdrApiDefaultExtension.Length + sizeof(UNICODE_NULL)) >=
2454 sizeof(NameBuffer))
2455 {
2456 /* No space to add the extension */
2459 "LDR: %s - Dll name missing extension; with extension "
2460 "added the name is too long\n"
2461 " DllName: (@ %p) \"%wZ\"\n"
2462 " DllName->Length: %u\n",
2464 DllName,
2465 DllName,
2466 DllName->Length);
2467 return STATUS_NAME_TOO_LONG;
2468 }
2469
2470 /* Add it. Needs to be null terminated, thus the length check above */
2473 }
2474
2475 /* Check for init flag and acquire lock */
2477
2478 _SEH2_TRY
2479 {
2480 /* Show debug message */
2481 if (ShowSnaps)
2482 {
2483 DPRINT1("LDR: LdrLoadDll, loading %wZ from %ws\n",
2484 &RawDllName,
2485 DllPath ? DllPath : L"");
2486 }
2487
2488 /* Check if the DLL is already loaded */
2490 &RawDllName,
2491 FALSE,
2492 Redirected,
2493 &LdrEntry))
2494 {
2495 /* Map it */
2497 DllPath,
2498 NameBuffer,
2499 DllCharacteristics,
2500 FALSE,
2501 Redirected,
2502 &LdrEntry);
2503 if (!NT_SUCCESS(Status))
2505
2506 /* FIXME: Need to mark the DLL range for the stack DB */
2507 //RtlpStkMarkDllRange(LdrEntry);
2508
2509 /* Check if IMAGE_FILE_EXECUTABLE_IMAGE was provided */
2510 if ((DllCharacteristics) &&
2511 (*DllCharacteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
2512 {
2513 /* This is not a DLL, so remove such data */
2514 LdrEntry->EntryPoint = NULL;
2515 LdrEntry->Flags &= ~LDRP_IMAGE_DLL;
2516 }
2517
2518 /* Make sure it's a DLL */
2519 if (LdrEntry->Flags & LDRP_IMAGE_DLL)
2520 {
2521 /* Check if this is a .NET Image */
2522 if (!(LdrEntry->Flags & LDRP_COR_IMAGE))
2523 {
2524 /* Walk the Import Descriptor */
2526 }
2527
2528 /* Update load count, unless it's locked */
2529 if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
2531
2532 /* Check if we failed */
2533 if (!NT_SUCCESS(Status))
2534 {
2535 /* Clear entrypoint, and insert into list */
2536 LdrEntry->EntryPoint = NULL;
2538 &LdrEntry->InInitializationOrderLinks);
2539
2540 /* Cancel the load */
2542
2543 /* Unload the DLL */
2544 if (ShowSnaps)
2545 {
2546 DbgPrint("LDR: Unloading %wZ due to error %x walking "
2547 "import descriptors\n",
2548 DllName,
2549 Status);
2550 }
2551 LdrUnloadDll(LdrEntry->DllBase);
2552
2553 /* Return the error */
2555 }
2556 }
2557 else if (LdrEntry->LoadCount != 0xFFFF)
2558 {
2559 /* Increase load count */
2560 LdrEntry->LoadCount++;
2561 }
2562
2563 /* Insert it into the list */
2565 &LdrEntry->InInitializationOrderLinks);
2566
2567 /* If we have to run the entrypoint, make sure the DB is ready */
2568 if (CallInit && LdrpLdrDatabaseIsSetup)
2569 {
2570 /* Notify Shim Engine */
2571 if (g_ShimsEnabled)
2572 {
2574 SE_DllLoaded(LdrEntry);
2575 }
2576
2577 /* Run the init routine */
2579 if (!NT_SUCCESS(Status))
2580 {
2581 /* Failed, unload the DLL */
2582 if (ShowSnaps)
2583 {
2584 DbgPrint("LDR: Unloading %wZ because either its init "
2585 "routine or one of its static imports failed; "
2586 "status = 0x%08lx\n",
2587 DllName,
2588 Status);
2589 }
2590 LdrUnloadDll(LdrEntry->DllBase);
2591 }
2592 }
2593 else
2594 {
2595 /* The DB isn't ready, which means we were loaded because of a forwarder */
2597 }
2598 }
2599 else
2600 {
2601 /* We were already loaded. Are we a DLL? */
2602 if ((LdrEntry->Flags & LDRP_IMAGE_DLL) && (LdrEntry->LoadCount != 0xFFFF))
2603 {
2604 /* Increase load count */
2605 LdrEntry->LoadCount++;
2607
2608 /* Clear the load in progress */
2610 }
2611 else
2612 {
2613 /* Not a DLL, just increase the load count */
2614 if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
2615 }
2616 }
2617
2618 }
2620 {
2621 /* Release the lock */
2623 }
2624 _SEH2_END;
2625
2626 /* Check for success */
2627 if (NT_SUCCESS(Status))
2628 {
2629 /* Return the base address */
2630 *BaseAddress = LdrEntry->DllBase;
2631 }
2632 else
2633 {
2634 /* Nothing found */
2635 *BaseAddress = NULL;
2636 }
2637
2638 /* Return status */
2639 return Status;
2640}
2641
2642ULONG
2643NTAPI
2645{
2646 PLIST_ENTRY ListHead, Entry;
2647 PLDR_DATA_TABLE_ENTRY LdrEntry;
2648 ULONG ModulesCount = 0;
2649
2650 /* Traverse the init list */
2651 ListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
2652 Entry = ListHead->Flink;
2653 while (Entry != ListHead)
2654 {
2655 /* Get the loader entry */
2656 LdrEntry = CONTAINING_RECORD(Entry,
2658 InInitializationOrderLinks);
2659
2660 /* Clear load in progress flag */
2661 LdrEntry->Flags &= ~LDRP_LOAD_IN_PROGRESS;
2662
2663 /* Check for modules with entry point count but not processed yet */
2664 if ((LdrEntry->EntryPoint) &&
2665 !(LdrEntry->Flags & LDRP_ENTRY_PROCESSED))
2666 {
2667 /* Increase counter */
2668 ModulesCount++;
2669 }
2670
2671 /* Advance to the next entry */
2672 Entry = Entry->Flink;
2673 }
2674
2675 /* Return final count */
2676 return ModulesCount;
2677}
2678
2680{
2683 PVOID Address;
2685 /* Skip Dll init */
2687 return NT_SUCCESS(Status) ? Address : NULL;
2688}
2689
2690VOID
2691NTAPI
2693{
2696 PVOID SE_InstallBeforeInit = LdrpGetShimEngineFunction("SE_InstallBeforeInit");
2697 PVOID SE_InstallAfterInit = LdrpGetShimEngineFunction("SE_InstallAfterInit");
2698 PVOID SE_ProcessDying = LdrpGetShimEngineFunction("SE_ProcessDying");
2699
2701 {
2708 }
2709 else
2710 {
2712 }
2713}
2714
2715VOID
2716NTAPI
2718{
2719 PLIST_ENTRY ListHead, Next;
2720 PLDR_DATA_TABLE_ENTRY LdrEntry;
2721
2722 ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
2723 Next = ListHead->Flink;
2724 while (Next != ListHead)
2725 {
2726 LdrEntry = CONTAINING_RECORD(Next, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
2727
2728 if (g_pShimEngineModule == LdrEntry->DllBase)
2729 {
2730 if (LdrEntry->EntryPoint)
2731 {
2732 _SEH2_TRY
2733 {
2734 LdrpCallInitRoutine(LdrEntry->EntryPoint, LdrEntry->DllBase, Reason, NULL);
2735 }
2737 {
2738 DPRINT1("WARNING: Exception 0x%x during LdrpRunShimEngineInitRoutine(%u)\n",
2740 }
2741 _SEH2_END;
2742 }
2743 return;
2744 }
2745
2746 Next = Next->Flink;
2747 }
2748}
2749
2750VOID
2751NTAPI
2753{
2754 UNICODE_STRING ShimLibraryName;
2755 PVOID ShimLibrary;
2757 RtlInitUnicodeString(&ShimLibraryName, ImageName);
2758 /* We should NOT pass CallInit = TRUE!
2759 If we do this, other init routines will be called before we get a chance to shim stuff.. */
2760 Status = LdrpLoadDll(FALSE, NULL, NULL, &ShimLibraryName, &ShimLibrary, FALSE);
2761 if (NT_SUCCESS(Status))
2762 {
2763 g_pShimEngineModule = ShimLibrary;
2766 if (g_ShimsEnabled)
2767 {
2770 SE_InstallBeforeInit(ProcessImage, pShimData);
2771 }
2772 }
2773}
2774
2775VOID
2776NTAPI
2778{
2779 /* Make sure we do not call into the shim engine anymore */
2784}
2785
2786/* 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:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
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
PIMAGE_NT_HEADERS WINAPI ImageNtHeader(_In_ PVOID)
#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:32
#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:4402
#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
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define _SEH2_LEAVE
Definition: filesup.c:20
_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
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_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:5863
NTSYSAPI PVOID WINAPI RtlReAllocateHeap(HANDLE, ULONG, PVOID, SIZE_T)
Definition: heap.c:2667
NTSYSAPI NTSTATUS WINAPI RtlInitUnicodeStringEx(PUNICODE_STRING, PCWSTR)
NTSYSAPI void WINAPI RtlReleaseActivationContext(HANDLE)
Definition: actctx.c:5373
#define NtCurrentTeb
#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:43
#define LDRP_REDIRECTED
Definition: ldrtypes.h:58
#define LDRP_ENTRY_PROCESSED
Definition: ldrtypes.h:44
BOOLEAN(NTAPI * PDLL_INIT_ROUTINE)(_In_ PVOID DllHandle, _In_ ULONG Reason, _In_opt_ PCONTEXT Context)
Definition: ldrtypes.h:254
_In_ PCWSTR _Out_ PVOID * ActCtx
Definition: ldrtypes.h:247
#define LDRP_IMAGE_NOT_AT_BASE
Definition: ldrtypes.h:51
#define LDRP_STATIC_LINK
Definition: ldrtypes.h:38
#define LDRP_COR_IMAGE
Definition: ldrtypes.h:52
_In_ PCWSTR FullDllName
Definition: ldrtypes.h:247
#define LDRP_IMAGE_DLL
Definition: ldrtypes.h:39
#define LDRP_LOAD_IN_PROGRESS
Definition: ldrtypes.h:42
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:2777
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:2752
BOOLEAN NTAPI LdrpCheckForLoadedDllHandle(IN PVOID Base, OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
Definition: ldrutils.c:1595
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:2409
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:1757
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:2717
VOID NTAPI LdrpFinalizeAndDeallocateDataTableEntry(IN PLDR_DATA_TABLE_ENTRY Entry)
Definition: ldrutils.c:1572
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:2226
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:1556
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:1953
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:1523
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:1641
ULONG NTAPI LdrpClearLoadInProgress(VOID)
Definition: ldrutils.c:2644
PVOID LdrpGetShimEngineFunction(PCSZ FunctionName)
Definition: ldrutils.c:2679
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:2692
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
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
#define _Notnull_
Definition: ms_sal.h:658
#define _Out_
Definition: ms_sal.h:345
#define _When_(expr, annos)
Definition: ms_sal.h:254
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
#define _In_range_(lb, ub)
Definition: ms_sal.h:571
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 ULONG __cdecl DbgPrintEx(_In_ ULONG ComponentId, _In_ ULONG Level, _In_z_ _Printf_format_string_ PCSTR Format,...)
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2439
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:476
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:3952
#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:65
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:59
#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:83
VOID NTAPI LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry)
Definition: ldrinit.c:1539
LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES]
Definition: ldrinit.c:60
UNICODE_STRING LdrpKnownDllPath
Definition: ldrinit.c:63
#define IMAGE_LOADER_FLAGS_COMPLUS
Definition: ntdllp.h:20
NTSTATUS NTAPI LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
Definition: ldrinit.c:641
BOOLEAN LdrpLdrDatabaseIsSetup
Definition: ldrinit.c:33
BOOLEAN ShowSnaps
Definition: ldrinit.c:81
HANDLE LdrpKnownDllObjectDirectory
Definition: ldrinit.c:62
#define LDRP_UPDATE_PIN
Definition: ntdllp.h:17
RTL_CRITICAL_SECTION LdrpLoaderLock
Definition: ldrinit.c:70
#define LDRP_UPDATE_REFCOUNT
Definition: ntdllp.h:15
VOID NTAPI LdrpEnsureLoaderLockIsHeld(VOID)
Definition: ldrinit.c:409
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_NO_MEMORY
Definition: ntstatus.h:260
#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:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
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
#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::@2140 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:143
LIST_ENTRY InLoadOrderLinks
Definition: ldrtypes.h:138
LIST_ENTRY InInitializationOrderLinks
Definition: ldrtypes.h:140
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:151
UNICODE_STRING BaseDllName
Definition: ldrtypes.h:145
PVOID PatchInformation
Definition: ldrtypes.h:164
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PVOID ArbitraryUserPointer
Definition: compat.h:719
LIST_ENTRY InInitializationOrderModuleList
Definition: ldrtypes.h:122
LIST_ENTRY InMemoryOrderModuleList
Definition: btrfs_drv.h:1895
LIST_ENTRY InLoadOrderModuleList
Definition: ldrtypes.h:120
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:167
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:3900
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:1648
char * LPSTR
Definition: xmlstorage.h:182
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180