ReactOS  0.4.15-dev-1177-g6cb3b62
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  goto Exit;
646  }
647 
648  /* Check for Safer restrictions */
649  if (!DllCharacteristics ||
650  !(*DllCharacteristics & IMAGE_FILE_SYSTEM))
651  {
652  /* Make sure it's executable */
653  Status = ZwQuerySection(*SectionHandle,
655  &SectionImageInfo,
657  NULL);
658  if (NT_SUCCESS(Status))
659  {
660  /* Bypass the check for .NET images */
661  if (!(SectionImageInfo.LoaderFlags & IMAGE_LOADER_FLAGS_COMPLUS))
662  {
663  /* Check with Safer */
666  {
667  /* Show debug message */
668  if (ShowSnaps)
669  {
670  DPRINT1("LDR: Loading of (%wZ) blocked by Winsafer\n",
671  &FullName);
672  }
673 
674  /* Failure case, close section handle */
675  NtClose(*SectionHandle);
676  *SectionHandle = NULL;
677  }
678  }
679  }
680  else
681  {
682  /* Failure case, close section handle */
683  NtClose(*SectionHandle);
684  *SectionHandle = NULL;
685  }
686  }
687 
688 Exit:
689  /* Close the file handle, we don't need it */
691 
692  /* Return status */
693  return Status;
694 }
695 
696 /* NOTE: This function is totally b0rked and doesn't handle the parameters/functionality it should */
697 BOOLEAN
698 NTAPI
700  PWSTR DllName,
702  PUNICODE_STRING BaseDllName)
703 {
704  PWCHAR NameBuffer, p1, p2 = 0;
705  ULONG Length;
706  ULONG BufSize = 500;
707 
708  /* Allocate space for full DLL name */
709  FullDllName->Buffer = RtlAllocateHeap(LdrpHeap, 0, BufSize + sizeof(UNICODE_NULL));
710  if (!FullDllName->Buffer) return FALSE;
711 
713  DllName,
714  NULL,
715  BufSize,
716  FullDllName->Buffer,
717  &BaseDllName->Buffer);
718 
719  if (!Length || Length > BufSize)
720  {
721  if (ShowSnaps)
722  {
723  DPRINT1("LDR: LdrResolveDllName - Unable to find ");
724  DPRINT1("%ws from %ws\n", DllName, DllPath ? DllPath : LdrpDefaultPath.Buffer);
725  }
726 
728  return FALSE;
729  }
730 
731  /* Construct full DLL name */
732  FullDllName->Length = Length;
733  FullDllName->MaximumLength = FullDllName->Length + sizeof(UNICODE_NULL);
734 
735  /* Allocate a new buffer */
736  NameBuffer = RtlAllocateHeap(LdrpHeap, 0, FullDllName->MaximumLength);
737  if (!NameBuffer)
738  {
739  RtlFreeHeap(LdrpHeap, 0, FullDllName->Buffer);
740  return FALSE;
741  }
742 
743  /* Copy over the contents from the previous one and free it */
744  RtlCopyMemory(NameBuffer, FullDllName->Buffer, FullDllName->MaximumLength);
745  RtlFreeHeap(LdrpHeap, 0, FullDllName->Buffer);
746  FullDllName->Buffer = NameBuffer;
747 
748  /* Find last backslash */
749  p1 = FullDllName->Buffer;
750  while (*p1)
751  {
752  if (*p1++ == L'\\')
753  {
754  p2 = p1;
755  }
756  }
757 
758  /* If found, set p1 to it, otherwise p1 points to the beginning of DllName */
759  if (p2)
760  p1 = p2;
761  else
762  p1 = DllName;
763 
764  p2 = p1;
765 
766  /* Calculate remaining length */
767  while (*p1) ++p1;
768 
769  /* Construct base DLL name */
770  BaseDllName->Length = (ULONG_PTR)p1 - (ULONG_PTR)p2;
771  BaseDllName->MaximumLength = BaseDllName->Length + sizeof(UNICODE_NULL);
772  BaseDllName->Buffer = RtlAllocateHeap(LdrpHeap, 0, BaseDllName->MaximumLength);
773 
774  if (!BaseDllName->Buffer)
775  {
776  RtlFreeHeap(LdrpHeap, 0, NameBuffer);
777  return FALSE;
778  }
779 
780  /* Copy base dll name to the new buffer */
781  RtlMoveMemory(BaseDllName->Buffer,
782  p2,
783  BaseDllName->Length);
784 
785  /* Null-terminate the string */
786  BaseDllName->Buffer[BaseDllName->Length / sizeof(WCHAR)] = 0;
787 
788  return TRUE;
789 }
790 
791 PVOID
792 NTAPI
794 {
795  PIMAGE_NT_HEADERS NtHeaders;
796  ULONG_PTR EntryPoint = 0;
797 
798  /* Get entry point offset from NT headers */
799  NtHeaders = RtlImageNtHeader(ImageBase);
800  if (NtHeaders)
801  {
802  /* Add image base */
803  EntryPoint = NtHeaders->OptionalHeader.AddressOfEntryPoint;
804  if (EntryPoint) EntryPoint += (ULONG_PTR)ImageBase;
805  }
806 
807  /* Return calculated pointer (or zero in case of failure) */
808  return (PVOID)EntryPoint;
809 }
810 
811 /* NOTE: This function is partially missing SxS */
812 NTSTATUS
813 NTAPI
816  PUNICODE_STRING BaseDllName,
817  HANDLE *SectionHandle)
818 {
820  HANDLE Section = NULL;
821  UNICODE_STRING DllNameUnic;
823  PCHAR p1;
824  PWCHAR p2;
825 
826  /* Zero initialize provided parameters */
827  if (SectionHandle) *SectionHandle = 0;
828 
829  if (FullDllName)
830  {
831  FullDllName->Length = 0;
832  FullDllName->MaximumLength = 0;
833  FullDllName->Buffer = NULL;
834  }
835 
836  if (BaseDllName)
837  {
838  BaseDllName->Length = 0;
839  BaseDllName->MaximumLength = 0;
840  BaseDllName->Buffer = NULL;
841  }
842 
843  /* If any of these three params are missing then fail */
844  if (!SectionHandle || !FullDllName || !BaseDllName)
846 
847  /* Check the Loader Lock */
849 
850  /* Upgrade DllName to a unicode string */
851  RtlInitUnicodeString(&DllNameUnic, DllName);
852 
853  /* FIXME: Missing RtlComputePrivatizedDllName_U related functionality */
854 
855  /* Get the activation context */
857  NULL,
858  ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
859  &DllNameUnic,
860  NULL);
861 
862  /* Check if it's a SxS or not */
865  {
866  /* NOTE: Here it's beneficial to allocate one big unicode string
867  using LdrpAllocateUnicodeString instead of fragmenting the heap
868  with two allocations as it's done now. */
869 
870  /* Set up BaseDllName */
871  BaseDllName->Length = DllNameUnic.Length;
872  BaseDllName->MaximumLength = DllNameUnic.MaximumLength;
873  BaseDllName->Buffer = RtlAllocateHeap(LdrpHeap,
874  0,
875  DllNameUnic.MaximumLength);
876  if (!BaseDllName->Buffer)
877  {
879  goto Failure;
880  }
881 
882  /* Copy the contents there */
883  RtlMoveMemory(BaseDllName->Buffer, DllNameUnic.Buffer, DllNameUnic.MaximumLength);
884 
885  /* Set up FullDllName */
886  FullDllName->Length = LdrpKnownDllPath.Length + BaseDllName->Length + sizeof(WCHAR);
887  FullDllName->MaximumLength = FullDllName->Length + sizeof(UNICODE_NULL);
888  FullDllName->Buffer = RtlAllocateHeap(LdrpHeap, 0, FullDllName->MaximumLength);
889  if (!FullDllName->Buffer)
890  {
892  goto Failure;
893  }
894 
896 
897  /* Put a slash there */
898  p1 = (PCHAR)FullDllName->Buffer + LdrpKnownDllPath.Length;
899  p2 = (PWCHAR)p1;
900  *p2++ = (WCHAR)'\\';
901  p1 = (PCHAR)p2;
902 
903  /* Set up DllNameUnic for a relative path */
904  DllNameUnic.Buffer = (PWSTR)p1;
905  DllNameUnic.Length = BaseDllName->Length;
906  DllNameUnic.MaximumLength = DllNameUnic.Length + sizeof(UNICODE_NULL);
907 
908  /* Copy the contents */
909  RtlMoveMemory(p1, BaseDllName->Buffer, BaseDllName->MaximumLength);
910 
911  /* There are all names, init attributes and open the section */
913  &DllNameUnic,
916  NULL);
917 
918  Status = NtOpenSection(&Section,
921  if (!NT_SUCCESS(Status))
922  {
923  /* Clear status in case it was just not found */
925  goto Failure;
926  }
927 
928  /* Pass section handle to the caller and return success */
929  *SectionHandle = Section;
930  return STATUS_SUCCESS;
931  }
932 
933 Failure:
934  /* Close section object if it was opened */
935  if (Section) NtClose(Section);
936 
937  /* Free string resources */
938  if (BaseDllName->Buffer) RtlFreeHeap(LdrpHeap, 0, BaseDllName->Buffer);
939  if (FullDllName->Buffer) RtlFreeHeap(LdrpHeap, 0, FullDllName->Buffer);
940 
941  /* Return status */
942  return Status;
943 }
944 
945 NTSTATUS
946 NTAPI
948  BOOLEAN Restore)
949 {
950  PIMAGE_NT_HEADERS NtHeaders;
951  PIMAGE_SECTION_HEADER Section;
953  PVOID SectionBase;
954  SIZE_T SectionSize;
955  ULONG NewProtection, OldProtection, i;
956 
957  /* Get the NT headers */
958  NtHeaders = RtlImageNtHeader(ViewBase);
959  if (!NtHeaders) return STATUS_INVALID_IMAGE_FORMAT;
960 
961  /* Compute address of the first section header */
962  Section = IMAGE_FIRST_SECTION(NtHeaders);
963 
964  /* Go through all sections */
965  for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++)
966  {
967  /* Check for read-only non-zero section */
968  if ((Section->SizeOfRawData) &&
969  !(Section->Characteristics & IMAGE_SCN_MEM_WRITE))
970  {
971  /* Check if we are setting or restoring protection */
972  if (Restore)
973  {
974  /* Set it to either EXECUTE or READONLY */
975  if (Section->Characteristics & IMAGE_SCN_MEM_EXECUTE)
976  {
977  NewProtection = PAGE_EXECUTE;
978  }
979  else
980  {
981  NewProtection = PAGE_READONLY;
982  }
983 
984  /* Add PAGE_NOCACHE if needed */
986  {
987  NewProtection |= PAGE_NOCACHE;
988  }
989  }
990  else
991  {
992  /* Enable write access */
993  NewProtection = PAGE_READWRITE;
994  }
995 
996  /* Get the section VA */
997  SectionBase = (PVOID)((ULONG_PTR)ViewBase + Section->VirtualAddress);
998  SectionSize = Section->SizeOfRawData;
999  if (SectionSize)
1000  {
1001  /* Set protection */
1003  &SectionBase,
1004  &SectionSize,
1005  NewProtection,
1006  &OldProtection);
1007  if (!NT_SUCCESS(Status)) return Status;
1008  }
1009  }
1010 
1011  /* Move to the next section */
1012  Section++;
1013  }
1014 
1015  /* Flush instruction cache if necessary */
1016  if (Restore) ZwFlushInstructionCache(NtCurrentProcess(), NULL, 0);
1017  return STATUS_SUCCESS;
1018 }
1019 
1020 /* NOTE: Not yet reviewed */
1021 NTSTATUS
1022 NTAPI
1024  IN PWSTR DllPath2,
1025  IN PWSTR DllName OPTIONAL,
1026  IN PULONG DllCharacteristics,
1027  IN BOOLEAN Static,
1028  IN BOOLEAN Redirect,
1029  OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry)
1030 {
1031  PTEB Teb = NtCurrentTeb();
1032  PPEB Peb = NtCurrentPeb();
1033  PWCHAR p1 = DllName;
1034  WCHAR TempChar;
1035  BOOLEAN KnownDll = FALSE;
1036  UNICODE_STRING FullDllName, BaseDllName;
1037  HANDLE SectionHandle = NULL, DllHandle = 0;
1038  UNICODE_STRING NtPathDllName;
1039  ULONG_PTR HardErrorParameters[2];
1040  UNICODE_STRING HardErrorDllName, HardErrorDllPath;
1041  ULONG Response;
1042  SIZE_T ViewSize = 0;
1043  PVOID ViewBase = NULL;
1044  PVOID ArbitraryUserPointer;
1045  PIMAGE_NT_HEADERS NtHeaders;
1046  NTSTATUS HardErrorStatus, Status;
1047  BOOLEAN OverlapDllFound = FALSE;
1048  ULONG_PTR ImageBase, ImageEnd;
1049  PLIST_ENTRY ListHead, NextEntry;
1050  PLDR_DATA_TABLE_ENTRY CandidateEntry, LdrEntry;
1051  ULONG_PTR CandidateBase, CandidateEnd;
1052  UNICODE_STRING OverlapDll;
1053  BOOLEAN RelocatableDll = TRUE;
1054  UNICODE_STRING IllegalDll;
1055  PVOID RelocData;
1056  ULONG RelocDataSize = 0;
1057 
1058  // FIXME: AppCompat stuff is missing
1059 
1060  if (ShowSnaps)
1061  {
1062  DPRINT1("LDR: LdrpMapDll: Image Name %ws, Search Path %ws\n",
1063  DllName,
1064  SearchPath ? SearchPath : L"");
1065  }
1066 
1067  /* Check if we have a known dll directory */
1068  if (LdrpKnownDllObjectDirectory && Redirect == FALSE)
1069  {
1070  /* Check if the path is full */
1071  while (*p1)
1072  {
1073  TempChar = *p1++;
1074  if (TempChar == '\\' || TempChar == '/' )
1075  {
1076  /* Complete path, don't do Known Dll lookup */
1077  goto SkipCheck;
1078  }
1079  }
1080 
1081  /* Try to find a Known DLL */
1082  Status = LdrpCheckForKnownDll(DllName,
1083  &FullDllName,
1084  &BaseDllName,
1085  &SectionHandle);
1086 
1088  {
1089  /* Failure */
1092  "LDR: %s - call to LdrpCheckForKnownDll(\"%ws\", ...) failed with status %x\n",
1093  __FUNCTION__,
1094  DllName,
1095  Status);
1096 
1097  return Status;
1098  }
1099  }
1100 
1101 SkipCheck:
1102 
1103  /* Check if the Known DLL Check returned something */
1104  if (!SectionHandle)
1105  {
1106  /* It didn't, so try to resolve the name now */
1108  DllName,
1109  &FullDllName,
1110  &BaseDllName))
1111  {
1112  /* Got a name, display a message */
1113  if (ShowSnaps)
1114  {
1115  DPRINT1("LDR: Loading (%s) %wZ\n",
1116  Static ? "STATIC" : "DYNAMIC",
1117  &FullDllName);
1118  }
1119 
1120  /* Convert to NT Name */
1122  &NtPathDllName,
1123  NULL,
1124  NULL))
1125  {
1126  /* Path was invalid */
1128  }
1129 
1130  /* Create a section for this dLL */
1131  Status = LdrpCreateDllSection(&NtPathDllName,
1132  DllHandle,
1133  DllCharacteristics,
1134  &SectionHandle);
1135 
1136  /* Free the NT Name */
1137  RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathDllName.Buffer);
1138 
1139  /* If we failed */
1140  if (!NT_SUCCESS(Status))
1141  {
1142  /* Free the name strings and return */
1144  LdrpFreeUnicodeString(&BaseDllName);
1145  return Status;
1146  }
1147  }
1148  else
1149  {
1150  /* We couldn't resolve the name, is this a static load? */
1151  if (Static)
1152  {
1153  /*
1154  * This is BAD! Static loads are CRITICAL. Bugcheck!
1155  * Initialize the strings for the error
1156  */
1157  RtlInitUnicodeString(&HardErrorDllName, DllName);
1158  RtlInitUnicodeString(&HardErrorDllPath,
1159  DllPath2 ? DllPath2 : LdrpDefaultPath.Buffer);
1160 
1161  /* Set them as error parameters */
1162  HardErrorParameters[0] = (ULONG_PTR)&HardErrorDllName;
1163  HardErrorParameters[1] = (ULONG_PTR)&HardErrorDllPath;
1164 
1165  /* Raise the hard error */
1167  2,
1168  0x00000003,
1169  HardErrorParameters,
1170  OptionOk,
1171  &Response);
1172 
1173  /* We're back, where we initializing? */
1175  }
1176 
1177  /* Return failure */
1178  return STATUS_DLL_NOT_FOUND;
1179  }
1180  }
1181  else
1182  {
1183  /* We have a section handle, so this is a known dll */
1184  KnownDll = TRUE;
1185  }
1186 
1187  /* Stuff the image name in the TIB, for the debugger */
1188  ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
1189  Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer;
1190 
1191  /* Map the DLL */
1192  ViewBase = NULL;
1193  ViewSize = 0;
1194  Status = NtMapViewOfSection(SectionHandle,
1195  NtCurrentProcess(),
1196  &ViewBase,
1197  0,
1198  0,
1199  NULL,
1200  &ViewSize,
1201  ViewShare,
1202  0,
1203  PAGE_READWRITE);
1204 
1205  /* Restore */
1206  Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
1207 
1208  /* Fail if we couldn't map it */
1209  if (!NT_SUCCESS(Status))
1210  {
1211  /* Close and return */
1212  NtClose(SectionHandle);
1213  return Status;
1214  }
1215 
1216  /* Get the NT Header */
1217  if (!(NtHeaders = RtlImageNtHeader(ViewBase)))
1218  {
1219  /* Invalid image, unmap, close handle and fail */
1221  NtClose(SectionHandle);
1223  }
1224 
1225  // FIXME: .NET support is missing
1226 
1227  /* Allocate an entry */
1228  if (!(LdrEntry = LdrpAllocateDataTableEntry(ViewBase)))
1229  {
1230  /* Invalid image, unmap, close handle and fail */
1232  NtClose(SectionHandle);
1233  return STATUS_NO_MEMORY;
1234  }
1235 
1236  /* Setup the entry */
1237  LdrEntry->Flags = Static ? LDRP_STATIC_LINK : 0;
1238  if (Redirect) LdrEntry->Flags |= LDRP_REDIRECTED;
1239  LdrEntry->LoadCount = 0;
1240  LdrEntry->FullDllName = FullDllName;
1241  LdrEntry->BaseDllName = BaseDllName;
1242  LdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(LdrEntry->DllBase);
1243 
1244  /* Show debug message */
1245  if (ShowSnaps)
1246  {
1247  DPRINT1("LDR: LdrpMapDll: Full Name %wZ, Base Name %wZ\n",
1248  &FullDllName,
1249  &BaseDllName);
1250  }
1251 
1252  /* Insert this entry */
1253  LdrpInsertMemoryTableEntry(LdrEntry);
1254 
1255  // LdrpSendDllNotifications(LdrEntry, TRUE, Status == STATUS_IMAGE_NOT_AT_BASE)
1256 
1257  /* Check for invalid CPU Image */
1259  {
1260  /* Load our header */
1262 
1263  /* Assume defaults if we don't have to run the Hard Error path */
1264  HardErrorStatus = STATUS_SUCCESS;
1266 
1267  /* Are we an NT 3.0 image? [Do these still exist? LOL -- IAI] */
1269  {
1270  /* Reset the entrypoint, save our Dll Name */
1271  LdrEntry->EntryPoint = 0;
1272  HardErrorParameters[0] = (ULONG_PTR)&FullDllName;
1273 
1274  /* Raise the error */
1276  1,
1277  1,
1278  HardErrorParameters,
1280  &Response);
1281  }
1282 
1283  /* Check if the user pressed cancel */
1284  if (NT_SUCCESS(HardErrorStatus) && Response == ResponseCancel)
1285  {
1286  /* Remove the DLL from the lists */
1287  RemoveEntryList(&LdrEntry->InLoadOrderLinks);
1288  RemoveEntryList(&LdrEntry->InMemoryOrderLinks);
1289  RemoveEntryList(&LdrEntry->HashLinks);
1290 
1291  /* Remove the LDR Entry */
1292  RtlFreeHeap(LdrpHeap, 0, LdrEntry );
1293 
1294  /* Unmap and close section */
1296  NtClose(SectionHandle);
1297 
1298  /* Did we do a hard error? */
1300  {
1301  /* Yup, so increase fatal error count if we are initializing */
1303  }
1304 
1305  /* Return failure */
1307  }
1308  }
1309  else
1310  {
1311  /* The image was valid. Is it a DLL? */
1312  if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
1313  {
1314  /* Set the DLL Flag */
1315  LdrEntry->Flags |= LDRP_IMAGE_DLL;
1316  }
1317 
1318  /* If we're not a DLL, clear the entrypoint */
1319  if (!(LdrEntry->Flags & LDRP_IMAGE_DLL))
1320  {
1321  LdrEntry->EntryPoint = 0;
1322  }
1323  }
1324 
1325  /* Return it for the caller */
1326  *DataTableEntry = LdrEntry;
1327 
1328  /* Check if we loaded somewhere else */
1330  {
1331  /* Write the flag */
1332  LdrEntry->Flags |= LDRP_IMAGE_NOT_AT_BASE;
1333 
1334  /* Find our region */
1335  ImageBase = (ULONG_PTR)NtHeaders->OptionalHeader.ImageBase;
1336  ImageEnd = ImageBase + ViewSize;
1337 
1338  DPRINT("LDR: LdrpMapDll Relocating Image Name %ws (%p-%p -> %p)\n", DllName, (PVOID)ImageBase, (PVOID)ImageEnd, ViewBase);
1339 
1340  /* Scan all the modules */
1341  ListHead = &Peb->Ldr->InLoadOrderModuleList;
1342  NextEntry = ListHead->Flink;
1343  while (NextEntry != ListHead)
1344  {
1345  /* Get the entry */
1346  CandidateEntry = CONTAINING_RECORD(NextEntry,
1348  InLoadOrderLinks);
1349  NextEntry = NextEntry->Flink;
1350 
1351  /* Get the entry's bounds */
1352  CandidateBase = (ULONG_PTR)CandidateEntry->DllBase;
1353  CandidateEnd = CandidateBase + CandidateEntry->SizeOfImage;
1354 
1355  /* Make sure this entry isn't unloading */
1356  if (!CandidateEntry->InMemoryOrderLinks.Flink) continue;
1357 
1358  /* Check if our regions are colliding */
1359  if ((ImageBase >= CandidateBase && ImageBase <= CandidateEnd) ||
1360  (ImageEnd >= CandidateBase && ImageEnd <= CandidateEnd) ||
1361  (CandidateBase >= ImageBase && CandidateBase <= ImageEnd))
1362  {
1363  /* Found who is overlapping */
1364  OverlapDllFound = TRUE;
1365  OverlapDll = CandidateEntry->FullDllName;
1366  break;
1367  }
1368  }
1369 
1370  /* Check if we found the DLL overlapping with us */
1371  if (!OverlapDllFound)
1372  {
1373  /* It's not another DLL, it's memory already here */
1374  RtlInitUnicodeString(&OverlapDll, L"Dynamically Allocated Memory");
1375  }
1376 
1377  DPRINT("Overlapping DLL: %wZ\n", &OverlapDll);
1378 
1379  /* Are we dealing with a DLL? */
1380  if (LdrEntry->Flags & LDRP_IMAGE_DLL)
1381  {
1382  /* Check if relocs were stripped */
1384  {
1385  /* Get the relocation data */
1386  RelocData = RtlImageDirectoryEntryToData(ViewBase,
1387  TRUE,
1389  &RelocDataSize);
1390 
1391  /* Does the DLL not have any? */
1392  if (!RelocData && !RelocDataSize)
1393  {
1394  /* We'll allow this and simply continue */
1395  goto NoRelocNeeded;
1396  }
1397  }
1398 
1399  /* See if this is an Illegal DLL - IE: user32 and kernel32 */
1400  RtlInitUnicodeString(&IllegalDll,L"user32.dll");
1401  if (RtlEqualUnicodeString(&BaseDllName, &IllegalDll, TRUE))
1402  {
1403  /* Can't relocate user32 */
1404  RelocatableDll = FALSE;
1405  }
1406  else
1407  {
1408  RtlInitUnicodeString(&IllegalDll, L"kernel32.dll");
1409  if (RtlEqualUnicodeString(&BaseDllName, &IllegalDll, TRUE))
1410  {
1411  /* Can't relocate kernel32 */
1412  RelocatableDll = FALSE;
1413  }
1414  }
1415 
1416  /* Known DLLs are not allowed to be relocated */
1417  if (KnownDll && !RelocatableDll)
1418  {
1419  /* Setup for hard error */
1420  HardErrorParameters[0] = (ULONG_PTR)&IllegalDll;
1421  HardErrorParameters[1] = (ULONG_PTR)&OverlapDll;
1422 
1423  DPRINT1("Illegal DLL relocation! %wZ overlaps %wZ\n", &OverlapDll, &IllegalDll);
1424 
1425  /* Raise the error */
1427  2,
1428  3,
1429  HardErrorParameters,
1430  OptionOk,
1431  &Response);
1432 
1433  /* If initializing, increase the error count */
1435 
1436  /* Don't do relocation */
1438  goto FailRelocate;
1439  }
1440 
1441  /* Change the protection to prepare for relocation */
1442  Status = LdrpSetProtection(ViewBase, FALSE);
1443 
1444  /* Make sure we changed the protection */
1445  if (NT_SUCCESS(Status))
1446  {
1447  /* Do the relocation */
1450 
1451  if (NT_SUCCESS(Status))
1452  {
1453  /* Stuff the image name in the TIB, for the debugger */
1454  ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
1455  Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer;
1456 #if 0
1457  /* Map the DLL */
1458  Status = NtMapViewOfSection(SectionHandle,
1459  NtCurrentProcess(),
1460  &ViewBase,
1461  0,
1462  0,
1463  NULL,
1464  &ViewSize,
1465  ViewShare,
1466  0,
1467  PAGE_READWRITE);
1468 #endif
1469  /* Restore */
1470  Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
1471 
1472  /* Return the protection */
1473  Status = LdrpSetProtection(ViewBase, TRUE);
1474  }
1475  }
1476 FailRelocate:
1477  /* Handle any kind of failure */
1478  if (!NT_SUCCESS(Status))
1479  {
1480  /* Remove it from the lists */
1481  RemoveEntryList(&LdrEntry->InLoadOrderLinks);
1482  RemoveEntryList(&LdrEntry->InMemoryOrderLinks);
1483  RemoveEntryList(&LdrEntry->HashLinks);
1484 
1485  /* Unmap it, clear the entry */
1487  LdrEntry = NULL;
1488  }
1489 
1490  /* Show debug message */
1491  if (ShowSnaps)
1492  {
1493  DPRINT1("LDR: Fixups %successfully re-applied @ %p\n",
1494  NT_SUCCESS(Status) ? "s" : "uns", ViewBase);
1495  }
1496  }
1497  else
1498  {
1499 NoRelocNeeded:
1500  /* Not a DLL, or no relocation needed */
1502 
1503  /* Stuff the image name in the TIB, for the debugger */
1504  ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
1505  Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer;
1506 #if 0
1507  /* Map the DLL */
1508  Status = NtMapViewOfSection(SectionHandle,
1509  NtCurrentProcess(),
1510  &ViewBase,
1511  0,
1512  0,
1513  NULL,
1514  &ViewSize,
1515  ViewShare,
1516  0,
1517  PAGE_READWRITE);
1518 #endif
1519  /* Restore */
1520  Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
1521 
1522  /* Show debug message */
1523  if (ShowSnaps)
1524  {
1525  DPRINT1("LDR: Fixups won't be re-applied to non-Dll @ %p\n", ViewBase);
1526  }
1527  }
1528  }
1529 
1530  // FIXME: LdrpCheckCorImage() is missing
1531 
1532  /* Check if this is an SMP Machine and a DLL */
1533  if ((LdrpNumberOfProcessors > 1) &&
1534  (LdrEntry && (LdrEntry->Flags & LDRP_IMAGE_DLL)))
1535  {
1536  /* Validate the image for MP */
1537  LdrpValidateImageForMp(LdrEntry);
1538  }
1539 
1540  // FIXME: LdrpCorUnloadImage() is missing
1541 
1542  /* Close section and return status */
1543  NtClose(SectionHandle);
1544  return Status;
1545 }
1546 
1548 NTAPI
1550 {
1551  PLDR_DATA_TABLE_ENTRY LdrEntry = NULL;
1552  PIMAGE_NT_HEADERS NtHeader;
1553 
1554  /* Make sure the header is valid */
1555  NtHeader = RtlImageNtHeader(BaseAddress);
1556  DPRINT("LdrpAllocateDataTableEntry(%p), NtHeader %p\n", BaseAddress, NtHeader);
1557 
1558  if (NtHeader)
1559  {
1560  /* Allocate an entry */
1561  LdrEntry = RtlAllocateHeap(LdrpHeap,
1563  sizeof(LDR_DATA_TABLE_ENTRY));
1564 
1565  /* Make sure we got one */
1566  if (LdrEntry)
1567  {
1568  /* Set it up */
1569  LdrEntry->DllBase = BaseAddress;
1570  LdrEntry->SizeOfImage = NtHeader->OptionalHeader.SizeOfImage;
1571  LdrEntry->TimeDateStamp = NtHeader->FileHeader.TimeDateStamp;
1572  LdrEntry->PatchInformation = NULL;
1573  }
1574  }
1575 
1576  /* Return the entry */
1577  return LdrEntry;
1578 }
1579 
1580 VOID
1581 NTAPI
1583 {
1584  PPEB_LDR_DATA PebData = NtCurrentPeb()->Ldr;
1585  ULONG i;
1586 
1587  /* Insert into hash table */
1588  i = LDR_GET_HASH_ENTRY(LdrEntry->BaseDllName.Buffer[0]);
1589  InsertTailList(&LdrpHashTable[i], &LdrEntry->HashLinks);
1590 
1591  /* Insert into other lists */
1592  InsertTailList(&PebData->InLoadOrderModuleList, &LdrEntry->InLoadOrderLinks);
1593  InsertTailList(&PebData->InMemoryOrderModuleList, &LdrEntry->InMemoryOrderLinks);
1594 }
1595 
1596 VOID
1597 NTAPI
1599 {
1600  /* Sanity check */
1601  ASSERT(Entry != NULL);
1602 
1603  /* Release the activation context if it exists and wasn't already released */
1604  if ((Entry->EntryPointActivationContext) &&
1605  (Entry->EntryPointActivationContext != INVALID_HANDLE_VALUE))
1606  {
1607  /* Mark it as invalid */
1608  RtlReleaseActivationContext(Entry->EntryPointActivationContext);
1609  Entry->EntryPointActivationContext = INVALID_HANDLE_VALUE;
1610  }
1611 
1612  /* Release the full dll name string */
1613  if (Entry->FullDllName.Buffer) LdrpFreeUnicodeString(&Entry->FullDllName);
1614 
1615  /* Finally free the entry's memory */
1616  RtlFreeHeap(LdrpHeap, 0, Entry);
1617 }
1618 
1619 BOOLEAN
1620 NTAPI
1622  OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
1623 {
1624  PLDR_DATA_TABLE_ENTRY Current;
1625  PLIST_ENTRY ListHead, Next;
1626 
1627  /* Check the cache first */
1628  if ((LdrpLoadedDllHandleCache) &&
1630  {
1631  /* We got lucky, return the cached entry */
1632  *LdrEntry = LdrpLoadedDllHandleCache;
1633  return TRUE;
1634  }
1635 
1636  /* Time for a lookup */
1637  ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
1638  Next = ListHead->Flink;
1639  while (Next != ListHead)
1640  {
1641  /* Get the current entry */
1642  Current = CONTAINING_RECORD(Next,
1644  InLoadOrderLinks);
1645 
1646  /* Make sure it's not unloading and check for a match */
1647  if ((Current->InMemoryOrderLinks.Flink) && (Base == Current->DllBase))
1648  {
1649  /* Save in cache */
1650  LdrpLoadedDllHandleCache = Current;
1651 
1652  /* Return it */
1653  *LdrEntry = Current;
1654  return TRUE;
1655  }
1656 
1657  /* Move to the next one */
1658  Next = Next->Flink;
1659  }
1660 
1661  /* Nothing found */
1662  return FALSE;
1663 }
1664 
1665 NTSTATUS
1666 NTAPI
1668  IN PUNICODE_STRING PathName,
1669  IN PUNICODE_STRING FullPathName,
1670  IN PUNICODE_STRING *ExpandedName)
1671 {
1673 // RTL_PATH_TYPE PathType;
1674 // BOOLEAN InvalidName;
1675  ULONG Length;
1676 
1677  /* Display debug output if snaps are on */
1678  if (ShowSnaps)
1679  {
1682  "LDR: %s - Expanding full name of %wZ\n",
1683  __FUNCTION__,
1684  OriginalName);
1685  }
1686 
1687  /* FIXME: Lock the PEB */
1688  //RtlEnterCriticalSection(&FastPebLock);
1689 #if 0
1690  /* Get the path name */
1691  Length = RtlGetFullPathName_Ustr(OriginalName,
1692  PathName->Length,
1693  PathName->Buffer,
1694  NULL,
1695  &InvalidName,
1696  &PathType);
1697 #else
1698  Length = 0;
1699 #endif
1700  if (!(Length) || (Length > UNICODE_STRING_MAX_BYTES))
1701  {
1702  /* Fail */
1704  goto Quickie;
1705  }
1706 
1707  /* Check if the length hasn't changed */
1709  {
1710  /* Return the same thing */
1711  *ExpandedName = PathName;
1712  PathName->Length = (USHORT)Length;
1713  goto Quickie;
1714  }
1715 
1716  /* Sanity check */
1717  ASSERT(Length >= sizeof(WCHAR));
1718 
1719  /* Allocate a string */
1720  Status = LdrpAllocateUnicodeString(FullPathName, Length - sizeof(WCHAR));
1721  if (!NT_SUCCESS(Status)) goto Quickie;
1722 
1723  /* Now get the full path again */
1724 #if 0
1725  Length = RtlGetFullPathName_Ustr(OriginalName,
1726  FullPathName->Length,
1727  FullPathName->Buffer,
1728  NULL,
1729  &InvalidName,
1730  &PathType);
1731 #else
1732  Length = 0;
1733 #endif
1734  if (!(Length) || (Length > FullPathName->Length))
1735  {
1736  /* Fail */
1737  LdrpFreeUnicodeString(FullPathName);
1739  }
1740  else
1741  {
1742  /* Return the expanded name */
1743  *ExpandedName = FullPathName;
1744  FullPathName->Length = (USHORT)Length;
1745  }
1746 
1747 Quickie:
1748  /* FIXME: Unlock the PEB */
1749  //RtlLeaveCriticalSection(&FastPebLock);
1750 
1751  /* Display debug output if snaps are on */
1752  if (ShowSnaps)
1753  {
1754  /* Check which output to use -- failure or success */
1755  if (NT_SUCCESS(Status))
1756  {
1759  "LDR: %s - Expanded to %wZ\n",
1760  __FUNCTION__,
1761  *ExpandedName);
1762  }
1763  else
1764  {
1767  "LDR: %s - Failed to expand %wZ; 0x%08x\n",
1768  __FUNCTION__,
1769  OriginalName,
1770  Status);
1771  }
1772  }
1773 
1774  /* If we failed, return NULL */
1775  if (!NT_SUCCESS(Status)) *ExpandedName = NULL;
1776 
1777  /* Return status */
1778  return Status;
1779 }
1780 
1781 NTSTATUS
1782 NTAPI
1784  IN PWCHAR DllName,
1785  IN PUNICODE_STRING PathName,
1786  IN PUNICODE_STRING FullPathName,
1787  IN PUNICODE_STRING *ExpandedName)
1788 {
1790  PWCHAR ActualSearchPath = *SearchPath;
1791  UNICODE_STRING TestName;
1792  NTSTATUS Status;
1793  PWCHAR Buffer, BufEnd = NULL;
1794  ULONG Length = 0;
1795  WCHAR p;
1796  //PWCHAR pp;
1797 
1798  /* Check if we don't have a search path */
1799  if (!ActualSearchPath) *SearchPath = LdrpDefaultPath.Buffer;
1800 
1801  /* Display debug output if snaps are on */
1802  if (ShowSnaps)
1803  {
1806  "LDR: %s - Looking for %ws in %ws\n",
1807  __FUNCTION__,
1808  DllName,
1809  *SearchPath);
1810  }
1811 
1812  /* Check if we're dealing with a relative path */
1814  {
1815  /* Good, we're not. Create the name string */
1816  Status = RtlInitUnicodeStringEx(&TestName, DllName);
1817  if (!NT_SUCCESS(Status)) goto Quickie;
1818 
1819  /* Make sure it exists */
1820  #if 0
1821  if (!RtlDoesFileExists_UstrEx(&TestName, TRUE))
1822  {
1823  /* It doesn't, fail */
1825  goto Quickie;
1826  }
1827  #endif
1828 
1829  /* Resolve the full name */
1830  Status = LdrpResolveFullName(&TestName,
1831  PathName,
1832  FullPathName,
1833  ExpandedName);
1834  goto Quickie;
1835  }
1836 
1837  /* FIXME: Handle relative case semicolon-lookup here */
1838 
1839  /* Calculate length */
1840  Length += (ULONG)wcslen(DllName) + 1;
1842  {
1843  /* Too long, fail */
1845  goto Quickie;
1846  }
1847 
1848  /* Allocate buffer */
1849  Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR));
1850  if (!Buffer)
1851  {
1852  /* Fail */
1854  goto Quickie;
1855  }
1856 
1857  /* FIXME: Setup TestName here */
1859  BufEnd = Buffer;
1860 
1861  /* Start loop */
1862  do
1863  {
1864  /* Get character */
1865  p = *ActualSearchPath;
1866  if (!(p) || (p == ';'))
1867  {
1868  /* FIXME: We don't have a character, or is a semicolon.*/
1869 
1870  /* Display debug output if snaps are on */
1871  if (ShowSnaps)
1872  {
1875  "LDR: %s - Looking for %ws\n",
1876  __FUNCTION__,
1877  Buffer);
1878  }
1879 
1880  /* Sanity check */
1881  TestName.Length = (USHORT)ALIGN_DOWN((BufEnd - Buffer), WCHAR);
1882 #if 0
1883  ASSERT(TestName.Length < TestName.MaximumLength);
1884 #endif
1885 
1886  /* Check if the file exists */
1887  #if 0
1888  if (RtlDoesFileExists_UstrEx(&TestName, FALSE))
1889  #endif
1890  {
1891  /* It does. Reallocate the buffer */
1892  TestName.MaximumLength = (USHORT)ALIGN_DOWN((BufEnd - Buffer), WCHAR) + sizeof(WCHAR);
1893  TestName.Buffer = RtlReAllocateHeap(RtlGetProcessHeap(),
1894  0,
1895  Buffer,
1896  TestName.MaximumLength);
1897  if (!TestName.Buffer)
1898  {
1899  /* Keep the old one */
1900  TestName.Buffer = Buffer;
1901  }
1902  else
1903  {
1904  /* Update buffer */
1905  Buffer = TestName.Buffer;
1906  }
1907 
1908  /* Make sure we have a buffer at least */
1909  ASSERT(TestName.Buffer);
1910 
1911  /* Resolve the name */
1912  *SearchPath = ActualSearchPath++;
1913  Status = LdrpResolveFullName(&TestName,
1914  PathName,
1915  FullPathName,
1916  ExpandedName);
1917  break;
1918  }
1919 
1920  /* Update buffer end */
1921  BufEnd = Buffer;
1922 
1923  /* Update string position */
1924  //pp = ActualSearchPath++;
1925  }
1926  else
1927  {
1928  /* Otherwise, write the character */
1929  *BufEnd = p;
1930  BufEnd++;
1931  }
1932 
1933  /* Check if the string is empty, meaning we're done */
1934  if (!(*ActualSearchPath)) TryAgain = TRUE;
1935 
1936  /* Advance in the string */
1937  ActualSearchPath++;
1938  } while (!TryAgain);
1939 
1940  /* Check if we had a buffer and free it */
1941  if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1942 
1943 Quickie:
1944  /* Check if we got here through failure */
1945  if (!NT_SUCCESS(Status)) *ExpandedName = NULL;
1946 
1947  /* Display debug output if snaps are on */
1948  if (ShowSnaps)
1949  {
1950  /* Check which output to use -- failure or success */
1951  if (NT_SUCCESS(Status))
1952  {
1955  "LDR: %s - Returning %wZ\n",
1956  __FUNCTION__,
1957  *ExpandedName);
1958  }
1959  else
1960  {
1963  "LDR: %s - Unable to locate %ws in %ws: 0x%08x\n",
1964  __FUNCTION__,
1965  DllName,
1966  ActualSearchPath,
1967  Status);
1968  }
1969  }
1970 
1971  /* Return status */
1972  return Status;
1973 }
1974 
1975 
1976 /* NOTE: This function is b0rked and in the process of being slowly unf*cked */
1977 BOOLEAN
1978 NTAPI
1980  IN PUNICODE_STRING DllName,
1981  IN BOOLEAN Flag,
1982  IN BOOLEAN RedirectedDll,
1983  OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
1984 {
1985  ULONG HashIndex;
1986  PLIST_ENTRY ListHead, ListEntry;
1987  PLDR_DATA_TABLE_ENTRY CurEntry;
1988  BOOLEAN FullPath = FALSE;
1989  PWCHAR wc;
1990  WCHAR NameBuf[266];
1991  UNICODE_STRING FullDllName, NtPathName;
1992  ULONG Length;
1994  NTSTATUS Status;
1995  HANDLE FileHandle, SectionHandle;
1997  PVOID ViewBase = NULL;
1998  SIZE_T ViewSize = 0;
1999  PIMAGE_NT_HEADERS NtHeader, NtHeader2;
2000  DPRINT("LdrpCheckForLoadedDll('%S' '%wZ' %u %u %p)\n", DllPath ? ((ULONG_PTR)DllPath == 1 ? L"" : DllPath) : L"", DllName, Flag, RedirectedDll, LdrEntry);
2001 
2002  /* Check if a dll name was provided */
2003  if (!(DllName->Buffer) || !(DllName->Buffer[0])) return FALSE;
2004 
2005  /* FIXME: Warning, "Flag" is used as magic instead of "Static" */
2006  /* FIXME: Warning, code does not support redirection at all */
2007 
2008  /* Look in the hash table if flag was set */
2009 lookinhash:
2010  if (Flag /* the second check is a hack */ && !RedirectedDll)
2011  {
2012  /* 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 */
2013 
2014  /* Get hash index */
2015  HashIndex = LDR_GET_HASH_ENTRY(DllName->Buffer[0]);
2016 
2017  /* Traverse that list */
2018  ListHead = &LdrpHashTable[HashIndex];
2019  ListEntry = ListHead->Flink;
2020  while (ListEntry != ListHead)
2021  {
2022  /* Get the current entry */
2023  CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, HashLinks);
2024 
2025  /* Check base name of that module */
2026  if (RtlEqualUnicodeString(DllName, &CurEntry->BaseDllName, TRUE))
2027  {
2028  /* It matches, return it */
2029  *LdrEntry = CurEntry;
2030  return TRUE;
2031  }
2032 
2033  /* Advance to the next entry */
2034  ListEntry = ListEntry->Flink;
2035  }
2036 
2037  /* Module was not found, return failure */
2038  return FALSE;
2039  }
2040 
2041  /* Check if this is a redirected DLL */
2042  if (RedirectedDll)
2043  {
2044  /* Redirected dlls already have a full path */
2045  FullPath = TRUE;
2046  FullDllName = *DllName;
2047  }
2048  else
2049  {
2050  /* Check if there is a full path in this DLL */
2051  wc = DllName->Buffer;
2052  while (*wc)
2053  {
2054  /* Check for a slash in the current position*/
2055  if ((*wc == L'\\') || (*wc == L'/'))
2056  {
2057  /* Found the slash, so dll name contains path */
2058  FullPath = TRUE;
2059 
2060  /* Setup full dll name string */
2061  FullDllName.Buffer = NameBuf;
2062 
2063  /* FIXME: This is from the Windows 2000 loader, not XP/2003, we should call LdrpSearchPath */
2065  DllName->Buffer,
2066  NULL,
2067  sizeof(NameBuf) - sizeof(UNICODE_NULL),
2068  FullDllName.Buffer,
2069  NULL);
2070 
2071  /* Check if that was successful */
2072  if (!(Length) || (Length > (sizeof(NameBuf) - sizeof(UNICODE_NULL))))
2073  {
2074  if (ShowSnaps)
2075  {
2076  DPRINT1("LDR: LdrpCheckForLoadedDll - Unable To Locate %wZ: 0x%08x\n",
2077  &DllName, Length);
2078  }
2079  }
2080 
2081  /* Full dll name is found */
2082  FullDllName.Length = Length;
2083  FullDllName.MaximumLength = FullDllName.Length + sizeof(UNICODE_NULL);
2084  break;
2085  }
2086 
2087  wc++;
2088  }
2089  }
2090 
2091  /* Go check the hash table */
2092  if (!FullPath)
2093  {
2094  Flag = TRUE;
2095  goto lookinhash;
2096  }
2097 
2098  /* FIXME: Warning, activation context missing */
2099  DPRINT("Warning, activation context missing\n");
2100 
2101  /* NOTE: From here on down, everything looks good */
2102 
2103  /* Loop the module list */
2104  ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
2105  ListEntry = ListHead->Flink;
2106  while (ListEntry != ListHead)
2107  {
2108  /* Get the current entry and advance to the next one */
2109  CurEntry = CONTAINING_RECORD(ListEntry,
2111  InLoadOrderLinks);
2112  ListEntry = ListEntry->Flink;
2113 
2114  /* Check if it's being unloaded */
2115  if (!CurEntry->InMemoryOrderLinks.Flink) continue;
2116 
2117  /* Check if name matches */
2119  &CurEntry->FullDllName,
2120  TRUE))
2121  {
2122  /* Found it */
2123  *LdrEntry = CurEntry;
2124  return TRUE;
2125  }
2126  }
2127 
2128  /* Convert given path to NT path */
2130  &NtPathName,
2131  NULL,
2132  NULL))
2133  {
2134  /* Fail if conversion failed */
2135  return FALSE;
2136  }
2137 
2138  /* Initialize object attributes and open it */
2140  &NtPathName,
2142  NULL,
2143  NULL);
2147  &Iosb,
2150 
2151  /* Free NT path name */
2152  RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
2153 
2154  /* If opening the file failed - return failure */
2155  if (!NT_SUCCESS(Status)) return FALSE;
2156 
2157  /* Create a section for this file */
2158  Status = NtCreateSection(&SectionHandle,
2162  NULL,
2163  NULL,
2164  PAGE_EXECUTE,
2165  SEC_COMMIT,
2166  FileHandle);
2167 
2168  /* Close file handle */
2170 
2171  /* If creating section failed - return failure */
2172  if (!NT_SUCCESS(Status)) return FALSE;
2173 
2174  /* Map view of this section */
2175  Status = ZwMapViewOfSection(SectionHandle,
2176  NtCurrentProcess(),
2177  &ViewBase,
2178  0,
2179  0,
2180  NULL,
2181  &ViewSize,
2182  ViewShare,
2183  0,
2184  PAGE_EXECUTE);
2185 
2186  /* Close section handle */
2187  NtClose(SectionHandle);
2188 
2189  /* If section mapping failed - return failure */
2190  if (!NT_SUCCESS(Status)) return FALSE;
2191 
2192  /* Get pointer to the NT header of this section */
2193  Status = RtlImageNtHeaderEx(0, ViewBase, ViewSize, &NtHeader);
2194  if (!(NT_SUCCESS(Status)) || !(NtHeader))
2195  {
2196  /* Unmap the section and fail */
2198  return FALSE;
2199  }
2200 
2201  /* Go through the list of modules again */
2202  ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
2203  ListEntry = ListHead->Flink;
2204  while (ListEntry != ListHead)
2205  {
2206  /* Get the current entry and advance to the next one */
2207  CurEntry = CONTAINING_RECORD(ListEntry,
2209  InLoadOrderLinks);
2210  ListEntry = ListEntry->Flink;
2211 
2212  /* Check if it's in the process of being unloaded */
2213  if (!CurEntry->InMemoryOrderLinks.Flink) continue;
2214 
2215  /* The header is untrusted, use SEH */
2216  _SEH2_TRY
2217  {
2218  /* Check if timedate stamp and sizes match */
2219  if ((CurEntry->TimeDateStamp == NtHeader->FileHeader.TimeDateStamp) &&
2220  (CurEntry->SizeOfImage == NtHeader->OptionalHeader.SizeOfImage))
2221  {
2222  /* Time, date and size match. Let's compare their headers */
2223  NtHeader2 = RtlImageNtHeader(CurEntry->DllBase);
2224  if (RtlCompareMemory(NtHeader2, NtHeader, sizeof(IMAGE_NT_HEADERS)))
2225  {
2226  /* Headers match too! Finally ask the kernel to compare mapped files */
2227  Status = ZwAreMappedFilesTheSame(CurEntry->DllBase, ViewBase);
2228  if (NT_SUCCESS(Status))
2229  {
2230  /* This is our entry!, unmap and return success */
2231  *LdrEntry = CurEntry;
2233  _SEH2_YIELD(return TRUE;)
2234  }
2235  }
2236  }
2237  }
2239  {
2240  _SEH2_YIELD(break;)
2241  }
2242  _SEH2_END;
2243  }
2244 
2245  /* Unmap the section and fail */
2247  return FALSE;
2248 }
2249 
2250 NTSTATUS
2251 NTAPI
2254  IN ULONG Ordinal,
2255  OUT PVOID *ProcedureAddress,
2256  IN BOOLEAN ExecuteInit)
2257 {
2259  UCHAR ImportBuffer[64];
2260  PLDR_DATA_TABLE_ENTRY LdrEntry;
2261  IMAGE_THUNK_DATA Thunk;
2262  PVOID ImageBase;
2263  PIMAGE_IMPORT_BY_NAME ImportName = NULL;
2264  PIMAGE_EXPORT_DIRECTORY ExportDir;
2265  ULONG ExportDirSize, Length;
2267 
2268  /* Show debug message */
2269  if (ShowSnaps) DPRINT1("LDR: LdrGetProcedureAddress by ");
2270 
2271  /* Check if we got a name */
2272  if (Name)
2273  {
2274  /* Show debug message */
2275  if (ShowSnaps) DbgPrint("NAME - %s\n", Name->Buffer);
2276 
2277  /* Make sure it's not too long */
2278  Length = Name->Length +
2279  sizeof(CHAR) +
2282  {
2283  /* Won't have enough space to add the hint */
2284  return STATUS_NAME_TOO_LONG;
2285  }
2286 
2287  /* Check if our buffer is large enough */
2288  if (Length > sizeof(ImportBuffer))
2289  {
2290  /* Allocate from heap, plus 2 bytes for the Hint */
2291  ImportName = RtlAllocateHeap(RtlGetProcessHeap(),
2292  0,
2293  Length);
2294  }
2295  else
2296  {
2297  /* Use our internal buffer */
2298  ImportName = (PIMAGE_IMPORT_BY_NAME)ImportBuffer;
2299  }
2300 
2301  /* Clear the hint */
2302  ImportName->Hint = 0;
2303 
2304  /* Copy the name and null-terminate it */
2305  RtlCopyMemory(ImportName->Name, Name->Buffer, Name->Length);
2306  ImportName->Name[Name->Length] = ANSI_NULL;
2307 
2308  /* Clear the high bit */
2309  ImageBase = ImportName;
2310  Thunk.u1.AddressOfData = 0;
2311  }
2312  else
2313  {
2314  /* Do it by ordinal */
2315  ImageBase = NULL;
2316 
2317  /* Show debug message */
2318  if (ShowSnaps) DbgPrint("ORDINAL - %lx\n", Ordinal);
2319 
2320  /* Make sure an ordinal was given */
2321  if (!Ordinal)
2322  {
2323  /* No ordinal */
2324  DPRINT1("No ordinal and no name\n");
2325  return STATUS_INVALID_PARAMETER;
2326  }
2327 
2328  /* Set the original flag in the thunk */
2329  Thunk.u1.Ordinal = Ordinal | IMAGE_ORDINAL_FLAG;
2330  }
2331 
2332  /* Acquire lock unless we are initting */
2334 
2335  _SEH2_TRY
2336  {
2337  /* Try to find the loaded DLL */
2338  if (!LdrpCheckForLoadedDllHandle(BaseAddress, &LdrEntry))
2339  {
2340  /* Invalid base */
2341  DPRINT1("Invalid base address %p\n", BaseAddress);
2343  _SEH2_YIELD(goto Quickie;)
2344  }
2345 
2346  /* Get the pointer to the export directory */
2347  ExportDir = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
2348  TRUE,
2350  &ExportDirSize);
2351 
2352  if (!ExportDir)
2353  {
2354  DPRINT1("Image %wZ has no exports, but were trying to get procedure %Z. BaseAddress asked 0x%p, got entry BA 0x%p\n",
2355  &LdrEntry->BaseDllName, Name, BaseAddress, LdrEntry->DllBase);
2357  _SEH2_YIELD(goto Quickie;)
2358  }
2359 
2360  /* Now get the thunk */
2361  Status = LdrpSnapThunk(LdrEntry->DllBase,
2362  ImageBase,
2363  &Thunk,
2364  &Thunk,
2365  ExportDir,
2366  ExportDirSize,
2367  FALSE,
2368  NULL);
2369 
2370  /* Finally, see if we're supposed to run the init routines */
2371  if ((NT_SUCCESS(Status)) && (ExecuteInit))
2372  {
2373  /*
2374  * It's possible a forwarded entry had us load the DLL. In that case,
2375  * then we will call its DllMain. Use the last loaded DLL for this.
2376  */
2377  Entry = NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Blink;
2378  LdrEntry = CONTAINING_RECORD(Entry,
2380  InInitializationOrderLinks);
2381 
2382  /* Make sure we didn't process it yet*/
2383  if (!(LdrEntry->Flags & LDRP_ENTRY_PROCESSED))
2384  {
2385  /* Call the init routine */
2386  _SEH2_TRY
2387  {
2389  }
2391  {
2392  /* Get the exception code */
2394  }
2395  _SEH2_END;
2396  }
2397  }
2398 
2399  /* Make sure we're OK till here */
2400  if (NT_SUCCESS(Status))
2401  {
2402  /* Return the address */
2403  *ProcedureAddress = (PVOID)Thunk.u1.Function;
2404  }
2405  }
2407  {
2408  /* Just ignore exceptions */
2409  }
2410  _SEH2_END;
2411 
2412 Quickie:
2413  /* Cleanup */
2414  if (ImportName && (ImportName != (PIMAGE_IMPORT_BY_NAME)ImportBuffer))
2415  {
2416  /* We allocated from heap, free it */
2417  RtlFreeHeap(RtlGetProcessHeap(), 0, ImportName);
2418  }
2419 
2420  /* Release the CS if we entered it */
2422 
2423  /* We're done */
2424  return Status;
2425 }
2426 
2427 NTSTATUS
2428 NTAPI
2431  IN PULONG DllCharacteristics OPTIONAL,
2432  IN PUNICODE_STRING DllName,
2434  IN BOOLEAN CallInit)
2435 {
2436  PPEB Peb = NtCurrentPeb();
2438  const WCHAR *p;
2439  BOOLEAN GotExtension;
2440  WCHAR c;
2441  WCHAR NameBuffer[MAX_PATH + 6];
2442  UNICODE_STRING RawDllName;
2443  PLDR_DATA_TABLE_ENTRY LdrEntry;
2444  BOOLEAN InInit = LdrpInLdrInit;
2445 
2446  /* Save the Raw DLL Name */
2447  if (DllName->Length >= sizeof(NameBuffer)) return STATUS_NAME_TOO_LONG;
2448  RtlInitEmptyUnicodeString(&RawDllName, NameBuffer, sizeof(NameBuffer));
2449  RtlCopyUnicodeString(&RawDllName, DllName);
2450 
2451  /* Find the extension, if present */
2452  p = DllName->Buffer + DllName->Length / sizeof(WCHAR) - 1;
2453  GotExtension = FALSE;
2454  while (p >= DllName->Buffer)
2455  {
2456  c = *p--;
2457  if (c == L'.')
2458  {
2459  GotExtension = TRUE;
2460  break;
2461  }
2462  else if (c == L'\\')
2463  {
2464  break;
2465  }
2466  }
2467 
2468  /* If no extension was found, add the default extension */
2469  if (!GotExtension)
2470  {
2471  /* Check that we have space to add one */
2472  if ((DllName->Length + LdrApiDefaultExtension.Length + sizeof(UNICODE_NULL)) >=
2473  sizeof(NameBuffer))
2474  {
2475  /* No space to add the extension */
2478  "LDR: %s - Dll name missing extension; with extension "
2479  "added the name is too long\n"
2480  " DllName: (@ %p) \"%wZ\"\n"
2481  " DllName->Length: %u\n",
2482  __FUNCTION__,
2483  DllName,
2484  DllName,
2485  DllName->Length);
2486  return STATUS_NAME_TOO_LONG;
2487  }
2488 
2489  /* Add it. Needs to be null terminated, thus the length check above */
2490  (VOID)RtlAppendUnicodeStringToString(&RawDllName,
2492  }
2493 
2494  /* Check for init flag and acquire lock */
2495  if (!InInit) RtlEnterCriticalSection(&LdrpLoaderLock);
2496 
2497  _SEH2_TRY
2498  {
2499  /* Show debug message */
2500  if (ShowSnaps)
2501  {
2502  DPRINT1("LDR: LdrLoadDll, loading %wZ from %ws\n",
2503  &RawDllName,
2504  DllPath ? DllPath : L"");
2505  }
2506 
2507  /* Check if the DLL is already loaded */
2509  &RawDllName,
2510  FALSE,
2511  Redirected,
2512  &LdrEntry))
2513  {
2514  /* Map it */
2516  DllPath,
2517  NameBuffer,
2518  DllCharacteristics,
2519  FALSE,
2520  Redirected,
2521  &LdrEntry);
2522  if (!NT_SUCCESS(Status))
2523  _SEH2_LEAVE;
2524 
2525  /* FIXME: Need to mark the DLL range for the stack DB */
2526  //RtlpStkMarkDllRange(LdrEntry);
2527 
2528  /* Check if IMAGE_FILE_EXECUTABLE_IMAGE was provided */
2529  if ((DllCharacteristics) &&
2530  (*DllCharacteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
2531  {
2532  /* This is not a DLL, so remove such data */
2533  LdrEntry->EntryPoint = NULL;
2534  LdrEntry->Flags &= ~LDRP_IMAGE_DLL;
2535  }
2536 
2537  /* Make sure it's a DLL */
2538  if (LdrEntry->Flags & LDRP_IMAGE_DLL)
2539  {
2540  /* Check if this is a .NET Image */
2541  if (!(LdrEntry->Flags & LDRP_COR_IMAGE))
2542  {
2543  /* Walk the Import Descriptor */
2545  }
2546 
2547  /* Update load count, unless it's locked */
2548  if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
2550 
2551  /* Check if we failed */
2552  if (!NT_SUCCESS(Status))
2553  {
2554  /* Clear entrypoint, and insert into list */
2555  LdrEntry->EntryPoint = NULL;
2557  &LdrEntry->InInitializationOrderLinks);
2558 
2559  /* Cancel the load */
2561 
2562  /* Unload the DLL */
2563  if (ShowSnaps)
2564  {
2565  DbgPrint("LDR: Unloading %wZ due to error %x walking "
2566  "import descriptors\n",
2567  DllName,
2568  Status);
2569  }
2570  LdrUnloadDll(LdrEntry->DllBase);
2571 
2572  /* Return the error */
2573  _SEH2_LEAVE;
2574  }
2575  }
2576  else if (LdrEntry->LoadCount != 0xFFFF)
2577  {
2578  /* Increase load count */
2579  LdrEntry->LoadCount++;
2580  }
2581 
2582  /* Insert it into the list */
2584  &LdrEntry->InInitializationOrderLinks);
2585 
2586  /* If we have to run the entrypoint, make sure the DB is ready */
2587  if (CallInit && LdrpLdrDatabaseIsSetup)
2588  {
2589  /* Notify Shim Engine */
2590  if (g_ShimsEnabled)
2591  {
2593  SE_DllLoaded(LdrEntry);
2594  }
2595 
2596  /* Run the init routine */
2598  if (!NT_SUCCESS(Status))
2599  {
2600  /* Failed, unload the DLL */
2601  if (ShowSnaps)
2602  {
2603  DbgPrint("LDR: Unloading %wZ because either its init "
2604  "routine or one of its static imports failed; "
2605  "status = 0x%08lx\n",
2606  DllName,
2607  Status);
2608  }
2609  LdrUnloadDll(LdrEntry->DllBase);
2610  }
2611  }
2612  else
2613  {
2614  /* The DB isn't ready, which means we were loaded because of a forwarder */
2616  }
2617  }
2618  else
2619  {
2620  /* We were already loaded. Are we a DLL? */
2621  if ((LdrEntry->Flags & LDRP_IMAGE_DLL) && (LdrEntry->LoadCount != 0xFFFF))
2622  {
2623  /* Increase load count */
2624  LdrEntry->LoadCount++;
2626 
2627  /* Clear the load in progress */
2629  }
2630  else
2631  {
2632  /* Not a DLL, just increase the load count */
2633  if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
2634  }
2635  }
2636 
2637  }
2639  {
2640  /* Release the lock */
2641  if (!InInit) RtlLeaveCriticalSection(&LdrpLoaderLock);
2642  }
2643  _SEH2_END;
2644 
2645  /* Check for success */
2646  if (NT_SUCCESS(Status))
2647  {
2648  /* Return the base address */
2649  *BaseAddress = LdrEntry->DllBase;
2650  }
2651  else
2652  {
2653  /* Nothing found */
2654  *BaseAddress = NULL;
2655  }
2656 
2657  /* Return status */
2658  return Status;
2659 }
2660 
2661 ULONG
2662 NTAPI
2664 {
2665  PLIST_ENTRY ListHead, Entry;
2666  PLDR_DATA_TABLE_ENTRY LdrEntry;
2667  ULONG ModulesCount = 0;
2668 
2669  /* Traverse the init list */
2670  ListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
2671  Entry = ListHead->Flink;
2672  while (Entry != ListHead)
2673  {
2674  /* Get the loader entry */
2675  LdrEntry = CONTAINING_RECORD(Entry,
2677  InInitializationOrderLinks);
2678 
2679  /* Clear load in progress flag */
2680  LdrEntry->Flags &= ~LDRP_LOAD_IN_PROGRESS;
2681 
2682  /* Check for modules with entry point count but not processed yet */
2683  if ((LdrEntry->EntryPoint) &&
2684  !(LdrEntry->Flags & LDRP_ENTRY_PROCESSED))
2685  {
2686  /* Increase counter */
2687  ModulesCount++;
2688  }
2689 
2690  /* Advance to the next entry */
2691  Entry = Entry->Flink;
2692  }
2693 
2694  /* Return final count */
2695  return ModulesCount;
2696 }
2697 
2699 {
2701  NTSTATUS Status;
2702  PVOID Address;
2704  /* Skip Dll init */
2706  return NT_SUCCESS(Status) ? Address : NULL;
2707 }
2708 
2709 VOID
2710 NTAPI
2712 {
2713  PVOID SE_DllLoaded = LdrpGetShimEngineFunction("SE_DllLoaded");
2714  PVOID SE_DllUnloaded = LdrpGetShimEngineFunction("SE_DllUnloaded");
2715  PVOID SE_InstallBeforeInit = LdrpGetShimEngineFunction("SE_InstallBeforeInit");
2716  PVOID SE_InstallAfterInit = LdrpGetShimEngineFunction("SE_InstallAfterInit");
2717  PVOID SE_ProcessDying = LdrpGetShimEngineFunction("SE_ProcessDying");
2718 
2720  {
2726  g_ShimsEnabled = TRUE;
2727  }
2728  else
2729  {
2731  }
2732 }
2733 
2734 VOID
2735 NTAPI
2737 {
2738  PLIST_ENTRY ListHead, Next;
2739  PLDR_DATA_TABLE_ENTRY LdrEntry;
2740 
2741  ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
2742  Next = ListHead->Flink;
2743  while (Next != ListHead)
2744  {
2745  LdrEntry = CONTAINING_RECORD(Next, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
2746 
2747  if (g_pShimEngineModule == LdrEntry->DllBase)
2748  {
2749  if (LdrEntry->EntryPoint)
2750  {
2751  _SEH2_TRY
2752  {
2753  LdrpCallInitRoutine(LdrEntry->EntryPoint, LdrEntry->DllBase, Reason, NULL);
2754  }
2756  {
2757  DPRINT1("WARNING: Exception 0x%x during LdrpRunShimEngineInitRoutine(%u)\n",
2759  }
2760  _SEH2_END;
2761  }
2762  return;
2763  }
2764 
2765  Next = Next->Flink;
2766  }
2767 }
2768 
2769 VOID
2770 NTAPI
2772 {
2773  UNICODE_STRING ShimLibraryName;
2774  PVOID ShimLibrary;
2775  NTSTATUS Status;
2776  RtlInitUnicodeString(&ShimLibraryName, ImageName);
2777  /* We should NOT pass CallInit = TRUE!
2778  If we do this, other init routines will be called before we get a chance to shim stuff.. */
2779  Status = LdrpLoadDll(FALSE, NULL, NULL, &ShimLibraryName, &ShimLibrary, FALSE);
2780  if (NT_SUCCESS(Status))
2781  {
2782  g_pShimEngineModule = ShimLibrary;
2785  if (g_ShimsEnabled)
2786  {
2789  SE_InstallBeforeInit(ProcessImage, pShimData);
2790  }
2791  }
2792 }
2793 
2794 VOID
2795 NTAPI
2797 {
2798  /* Make sure we do not call into the shim engine anymore */
2803 }
2804 
2805 /* 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:2711
BOOLEAN NTAPI LdrpResolveDllName(PWSTR DllPath, PWSTR DllName, PUNICODE_STRING FullDllName, PUNICODE_STRING BaseDllName)
Definition: ldrutils.c:699
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
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
_In_ CDROM_SCAN_FOR_SPECIAL_INFO _In_ PCDROM_SCAN_FOR_SPECIAL_HANDLER Function
Definition: cdrom.h:1154
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 TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define LDRP_REDIRECTED
Definition: ldrtypes.h:58
uint16_t * PWSTR
Definition: typedefs.h:56
BOOLEAN NTAPI LdrpCheckForLoadedDllHandle(IN PVOID Base, OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
Definition: ldrutils.c:1621
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:1598
VOID NTAPI LdrpInsertMemoryTableEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: ldrutils.c:1582
VOID NTAPI LdrpRunShimEngineInitRoutine(IN ULONG Reason)
Definition: ldrutils.c:2736
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:479
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:131
NTSTATUS NTAPI LdrpResolveFullName(IN PUNICODE_STRING OriginalName, IN PUNICODE_STRING PathName, IN PUNICODE_STRING FullPathName, IN PUNICODE_STRING *ExpandedName)
Definition: ldrutils.c:1667
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:1389
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
Definition: pedump.c:270
uint16_t * PWCHAR
Definition: typedefs.h:56
#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:467
#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:1023
#define FILE_SHARE_READ
Definition: compat.h:136
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:2429
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
#define SearchPath
Definition: winbase.h:3740
_SEH2_TRY
Definition: create.c:4226
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
uint32_t ULONG_PTR
Definition: typedefs.h:65
#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:2771
#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 FALSE
Definition: types.h:117
#define UNICODE_NULL
#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:1382
LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES]
Definition: ldrinit.c:60
#define STATUS_ILLEGAL_DLL_RELOCATION
Definition: ntstatus.h:742
#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:2252
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:498
#define IMAGE_SCN_MEM_NOT_CACHED
Definition: ntimage.h:236
#define DLL_PROCESS_DETACH
Definition: compat.h:130
#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:1979
PVOID PatchInformation
Definition: ldrtypes.h:164
VOID NTAPI SE_ProcessDying(VOID)
Definition: shimeng.c:1427
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
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:1549
PVOID g_pShimEngineModule
Definition: ldrutils.c:22
union _IMAGE_THUNK_DATA32::@2106 u1
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:359
#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:4402
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ALIGN_DOWN(size, type)
Definition: umtypes.h:88
static void Exit(void)
Definition: sock.c:1331
HANDLE LdrpKnownDllObjectDirectory
Definition: ldrinit.c:62
#define MAX_PATH
Definition: compat.h:34
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:5713
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:5909
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:2663
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:1783
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
Definition: ncftp.h:89
VOID NTAPI LdrpUnloadShimEngine()
Definition: ldrutils.c:2796
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
Status
Definition: gdiplustypes.h:24
#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:557
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:139
#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:119
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:5242
#define IMAGE_DIRECTORY_ENTRY_EXPORT
Definition: compat.h:151
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
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:814
#define IMAGE_LOADER_FLAGS_COMPLUS
Definition: ntdllp.h:20
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define STATUS_IMAGE_NOT_AT_BASE
Definition: ntstatus.h:117
Definition: compat.h:583
#define LDRP_COR_IMAGE
Definition: ldrtypes.h:52
NTSTATUS NTAPI LdrUnloadDll(IN PVOID BaseAddress)
Definition: ldrapi.c:1322
_SEH2_END
Definition: create.c:4400
#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:545
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:260
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:2698
UNICODE_STRING FullDllName
Definition: btrfs_drv.h:1928
UNICODE_STRING BaseDllName
Definition: ldrtypes.h:145
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
_SEH2_FINALLY
Definition: create.c:4371
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:138
NTSYSAPI NTSTATUS NTAPI ZwAreMappedFilesTheSame(_In_ PVOID File1MappedAsAnImage, _In_ PVOID File2MappedAsFile)
#define STATUS_PROCEDURE_NOT_FOUND
Definition: ntstatus.h:358
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
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:554
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:5832
#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:947
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:262
NTSYSAPI PVOID WINAPI RtlReAllocateHeap(HANDLE, ULONG, PVOID, SIZE_T)
Definition: heap.c:2622
#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:793
#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:295
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define STATUS_CONFLICTING_ADDRESSES
Definition: ntstatus.h:261
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