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