ReactOS  0.4.15-dev-321-g2d9b385
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 = (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 
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  DPRINT("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  DPRINT("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  DPRINT1("Illegal DLL relocation! %wZ overlaps %wZ\n", &OverlapDll, &IllegalDll);
1421 
1422  /* Raise the error */
1424  2,
1425  3,
1426  HardErrorParameters,
1427  OptionOk,
1428  &Response);
1429 
1430  /* If initializing, increase the error count */
1432 
1433  /* Don't do relocation */
1435  goto FailRelocate;
1436  }
1437 
1438  /* Change the protection to prepare for relocation */
1439  Status = LdrpSetProtection(ViewBase, FALSE);
1440 
1441  /* Make sure we changed the protection */
1442  if (NT_SUCCESS(Status))
1443  {
1444  /* Do the relocation */
1447 
1448  if (NT_SUCCESS(Status))
1449  {
1450  /* Stuff the image name in the TIB, for the debugger */
1451  ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
1452  Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer;
1453 #if 0
1454  /* Map the DLL */
1455  Status = NtMapViewOfSection(SectionHandle,
1456  NtCurrentProcess(),
1457  &ViewBase,
1458  0,
1459  0,
1460  NULL,
1461  &ViewSize,
1462  ViewShare,
1463  0,
1464  PAGE_READWRITE);
1465 #endif
1466  /* Restore */
1467  Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
1468 
1469  /* Return the protection */
1470  Status = LdrpSetProtection(ViewBase, TRUE);
1471  }
1472  }
1473 FailRelocate:
1474  /* Handle any kind of failure */
1475  if (!NT_SUCCESS(Status))
1476  {
1477  /* Remove it from the lists */
1478  RemoveEntryList(&LdrEntry->InLoadOrderLinks);
1479  RemoveEntryList(&LdrEntry->InMemoryOrderLinks);
1480  RemoveEntryList(&LdrEntry->HashLinks);
1481 
1482  /* Unmap it, clear the entry */
1484  LdrEntry = NULL;
1485  }
1486 
1487  /* Show debug message */
1488  if (ShowSnaps)
1489  {
1490  DPRINT1("LDR: Fixups %successfully re-applied @ %p\n",
1491  NT_SUCCESS(Status) ? "s" : "uns", ViewBase);
1492  }
1493  }
1494  else
1495  {
1496 NoRelocNeeded:
1497  /* Not a DLL, or no relocation needed */
1499 
1500  /* Stuff the image name in the TIB, for the debugger */
1501  ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
1502  Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer;
1503 #if 0
1504  /* Map the DLL */
1505  Status = NtMapViewOfSection(SectionHandle,
1506  NtCurrentProcess(),
1507  &ViewBase,
1508  0,
1509  0,
1510  NULL,
1511  &ViewSize,
1512  ViewShare,
1513  0,
1514  PAGE_READWRITE);
1515 #endif
1516  /* Restore */
1517  Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
1518 
1519  /* Show debug message */
1520  if (ShowSnaps)
1521  {
1522  DPRINT1("LDR: Fixups won't be re-applied to non-Dll @ %p\n", ViewBase);
1523  }
1524  }
1525  }
1526 
1527  // FIXME: LdrpCheckCorImage() is missing
1528 
1529  /* Check if this is an SMP Machine and a DLL */
1530  if ((LdrpNumberOfProcessors > 1) &&
1531  (LdrEntry && (LdrEntry->Flags & LDRP_IMAGE_DLL)))
1532  {
1533  /* Validate the image for MP */
1534  LdrpValidateImageForMp(LdrEntry);
1535  }
1536 
1537  // FIXME: LdrpCorUnloadImage() is missing
1538 
1539  /* Close section and return status */
1540  NtClose(SectionHandle);
1541  return Status;
1542 }
1543 
1545 NTAPI
1547 {
1548  PLDR_DATA_TABLE_ENTRY LdrEntry = NULL;
1549  PIMAGE_NT_HEADERS NtHeader;
1550 
1551  /* Make sure the header is valid */
1552  NtHeader = RtlImageNtHeader(BaseAddress);
1553  DPRINT("LdrpAllocateDataTableEntry(%p), NtHeader %p\n", BaseAddress, NtHeader);
1554 
1555  if (NtHeader)
1556  {
1557  /* Allocate an entry */
1558  LdrEntry = RtlAllocateHeap(LdrpHeap,
1560  sizeof(LDR_DATA_TABLE_ENTRY));
1561 
1562  /* Make sure we got one */
1563  if (LdrEntry)
1564  {
1565  /* Set it up */
1566  LdrEntry->DllBase = BaseAddress;
1567  LdrEntry->SizeOfImage = NtHeader->OptionalHeader.SizeOfImage;
1568  LdrEntry->TimeDateStamp = NtHeader->FileHeader.TimeDateStamp;
1569  LdrEntry->PatchInformation = NULL;
1570  }
1571  }
1572 
1573  /* Return the entry */
1574  return LdrEntry;
1575 }
1576 
1577 VOID
1578 NTAPI
1580 {
1581  PPEB_LDR_DATA PebData = NtCurrentPeb()->Ldr;
1582  ULONG i;
1583 
1584  /* Insert into hash table */
1585  i = LDR_GET_HASH_ENTRY(LdrEntry->BaseDllName.Buffer[0]);
1586  InsertTailList(&LdrpHashTable[i], &LdrEntry->HashLinks);
1587 
1588  /* Insert into other lists */
1589  InsertTailList(&PebData->InLoadOrderModuleList, &LdrEntry->InLoadOrderLinks);
1590  InsertTailList(&PebData->InMemoryOrderModuleList, &LdrEntry->InMemoryOrderLinks);
1591 }
1592 
1593 VOID
1594 NTAPI
1596 {
1597  /* Sanity check */
1598  ASSERT(Entry != NULL);
1599 
1600  /* Release the activation context if it exists and wasn't already released */
1601  if ((Entry->EntryPointActivationContext) &&
1602  (Entry->EntryPointActivationContext != INVALID_HANDLE_VALUE))
1603  {
1604  /* Mark it as invalid */
1605  RtlReleaseActivationContext(Entry->EntryPointActivationContext);
1606  Entry->EntryPointActivationContext = INVALID_HANDLE_VALUE;
1607  }
1608 
1609  /* Release the full dll name string */
1610  if (Entry->FullDllName.Buffer) LdrpFreeUnicodeString(&Entry->FullDllName);
1611 
1612  /* Finally free the entry's memory */
1613  RtlFreeHeap(LdrpHeap, 0, Entry);
1614 }
1615 
1616 BOOLEAN
1617 NTAPI
1619  OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
1620 {
1621  PLDR_DATA_TABLE_ENTRY Current;
1622  PLIST_ENTRY ListHead, Next;
1623 
1624  /* Check the cache first */
1625  if ((LdrpLoadedDllHandleCache) &&
1627  {
1628  /* We got lucky, return the cached entry */
1629  *LdrEntry = LdrpLoadedDllHandleCache;
1630  return TRUE;
1631  }
1632 
1633  /* Time for a lookup */
1634  ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
1635  Next = ListHead->Flink;
1636  while (Next != ListHead)
1637  {
1638  /* Get the current entry */
1639  Current = CONTAINING_RECORD(Next,
1641  InLoadOrderLinks);
1642 
1643  /* Make sure it's not unloading and check for a match */
1644  if ((Current->InMemoryOrderLinks.Flink) && (Base == Current->DllBase))
1645  {
1646  /* Save in cache */
1647  LdrpLoadedDllHandleCache = Current;
1648 
1649  /* Return it */
1650  *LdrEntry = Current;
1651  return TRUE;
1652  }
1653 
1654  /* Move to the next one */
1655  Next = Next->Flink;
1656  }
1657 
1658  /* Nothing found */
1659  return FALSE;
1660 }
1661 
1662 NTSTATUS
1663 NTAPI
1665  IN PUNICODE_STRING PathName,
1666  IN PUNICODE_STRING FullPathName,
1667  IN PUNICODE_STRING *ExpandedName)
1668 {
1670 // RTL_PATH_TYPE PathType;
1671 // BOOLEAN InvalidName;
1672  ULONG Length;
1673 
1674  /* Display debug output if snaps are on */
1675  if (ShowSnaps)
1676  {
1679  "LDR: %s - Expanding full name of %wZ\n",
1680  __FUNCTION__,
1681  OriginalName);
1682  }
1683 
1684  /* FIXME: Lock the PEB */
1685  //RtlEnterCriticalSection(&FastPebLock);
1686 #if 0
1687  /* Get the path name */
1688  Length = RtlGetFullPathName_Ustr(OriginalName,
1689  PathName->Length,
1690  PathName->Buffer,
1691  NULL,
1692  &InvalidName,
1693  &PathType);
1694 #else
1695  Length = 0;
1696 #endif
1697  if (!(Length) || (Length > UNICODE_STRING_MAX_BYTES))
1698  {
1699  /* Fail */
1701  goto Quickie;
1702  }
1703 
1704  /* Check if the length hasn't changed */
1706  {
1707  /* Return the same thing */
1708  *ExpandedName = PathName;
1709  PathName->Length = (USHORT)Length;
1710  goto Quickie;
1711  }
1712 
1713  /* Sanity check */
1714  ASSERT(Length >= sizeof(WCHAR));
1715 
1716  /* Allocate a string */
1717  Status = LdrpAllocateUnicodeString(FullPathName, Length - sizeof(WCHAR));
1718  if (!NT_SUCCESS(Status)) goto Quickie;
1719 
1720  /* Now get the full path again */
1721 #if 0
1722  Length = RtlGetFullPathName_Ustr(OriginalName,
1723  FullPathName->Length,
1724  FullPathName->Buffer,
1725  NULL,
1726  &InvalidName,
1727  &PathType);
1728 #else
1729  Length = 0;
1730 #endif
1731  if (!(Length) || (Length > FullPathName->Length))
1732  {
1733  /* Fail */
1734  LdrpFreeUnicodeString(FullPathName);
1736  }
1737  else
1738  {
1739  /* Return the expanded name */
1740  *ExpandedName = FullPathName;
1741  FullPathName->Length = (USHORT)Length;
1742  }
1743 
1744 Quickie:
1745  /* FIXME: Unlock the PEB */
1746  //RtlLeaveCriticalSection(&FastPebLock);
1747 
1748  /* Display debug output if snaps are on */
1749  if (ShowSnaps)
1750  {
1751  /* Check which output to use -- failure or success */
1752  if (NT_SUCCESS(Status))
1753  {
1756  "LDR: %s - Expanded to %wZ\n",
1757  __FUNCTION__,
1758  *ExpandedName);
1759  }
1760  else
1761  {
1764  "LDR: %s - Failed to expand %wZ; 0x%08x\n",
1765  __FUNCTION__,
1766  OriginalName,
1767  Status);
1768  }
1769  }
1770 
1771  /* If we failed, return NULL */
1772  if (!NT_SUCCESS(Status)) *ExpandedName = NULL;
1773 
1774  /* Return status */
1775  return Status;
1776 }
1777 
1778 NTSTATUS
1779 NTAPI
1781  IN PWCHAR DllName,
1782  IN PUNICODE_STRING PathName,
1783  IN PUNICODE_STRING FullPathName,
1784  IN PUNICODE_STRING *ExpandedName)
1785 {
1787  PWCHAR ActualSearchPath = *SearchPath;
1788  UNICODE_STRING TestName;
1789  NTSTATUS Status;
1790  PWCHAR Buffer, BufEnd = NULL;
1791  ULONG Length = 0;
1792  WCHAR p;
1793  //PWCHAR pp;
1794 
1795  /* Check if we don't have a search path */
1796  if (!ActualSearchPath) *SearchPath = LdrpDefaultPath.Buffer;
1797 
1798  /* Display debug output if snaps are on */
1799  if (ShowSnaps)
1800  {
1803  "LDR: %s - Looking for %ws in %ws\n",
1804  __FUNCTION__,
1805  DllName,
1806  *SearchPath);
1807  }
1808 
1809  /* Check if we're dealing with a relative path */
1811  {
1812  /* Good, we're not. Create the name string */
1813  Status = RtlInitUnicodeStringEx(&TestName, DllName);
1814  if (!NT_SUCCESS(Status)) goto Quickie;
1815 
1816  /* Make sure it exists */
1817  #if 0
1818  if (!RtlDoesFileExists_UstrEx(&TestName, TRUE))
1819  {
1820  /* It doesn't, fail */
1822  goto Quickie;
1823  }
1824  #endif
1825 
1826  /* Resolve the full name */
1827  Status = LdrpResolveFullName(&TestName,
1828  PathName,
1829  FullPathName,
1830  ExpandedName);
1831  goto Quickie;
1832  }
1833 
1834  /* FIXME: Handle relative case semicolon-lookup here */
1835 
1836  /* Calculate length */
1837  Length += (ULONG)wcslen(DllName) + 1;
1839  {
1840  /* Too long, fail */
1842  goto Quickie;
1843  }
1844 
1845  /* Allocate buffer */
1846  Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR));
1847  if (!Buffer)
1848  {
1849  /* Fail */
1851  goto Quickie;
1852  }
1853 
1854  /* FIXME: Setup TestName here */
1856  BufEnd = Buffer;
1857 
1858  /* Start loop */
1859  do
1860  {
1861  /* Get character */
1862  p = *ActualSearchPath;
1863  if (!(p) || (p == ';'))
1864  {
1865  /* FIXME: We don't have a character, or is a semicolon.*/
1866 
1867  /* Display debug output if snaps are on */
1868  if (ShowSnaps)
1869  {
1872  "LDR: %s - Looking for %ws\n",
1873  __FUNCTION__,
1874  Buffer);
1875  }
1876 
1877  /* Sanity check */
1878  TestName.Length = (USHORT)ALIGN_DOWN((BufEnd - Buffer), WCHAR);
1879 #if 0
1880  ASSERT(TestName.Length < TestName.MaximumLength);
1881 #endif
1882 
1883  /* Check if the file exists */
1884  #if 0
1885  if (RtlDoesFileExists_UstrEx(&TestName, FALSE))
1886  #endif
1887  {
1888  /* It does. Reallocate the buffer */
1889  TestName.MaximumLength = (USHORT)ALIGN_DOWN((BufEnd - Buffer), WCHAR) + sizeof(WCHAR);
1890  TestName.Buffer = RtlReAllocateHeap(RtlGetProcessHeap(),
1891  0,
1892  Buffer,
1893  TestName.MaximumLength);
1894  if (!TestName.Buffer)
1895  {
1896  /* Keep the old one */
1897  TestName.Buffer = Buffer;
1898  }
1899  else
1900  {
1901  /* Update buffer */
1902  Buffer = TestName.Buffer;
1903  }
1904 
1905  /* Make sure we have a buffer at least */
1906  ASSERT(TestName.Buffer);
1907 
1908  /* Resolve the name */
1909  *SearchPath = ActualSearchPath++;
1910  Status = LdrpResolveFullName(&TestName,
1911  PathName,
1912  FullPathName,
1913  ExpandedName);
1914  break;
1915  }
1916 
1917  /* Update buffer end */
1918  BufEnd = Buffer;
1919 
1920  /* Update string position */
1921  //pp = ActualSearchPath++;
1922  }
1923  else
1924  {
1925  /* Otherwise, write the character */
1926  *BufEnd = p;
1927  BufEnd++;
1928  }
1929 
1930  /* Check if the string is empty, meaning we're done */
1931  if (!(*ActualSearchPath)) TryAgain = TRUE;
1932 
1933  /* Advance in the string */
1934  ActualSearchPath++;
1935  } while (!TryAgain);
1936 
1937  /* Check if we had a buffer and free it */
1938  if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1939 
1940 Quickie:
1941  /* Check if we got here through failure */
1942  if (!NT_SUCCESS(Status)) *ExpandedName = NULL;
1943 
1944  /* Display debug output if snaps are on */
1945  if (ShowSnaps)
1946  {
1947  /* Check which output to use -- failure or success */
1948  if (NT_SUCCESS(Status))
1949  {
1952  "LDR: %s - Returning %wZ\n",
1953  __FUNCTION__,
1954  *ExpandedName);
1955  }
1956  else
1957  {
1960  "LDR: %s - Unable to locate %ws in %ws: 0x%08x\n",
1961  __FUNCTION__,
1962  DllName,
1963  ActualSearchPath,
1964  Status);
1965  }
1966  }
1967 
1968  /* Return status */
1969  return Status;
1970 }
1971 
1972 
1973 /* NOTE: This function is b0rked and in the process of being slowly unf*cked */
1974 BOOLEAN
1975 NTAPI
1977  IN PUNICODE_STRING DllName,
1978  IN BOOLEAN Flag,
1979  IN BOOLEAN RedirectedDll,
1980  OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
1981 {
1982  ULONG HashIndex;
1983  PLIST_ENTRY ListHead, ListEntry;
1984  PLDR_DATA_TABLE_ENTRY CurEntry;
1985  BOOLEAN FullPath = FALSE;
1986  PWCHAR wc;
1987  WCHAR NameBuf[266];
1988  UNICODE_STRING FullDllName, NtPathName;
1989  ULONG Length;
1991  NTSTATUS Status;
1992  HANDLE FileHandle, SectionHandle;
1994  PVOID ViewBase = NULL;
1995  SIZE_T ViewSize = 0;
1996  PIMAGE_NT_HEADERS NtHeader, NtHeader2;
1997  DPRINT("LdrpCheckForLoadedDll('%S' '%wZ' %u %u %p)\n", DllPath ? ((ULONG_PTR)DllPath == 1 ? L"" : DllPath) : L"", DllName, Flag, RedirectedDll, LdrEntry);
1998 
1999  /* Check if a dll name was provided */
2000  if (!(DllName->Buffer) || !(DllName->Buffer[0])) return FALSE;
2001 
2002  /* FIXME: Warning, "Flag" is used as magic instead of "Static" */
2003  /* FIXME: Warning, code does not support redirection at all */
2004 
2005  /* Look in the hash table if flag was set */
2006 lookinhash:
2007  if (Flag /* the second check is a hack */ && !RedirectedDll)
2008  {
2009  /* 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 */
2010 
2011  /* Get hash index */
2012  HashIndex = LDR_GET_HASH_ENTRY(DllName->Buffer[0]);
2013 
2014  /* Traverse that list */
2015  ListHead = &LdrpHashTable[HashIndex];
2016  ListEntry = ListHead->Flink;
2017  while (ListEntry != ListHead)
2018  {
2019  /* Get the current entry */
2020  CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, HashLinks);
2021 
2022  /* Check base name of that module */
2023  if (RtlEqualUnicodeString(DllName, &CurEntry->BaseDllName, TRUE))
2024  {
2025  /* It matches, return it */
2026  *LdrEntry = CurEntry;
2027  return TRUE;
2028  }
2029 
2030  /* Advance to the next entry */
2031  ListEntry = ListEntry->Flink;
2032  }
2033 
2034  /* Module was not found, return failure */
2035  return FALSE;
2036  }
2037 
2038  /* Check if this is a redirected DLL */
2039  if (RedirectedDll)
2040  {
2041  /* Redirected dlls already have a full path */
2042  FullPath = TRUE;
2043  FullDllName = *DllName;
2044  }
2045  else
2046  {
2047  /* Check if there is a full path in this DLL */
2048  wc = DllName->Buffer;
2049  while (*wc)
2050  {
2051  /* Check for a slash in the current position*/
2052  if ((*wc == L'\\') || (*wc == L'/'))
2053  {
2054  /* Found the slash, so dll name contains path */
2055  FullPath = TRUE;
2056 
2057  /* Setup full dll name string */
2058  FullDllName.Buffer = NameBuf;
2059 
2060  /* FIXME: This is from the Windows 2000 loader, not XP/2003, we should call LdrpSearchPath */
2062  DllName->Buffer,
2063  NULL,
2064  sizeof(NameBuf) - sizeof(UNICODE_NULL),
2065  FullDllName.Buffer,
2066  NULL);
2067 
2068  /* Check if that was successful */
2069  if (!(Length) || (Length > (sizeof(NameBuf) - sizeof(UNICODE_NULL))))
2070  {
2071  if (ShowSnaps)
2072  {
2073  DPRINT1("LDR: LdrpCheckForLoadedDll - Unable To Locate %wZ: 0x%08x\n",
2074  &DllName, Length);
2075  }
2076  }
2077 
2078  /* Full dll name is found */
2079  FullDllName.Length = Length;
2080  FullDllName.MaximumLength = FullDllName.Length + sizeof(UNICODE_NULL);
2081  break;
2082  }
2083 
2084  wc++;
2085  }
2086  }
2087 
2088  /* Go check the hash table */
2089  if (!FullPath)
2090  {
2091  Flag = TRUE;
2092  goto lookinhash;
2093  }
2094 
2095  /* FIXME: Warning, activation context missing */
2096  DPRINT("Warning, activation context missing\n");
2097 
2098  /* NOTE: From here on down, everything looks good */
2099 
2100  /* Loop the module list */
2101  ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
2102  ListEntry = ListHead->Flink;
2103  while (ListEntry != ListHead)
2104  {
2105  /* Get the current entry and advance to the next one */
2106  CurEntry = CONTAINING_RECORD(ListEntry,
2108  InLoadOrderLinks);
2109  ListEntry = ListEntry->Flink;
2110 
2111  /* Check if it's being unloaded */
2112  if (!CurEntry->InMemoryOrderLinks.Flink) continue;
2113 
2114  /* Check if name matches */
2116  &CurEntry->FullDllName,
2117  TRUE))
2118  {
2119  /* Found it */
2120  *LdrEntry = CurEntry;
2121  return TRUE;
2122  }
2123  }
2124 
2125  /* Convert given path to NT path */
2127  &NtPathName,
2128  NULL,
2129  NULL))
2130  {
2131  /* Fail if conversion failed */
2132  return FALSE;
2133  }
2134 
2135  /* Initialize object attributes and open it */
2137  &NtPathName,
2139  NULL,
2140  NULL);
2144  &Iosb,
2147 
2148  /* Free NT path name */
2149  RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
2150 
2151  /* If opening the file failed - return failure */
2152  if (!NT_SUCCESS(Status)) return FALSE;
2153 
2154  /* Create a section for this file */
2155  Status = NtCreateSection(&SectionHandle,
2159  NULL,
2160  NULL,
2161  PAGE_EXECUTE,
2162  SEC_COMMIT,
2163  FileHandle);
2164 
2165  /* Close file handle */
2167 
2168  /* If creating section failed - return failure */
2169  if (!NT_SUCCESS(Status)) return FALSE;
2170 
2171  /* Map view of this section */
2172  Status = ZwMapViewOfSection(SectionHandle,
2173  NtCurrentProcess(),
2174  &ViewBase,
2175  0,
2176  0,
2177  NULL,
2178  &ViewSize,
2179  ViewShare,
2180  0,
2181  PAGE_EXECUTE);
2182 
2183  /* Close section handle */
2184  NtClose(SectionHandle);
2185 
2186  /* If section mapping failed - return failure */
2187  if (!NT_SUCCESS(Status)) return FALSE;
2188 
2189  /* Get pointer to the NT header of this section */
2190  Status = RtlImageNtHeaderEx(0, ViewBase, ViewSize, &NtHeader);
2191  if (!(NT_SUCCESS(Status)) || !(NtHeader))
2192  {
2193  /* Unmap the section and fail */
2195  return FALSE;
2196  }
2197 
2198  /* Go through the list of modules again */
2199  ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
2200  ListEntry = ListHead->Flink;
2201  while (ListEntry != ListHead)
2202  {
2203  /* Get the current entry and advance to the next one */
2204  CurEntry = CONTAINING_RECORD(ListEntry,
2206  InLoadOrderLinks);
2207  ListEntry = ListEntry->Flink;
2208 
2209  /* Check if it's in the process of being unloaded */
2210  if (!CurEntry->InMemoryOrderLinks.Flink) continue;
2211 
2212  /* The header is untrusted, use SEH */
2213  _SEH2_TRY
2214  {
2215  /* Check if timedate stamp and sizes match */
2216  if ((CurEntry->TimeDateStamp == NtHeader->FileHeader.TimeDateStamp) &&
2217  (CurEntry->SizeOfImage == NtHeader->OptionalHeader.SizeOfImage))
2218  {
2219  /* Time, date and size match. Let's compare their headers */
2220  NtHeader2 = RtlImageNtHeader(CurEntry->DllBase);
2221  if (RtlCompareMemory(NtHeader2, NtHeader, sizeof(IMAGE_NT_HEADERS)))
2222  {
2223  /* Headers match too! Finally ask the kernel to compare mapped files */
2224  Status = ZwAreMappedFilesTheSame(CurEntry->DllBase, ViewBase);
2225  if (NT_SUCCESS(Status))
2226  {
2227  /* This is our entry!, unmap and return success */
2228  *LdrEntry = CurEntry;
2230  _SEH2_YIELD(return TRUE;)
2231  }
2232  }
2233  }
2234  }
2236  {
2237  _SEH2_YIELD(break;)
2238  }
2239  _SEH2_END;
2240  }
2241 
2242  /* Unmap the section and fail */
2244  return FALSE;
2245 }
2246 
2247 NTSTATUS
2248 NTAPI
2251  IN ULONG Ordinal,
2252  OUT PVOID *ProcedureAddress,
2253  IN BOOLEAN ExecuteInit)
2254 {
2256  UCHAR ImportBuffer[64];
2257  PLDR_DATA_TABLE_ENTRY LdrEntry;
2258  IMAGE_THUNK_DATA Thunk;
2259  PVOID ImageBase;
2260  PIMAGE_IMPORT_BY_NAME ImportName = NULL;
2261  PIMAGE_EXPORT_DIRECTORY ExportDir;
2262  ULONG ExportDirSize, Length;
2264 
2265  /* Show debug message */
2266  if (ShowSnaps) DPRINT1("LDR: LdrGetProcedureAddress by ");
2267 
2268  /* Check if we got a name */
2269  if (Name)
2270  {
2271  /* Show debug message */
2272  if (ShowSnaps) DbgPrint("NAME - %s\n", Name->Buffer);
2273 
2274  /* Make sure it's not too long */
2275  Length = Name->Length +
2276  sizeof(CHAR) +
2279  {
2280  /* Won't have enough space to add the hint */
2281  return STATUS_NAME_TOO_LONG;
2282  }
2283 
2284  /* Check if our buffer is large enough */
2285  if (Length > sizeof(ImportBuffer))
2286  {
2287  /* Allocate from heap, plus 2 bytes for the Hint */
2288  ImportName = RtlAllocateHeap(RtlGetProcessHeap(),
2289  0,
2290  Length);
2291  }
2292  else
2293  {
2294  /* Use our internal buffer */
2295  ImportName = (PIMAGE_IMPORT_BY_NAME)ImportBuffer;
2296  }
2297 
2298  /* Clear the hint */
2299  ImportName->Hint = 0;
2300 
2301  /* Copy the name and null-terminate it */
2302  RtlCopyMemory(ImportName->Name, Name->Buffer, Name->Length);
2303  ImportName->Name[Name->Length] = ANSI_NULL;
2304 
2305  /* Clear the high bit */
2306  ImageBase = ImportName;
2307  Thunk.u1.AddressOfData = 0;
2308  }
2309  else
2310  {
2311  /* Do it by ordinal */
2312  ImageBase = NULL;
2313 
2314  /* Show debug message */
2315  if (ShowSnaps) DbgPrint("ORDINAL - %lx\n", Ordinal);
2316 
2317  /* Make sure an ordinal was given */
2318  if (!Ordinal)
2319  {
2320  /* No ordinal */
2321  DPRINT1("No ordinal and no name\n");
2322  return STATUS_INVALID_PARAMETER;
2323  }
2324 
2325  /* Set the original flag in the thunk */
2326  Thunk.u1.Ordinal = Ordinal | IMAGE_ORDINAL_FLAG;
2327  }
2328 
2329  /* Acquire lock unless we are initting */
2331 
2332  _SEH2_TRY
2333  {
2334  /* Try to find the loaded DLL */
2335  if (!LdrpCheckForLoadedDllHandle(BaseAddress, &LdrEntry))
2336  {
2337  /* Invalid base */
2338  DPRINT1("Invalid base address %p\n", BaseAddress);
2340  _SEH2_YIELD(goto Quickie;)
2341  }
2342 
2343  /* Get the pointer to the export directory */
2344  ExportDir = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
2345  TRUE,
2347  &ExportDirSize);
2348 
2349  if (!ExportDir)
2350  {
2351  DPRINT1("Image %wZ has no exports, but were trying to get procedure %Z. BaseAddress asked 0x%p, got entry BA 0x%p\n",
2352  &LdrEntry->BaseDllName, Name, BaseAddress, LdrEntry->DllBase);
2354  _SEH2_YIELD(goto Quickie;)
2355  }
2356 
2357  /* Now get the thunk */
2358  Status = LdrpSnapThunk(LdrEntry->DllBase,
2359  ImageBase,
2360  &Thunk,
2361  &Thunk,
2362  ExportDir,
2363  ExportDirSize,
2364  FALSE,
2365  NULL);
2366 
2367  /* Finally, see if we're supposed to run the init routines */
2368  if ((NT_SUCCESS(Status)) && (ExecuteInit))
2369  {
2370  /*
2371  * It's possible a forwarded entry had us load the DLL. In that case,
2372  * then we will call its DllMain. Use the last loaded DLL for this.
2373  */
2374  Entry = NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Blink;
2375  LdrEntry = CONTAINING_RECORD(Entry,
2377  InInitializationOrderLinks);
2378 
2379  /* Make sure we didn't process it yet*/
2380  if (!(LdrEntry->Flags & LDRP_ENTRY_PROCESSED))
2381  {
2382  /* Call the init routine */
2383  _SEH2_TRY
2384  {
2386  }
2388  {
2389  /* Get the exception code */
2391  }
2392  _SEH2_END;
2393  }
2394  }
2395 
2396  /* Make sure we're OK till here */
2397  if (NT_SUCCESS(Status))
2398  {
2399  /* Return the address */
2400  *ProcedureAddress = (PVOID)Thunk.u1.Function;
2401  }
2402  }
2404  {
2405  /* Just ignore exceptions */
2406  }
2407  _SEH2_END;
2408 
2409 Quickie:
2410  /* Cleanup */
2411  if (ImportName && (ImportName != (PIMAGE_IMPORT_BY_NAME)ImportBuffer))
2412  {
2413  /* We allocated from heap, free it */
2414  RtlFreeHeap(RtlGetProcessHeap(), 0, ImportName);
2415  }
2416 
2417  /* Release the CS if we entered it */
2419 
2420  /* We're done */
2421  return Status;
2422 }
2423 
2424 NTSTATUS
2425 NTAPI
2428  IN PULONG DllCharacteristics OPTIONAL,
2429  IN PUNICODE_STRING DllName,
2431  IN BOOLEAN CallInit)
2432 {
2433  PPEB Peb = NtCurrentPeb();
2435  const WCHAR *p;
2436  BOOLEAN GotExtension;
2437  WCHAR c;
2438  WCHAR NameBuffer[MAX_PATH + 6];
2439  UNICODE_STRING RawDllName;
2440  PLDR_DATA_TABLE_ENTRY LdrEntry;
2441  BOOLEAN InInit = LdrpInLdrInit;
2442 
2443  /* Save the Raw DLL Name */
2444  if (DllName->Length >= sizeof(NameBuffer)) return STATUS_NAME_TOO_LONG;
2445  RtlInitEmptyUnicodeString(&RawDllName, NameBuffer, sizeof(NameBuffer));
2446  RtlCopyUnicodeString(&RawDllName, DllName);
2447 
2448  /* Find the extension, if present */
2449  p = DllName->Buffer + DllName->Length / sizeof(WCHAR) - 1;
2450  GotExtension = FALSE;
2451  while (p >= DllName->Buffer)
2452  {
2453  c = *p--;
2454  if (c == L'.')
2455  {
2456  GotExtension = TRUE;
2457  break;
2458  }
2459  else if (c == L'\\')
2460  {
2461  break;
2462  }
2463  }
2464 
2465  /* If no extension was found, add the default extension */
2466  if (!GotExtension)
2467  {
2468  /* Check that we have space to add one */
2469  if ((DllName->Length + LdrApiDefaultExtension.Length + sizeof(UNICODE_NULL)) >=
2470  sizeof(NameBuffer))
2471  {
2472  /* No space to add the extension */
2475  "LDR: %s - Dll name missing extension; with extension "
2476  "added the name is too long\n"
2477  " DllName: (@ %p) \"%wZ\"\n"
2478  " DllName->Length: %u\n",
2479  __FUNCTION__,
2480  DllName,
2481  DllName,
2482  DllName->Length);
2483  return STATUS_NAME_TOO_LONG;
2484  }
2485 
2486  /* Add it. Needs to be null terminated, thus the length check above */
2487  (VOID)RtlAppendUnicodeStringToString(&RawDllName,
2489  }
2490 
2491  /* Check for init flag and acquire lock */
2492  if (!InInit) RtlEnterCriticalSection(&LdrpLoaderLock);
2493 
2494  _SEH2_TRY
2495  {
2496  /* Show debug message */
2497  if (ShowSnaps)
2498  {
2499  DPRINT1("LDR: LdrLoadDll, loading %wZ from %ws\n",
2500  &RawDllName,
2501  DllPath ? DllPath : L"");
2502  }
2503 
2504  /* Check if the DLL is already loaded */
2506  &RawDllName,
2507  FALSE,
2508  Redirected,
2509  &LdrEntry))
2510  {
2511  /* Map it */
2513  DllPath,
2514  NameBuffer,
2515  DllCharacteristics,
2516  FALSE,
2517  Redirected,
2518  &LdrEntry);
2519  if (!NT_SUCCESS(Status))
2520  _SEH2_LEAVE;
2521 
2522  /* FIXME: Need to mark the DLL range for the stack DB */
2523  //RtlpStkMarkDllRange(LdrEntry);
2524 
2525  /* Check if IMAGE_FILE_EXECUTABLE_IMAGE was provided */
2526  if ((DllCharacteristics) &&
2527  (*DllCharacteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
2528  {
2529  /* This is not a DLL, so remove such data */
2530  LdrEntry->EntryPoint = NULL;
2531  LdrEntry->Flags &= ~LDRP_IMAGE_DLL;
2532  }
2533 
2534  /* Make sure it's a DLL */
2535  if (LdrEntry->Flags & LDRP_IMAGE_DLL)
2536  {
2537  /* Check if this is a .NET Image */
2538  if (!(LdrEntry->Flags & LDRP_COR_IMAGE))
2539  {
2540  /* Walk the Import Descriptor */
2542  }
2543 
2544  /* Update load count, unless it's locked */
2545  if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
2547 
2548  /* Check if we failed */
2549  if (!NT_SUCCESS(Status))
2550  {
2551  /* Clear entrypoint, and insert into list */
2552  LdrEntry->EntryPoint = NULL;
2554  &LdrEntry->InInitializationOrderLinks);
2555 
2556  /* Cancel the load */
2558 
2559  /* Unload the DLL */
2560  if (ShowSnaps)
2561  {
2562  DbgPrint("LDR: Unloading %wZ due to error %x walking "
2563  "import descriptors\n",
2564  DllName,
2565  Status);
2566  }
2567  LdrUnloadDll(LdrEntry->DllBase);
2568 
2569  /* Return the error */
2570  _SEH2_LEAVE;
2571  }
2572  }
2573  else if (LdrEntry->LoadCount != 0xFFFF)
2574  {
2575  /* Increase load count */
2576  LdrEntry->LoadCount++;
2577  }
2578 
2579  /* Insert it into the list */
2581  &LdrEntry->InInitializationOrderLinks);
2582 
2583  /* If we have to run the entrypoint, make sure the DB is ready */
2584  if (CallInit && LdrpLdrDatabaseIsSetup)
2585  {
2586  /* Notify Shim Engine */
2587  if (g_ShimsEnabled)
2588  {
2590  SE_DllLoaded(LdrEntry);
2591  }
2592 
2593  /* Run the init routine */
2595  if (!NT_SUCCESS(Status))
2596  {
2597  /* Failed, unload the DLL */
2598  if (ShowSnaps)
2599  {
2600  DbgPrint("LDR: Unloading %wZ because either its init "
2601  "routine or one of its static imports failed; "
2602  "status = 0x%08lx\n",
2603  DllName,
2604  Status);
2605  }
2606  LdrUnloadDll(LdrEntry->DllBase);
2607  }
2608  }
2609  else
2610  {
2611  /* The DB isn't ready, which means we were loaded because of a forwarder */
2613  }
2614  }
2615  else
2616  {
2617  /* We were already loaded. Are we a DLL? */
2618  if ((LdrEntry->Flags & LDRP_IMAGE_DLL) && (LdrEntry->LoadCount != 0xFFFF))
2619  {
2620  /* Increase load count */
2621  LdrEntry->LoadCount++;
2623 
2624  /* Clear the load in progress */
2626  }
2627  else
2628  {
2629  /* Not a DLL, just increase the load count */
2630  if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
2631  }
2632  }
2633 
2634  }
2636  {
2637  /* Release the lock */
2638  if (!InInit) RtlLeaveCriticalSection(&LdrpLoaderLock);
2639  }
2640  _SEH2_END;
2641 
2642  /* Check for success */
2643  if (NT_SUCCESS(Status))
2644  {
2645  /* Return the base address */
2646  *BaseAddress = LdrEntry->DllBase;
2647  }
2648  else
2649  {
2650  /* Nothing found */
2651  *BaseAddress = NULL;
2652  }
2653 
2654  /* Return status */
2655  return Status;
2656 }
2657 
2658 ULONG
2659 NTAPI
2661 {
2662  PLIST_ENTRY ListHead, Entry;
2663  PLDR_DATA_TABLE_ENTRY LdrEntry;
2664  ULONG ModulesCount = 0;
2665 
2666  /* Traverse the init list */
2667  ListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
2668  Entry = ListHead->Flink;
2669  while (Entry != ListHead)
2670  {
2671  /* Get the loader entry */
2672  LdrEntry = CONTAINING_RECORD(Entry,
2674  InInitializationOrderLinks);
2675 
2676  /* Clear load in progress flag */
2677  LdrEntry->Flags &= ~LDRP_LOAD_IN_PROGRESS;
2678 
2679  /* Check for modules with entry point count but not processed yet */
2680  if ((LdrEntry->EntryPoint) &&
2681  !(LdrEntry->Flags & LDRP_ENTRY_PROCESSED))
2682  {
2683  /* Increase counter */
2684  ModulesCount++;
2685  }
2686 
2687  /* Advance to the next entry */
2688  Entry = Entry->Flink;
2689  }
2690 
2691  /* Return final count */
2692  return ModulesCount;
2693 }
2694 
2696 {
2698  NTSTATUS Status;
2699  PVOID Address;
2701  /* Skip Dll init */
2703  return NT_SUCCESS(Status) ? Address : NULL;
2704 }
2705 
2706 VOID
2707 NTAPI
2709 {
2710  PVOID SE_DllLoaded = LdrpGetShimEngineFunction("SE_DllLoaded");
2711  PVOID SE_DllUnloaded = LdrpGetShimEngineFunction("SE_DllUnloaded");
2712  PVOID SE_InstallBeforeInit = LdrpGetShimEngineFunction("SE_InstallBeforeInit");
2713  PVOID SE_InstallAfterInit = LdrpGetShimEngineFunction("SE_InstallAfterInit");
2714  PVOID SE_ProcessDying = LdrpGetShimEngineFunction("SE_ProcessDying");
2715 
2717  {
2723  g_ShimsEnabled = TRUE;
2724  }
2725  else
2726  {
2728  }
2729 }
2730 
2731 VOID
2732 NTAPI
2734 {
2735  PLIST_ENTRY ListHead, Next;
2736  PLDR_DATA_TABLE_ENTRY LdrEntry;
2737 
2738  ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
2739  Next = ListHead->Flink;
2740  while (Next != ListHead)
2741  {
2742  LdrEntry = CONTAINING_RECORD(Next, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
2743 
2744  if (g_pShimEngineModule == LdrEntry->DllBase)
2745  {
2746  if (LdrEntry->EntryPoint)
2747  {
2748  _SEH2_TRY
2749  {
2750  LdrpCallInitRoutine(LdrEntry->EntryPoint, LdrEntry->DllBase, Reason, NULL);
2751  }
2753  {
2754  DPRINT1("WARNING: Exception 0x%x during LdrpRunShimEngineInitRoutine(%u)\n",
2756  }
2757  _SEH2_END;
2758  }
2759  return;
2760  }
2761 
2762  Next = Next->Flink;
2763  }
2764 }
2765 
2766 VOID
2767 NTAPI
2769 {
2770  UNICODE_STRING ShimLibraryName;
2771  PVOID ShimLibrary;
2772  NTSTATUS Status;
2773  RtlInitUnicodeString(&ShimLibraryName, ImageName);
2774  /* We should NOT pass CallInit = TRUE!
2775  If we do this, other init routines will be called before we get a chance to shim stuff.. */
2776  Status = LdrpLoadDll(FALSE, NULL, NULL, &ShimLibraryName, &ShimLibrary, FALSE);
2777  if (NT_SUCCESS(Status))
2778  {
2779  g_pShimEngineModule = ShimLibrary;
2782  if (g_ShimsEnabled)
2783  {
2786  SE_InstallBeforeInit(ProcessImage, pShimData);
2787  }
2788  }
2789 }
2790 
2791 VOID
2792 NTAPI
2794 {
2795  /* Make sure we do not call into the shim engine anymore */
2800 }
2801 
2802 /* 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:42
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:44
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:39
VOID NTAPI LdrpGetShimEngineInterface()
Definition: ldrutils.c:2708
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:3782
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define LL
Definition: tui.h:84
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:122
#define IMAGE_FILE_SYSTEM
Definition: pedump.c:168
NTSYSAPI NTSTATUS WINAPI RtlInitUnicodeStringEx(PUNICODE_STRING, PCWSTR)
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:3373
struct _Entry Entry
Definition: kefuncs.h:627
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
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
LIST_ENTRY InLoadOrderModuleList
Definition: ldrtypes.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define LDRP_REDIRECTED
Definition: ldrtypes.h:58
uint16_t * PWSTR
Definition: typedefs.h:55
BOOLEAN NTAPI LdrpCheckForLoadedDllHandle(IN PVOID Base, OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
Definition: ldrutils.c:1618
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:606
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2373
LIST_ENTRY InMemoryOrderModuleList
Definition: btrfs_drv.h:1941
VOID WINAPI SE_DllLoaded(PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: shimeng.c:1433
#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:1422
VOID NTAPI LdrpFinalizeAndDeallocateDataTableEntry(IN PLDR_DATA_TABLE_ENTRY Entry)
Definition: ldrutils.c:1595
VOID NTAPI LdrpInsertMemoryTableEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: ldrutils.c:1579
VOID NTAPI LdrpRunShimEngineInitRoutine(IN ULONG Reason)
Definition: ldrutils.c:2733
ULONG SizeOfImage
Definition: ldrtypes.h:143
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:400
struct _IMAGE_IMPORT_DESCRIPTOR * PIMAGE_IMPORT_DESCRIPTOR
VOID NTAPI LdrpCallTlsInitializers(IN PLDR_DATA_TABLE_ENTRY LdrEntry, IN ULONG Reason)
Definition: ldrutils.c:473
PVOID ImageBaseAddress
Definition: ntddk_ex.h:245
struct _IMAGE_IMPORT_BY_NAME * PIMAGE_IMPORT_BY_NAME
#define DLL_PROCESS_ATTACH
Definition: compat.h:120
NTSTATUS NTAPI LdrpResolveFullName(IN PUNICODE_STRING OriginalName, IN PUNICODE_STRING PathName, IN PUNICODE_STRING FullPathName, IN PUNICODE_STRING *ExpandedName)
Definition: ldrutils.c:1664
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:55
#define InsertTailList(ListHead, Entry)
char * LPSTR
Definition: xmlstorage.h:182
PVOID g_pfnSE_InstallBeforeInit
Definition: ldrutils.c:25
#define UNICODE_STRING_MAX_BYTES
PVOID ArbitraryUserPointer
Definition: compat.h:388
#define IMAGE_FILE_DLL
Definition: pedump.c:169
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:2426
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
#define SearchPath
Definition: winbase.h:3740
_SEH2_TRY
Definition: create.c:4250
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
uint32_t ULONG_PTR
Definition: typedefs.h:64
#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:1926
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:2768
#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:681
#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:203
VOID NTAPI SE_InstallBeforeInit(PUNICODE_STRING ProcessImage, PVOID pShimData)
Definition: shimeng.c:1403
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:3554
#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:3501
#define LDRP_IMAGE_NOT_AT_BASE
Definition: ldrtypes.h:51
unsigned char BOOLEAN
BOOLEAN(NTAPI * PDLL_INIT_ROUTINE)(_In_ PVOID DllHandle, _In_ ULONG Reason, _In_opt_ PCONTEXT Context)
Definition: ldrtypes.h:254
smooth NULL
Definition: ftsmooth.c:416
static WCHAR Address[46]
Definition: ping.c:68
#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
NTSTATUS NTAPI RtlImageNtHeaderEx(_In_ ULONG Flags, _In_ PVOID Base, _In_ ULONG64 Size, _Out_ PIMAGE_NT_HEADERS *OutHeaders)
Definition: libsupp.c:32
#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:247
NTSTATUS NTAPI LdrpGetProcedureAddress(IN PVOID BaseAddress, IN PANSI_STRING Name, IN ULONG Ordinal, OUT PVOID *ProcedureAddress, IN BOOLEAN ExecuteInit)
Definition: ldrutils.c:2249
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 DLL_PROCESS_DETACH
Definition: compat.h:119
#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:588
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:1976
PVOID PatchInformation
Definition: ldrtypes.h:164
VOID NTAPI SE_ProcessDying(VOID)
Definition: shimeng.c:1427
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
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:72
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
PLDR_DATA_TABLE_ENTRY NTAPI LdrpAllocateDataTableEntry(IN PVOID BaseAddress)
Definition: ldrutils.c:1546
PVOID g_pShimEngineModule
Definition: ldrutils.c:22
VOID WINAPI SE_DllUnloaded(PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: shimeng.c:1451
#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
__wchar_t WCHAR
Definition: xmlstorage.h:180
return Iosb
Definition: create.c:4426
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#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
NTSYSAPI NTSTATUS WINAPI RtlFindActivationContextSectionString(ULONG, const GUID *, ULONG, const UNICODE_STRING *, PVOID)
Definition: actctx.c:5743
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:5939
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:2660
struct _LDR_DATA_TABLE_ENTRY * PLDR_DATA_TABLE_ENTRY
_In_ PCWSTR _Out_ PVOID * ActCtx
Definition: ldrtypes.h:247
NTSTATUS NTAPI LdrpSearchPath(IN PWCHAR *SearchPath, IN PWCHAR DllName, IN PUNICODE_STRING PathName, IN PUNICODE_STRING FullPathName, IN PUNICODE_STRING *ExpandedName)
Definition: ldrutils.c:1780
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
Definition: ncftp.h:89
VOID NTAPI LdrpUnloadShimEngine()
Definition: ldrutils.c:2793
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:43
static const WCHAR L[]
Definition: oid.c:1250
#define RtlImageDirectoryEntryToData
Definition: compat.h:469
LIST_ENTRY HashLinks
Definition: ldrtypes.h:151
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:454
#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:821
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
Definition: btrfs_drv.h:1922
ULONG LdrpNumberOfProcessors
Definition: ldrinit.c:55
Definition: typedefs.h:118
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
#define SYNCHRONIZE
Definition: nt_native.h:61
NTSYSAPI void WINAPI RtlReleaseActivationContext(HANDLE)
Definition: actctx.c:5272
#define IMAGE_DIRECTORY_ENTRY_EXPORT
Definition: compat.h:140
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
Status
Definition: gdiplustypes.h:24
UNICODE_STRING LdrpKnownDllPath
Definition: ldrinit.c:63
ULONG TimeDateStamp
Definition: btrfs_drv.h:1935
LIST_ENTRY InLoadOrderLinks
Definition: ldrtypes.h:138
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:79
#define STATUS_IMAGE_NOT_AT_BASE
Definition: ntstatus.h:117
Definition: compat.h:493
#define LDRP_COR_IMAGE
Definition: ldrtypes.h:52
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:20
#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:1924
PPEB_LDR_DATA Ldr
Definition: btrfs_drv.h:1958
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:2695
UNICODE_STRING FullDllName
Definition: btrfs_drv.h:1928
UNICODE_STRING BaseDllName
Definition: ldrtypes.h:145
#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
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:1274
struct _IMAGE_BOUND_IMPORT_DESCRIPTOR * PIMAGE_BOUND_IMPORT_DESCRIPTOR
#define RtlImageNtHeader
Definition: compat.h:466
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:5862
#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:40
_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:207
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
NTSYSAPI PVOID WINAPI RtlReAllocateHeap(HANDLE, ULONG, PVOID, SIZE_T)
Definition: heap.c:2562
#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)
union _IMAGE_THUNK_DATA32::@2099 u1
#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:3014
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:112
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:332
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
LIST_ENTRY InInitializationOrderLinks
Definition: ldrtypes.h:140
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
USHORT LoadCount
Definition: ntddk_ex.h:208
#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