ReactOS  r75384
sysldr.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: BSD - See COPYING.ARM in the top level directory
4  * FILE: ntoskrnl/mm/ARM3/sysldr.c
5  * PURPOSE: Contains the Kernel Loader (SYSLDR) for loading PE files.
6  * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7  * ReactOS Portable Systems Group
8  */
9 
10 /* INCLUDES *******************************************************************/
11 
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15 
16 #define MODULE_INVOLVED_IN_ARM3
17 #include <mm/ARM3/miarm.h>
18 
19 static
20 inline
21 VOID
23  IN PCHAR Format,
24  IN ...)
25 {
26  va_list ap;
27  va_start(ap, Format);
28  vsprintf(Buffer, Format, ap);
29  va_end(ap);
30 }
31 
32 /* GLOBALS ********************************************************************/
33 
40 
42 
45 
48 
52 
53 /* FUNCTIONS ******************************************************************/
54 
55 PVOID
56 NTAPI
58 {
59  ULONG DebugSize;
60  PVOID DebugDirectory = NULL;
61  PAGED_CODE();
62 
63  /* Make sure it's safe to access the image */
64  _SEH2_TRY
65  {
66  /* Get the debug directory */
67  DebugDirectory = RtlImageDirectoryEntryToData(BaseAddress,
68  TRUE,
70  &DebugSize);
71  }
73  {
74  /* Nothing */
75  }
76  _SEH2_END;
77 
78  /* Return the directory */
79  return DebugDirectory;
80 }
81 
83 NTAPI
85  OUT PVOID *ImageBase,
87  IN BOOLEAN SessionLoad,
88  IN PLDR_DATA_TABLE_ENTRY LdrEntry)
89 {
90  PROS_SECTION_OBJECT Section = *SectionPtr;
93  PVOID Base = NULL;
94  SIZE_T ViewSize = 0;
96  LARGE_INTEGER SectionOffset = {{0, 0}};
98  PFN_COUNT PteCount;
99  PMMPTE PointerPte, LastPte;
100  PVOID DriverBase;
101  MMPTE TempPte;
102  KIRQL OldIrql;
103  PFN_NUMBER PageFrameIndex;
104  PAGED_CODE();
105 
106  /* Detect session load */
107  if (SessionLoad)
108  {
109  /* Fail */
110  UNIMPLEMENTED_DBGBREAK("Session loading not yet supported!\n");
111  return STATUS_NOT_IMPLEMENTED;
112  }
113 
114  /* Not session load, shouldn't have an entry */
115  ASSERT(LdrEntry == NULL);
116 
117  /* Attach to the system process */
119 
120  /* Check if we need to load symbols */
122  {
123  /* Yes we do */
124  LoadSymbols = TRUE;
125  NtGlobalFlag &= ~FLG_ENABLE_KDEBUG_SYMBOL_LOAD;
126  }
127 
128  /* Map the driver */
129  Process = PsGetCurrentProcess();
130  Status = MmMapViewOfSection(Section,
131  Process,
132  &Base,
133  0,
134  0,
135  &SectionOffset,
136  &ViewSize,
137  ViewUnmap,
138  0,
139  PAGE_EXECUTE);
140 
141  /* Re-enable the flag */
142  if (LoadSymbols) NtGlobalFlag |= FLG_ENABLE_KDEBUG_SYMBOL_LOAD;
143 
144  /* Check if we failed with distinguished status code */
146  {
147  /* Change it to something more generic */
149  }
150 
151  /* Now check if we failed */
152  if (!NT_SUCCESS(Status))
153  {
154  /* Detach and return */
155  DPRINT1("MmMapViewOfSection failed with status 0x%x\n", Status);
156  KeUnstackDetachProcess(&ApcState);
157  return Status;
158  }
159 
160  /* Reserve system PTEs needed */
162  PointerPte = MiReserveSystemPtes(PteCount, SystemPteSpace);
163  if (!PointerPte)
164  {
165  DPRINT1("MiReserveSystemPtes failed\n");
166  KeUnstackDetachProcess(&ApcState);
168  }
169 
170  /* New driver base */
171  LastPte = PointerPte + PteCount;
172  DriverBase = MiPteToAddress(PointerPte);
173 
174  /* The driver is here */
175  *ImageBase = DriverBase;
176  DPRINT1("Loading: %wZ at %p with %lx pages\n", FileName, DriverBase, PteCount);
177 
178  /* Lock the PFN database */
180 
181  /* Loop the new driver PTEs */
182  TempPte = ValidKernelPte;
183  while (PointerPte < LastPte)
184  {
185  /* Make sure the PTE is not valid for whatever reason */
186  ASSERT(PointerPte->u.Hard.Valid == 0);
187 
188  /* Some debug stuff */
190 #if MI_TRACE_PFNS
191  if (FileName->Buffer)
192  {
193  PWCHAR pos = NULL;
194  ULONG len = 0;
195  pos = wcsrchr(FileName->Buffer, '\\');
196  len = wcslen(pos) * sizeof(WCHAR);
197  if (pos) snprintf(MI_PFN_CURRENT_PROCESS_NAME, min(16, len), "%S", pos);
198  }
199 #endif
200 
201  /* Grab a page */
202  PageFrameIndex = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
203 
204  /* Initialize its PFN entry */
205  MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
206 
207  /* Write the PTE */
208  TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
209  MI_WRITE_VALID_PTE(PointerPte, TempPte);
210 
211  /* Move on */
212  PointerPte++;
213  }
214 
215  /* Release the PFN lock */
217 
218  /* Copy the image */
219  RtlCopyMemory(DriverBase, Base, PteCount << PAGE_SHIFT);
220 
221  /* Now unmap the view */
222  Status = MmUnmapViewOfSection(Process, Base);
223  ASSERT(NT_SUCCESS(Status));
224 
225  /* Detach and return status */
226  KeUnstackDetachProcess(&ApcState);
227  return Status;
228 }
229 
230 PVOID
231 NTAPI
233  IN PCHAR ExportName)
234 {
235  PULONG NameTable;
236  PUSHORT OrdinalTable;
237  PIMAGE_EXPORT_DIRECTORY ExportDirectory;
238  LONG Low = 0, Mid = 0, High, Ret;
239  USHORT Ordinal;
240  PVOID Function;
241  ULONG ExportSize;
242  PULONG ExportTable;
243  PAGED_CODE();
244 
245  /* Get the export directory */
246  ExportDirectory = RtlImageDirectoryEntryToData(DllBase,
247  TRUE,
249  &ExportSize);
250  if (!ExportDirectory) return NULL;
251 
252  /* Setup name tables */
253  NameTable = (PULONG)((ULONG_PTR)DllBase +
254  ExportDirectory->AddressOfNames);
255  OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase +
256  ExportDirectory->AddressOfNameOrdinals);
257 
258  /* Do a binary search */
259  High = ExportDirectory->NumberOfNames - 1;
260  while (High >= Low)
261  {
262  /* Get new middle value */
263  Mid = (Low + High) >> 1;
264 
265  /* Compare name */
266  Ret = strcmp(ExportName, (PCHAR)DllBase + NameTable[Mid]);
267  if (Ret < 0)
268  {
269  /* Update high */
270  High = Mid - 1;
271  }
272  else if (Ret > 0)
273  {
274  /* Update low */
275  Low = Mid + 1;
276  }
277  else
278  {
279  /* We got it */
280  break;
281  }
282  }
283 
284  /* Check if we couldn't find it */
285  if (High < Low) return NULL;
286 
287  /* Otherwise, this is the ordinal */
288  Ordinal = OrdinalTable[Mid];
289 
290  /* Resolve the address and write it */
291  ExportTable = (PULONG)((ULONG_PTR)DllBase +
292  ExportDirectory->AddressOfFunctions);
293  Function = (PVOID)((ULONG_PTR)DllBase + ExportTable[Ordinal]);
294 
295  /* Check if the function is actually a forwarder */
296  if (((ULONG_PTR)Function > (ULONG_PTR)ExportDirectory) &&
297  ((ULONG_PTR)Function < ((ULONG_PTR)ExportDirectory + ExportSize)))
298  {
299  /* It is, fail */
300  return NULL;
301  }
302 
303  /* We found it */
304  return Function;
305 }
306 
307 NTSTATUS
308 NTAPI
310  IN PLIST_ENTRY ListHead)
311 {
312  UNICODE_STRING ServicesKeyName = RTL_CONSTANT_STRING(
313  L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
314  PMM_DLL_INITIALIZE DllInit;
315  UNICODE_STRING RegPath, ImportName;
317 
318  /* Try to see if the image exports a DllInitialize routine */
319  DllInit = (PMM_DLL_INITIALIZE)MiLocateExportName(LdrEntry->DllBase,
320  "DllInitialize");
321  if (!DllInit) return STATUS_SUCCESS;
322 
323  /* Do a temporary copy of BaseDllName called ImportName
324  * because we'll alter the length of the string
325  */
326  ImportName.Length = LdrEntry->BaseDllName.Length;
327  ImportName.MaximumLength = LdrEntry->BaseDllName.MaximumLength;
328  ImportName.Buffer = LdrEntry->BaseDllName.Buffer;
329 
330  /* Obtain the path to this dll's service in the registry */
331  RegPath.MaximumLength = ServicesKeyName.Length +
332  ImportName.Length + sizeof(UNICODE_NULL);
334  RegPath.MaximumLength,
335  TAG_LDR_WSTR);
336 
337  /* Check if this allocation was unsuccessful */
338  if (!RegPath.Buffer) return STATUS_INSUFFICIENT_RESOURCES;
339 
340  /* Build and append the service name itself */
341  RegPath.Length = ServicesKeyName.Length;
342  RtlCopyMemory(RegPath.Buffer,
343  ServicesKeyName.Buffer,
344  ServicesKeyName.Length);
345 
346  /* Check if there is a dot in the filename */
347  if (wcschr(ImportName.Buffer, L'.'))
348  {
349  /* Remove the extension */
350  ImportName.Length = (USHORT)(wcschr(ImportName.Buffer, L'.') -
351  ImportName.Buffer) * sizeof(WCHAR);
352  }
353 
354  /* Append service name (the basename without extension) */
355  RtlAppendUnicodeStringToString(&RegPath, &ImportName);
356 
357  /* Now call the DllInit func */
358  DPRINT("Calling DllInit(%wZ)\n", &RegPath);
359  Status = DllInit(&RegPath);
360 
361  /* Clean up */
363 
364  /* Return status value which DllInitialize returned */
365  return Status;
366 }
367 
368 BOOLEAN
369 NTAPI
371 {
374  PAGED_CODE();
375 
376  /* Get the unload routine */
377  Func = (PMM_DLL_UNLOAD)MiLocateExportName(LdrEntry->DllBase, "DllUnload");
378  if (!Func) return FALSE;
379 
380  /* Call it and check for success */
381  Status = Func();
382  if (!NT_SUCCESS(Status)) return FALSE;
383 
384  /* Lie about the load count so we can unload the image */
385  ASSERT(LdrEntry->LoadCount == 0);
386  LdrEntry->LoadCount = 1;
387 
388  /* Unload it and return true */
389  MmUnloadSystemImage(LdrEntry);
390  return TRUE;
391 }
392 
393 NTSTATUS
394 NTAPI
396 {
397  SIZE_T i;
398  LOAD_IMPORTS SingleEntry;
399  PLDR_DATA_TABLE_ENTRY LdrEntry;
400  PVOID CurrentImports;
401  PAGED_CODE();
402 
403  /* Check if there's no imports or if we're a boot driver */
404  if ((ImportList == MM_SYSLDR_NO_IMPORTS) ||
405  (ImportList == MM_SYSLDR_BOOT_LOADED) ||
406  (ImportList->Count == 0))
407  {
408  /* Then there's nothing to do */
409  return STATUS_SUCCESS;
410  }
411 
412  /* Check for single-entry */
413  if ((ULONG_PTR)ImportList & MM_SYSLDR_SINGLE_ENTRY)
414  {
415  /* Set it up */
416  SingleEntry.Count = 1;
417  SingleEntry.Entry[0] = (PVOID)((ULONG_PTR)ImportList &~ MM_SYSLDR_SINGLE_ENTRY);
418 
419  /* Use this as the import list */
420  ImportList = &SingleEntry;
421  }
422 
423  /* Loop the import list */
424  for (i = 0; (i < ImportList->Count) && (ImportList->Entry[i]); i++)
425  {
426  /* Get the entry */
427  LdrEntry = ImportList->Entry[i];
428  DPRINT1("%wZ <%wZ>\n", &LdrEntry->FullDllName, &LdrEntry->BaseDllName);
429 
430  /* Skip boot loaded images */
431  if (LdrEntry->LoadedImports == MM_SYSLDR_BOOT_LOADED) continue;
432 
433  /* Dereference the entry */
434  ASSERT(LdrEntry->LoadCount >= 1);
435  if (!--LdrEntry->LoadCount)
436  {
437  /* Save the import data in case unload fails */
438  CurrentImports = LdrEntry->LoadedImports;
439 
440  /* This is the last entry */
442  if (MiCallDllUnloadAndUnloadDll(LdrEntry))
443  {
444  /* Unloading worked, parse this DLL's imports too */
445  MiDereferenceImports(CurrentImports);
446 
447  /* Check if we had valid imports */
448  if ((CurrentImports != MM_SYSLDR_BOOT_LOADED) &&
449  (CurrentImports != MM_SYSLDR_NO_IMPORTS) &&
450  !((ULONG_PTR)CurrentImports & MM_SYSLDR_SINGLE_ENTRY))
451  {
452  /* Free them */
453  ExFreePoolWithTag(CurrentImports, TAG_LDR_IMPORTS);
454  }
455  }
456  else
457  {
458  /* Unload failed, restore imports */
459  LdrEntry->LoadedImports = CurrentImports;
460  }
461  }
462  }
463 
464  /* Done */
465  return STATUS_SUCCESS;
466 }
467 
468 VOID
469 NTAPI
471 {
472  PAGED_CODE();
473 
474  /* Check if there's no imports or we're a boot driver or only one entry */
475  if ((LdrEntry->LoadedImports == MM_SYSLDR_BOOT_LOADED) ||
476  (LdrEntry->LoadedImports == MM_SYSLDR_NO_IMPORTS) ||
477  ((ULONG_PTR)LdrEntry->LoadedImports & MM_SYSLDR_SINGLE_ENTRY))
478  {
479  /* Nothing to do */
480  return;
481  }
482 
483  /* Otherwise, free the import list */
484  ExFreePoolWithTag(LdrEntry->LoadedImports, TAG_LDR_IMPORTS);
485  LdrEntry->LoadedImports = MM_SYSLDR_BOOT_LOADED;
486 }
487 
488 PVOID
489 NTAPI
491  IN PANSI_STRING ExportName)
492 {
493  PULONG NameTable;
494  PUSHORT OrdinalTable;
495  PIMAGE_EXPORT_DIRECTORY ExportDirectory;
496  LONG Low = 0, Mid = 0, High, Ret;
497  USHORT Ordinal;
498  PVOID Function;
499  ULONG ExportSize;
500  PULONG ExportTable;
501  PAGED_CODE();
502 
503  /* Get the export directory */
504  ExportDirectory = RtlImageDirectoryEntryToData(DllBase,
505  TRUE,
507  &ExportSize);
508  if (!ExportDirectory) return NULL;
509 
510  /* Setup name tables */
511  NameTable = (PULONG)((ULONG_PTR)DllBase +
512  ExportDirectory->AddressOfNames);
513  OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase +
514  ExportDirectory->AddressOfNameOrdinals);
515 
516  /* Do a binary search */
517  High = ExportDirectory->NumberOfNames - 1;
518  while (High >= Low)
519  {
520  /* Get new middle value */
521  Mid = (Low + High) >> 1;
522 
523  /* Compare name */
524  Ret = strcmp(ExportName->Buffer, (PCHAR)DllBase + NameTable[Mid]);
525  if (Ret < 0)
526  {
527  /* Update high */
528  High = Mid - 1;
529  }
530  else if (Ret > 0)
531  {
532  /* Update low */
533  Low = Mid + 1;
534  }
535  else
536  {
537  /* We got it */
538  break;
539  }
540  }
541 
542  /* Check if we couldn't find it */
543  if (High < Low) return NULL;
544 
545  /* Otherwise, this is the ordinal */
546  Ordinal = OrdinalTable[Mid];
547 
548  /* Validate the ordinal */
549  if (Ordinal >= ExportDirectory->NumberOfFunctions) return NULL;
550 
551  /* Resolve the address and write it */
552  ExportTable = (PULONG)((ULONG_PTR)DllBase +
553  ExportDirectory->AddressOfFunctions);
554  Function = (PVOID)((ULONG_PTR)DllBase + ExportTable[Ordinal]);
555 
556  /* We found it! */
557  ASSERT((Function < (PVOID)ExportDirectory) ||
558  (Function > (PVOID)((ULONG_PTR)ExportDirectory + ExportSize)));
559 
560  return Function;
561 }
562 
563 VOID
564 NTAPI
566  IN BOOLEAN Insert)
567 {
568  KIRQL OldIrql;
569 
570  /* Acquire module list lock */
573 
574  /* Acquire the spinlock too as we will insert or remove the entry */
576 
577  /* Insert or remove from the list */
578  if (Insert)
579  InsertTailList(&PsLoadedModuleList, &LdrEntry->InLoadOrderLinks);
580  else
581  RemoveEntryList(&LdrEntry->InLoadOrderLinks);
582 
583  /* Release locks */
587 }
588 
589 VOID
590 NTAPI
593  IN PVOID OldBase,
594  IN PVOID NewBase,
595  IN ULONG Size)
596 {
597  ULONG_PTR OldBaseTop, Delta;
598  PLDR_DATA_TABLE_ENTRY LdrEntry;
599  PLIST_ENTRY NextEntry;
600  ULONG ImportSize;
601  //
602  // FIXME: MINGW-W64 must fix LD to generate drivers that Windows can load,
603  // since a real version of Windows would fail at this point, but they seem
604  // busy implementing features such as "HotPatch" support in GCC 4.6 instead,
605  // a feature which isn't even used by Windows. Priorities, priorities...
606  // Please note that Microsoft WDK EULA and license prohibits using
607  // the information contained within it for the generation of "non-Windows"
608  // drivers, which is precisely what LD will generate, since an LD driver
609  // will not load on Windows.
610  //
611 #ifdef _WORKING_LINKER_
612  ULONG i;
613 #endif
614  PULONG_PTR ImageThunk;
615  PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
616 
617  /* Calculate the top and delta */
618  OldBaseTop = (ULONG_PTR)OldBase + Size - 1;
619  Delta = (ULONG_PTR)NewBase - (ULONG_PTR)OldBase;
620 
621  /* Loop the loader block */
622  for (NextEntry = LoaderBlock->LoadOrderListHead.Flink;
623  NextEntry != &LoaderBlock->LoadOrderListHead;
624  NextEntry = NextEntry->Flink)
625  {
626  /* Get the loader entry */
627  LdrEntry = CONTAINING_RECORD(NextEntry,
629  InLoadOrderLinks);
630 #ifdef _WORKING_LINKER_
631  /* Get the IAT */
632  ImageThunk = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
633  TRUE,
635  &ImportSize);
636  if (!ImageThunk) continue;
637 
638  /* Make sure we have an IAT */
639  DPRINT("[Mm0]: Updating thunks in: %wZ\n", &LdrEntry->BaseDllName);
640  for (i = 0; i < ImportSize; i++, ImageThunk++)
641  {
642  /* Check if it's within this module */
643  if ((*ImageThunk >= (ULONG_PTR)OldBase) && (*ImageThunk <= OldBaseTop))
644  {
645  /* Relocate it */
646  DPRINT("[Mm0]: Updating IAT at: %p. Old Entry: %p. New Entry: %p.\n",
647  ImageThunk, *ImageThunk, *ImageThunk + Delta);
648  *ImageThunk += Delta;
649  }
650  }
651 #else
652  /* Get the import table */
653  ImportDescriptor = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
654  TRUE,
656  &ImportSize);
657  if (!ImportDescriptor) continue;
658 
659  /* Make sure we have an IAT */
660  DPRINT("[Mm0]: Updating thunks in: %wZ\n", &LdrEntry->BaseDllName);
661  while ((ImportDescriptor->Name) &&
662  (ImportDescriptor->OriginalFirstThunk))
663  {
664  /* Get the image thunk */
665  ImageThunk = (PVOID)((ULONG_PTR)LdrEntry->DllBase +
666  ImportDescriptor->FirstThunk);
667  while (*ImageThunk)
668  {
669  /* Check if it's within this module */
670  if ((*ImageThunk >= (ULONG_PTR)OldBase) && (*ImageThunk <= OldBaseTop))
671  {
672  /* Relocate it */
673  DPRINT("[Mm0]: Updating IAT at: %p. Old Entry: %p. New Entry: %p.\n",
674  ImageThunk, *ImageThunk, *ImageThunk + Delta);
675  *ImageThunk += Delta;
676  }
677 
678  /* Go to the next thunk */
679  ImageThunk++;
680  }
681 
682  /* Go to the next import */
683  ImportDescriptor++;
684  }
685 #endif
686  }
687 }
688 
689 NTSTATUS
690 NTAPI
692  IN PVOID ImageBase,
695  IN PIMAGE_EXPORT_DIRECTORY ExportDirectory,
696  IN ULONG ExportSize,
697  IN BOOLEAN SnapForwarder,
698  OUT PCHAR *MissingApi)
699 {
700  BOOLEAN IsOrdinal;
701  USHORT Ordinal;
702  PULONG NameTable;
703  PUSHORT OrdinalTable;
704  PIMAGE_IMPORT_BY_NAME NameImport;
705  USHORT Hint;
706  ULONG Low = 0, Mid = 0, High;
707  LONG Ret;
709  PCHAR MissingForwarder;
710  CHAR NameBuffer[MAXIMUM_FILENAME_LENGTH];
711  PULONG ExportTable;
712  ANSI_STRING DllName;
713  UNICODE_STRING ForwarderName;
714  PLIST_ENTRY NextEntry;
715  PLDR_DATA_TABLE_ENTRY LdrEntry;
716  ULONG ForwardExportSize;
717  PIMAGE_EXPORT_DIRECTORY ForwardExportDirectory;
718  PIMAGE_IMPORT_BY_NAME ForwardName;
719  SIZE_T ForwardLength;
720  IMAGE_THUNK_DATA ForwardThunk;
721  PAGED_CODE();
722 
723  /* Check if this is an ordinal */
724  IsOrdinal = IMAGE_SNAP_BY_ORDINAL(Name->u1.Ordinal);
725  if ((IsOrdinal) && !(SnapForwarder))
726  {
727  /* Get the ordinal number and set it as missing */
728  Ordinal = (USHORT)(IMAGE_ORDINAL(Name->u1.Ordinal) -
729  ExportDirectory->Base);
730  *MissingApi = (PCHAR)(ULONG_PTR)Ordinal;
731  }
732  else
733  {
734  /* Get the VA if we don't have to snap */
735  if (!SnapForwarder) Name->u1.AddressOfData += (ULONG_PTR)ImageBase;
736  NameImport = (PIMAGE_IMPORT_BY_NAME)Name->u1.AddressOfData;
737 
738  /* Copy the procedure name */
739  RtlStringCbCopyA(*MissingApi,
741  (PCHAR)&NameImport->Name[0]);
742 
743  /* Setup name tables */
744  DPRINT("Import name: %s\n", NameImport->Name);
745  NameTable = (PULONG)((ULONG_PTR)DllBase +
746  ExportDirectory->AddressOfNames);
747  OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase +
748  ExportDirectory->AddressOfNameOrdinals);
749 
750  /* Get the hint and check if it's valid */
751  Hint = NameImport->Hint;
752  if ((Hint < ExportDirectory->NumberOfNames) &&
753  !(strcmp((PCHAR)NameImport->Name, (PCHAR)DllBase + NameTable[Hint])))
754  {
755  /* We have a match, get the ordinal number from here */
756  Ordinal = OrdinalTable[Hint];
757  }
758  else
759  {
760  /* Do a binary search */
761  High = ExportDirectory->NumberOfNames - 1;
762  while (High >= Low)
763  {
764  /* Get new middle value */
765  Mid = (Low + High) >> 1;
766 
767  /* Compare name */
768  Ret = strcmp((PCHAR)NameImport->Name, (PCHAR)DllBase + NameTable[Mid]);
769  if (Ret < 0)
770  {
771  /* Update high */
772  High = Mid - 1;
773  }
774  else if (Ret > 0)
775  {
776  /* Update low */
777  Low = Mid + 1;
778  }
779  else
780  {
781  /* We got it */
782  break;
783  }
784  }
785 
786  /* Check if we couldn't find it */
787  if (High < Low)
788  {
789  DPRINT1("Warning: Driver failed to load, %s not found\n", NameImport->Name);
791  }
792 
793  /* Otherwise, this is the ordinal */
794  Ordinal = OrdinalTable[Mid];
795  }
796  }
797 
798  /* Check if the ordinal is invalid */
799  if (Ordinal >= ExportDirectory->NumberOfFunctions)
800  {
801  /* Fail */
803  }
804  else
805  {
806  /* In case the forwarder is missing */
807  MissingForwarder = NameBuffer;
808 
809  /* Resolve the address and write it */
810  ExportTable = (PULONG)((ULONG_PTR)DllBase +
811  ExportDirectory->AddressOfFunctions);
812  Address->u1.Function = (ULONG_PTR)DllBase + ExportTable[Ordinal];
813 
814  /* Assume success from now on */
815  Status = STATUS_SUCCESS;
816 
817  /* Check if the function is actually a forwarder */
818  if ((Address->u1.Function > (ULONG_PTR)ExportDirectory) &&
819  (Address->u1.Function < ((ULONG_PTR)ExportDirectory + ExportSize)))
820  {
821  /* Now assume failure in case the forwarder doesn't exist */
823 
824  /* Build the forwarder name */
825  DllName.Buffer = (PCHAR)Address->u1.Function;
826  DllName.Length = (USHORT)(strchr(DllName.Buffer, '.') -
827  DllName.Buffer) +
828  sizeof(ANSI_NULL);
829  DllName.MaximumLength = DllName.Length;
830 
831  /* Convert it */
832  if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ForwarderName,
833  &DllName,
834  TRUE)))
835  {
836  /* We failed, just return an error */
837  return Status;
838  }
839 
840  /* Loop the module list */
841  NextEntry = PsLoadedModuleList.Flink;
842  while (NextEntry != &PsLoadedModuleList)
843  {
844  /* Get the loader entry */
845  LdrEntry = CONTAINING_RECORD(NextEntry,
847  InLoadOrderLinks);
848 
849  /* Check if it matches */
850  if (RtlPrefixUnicodeString(&ForwarderName,
851  &LdrEntry->BaseDllName,
852  TRUE))
853  {
854  /* Get the forwarder export directory */
855  ForwardExportDirectory =
857  TRUE,
859  &ForwardExportSize);
860  if (!ForwardExportDirectory) break;
861 
862  /* Allocate a name entry */
863  ForwardLength = strlen(DllName.Buffer + DllName.Length) +
864  sizeof(ANSI_NULL);
865  ForwardName = ExAllocatePoolWithTag(PagedPool,
866  sizeof(*ForwardName) +
867  ForwardLength,
868  TAG_LDR_WSTR);
869  if (!ForwardName) break;
870 
871  /* Copy the data */
872  RtlCopyMemory(&ForwardName->Name[0],
873  DllName.Buffer + DllName.Length,
874  ForwardLength);
875  ForwardName->Hint = 0;
876 
877  /* Set the new address */
878  ForwardThunk.u1.AddressOfData = (ULONG_PTR)ForwardName;
879 
880  /* Snap the forwarder */
881  Status = MiSnapThunk(LdrEntry->DllBase,
882  ImageBase,
883  &ForwardThunk,
884  &ForwardThunk,
885  ForwardExportDirectory,
886  ForwardExportSize,
887  TRUE,
888  &MissingForwarder);
889 
890  /* Free the forwarder name and set the thunk */
891  ExFreePoolWithTag(ForwardName, TAG_LDR_WSTR);
892  Address->u1 = ForwardThunk.u1;
893  break;
894  }
895 
896  /* Go to the next entry */
897  NextEntry = NextEntry->Flink;
898  }
899 
900  /* Free the name */
901  RtlFreeUnicodeString(&ForwarderName);
902  }
903  }
904 
905  /* Return status */
906  return Status;
907 }
908 
909 NTSTATUS
910 NTAPI
912 {
914  PVOID BaseAddress = LdrEntry->DllBase;
916  STRING TempName;
917  BOOLEAN HadEntry = FALSE;
918 
919  /* Acquire the loader lock */
921  KeWaitForSingleObject(&MmSystemLoadLock,
923  KernelMode,
924  FALSE,
925  NULL);
926 
927  /* Check if this driver was loaded at boot and didn't get imports parsed */
928  if (LdrEntry->LoadedImports == MM_SYSLDR_BOOT_LOADED) goto Done;
929 
930  /* We should still be alive */
931  ASSERT(LdrEntry->LoadCount != 0);
932  LdrEntry->LoadCount--;
933 
934  /* Check if we're still loaded */
935  if (LdrEntry->LoadCount) goto Done;
936 
937  /* We should cleanup... are symbols loaded */
938  if (LdrEntry->Flags & LDRP_DEBUG_SYMBOLS_LOADED)
939  {
940  /* Create the ANSI name */
941  Status = RtlUnicodeStringToAnsiString(&TempName,
942  &LdrEntry->BaseDllName,
943  TRUE);
944  if (NT_SUCCESS(Status))
945  {
946  /* Unload the symbols */
947  DbgUnLoadImageSymbols(&TempName,
948  BaseAddress,
950  RtlFreeAnsiString(&TempName);
951  }
952  }
953 
954  /* FIXME: Free the driver */
955  DPRINT1("Leaking driver: %wZ\n", &LdrEntry->BaseDllName);
956  //MmFreeSection(LdrEntry->DllBase);
957 
958  /* Check if we're linked in */
959  if (LdrEntry->InLoadOrderLinks.Flink)
960  {
961  /* Remove us */
962  MiProcessLoaderEntry(LdrEntry, FALSE);
963  HadEntry = TRUE;
964  }
965 
966  /* Dereference and clear the imports */
968  MiClearImports(LdrEntry);
969 
970  /* Check if the entry needs to go away */
971  if (HadEntry)
972  {
973  /* Check if it had a name */
974  if (LdrEntry->FullDllName.Buffer)
975  {
976  /* Free it */
978  }
979 
980  /* Check if we had a section */
981  if (LdrEntry->SectionPointer)
982  {
983  /* Dereference it */
985  }
986 
987  /* Free the entry */
989  }
990 
991  /* Release the system lock and return */
992 Done:
993  KeReleaseMutant(&MmSystemLoadLock, 1, FALSE, FALSE);
995  return STATUS_SUCCESS;
996 }
997 
998 NTSTATUS
999 NTAPI
1001  IN PUNICODE_STRING ImageFileDirectory,
1002  IN PUNICODE_STRING NamePrefix OPTIONAL,
1003  OUT PCHAR *MissingApi,
1004  OUT PWCHAR *MissingDriver,
1005  OUT PLOAD_IMPORTS *LoadImports)
1006 {
1007  static UNICODE_STRING DriversFolderName = RTL_CONSTANT_STRING(L"drivers\\");
1008  PCHAR MissingApiBuffer = *MissingApi, ImportName;
1009  PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor, CurrentImport;
1010  ULONG ImportSize, ImportCount = 0, LoadedImportsSize, ExportSize;
1011  PLOAD_IMPORTS LoadedImports, NewImports;
1012  ULONG GdiLink, NormalLink, i;
1013  BOOLEAN ReferenceNeeded, Loaded;
1014  ANSI_STRING TempString;
1015  UNICODE_STRING NameString, DllName;
1016  PLDR_DATA_TABLE_ENTRY LdrEntry = NULL, DllEntry, ImportEntry = NULL;
1017  PVOID ImportBase, DllBase;
1018  PLIST_ENTRY NextEntry;
1019  PIMAGE_EXPORT_DIRECTORY ExportDirectory;
1020  NTSTATUS Status;
1021  PIMAGE_THUNK_DATA OrigThunk, FirstThunk;
1022  PAGED_CODE();
1023  DPRINT("%s - ImageBase: %p. ImageFileDirectory: %wZ\n",
1024  __FUNCTION__, ImageBase, ImageFileDirectory);
1025 
1026  /* No name string buffer yet */
1027  NameString.Buffer = NULL;
1028 
1029  /* Assume no imports */
1030  *LoadImports = MM_SYSLDR_NO_IMPORTS;
1031 
1032  /* Get the import descriptor */
1033  ImportDescriptor = RtlImageDirectoryEntryToData(ImageBase,
1034  TRUE,
1036  &ImportSize);
1037  if (!ImportDescriptor) return STATUS_SUCCESS;
1038 
1039  /* Loop all imports to count them */
1040  for (CurrentImport = ImportDescriptor;
1041  (CurrentImport->Name) && (CurrentImport->OriginalFirstThunk);
1042  CurrentImport++)
1043  {
1044  /* One more */
1045  ImportCount++;
1046  }
1047 
1048  /* Make sure we have non-zero imports */
1049  if (ImportCount)
1050  {
1051  /* Calculate and allocate the list we'll need */
1052  LoadedImportsSize = ImportCount * sizeof(PVOID) + sizeof(SIZE_T);
1053  LoadedImports = ExAllocatePoolWithTag(PagedPool,
1054  LoadedImportsSize,
1055  TAG_LDR_IMPORTS);
1056  if (LoadedImports)
1057  {
1058  /* Zero it */
1059  RtlZeroMemory(LoadedImports, LoadedImportsSize);
1060  LoadedImports->Count = ImportCount;
1061  }
1062  }
1063  else
1064  {
1065  /* No table */
1066  LoadedImports = NULL;
1067  }
1068 
1069  /* Reset the import count and loop descriptors again */
1070  ImportCount = GdiLink = NormalLink = 0;
1071  while ((ImportDescriptor->Name) && (ImportDescriptor->OriginalFirstThunk))
1072  {
1073  /* Get the name */
1074  ImportName = (PCHAR)((ULONG_PTR)ImageBase + ImportDescriptor->Name);
1075 
1076  /* Check if this is a GDI driver */
1077  GdiLink = GdiLink |
1078  !(_strnicmp(ImportName, "win32k", sizeof("win32k") - 1));
1079 
1080  /* We can also allow dxapi (for Windows compat, allow IRT and coverage )*/
1081  NormalLink = NormalLink |
1082  ((_strnicmp(ImportName, "win32k", sizeof("win32k") - 1)) &&
1083  (_strnicmp(ImportName, "dxapi", sizeof("dxapi") - 1)) &&
1084  (_strnicmp(ImportName, "coverage", sizeof("coverage") - 1)) &&
1085  (_strnicmp(ImportName, "irt", sizeof("irt") - 1)));
1086 
1087  /* Check if this is a valid GDI driver */
1088  if ((GdiLink) && (NormalLink))
1089  {
1090  /* It's not, it's importing stuff it shouldn't be! */
1091  Status = STATUS_PROCEDURE_NOT_FOUND;
1092  goto Failure;
1093  }
1094 
1095  /* Check for user-mode printer or video card drivers, which don't belong */
1096  if (!(_strnicmp(ImportName, "ntdll", sizeof("ntdll") - 1)) ||
1097  !(_strnicmp(ImportName, "winsrv", sizeof("winsrv") - 1)) ||
1098  !(_strnicmp(ImportName, "advapi32", sizeof("advapi32") - 1)) ||
1099  !(_strnicmp(ImportName, "kernel32", sizeof("kernel32") - 1)) ||
1100  !(_strnicmp(ImportName, "user32", sizeof("user32") - 1)) ||
1101  !(_strnicmp(ImportName, "gdi32", sizeof("gdi32") - 1)))
1102  {
1103  /* This is not kernel code */
1104  Status = STATUS_PROCEDURE_NOT_FOUND;
1105  goto Failure;
1106  }
1107 
1108  /* Check if this is a "core" import, which doesn't get referenced */
1109  if (!(_strnicmp(ImportName, "ntoskrnl", sizeof("ntoskrnl") - 1)) ||
1110  !(_strnicmp(ImportName, "win32k", sizeof("win32k") - 1)) ||
1111  !(_strnicmp(ImportName, "hal", sizeof("hal") - 1)))
1112  {
1113  /* Don't reference this */
1114  ReferenceNeeded = FALSE;
1115  }
1116  else
1117  {
1118  /* Reference these modules */
1119  ReferenceNeeded = TRUE;
1120  }
1121 
1122  /* Now setup a unicode string for the import */
1123  RtlInitAnsiString(&TempString, ImportName);
1124  Status = RtlAnsiStringToUnicodeString(&NameString, &TempString, TRUE);
1125  if (!NT_SUCCESS(Status))
1126  {
1127  /* Failed */
1128  goto Failure;
1129  }
1130 
1131  /* We don't support name prefixes yet */
1132  if (NamePrefix) DPRINT1("Name Prefix not yet supported!\n");
1133 
1134  /* Remember that we haven't loaded the import at this point */
1135 CheckDllState:
1136  Loaded = FALSE;
1137  ImportBase = NULL;
1138 
1139  /* Loop the driver list */
1140  NextEntry = PsLoadedModuleList.Flink;
1141  while (NextEntry != &PsLoadedModuleList)
1142  {
1143  /* Get the loader entry and compare the name */
1144  LdrEntry = CONTAINING_RECORD(NextEntry,
1146  InLoadOrderLinks);
1147  if (RtlEqualUnicodeString(&NameString,
1148  &LdrEntry->BaseDllName,
1149  TRUE))
1150  {
1151  /* Get the base address */
1152  ImportBase = LdrEntry->DllBase;
1153 
1154  /* Check if we haven't loaded yet, and we need references */
1155  if (!(Loaded) && (ReferenceNeeded))
1156  {
1157  /* Make sure we're not already loading */
1158  if (!(LdrEntry->Flags & LDRP_LOAD_IN_PROGRESS))
1159  {
1160  /* Increase the load count */
1161  LdrEntry->LoadCount++;
1162  }
1163  }
1164 
1165  /* Done, break out */
1166  break;
1167  }
1168 
1169  /* Go to the next entry */
1170  NextEntry = NextEntry->Flink;
1171  }
1172 
1173  /* Check if we haven't loaded the import yet */
1174  if (!ImportBase)
1175  {
1176  /* Setup the import DLL name */
1177  DllName.MaximumLength = NameString.Length +
1178  ImageFileDirectory->Length +
1179  sizeof(UNICODE_NULL);
1181  DllName.MaximumLength,
1182  TAG_LDR_WSTR);
1183  if (!DllName.Buffer)
1184  {
1185  /* We're out of resources */
1187  goto Failure;
1188  }
1189 
1190  /* Add the import name to the base directory */
1191  RtlCopyUnicodeString(&DllName, ImageFileDirectory);
1193  &NameString);
1194 
1195  /* Load the image */
1196  Status = MmLoadSystemImage(&DllName,
1197  NamePrefix,
1198  NULL,
1199  FALSE,
1200  (PVOID *)&DllEntry,
1201  &DllBase);
1202 
1203  /* win32k / GDI drivers can also import from system32 folder */
1204  if ((Status == STATUS_OBJECT_NAME_NOT_FOUND) &&
1205  (MI_IS_SESSION_ADDRESS(ImageBase) || 1)) // HACK
1206  {
1207  /* Free the old name buffer */
1209 
1210  /* Calculate size for a string the adds 'drivers\' */
1211  DllName.MaximumLength += DriversFolderName.Length;
1212 
1213  /* Allocate the new buffer */
1215  DllName.MaximumLength,
1216  TAG_LDR_WSTR);
1217  if (!DllName.Buffer)
1218  {
1219  /* We're out of resources */
1221  goto Failure;
1222  }
1223 
1224  /* Copy image directory and append 'drivers\' folder name */
1225  RtlCopyUnicodeString(&DllName, ImageFileDirectory);
1226  RtlAppendUnicodeStringToString(&DllName, &DriversFolderName);
1227 
1228  /* Now add the import name */
1229  RtlAppendUnicodeStringToString(&DllName, &NameString);
1230 
1231  /* Try once again to load the image */
1232  Status = MmLoadSystemImage(&DllName,
1233  NamePrefix,
1234  NULL,
1235  FALSE,
1236  (PVOID *)&DllEntry,
1237  &DllBase);
1238  }
1239 
1240  if (!NT_SUCCESS(Status))
1241  {
1242  /* Fill out the information for the error */
1243  *MissingDriver = DllName.Buffer;
1244  *(PULONG)MissingDriver |= 1;
1245  *MissingApi = NULL;
1246 
1247  DPRINT1("Failed to load dependency: %wZ\n", &DllName);
1248 
1249  /* Don't free the name */
1250  DllName.Buffer = NULL;
1251 
1252  /* Cleanup and return */
1253  goto Failure;
1254  }
1255 
1256  /* We can free the DLL Name */
1258  DllName.Buffer = NULL;
1259 
1260  /* We're now loaded */
1261  Loaded = TRUE;
1262 
1263  /* Sanity check */
1264  ASSERT(DllBase == DllEntry->DllBase);
1265 
1266  /* Call the initialization routines */
1267  Status = MmCallDllInitialize(DllEntry, &PsLoadedModuleList);
1268  if (!NT_SUCCESS(Status))
1269  {
1270  /* We failed, unload the image */
1271  MmUnloadSystemImage(DllEntry);
1272  ERROR_DBGBREAK("MmCallDllInitialize failed with status 0x%x\n", Status);
1273  Loaded = FALSE;
1274  }
1275 
1276  /* Loop again to make sure that everything is OK */
1277  goto CheckDllState;
1278  }
1279 
1280  /* Check if we're support to reference this import */
1281  if ((ReferenceNeeded) && (LoadedImports))
1282  {
1283  /* Make sure we're not already loading */
1284  if (!(LdrEntry->Flags & LDRP_LOAD_IN_PROGRESS))
1285  {
1286  /* Add the entry */
1287  LoadedImports->Entry[ImportCount] = LdrEntry;
1288  ImportCount++;
1289  }
1290  }
1291 
1292  /* Free the import name */
1293  RtlFreeUnicodeString(&NameString);
1294 
1295  /* Set the missing driver name and get the export directory */
1296  *MissingDriver = LdrEntry->BaseDllName.Buffer;
1297  ExportDirectory = RtlImageDirectoryEntryToData(ImportBase,
1298  TRUE,
1300  &ExportSize);
1301  if (!ExportDirectory)
1302  {
1303  /* Cleanup and return */
1304  DPRINT1("Warning: Driver failed to load, %S not found\n", *MissingDriver);
1306  goto Failure;
1307  }
1308 
1309  /* Make sure we have an IAT */
1310  if (ImportDescriptor->OriginalFirstThunk)
1311  {
1312  /* Get the first thunks */
1313  OrigThunk = (PVOID)((ULONG_PTR)ImageBase +
1314  ImportDescriptor->OriginalFirstThunk);
1315  FirstThunk = (PVOID)((ULONG_PTR)ImageBase +
1316  ImportDescriptor->FirstThunk);
1317 
1318  /* Loop the IAT */
1319  while (OrigThunk->u1.AddressOfData)
1320  {
1321  /* Snap thunk */
1322  Status = MiSnapThunk(ImportBase,
1323  ImageBase,
1324  OrigThunk++,
1325  FirstThunk++,
1326  ExportDirectory,
1327  ExportSize,
1328  FALSE,
1329  MissingApi);
1330  if (!NT_SUCCESS(Status))
1331  {
1332  /* Cleanup and return */
1333  goto Failure;
1334  }
1335 
1336  /* Reset the buffer */
1337  *MissingApi = MissingApiBuffer;
1338  }
1339  }
1340 
1341  /* Go to the next import */
1342  ImportDescriptor++;
1343  }
1344 
1345  /* Check if we have an import list */
1346  if (LoadedImports)
1347  {
1348  /* Reset the count again, and loop entries */
1349  ImportCount = 0;
1350  for (i = 0; i < LoadedImports->Count; i++)
1351  {
1352  if (LoadedImports->Entry[i])
1353  {
1354  /* Got an entry, OR it with 1 in case it's the single entry */
1355  ImportEntry = (PVOID)((ULONG_PTR)LoadedImports->Entry[i] |
1357  ImportCount++;
1358  }
1359  }
1360 
1361  /* Check if we had no imports */
1362  if (!ImportCount)
1363  {
1364  /* Free the list and set it to no imports */
1365  ExFreePoolWithTag(LoadedImports, TAG_LDR_IMPORTS);
1366  LoadedImports = MM_SYSLDR_NO_IMPORTS;
1367  }
1368  else if (ImportCount == 1)
1369  {
1370  /* Just one entry, we can free the table and only use our entry */
1371  ExFreePoolWithTag(LoadedImports, TAG_LDR_IMPORTS);
1372  LoadedImports = (PLOAD_IMPORTS)ImportEntry;
1373  }
1374  else if (ImportCount != LoadedImports->Count)
1375  {
1376  /* Allocate a new list */
1377  LoadedImportsSize = ImportCount * sizeof(PVOID) + sizeof(SIZE_T);
1378  NewImports = ExAllocatePoolWithTag(PagedPool,
1379  LoadedImportsSize,
1380  TAG_LDR_IMPORTS);
1381  if (NewImports)
1382  {
1383  /* Set count */
1384  NewImports->Count = 0;
1385 
1386  /* Loop all the imports */
1387  for (i = 0; i < LoadedImports->Count; i++)
1388  {
1389  /* Make sure it's valid */
1390  if (LoadedImports->Entry[i])
1391  {
1392  /* Copy it */
1393  NewImports->Entry[NewImports->Count] = LoadedImports->Entry[i];
1394  NewImports->Count++;
1395  }
1396  }
1397 
1398  /* Free the old copy */
1399  ExFreePoolWithTag(LoadedImports, TAG_LDR_IMPORTS);
1400  LoadedImports = NewImports;
1401  }
1402  }
1403 
1404  /* Return the list */
1405  *LoadImports = LoadedImports;
1406  }
1407 
1408  /* Return success */
1409  return STATUS_SUCCESS;
1410 
1411 Failure:
1412 
1413  /* Cleanup and return */
1414  RtlFreeUnicodeString(&NameString);
1415 
1416  if (LoadedImports)
1417  {
1418  MiDereferenceImports(LoadedImports);
1419  ExFreePoolWithTag(LoadedImports, TAG_LDR_IMPORTS);
1420  }
1421 
1422  return Status;
1423 }
1424 
1425 VOID
1426 NTAPI
1428  IN PVOID InitEnd)
1429 {
1430  PMMPTE PointerPte;
1431  PFN_NUMBER PagesFreed;
1432 
1433  /* Get the start PTE */
1434  PointerPte = MiAddressToPte(InitStart);
1435  ASSERT(MI_IS_PHYSICAL_ADDRESS(InitStart) == FALSE);
1436 
1437  /* Compute the number of pages we expect to free */
1438  PagesFreed = (PFN_NUMBER)(MiAddressToPte(InitEnd) - PointerPte + 1);
1439 
1440  /* Try to actually free them */
1441  PagesFreed = MiDeleteSystemPageableVm(PointerPte,
1442  PagesFreed,
1443  0,
1444  NULL);
1445 }
1446 
1447 VOID
1448 NTAPI
1451  OUT PVOID *EndVa)
1452 {
1453  ULONG Size, SectionCount, Alignment;
1454  PLDR_DATA_TABLE_ENTRY LdrEntry;
1455  ULONG_PTR DllBase, InitStart, InitEnd, ImageEnd, InitCode;
1456  PLIST_ENTRY NextEntry;
1457  PIMAGE_NT_HEADERS NtHeader;
1458  PIMAGE_SECTION_HEADER Section, LastSection;
1459  BOOLEAN InitFound;
1460 
1461  /* So we don't free our own code yet */
1462  InitCode = (ULONG_PTR)&MiFindInitializationCode;
1463 
1464  /* Assume failure */
1465  *StartVa = NULL;
1466 
1467  /* Enter a critical region while we loop the list */
1469 
1470  /* Loop all loaded modules */
1471  NextEntry = PsLoadedModuleList.Flink;
1472  while (NextEntry != &PsLoadedModuleList)
1473  {
1474  /* Get the loader entry and its DLL base */
1475  LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
1476  DllBase = (ULONG_PTR)LdrEntry->DllBase;
1477 
1478  /* Only process boot loaded images. Other drivers are processed by
1479  MmFreeDriverInitialization */
1480  if (LdrEntry->Flags & LDRP_MM_LOADED)
1481  {
1482  /* Keep going */
1483  NextEntry = NextEntry->Flink;
1484  continue;
1485  }
1486 
1487  /* Get the NT header */
1488  NtHeader = RtlImageNtHeader((PVOID)DllBase);
1489  if (!NtHeader)
1490  {
1491  /* Keep going */
1492  NextEntry = NextEntry->Flink;
1493  continue;
1494  }
1495 
1496  /* Get the first section, the section count, and scan them all */
1497  Section = IMAGE_FIRST_SECTION(NtHeader);
1498  SectionCount = NtHeader->FileHeader.NumberOfSections;
1499  InitStart = 0;
1500  while (SectionCount > 0)
1501  {
1502  /* Assume failure */
1503  InitFound = FALSE;
1504 
1505  /* Is this the INIT section or a discardable section? */
1506  if ((*(PULONG)Section->Name == 'TINI') ||
1508  {
1509  /* Remember this */
1510  InitFound = TRUE;
1511  }
1512 
1513  if (InitFound)
1514  {
1515  /* Pick the biggest size -- either raw or virtual */
1516  Size = max(Section->SizeOfRawData, Section->Misc.VirtualSize);
1517 
1518  /* Read the section alignment */
1519  Alignment = NtHeader->OptionalHeader.SectionAlignment;
1520 
1521  /* Align the start and end addresses appropriately */
1522  InitStart = DllBase + Section->VirtualAddress;
1523  InitEnd = ((Alignment + InitStart + Size - 2) & 0xFFFFF000) - 1;
1524  InitStart = (InitStart + (PAGE_SIZE - 1)) & 0xFFFFF000;
1525 
1526  /* Have we reached the last section? */
1527  if (SectionCount == 1)
1528  {
1529  /* Remember this */
1530  LastSection = Section;
1531  }
1532  else
1533  {
1534  /* We have not, loop all the sections */
1535  LastSection = NULL;
1536  do
1537  {
1538  /* Keep going until we find a non-discardable section range */
1539  SectionCount--;
1540  Section++;
1542  {
1543  /* Discardable, so record it, then keep going */
1544  LastSection = Section;
1545  }
1546  else
1547  {
1548  /* Non-contigous discard flag, or no flag, break out */
1549  break;
1550  }
1551  }
1552  while (SectionCount > 1);
1553  }
1554 
1555  /* Have we found a discardable or init section? */
1556  if (LastSection)
1557  {
1558  /* Pick the biggest size -- either raw or virtual */
1559  Size = max(LastSection->SizeOfRawData, LastSection->Misc.VirtualSize);
1560 
1561  /* Use this as the end of the section address */
1562  InitEnd = DllBase + LastSection->VirtualAddress + Size - 1;
1563 
1564  /* Have we reached the last section yet? */
1565  if (SectionCount != 1)
1566  {
1567  /* Then align this accross the session boundary */
1568  InitEnd = ((Alignment + InitEnd - 1) & 0XFFFFF000) - 1;
1569  }
1570  }
1571 
1572  /* Make sure we don't let the init section go past the image */
1573  ImageEnd = DllBase + LdrEntry->SizeOfImage;
1574  if (InitEnd > ImageEnd) InitEnd = (ImageEnd - 1) | (PAGE_SIZE - 1);
1575 
1576  /* Make sure we have a valid, non-zero init section */
1577  if (InitStart <= InitEnd)
1578  {
1579  /* Make sure we are not within this code itself */
1580  if ((InitCode >= InitStart) && (InitCode <= InitEnd))
1581  {
1582  /* Return it, we can't free ourselves now */
1583  ASSERT(*StartVa == 0);
1584  *StartVa = (PVOID)InitStart;
1585  *EndVa = (PVOID)InitEnd;
1586  }
1587  else
1588  {
1589  /* This isn't us -- go ahead and free it */
1590  ASSERT(MI_IS_PHYSICAL_ADDRESS((PVOID)InitStart) == FALSE);
1591  MiFreeInitializationCode((PVOID)InitStart, (PVOID)InitEnd);
1592  }
1593  }
1594  }
1595 
1596  /* Move to the next section */
1597  SectionCount--;
1598  Section++;
1599  }
1600 
1601  /* Move to the next module */
1602  NextEntry = NextEntry->Flink;
1603  }
1604 
1605  /* Leave the critical region and return */
1607 }
1608 
1609 /*
1610  * Note: This function assumes that all discardable sections are at the end of
1611  * the PE file. It searches backwards until it finds the non-discardable section
1612  */
1613 VOID
1614 NTAPI
1616 {
1617  PMMPTE StartPte, EndPte;
1618  PFN_NUMBER PageCount;
1619  PVOID DllBase;
1620  ULONG i;
1621  PIMAGE_NT_HEADERS NtHeader;
1622  PIMAGE_SECTION_HEADER Section, DiscardSection;
1623 
1624  /* Get the base address and the page count */
1625  DllBase = LdrEntry->DllBase;
1626  PageCount = LdrEntry->SizeOfImage >> PAGE_SHIFT;
1627 
1628  /* Get the last PTE in this image */
1629  EndPte = MiAddressToPte(DllBase) + PageCount;
1630 
1631  /* Get the NT header */
1632  NtHeader = RtlImageNtHeader(DllBase);
1633  if (!NtHeader) return;
1634 
1635  /* Get the last section and loop each section backwards */
1636  Section = IMAGE_FIRST_SECTION(NtHeader) + NtHeader->FileHeader.NumberOfSections;
1637  DiscardSection = NULL;
1638  for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++)
1639  {
1640  /* Go back a section and check if it's discardable */
1641  Section--;
1643  {
1644  /* It is, select it for freeing */
1645  DiscardSection = Section;
1646  }
1647  else
1648  {
1649  /* No more discardable sections exist, bail out */
1650  break;
1651  }
1652  }
1653 
1654  /* Bail out if there's nothing to free */
1655  if (!DiscardSection) return;
1656 
1657  /* Push the DLL base to the first disacrable section, and get its PTE */
1658  DllBase = (PVOID)ROUND_TO_PAGES((ULONG_PTR)DllBase + DiscardSection->VirtualAddress);
1659  ASSERT(MI_IS_PHYSICAL_ADDRESS(DllBase) == FALSE);
1660  StartPte = MiAddressToPte(DllBase);
1661 
1662  /* Check how many pages to free total */
1663  PageCount = (PFN_NUMBER)(EndPte - StartPte);
1664  if (!PageCount) return;
1665 
1666  /* Delete this many PTEs */
1667  MiDeleteSystemPageableVm(StartPte, PageCount, 0, NULL);
1668 }
1669 
1670 VOID
1671 NTAPI
1674 {
1675  PLIST_ENTRY NextEntry;
1676  ULONG i = 0;
1677  PIMAGE_NT_HEADERS NtHeader;
1678  PLDR_DATA_TABLE_ENTRY LdrEntry;
1679  PIMAGE_FILE_HEADER FileHeader;
1680  BOOLEAN ValidRelocs;
1681  PIMAGE_DATA_DIRECTORY DataDirectory;
1682  PVOID DllBase, NewImageAddress;
1683  NTSTATUS Status;
1684  PMMPTE PointerPte, StartPte, LastPte;
1685  PFN_COUNT PteCount;
1686  PMMPFN Pfn1;
1687  MMPTE TempPte, OldPte;
1688 
1689  /* Loop driver list */
1690  for (NextEntry = LoaderBlock->LoadOrderListHead.Flink;
1691  NextEntry != &LoaderBlock->LoadOrderListHead;
1692  NextEntry = NextEntry->Flink)
1693  {
1694  /* Get the loader entry and NT header */
1695  LdrEntry = CONTAINING_RECORD(NextEntry,
1697  InLoadOrderLinks);
1698  NtHeader = RtlImageNtHeader(LdrEntry->DllBase);
1699 
1700  /* Debug info */
1701  DPRINT("[Mm0]: Driver at: %p ending at: %p for module: %wZ\n",
1702  LdrEntry->DllBase,
1703  (ULONG_PTR)LdrEntry->DllBase + LdrEntry->SizeOfImage,
1704  &LdrEntry->FullDllName);
1705 
1706  /* Get the first PTE and the number of PTEs we'll need */
1707  PointerPte = StartPte = MiAddressToPte(LdrEntry->DllBase);
1708  PteCount = ROUND_TO_PAGES(LdrEntry->SizeOfImage) >> PAGE_SHIFT;
1709  LastPte = StartPte + PteCount;
1710 
1711 #if MI_TRACE_PFNS
1712  /* Loop the PTEs */
1713  while (PointerPte < LastPte)
1714  {
1715  ULONG len;
1716  ASSERT(PointerPte->u.Hard.Valid == 1);
1717  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
1718  len = wcslen(LdrEntry->BaseDllName.Buffer) * sizeof(WCHAR);
1719  snprintf(Pfn1->ProcessName, min(16, len), "%S", LdrEntry->BaseDllName.Buffer);
1720  PointerPte++;
1721  }
1722 #endif
1723  /* Skip kernel and HAL */
1724  /* ROS HACK: Skip BOOTVID/KDCOM too */
1725  i++;
1726  if (i <= 4) continue;
1727 
1728  /* Skip non-drivers */
1729  if (!NtHeader) continue;
1730 
1731  /* Get the file header and make sure we can relocate */
1732  FileHeader = &NtHeader->FileHeader;
1733  if (FileHeader->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) continue;
1734  if (NtHeader->OptionalHeader.NumberOfRvaAndSizes <
1736 
1737  /* Everything made sense until now, check the relocation section too */
1738  DataDirectory = &NtHeader->OptionalHeader.
1739  DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
1740  if (!DataDirectory->VirtualAddress)
1741  {
1742  /* We don't really have relocations */
1743  ValidRelocs = FALSE;
1744  }
1745  else
1746  {
1747  /* Make sure the size is valid */
1748  if ((DataDirectory->VirtualAddress + DataDirectory->Size) >
1749  LdrEntry->SizeOfImage)
1750  {
1751  /* They're not, skip */
1752  continue;
1753  }
1754 
1755  /* We have relocations */
1756  ValidRelocs = TRUE;
1757  }
1758 
1759  /* Remember the original address */
1760  DllBase = LdrEntry->DllBase;
1761 
1762  /* Loop the PTEs */
1763  PointerPte = StartPte;
1764  while (PointerPte < LastPte)
1765  {
1766  /* Mark the page modified in the PFN database */
1767  ASSERT(PointerPte->u.Hard.Valid == 1);
1768  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
1769  ASSERT(Pfn1->u3.e1.Rom == 0);
1770  Pfn1->u3.e1.Modified = TRUE;
1771 
1772  /* Next */
1773  PointerPte++;
1774  }
1775 
1776  /* Now reserve system PTEs for the image */
1777  PointerPte = MiReserveSystemPtes(PteCount, SystemPteSpace);
1778  if (!PointerPte)
1779  {
1780  /* Shouldn't happen */
1781  ERROR_FATAL("[Mm0]: Couldn't allocate driver section!\n");
1782  return;
1783  }
1784 
1785  /* This is the new virtual address for the module */
1786  LastPte = PointerPte + PteCount;
1787  NewImageAddress = MiPteToAddress(PointerPte);
1788 
1789  /* Sanity check */
1790  DPRINT("[Mm0]: Copying from: %p to: %p\n", DllBase, NewImageAddress);
1792 
1793  /* Loop the new driver PTEs */
1794  TempPte = ValidKernelPte;
1795  while (PointerPte < LastPte)
1796  {
1797  /* Copy the old data */
1798  OldPte = *StartPte;
1799  ASSERT(OldPte.u.Hard.Valid == 1);
1800 
1801  /* Set page number from the loader's memory */
1802  TempPte.u.Hard.PageFrameNumber = OldPte.u.Hard.PageFrameNumber;
1803 
1804  /* Write it */
1805  MI_WRITE_VALID_PTE(PointerPte, TempPte);
1806 
1807  /* Move on */
1808  PointerPte++;
1809  StartPte++;
1810  }
1811 
1812  /* Update position */
1813  PointerPte -= PteCount;
1814 
1815  /* Sanity check */
1816  ASSERT(*(PULONG)NewImageAddress == *(PULONG)DllBase);
1817 
1818  /* Set the image base to the address where the loader put it */
1819  NtHeader->OptionalHeader.ImageBase = (ULONG_PTR)DllBase;
1820 
1821  /* Check if we had relocations */
1822  if (ValidRelocs)
1823  {
1824  /* Relocate the image */
1825  Status = LdrRelocateImageWithBias(NewImageAddress,
1826  0,
1827  "SYSLDR",
1831  if (!NT_SUCCESS(Status))
1832  {
1833  /* This shouldn't happen */
1834  ERROR_FATAL("Relocations failed!\n");
1835  return;
1836  }
1837  }
1838 
1839  /* Update the loader entry */
1840  LdrEntry->DllBase = NewImageAddress;
1841 
1842  /* Update the thunks */
1843  DPRINT("[Mm0]: Updating thunks to: %wZ\n", &LdrEntry->BaseDllName);
1844  MiUpdateThunks(LoaderBlock,
1845  DllBase,
1846  NewImageAddress,
1847  LdrEntry->SizeOfImage);
1848 
1849  /* Update the loader entry */
1850  LdrEntry->Flags |= LDRP_SYSTEM_MAPPED;
1851  LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)NewImageAddress +
1853  LdrEntry->SizeOfImage = PteCount << PAGE_SHIFT;
1854 
1855  /* FIXME: We'll need to fixup the PFN linkage when switching to ARM3 */
1856  }
1857 }
1858 
1859 NTSTATUS
1860 NTAPI
1863 {
1864  PLIST_ENTRY NextEntry, NextEntry2;
1865  PLDR_DATA_TABLE_ENTRY LdrEntry, KernelEntry, HalEntry, LdrEntry2, LastEntry;
1866  PLDR_DATA_TABLE_ENTRY* EntryArray;
1867  UNICODE_STRING KernelName = RTL_CONSTANT_STRING(L"ntoskrnl.exe");
1869  PLOAD_IMPORTS LoadedImports;
1870  ULONG LoadedImportsSize, ImportSize;
1871  PULONG_PTR ImageThunk;
1872  ULONG_PTR DllBase, DllEnd;
1873  ULONG Modules = 0, i, j = 0;
1874  PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
1875 
1876  /* Initialize variables */
1877  KernelEntry = HalEntry = LastEntry = NULL;
1878 
1879  /* Loop the loaded module list... we are early enough that no lock is needed */
1880  NextEntry = PsLoadedModuleList.Flink;
1881  while (NextEntry != &PsLoadedModuleList)
1882  {
1883  /* Get the entry */
1884  LdrEntry = CONTAINING_RECORD(NextEntry,
1886  InLoadOrderLinks);
1887 
1888  /* Check if it's the kernel or HAL */
1889  if (RtlEqualUnicodeString(&KernelName, &LdrEntry->BaseDllName, TRUE))
1890  {
1891  /* Found it */
1892  KernelEntry = LdrEntry;
1893  }
1894  else if (RtlEqualUnicodeString(&HalName, &LdrEntry->BaseDllName, TRUE))
1895  {
1896  /* Found it */
1897  HalEntry = LdrEntry;
1898  }
1899 
1900  /* Check if this is a driver DLL */
1901  if (LdrEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL)
1902  {
1903  /* Check if this is the HAL or kernel */
1904  if ((LdrEntry == HalEntry) || (LdrEntry == KernelEntry))
1905  {
1906  /* Add a reference */
1907  LdrEntry->LoadCount = 1;
1908  }
1909  else
1910  {
1911  /* No referencing needed */
1912  LdrEntry->LoadCount = 0;
1913  }
1914  }
1915  else
1916  {
1917  /* Add a reference for all other modules as well */
1918  LdrEntry->LoadCount = 1;
1919  }
1920 
1921  /* Remember this came from the loader */
1923 
1924  /* Keep looping */
1925  NextEntry = NextEntry->Flink;
1926  Modules++;
1927  }
1928 
1929  /* We must have at least found the kernel and HAL */
1930  if (!(HalEntry) || (!KernelEntry)) return STATUS_NOT_FOUND;
1931 
1932  /* Allocate the list */
1933  EntryArray = ExAllocatePoolWithTag(PagedPool, Modules * sizeof(PVOID), TAG_LDR_IMPORTS);
1934  if (!EntryArray) return STATUS_INSUFFICIENT_RESOURCES;
1935 
1936  /* Loop the loaded module list again */
1937  NextEntry = PsLoadedModuleList.Flink;
1938  while (NextEntry != &PsLoadedModuleList)
1939  {
1940  /* Get the entry */
1941  LdrEntry = CONTAINING_RECORD(NextEntry,
1943  InLoadOrderLinks);
1944 #ifdef _WORKING_LOADER_
1945  /* Get its imports */
1946  ImageThunk = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
1947  TRUE,
1949  &ImportSize);
1950  if (!ImageThunk)
1951 #else
1952  /* Get its imports */
1953  ImportDescriptor = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
1954  TRUE,
1956  &ImportSize);
1957  if (!ImportDescriptor)
1958 #endif
1959  {
1960  /* None present */
1961  LdrEntry->LoadedImports = MM_SYSLDR_NO_IMPORTS;
1962  NextEntry = NextEntry->Flink;
1963  continue;
1964  }
1965 
1966  /* Clear the list and count the number of IAT thunks */
1967  RtlZeroMemory(EntryArray, Modules * sizeof(PVOID));
1968 #ifdef _WORKING_LOADER_
1969  ImportSize /= sizeof(ULONG_PTR);
1970 
1971  /* Scan the thunks */
1972  for (i = 0, DllBase = 0, DllEnd = 0; i < ImportSize; i++, ImageThunk++)
1973 #else
1974  DllBase = DllEnd = i = 0;
1975  while ((ImportDescriptor->Name) &&
1976  (ImportDescriptor->OriginalFirstThunk))
1977  {
1978  /* Get the image thunk */
1979  ImageThunk = (PVOID)((ULONG_PTR)LdrEntry->DllBase +
1980  ImportDescriptor->FirstThunk);
1981  while (*ImageThunk)
1982 #endif
1983  {
1984  /* Do we already have an address? */
1985  if (DllBase)
1986  {
1987  /* Is the thunk in the same address? */
1988  if ((*ImageThunk >= DllBase) && (*ImageThunk < DllEnd))
1989  {
1990  /* Skip it, we already have a reference for it */
1991  ASSERT(EntryArray[j]);
1992  ImageThunk++;
1993  continue;
1994  }
1995  }
1996 
1997  /* Loop the loaded module list to locate this address owner */
1998  j = 0;
1999  NextEntry2 = PsLoadedModuleList.Flink;
2000  while (NextEntry2 != &PsLoadedModuleList)
2001  {
2002  /* Get the entry */
2003  LdrEntry2 = CONTAINING_RECORD(NextEntry2,
2005  InLoadOrderLinks);
2006 
2007  /* Get the address range for this module */
2008  DllBase = (ULONG_PTR)LdrEntry2->DllBase;
2009  DllEnd = DllBase + LdrEntry2->SizeOfImage;
2010 
2011  /* Check if this IAT entry matches it */
2012  if ((*ImageThunk >= DllBase) && (*ImageThunk < DllEnd))
2013  {
2014  /* Save it */
2015  //DPRINT1("Found imported dll: %wZ\n", &LdrEntry2->BaseDllName);
2016  EntryArray[j] = LdrEntry2;
2017  break;
2018  }
2019 
2020  /* Keep searching */
2021  NextEntry2 = NextEntry2->Flink;
2022  j++;
2023  }
2024 
2025  /* Do we have a thunk outside the range? */
2026  if ((*ImageThunk < DllBase) || (*ImageThunk >= DllEnd))
2027  {
2028  /* Could be 0... */
2029  if (*ImageThunk)
2030  {
2031  /* Should not be happening */
2032  ERROR_FATAL("Broken IAT entry for %p at %p (%lx)\n",
2033  LdrEntry, ImageThunk, *ImageThunk);
2034  }
2035 
2036  /* Reset if we hit this */
2037  DllBase = 0;
2038  }
2039 #ifndef _WORKING_LOADER_
2040  ImageThunk++;
2041  }
2042 
2043  i++;
2044  ImportDescriptor++;
2045 #endif
2046  }
2047 
2048  /* Now scan how many imports we really have */
2049  for (i = 0, ImportSize = 0; i < Modules; i++)
2050  {
2051  /* Skip HAL and kernel */
2052  if ((EntryArray[i]) &&
2053  (EntryArray[i] != HalEntry) &&
2054  (EntryArray[i] != KernelEntry))
2055  {
2056  /* A valid reference */
2057  LastEntry = EntryArray[i];
2058  ImportSize++;
2059  }
2060  }
2061 
2062  /* Do we have any imports after all? */
2063  if (!ImportSize)
2064  {
2065  /* No */
2066  LdrEntry->LoadedImports = MM_SYSLDR_NO_IMPORTS;
2067  }
2068  else if (ImportSize == 1)
2069  {
2070  /* A single entry import */
2071  LdrEntry->LoadedImports = (PVOID)((ULONG_PTR)LastEntry | MM_SYSLDR_SINGLE_ENTRY);
2072  LastEntry->LoadCount++;
2073  }
2074  else
2075  {
2076  /* We need an import table */
2077  LoadedImportsSize = ImportSize * sizeof(PVOID) + sizeof(SIZE_T);
2078  LoadedImports = ExAllocatePoolWithTag(PagedPool,
2079  LoadedImportsSize,
2080  TAG_LDR_IMPORTS);
2081  ASSERT(LoadedImports);
2082 
2083  /* Save the count */
2084  LoadedImports->Count = ImportSize;
2085 
2086  /* Now copy all imports */
2087  for (i = 0, j = 0; i < Modules; i++)
2088  {
2089  /* Skip HAL and kernel */
2090  if ((EntryArray[i]) &&
2091  (EntryArray[i] != HalEntry) &&
2092  (EntryArray[i] != KernelEntry))
2093  {
2094  /* A valid reference */
2095  //DPRINT1("Found valid entry: %p\n", EntryArray[i]);
2096  LoadedImports->Entry[j] = EntryArray[i];
2097  EntryArray[i]->LoadCount++;
2098  j++;
2099  }
2100  }
2101 
2102  /* Should had as many entries as we expected */
2103  ASSERT(j == ImportSize);
2104  LdrEntry->LoadedImports = LoadedImports;
2105  }
2106 
2107  /* Next */
2108  NextEntry = NextEntry->Flink;
2109  }
2110 
2111  /* Free the initial array */
2112  ExFreePoolWithTag(EntryArray, TAG_LDR_IMPORTS);
2113 
2114  /* FIXME: Might not need to keep the HAL/Kernel imports around */
2115 
2116  /* Kernel and HAL are loaded at boot */
2117  KernelEntry->LoadedImports = MM_SYSLDR_BOOT_LOADED;
2119 
2120  /* All worked well */
2121  return STATUS_SUCCESS;
2122 }
2123 
2124 VOID
2125 NTAPI
2128 {
2129  ULONG_PTR DllBase;
2130  PIMAGE_NT_HEADERS NtHeaders;
2131  PIMAGE_SECTION_HEADER SectionHeader;
2132  ULONG Sections, Size;
2133 
2134  /* Get the kernel section header */
2135  DllBase = (ULONG_PTR)LdrEntry->DllBase;
2136  NtHeaders = RtlImageNtHeader((PVOID)DllBase);
2137  SectionHeader = IMAGE_FIRST_SECTION(NtHeaders);
2138 
2139  /* Loop all the sections */
2140  Sections = NtHeaders->FileHeader.NumberOfSections;
2141  while (Sections)
2142  {
2143  /* Grab the size of the section */
2144  Size = max(SectionHeader->SizeOfRawData, SectionHeader->Misc.VirtualSize);
2145 
2146  /* Check for .RSRC section */
2147  if (*(PULONG)SectionHeader->Name == 'rsr.')
2148  {
2149  /* Remember the PTEs so we can modify them later */
2150  MiKernelResourceStartPte = MiAddressToPte(DllBase +
2151  SectionHeader->VirtualAddress);
2152  MiKernelResourceEndPte = MiKernelResourceStartPte +
2153  BYTES_TO_PAGES(SectionHeader->VirtualAddress + Size);
2154  }
2155  else if (*(PULONG)SectionHeader->Name == 'LOOP')
2156  {
2157  /* POOLCODE vs. POOLMI */
2158  if (*(PULONG)&SectionHeader->Name[4] == 'EDOC')
2159  {
2160  /* Found Ex* Pool code */
2161  ExPoolCodeStart = DllBase + SectionHeader->VirtualAddress;
2163  }
2164  else if (*(PUSHORT)&SectionHeader->Name[4] == 'MI')
2165  {
2166  /* Found Mm* Pool code */
2167  MmPoolCodeStart = DllBase + SectionHeader->VirtualAddress;
2169  }
2170  }
2171  else if ((*(PULONG)SectionHeader->Name == 'YSIM') &&
2172  (*(PULONG)&SectionHeader->Name[4] == 'ETPS'))
2173  {
2174  /* Found MISYSPTE (Mm System PTE code)*/
2175  MmPteCodeStart = DllBase + SectionHeader->VirtualAddress;
2177  }
2178 
2179  /* Keep going */
2180  Sections--;
2181  SectionHeader++;
2182  }
2183 }
2184 
2185 BOOLEAN
2186 NTAPI
2189 {
2190  PLDR_DATA_TABLE_ENTRY LdrEntry, NewEntry;
2191  PLIST_ENTRY ListHead, NextEntry;
2192  ULONG EntrySize;
2193 
2194  /* Setup the loaded module list and locks */
2197  InitializeListHead(&PsLoadedModuleList);
2198 
2199  /* Get loop variables and the kernel entry */
2200  ListHead = &LoaderBlock->LoadOrderListHead;
2201  NextEntry = ListHead->Flink;
2202  LdrEntry = CONTAINING_RECORD(NextEntry,
2204  InLoadOrderLinks);
2205  PsNtosImageBase = (ULONG_PTR)LdrEntry->DllBase;
2206 
2207  /* Locate resource section, pool code, and system pte code */
2208  MiLocateKernelSections(LdrEntry);
2209 
2210  /* Loop the loader block */
2211  while (NextEntry != ListHead)
2212  {
2213  /* Get the loader entry */
2214  LdrEntry = CONTAINING_RECORD(NextEntry,
2216  InLoadOrderLinks);
2217 
2218  /* FIXME: ROS HACK. Make sure this is a driver */
2219  if (!RtlImageNtHeader(LdrEntry->DllBase))
2220  {
2221  /* Skip this entry */
2222  NextEntry = NextEntry->Flink;
2223  continue;
2224  }
2225 
2226  /* Calculate the size we'll need and allocate a copy */
2227  EntrySize = sizeof(LDR_DATA_TABLE_ENTRY) +
2228  LdrEntry->BaseDllName.MaximumLength +
2229  sizeof(UNICODE_NULL);
2230  NewEntry = ExAllocatePoolWithTag(NonPagedPool, EntrySize, TAG_MODULE_OBJECT);
2231  if (!NewEntry) return FALSE;
2232 
2233  /* Copy the entry over */
2234  *NewEntry = *LdrEntry;
2235 
2236  /* Allocate the name */
2237  NewEntry->FullDllName.Buffer =
2239  LdrEntry->FullDllName.MaximumLength +
2240  sizeof(UNICODE_NULL),
2241  TAG_LDR_WSTR);
2242  if (!NewEntry->FullDllName.Buffer)
2243  {
2245  return FALSE;
2246  }
2247 
2248  /* Set the base name */
2249  NewEntry->BaseDllName.Buffer = (PVOID)(NewEntry + 1);
2250 
2251  /* Copy the full and base name */
2252  RtlCopyMemory(NewEntry->FullDllName.Buffer,
2253  LdrEntry->FullDllName.Buffer,
2254  LdrEntry->FullDllName.MaximumLength);
2255  RtlCopyMemory(NewEntry->BaseDllName.Buffer,
2256  LdrEntry->BaseDllName.Buffer,
2257  LdrEntry->BaseDllName.MaximumLength);
2258 
2259  /* Null-terminate the base name */
2260  NewEntry->BaseDllName.Buffer[NewEntry->BaseDllName.Length /
2261  sizeof(WCHAR)] = UNICODE_NULL;
2262 
2263  /* Insert the entry into the list */
2264  InsertTailList(&PsLoadedModuleList, &NewEntry->InLoadOrderLinks);
2265  NextEntry = NextEntry->Flink;
2266  }
2267 
2268  /* Build the import lists for the boot drivers */
2270 
2271  /* We're done */
2272  return TRUE;
2273 }
2274 
2275 LOGICAL
2276 NTAPI
2278  IN OUT PVOID *ImageBaseAddress,
2279  IN PUNICODE_STRING BaseImageName,
2280  IN BOOLEAN BootDriver)
2281 {
2282  PLIST_ENTRY NextEntry;
2283  BOOLEAN DriverFound = FALSE;
2284  PMI_LARGE_PAGE_DRIVER_ENTRY LargePageDriverEntry;
2286  ASSERT(*ImageBaseAddress >= MmSystemRangeStart);
2287 
2288 #ifdef _X86_
2289  if (!(KeFeatureBits & KF_LARGE_PAGE)) return FALSE;
2290  if (!(__readcr4() & CR4_PSE)) return FALSE;
2291 #endif
2292 
2293  /* Make sure there's enough system PTEs for a large page driver */
2295  {
2296  return FALSE;
2297  }
2298 
2299  /* This happens if the registry key had a "*" (wildcard) in it */
2300  if (MiLargePageAllDrivers == 0)
2301  {
2302  /* It didn't, so scan the list */
2303  NextEntry = MiLargePageDriverList.Flink;
2304  while (NextEntry != &MiLargePageDriverList)
2305  {
2306  /* Check if the driver name matches */
2307  LargePageDriverEntry = CONTAINING_RECORD(NextEntry,
2309  Links);
2310  if (RtlEqualUnicodeString(BaseImageName,
2311  &LargePageDriverEntry->BaseName,
2312  TRUE))
2313  {
2314  /* Enable large pages for this driver */
2315  DriverFound = TRUE;
2316  break;
2317  }
2318 
2319  /* Keep trying */
2320  NextEntry = NextEntry->Flink;
2321  }
2322 
2323  /* If we didn't find the driver, it doesn't need large pages */
2324  if (DriverFound == FALSE) return FALSE;
2325  }
2326 
2327  /* Nothing to do yet */
2328  DPRINT1("Large pages not supported!\n");
2329  return FALSE;
2330 }
2331 
2332 ULONG
2333 NTAPI
2335  IN ULONG SectionProtection)
2336 {
2337  ULONG Protection = MM_ZERO_ACCESS;
2338 
2339  /* Check if the caller gave anything */
2340  if (SectionProtection)
2341  {
2342  /* Always turn on execute access */
2343  SectionProtection |= IMAGE_SCN_MEM_EXECUTE;
2344 
2345  /* Check if the registry setting is on or not */
2347  {
2348  /* Turn on write access too */
2349  SectionProtection |= (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE);
2350  }
2351  }
2352 
2353  /* Convert to internal PTE flags */
2354  if (SectionProtection & IMAGE_SCN_MEM_EXECUTE) Protection |= MM_EXECUTE;
2355  if (SectionProtection & IMAGE_SCN_MEM_READ) Protection |= MM_READONLY;
2356 
2357  /* Check for write access */
2358  if (SectionProtection & IMAGE_SCN_MEM_WRITE)
2359  {
2360  /* Session space is not supported */
2361  if (SessionSpace)
2362  {
2363  DPRINT1("Session drivers not supported\n");
2364  ASSERT(SessionSpace == FALSE);
2365  }
2366  else
2367  {
2368  /* Convert to internal PTE flag */
2369  Protection = (Protection & MM_EXECUTE) ? MM_EXECUTE_READWRITE : MM_READWRITE;
2370  }
2371  }
2372 
2373  /* If there's no access at all by now, convert to internal no access flag */
2374  if (Protection == MM_ZERO_ACCESS) Protection = MM_NOACCESS;
2375 
2376  /* Return the computed PTE protection */
2377  return Protection;
2378 }
2379 
2380 VOID
2381 NTAPI
2383  IN PMMPTE LastPte,
2384  IN ULONG ProtectionMask)
2385 {
2386  /* I'm afraid to introduce regressions at the moment... */
2387  return;
2388 }
2389 
2390 VOID
2391 NTAPI
2393 {
2394  PIMAGE_NT_HEADERS NtHeaders;
2395  PIMAGE_SECTION_HEADER Section;
2396  PFN_NUMBER DriverPages;
2397  ULONG CurrentProtection, SectionProtection, CombinedProtection = 0, ProtectionMask;
2398  ULONG Sections, Size;
2399  ULONG_PTR BaseAddress, CurrentAddress;
2400  PMMPTE PointerPte, StartPte, LastPte, CurrentPte, ComboPte = NULL;
2401  ULONG CurrentMask, CombinedMask = 0;
2402  PAGED_CODE();
2403 
2404  /* No need to write protect physical memory-backed drivers (large pages) */
2405  if (MI_IS_PHYSICAL_ADDRESS(ImageBase)) return;
2406 
2407  /* Get the image headers */
2408  NtHeaders = RtlImageNtHeader(ImageBase);
2409  if (!NtHeaders) return;
2410 
2411  /* Check if this is a session driver or not */
2412  if (!MI_IS_SESSION_ADDRESS(ImageBase))
2413  {
2414  /* Don't touch NT4 drivers */
2415  if (NtHeaders->OptionalHeader.MajorOperatingSystemVersion < 5) return;
2416  if (NtHeaders->OptionalHeader.MajorImageVersion < 5) return;
2417  }
2418  else
2419  {
2420  /* Not supported */
2421  UNIMPLEMENTED_DBGBREAK("Session drivers not supported\n");
2422  }
2423 
2424  /* These are the only protection masks we care about */
2426 
2427  /* Calculate the number of pages this driver is occupying */
2428  DriverPages = BYTES_TO_PAGES(NtHeaders->OptionalHeader.SizeOfImage);
2429 
2430  /* Get the number of sections and the first section header */
2431  Sections = NtHeaders->FileHeader.NumberOfSections;
2432  ASSERT(Sections != 0);
2433  Section = IMAGE_FIRST_SECTION(NtHeaders);
2434 
2435  /* Loop all the sections */
2436  CurrentAddress = (ULONG_PTR)ImageBase;
2437  while (Sections)
2438  {
2439  /* Get the section size */
2440  Size = max(Section->SizeOfRawData, Section->Misc.VirtualSize);
2441 
2442  /* Get its virtual address */
2443  BaseAddress = (ULONG_PTR)ImageBase + Section->VirtualAddress;
2444  if (BaseAddress < CurrentAddress)
2445  {
2446  /* Windows doesn't like these */
2447  DPRINT1("Badly linked image!\n");
2448  return;
2449  }
2450 
2451  /* Remember the current address */
2452  CurrentAddress = BaseAddress + Size - 1;
2453 
2454  /* Next */
2455  Sections--;
2456  Section++;
2457  }
2458 
2459  /* Get the number of sections and the first section header */
2460  Sections = NtHeaders->FileHeader.NumberOfSections;
2461  ASSERT(Sections != 0);
2462  Section = IMAGE_FIRST_SECTION(NtHeaders);
2463 
2464  /* Set the address at the end to initialize the loop */
2465  CurrentAddress = (ULONG_PTR)Section + Sections - 1;
2466  CurrentProtection = IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ;
2467 
2468  /* Set the PTE points for the image, and loop its sections */
2469  StartPte = MiAddressToPte(ImageBase);
2470  LastPte = StartPte + DriverPages;
2471  while (Sections)
2472  {
2473  /* Get the section size */
2474  Size = max(Section->SizeOfRawData, Section->Misc.VirtualSize);
2475 
2476  /* Get its virtual address and PTE */
2477  BaseAddress = (ULONG_PTR)ImageBase + Section->VirtualAddress;
2478  PointerPte = MiAddressToPte(BaseAddress);
2479 
2480  /* Check if we were already protecting a run, and found a new run */
2481  if ((ComboPte) && (PointerPte > ComboPte))
2482  {
2483  /* Compute protection */
2484  CombinedMask = MiComputeDriverProtection(FALSE, CombinedProtection);
2485 
2486  /* Set it */
2487  MiSetSystemCodeProtection(ComboPte, ComboPte, CombinedMask);
2488 
2489  /* Check for overlap */
2490  if (ComboPte == StartPte) StartPte++;
2491 
2492  /* One done, reset variables */
2493  ComboPte = NULL;
2494  CombinedProtection = 0;
2495  }
2496 
2497  /* Break out when needed */
2498  if (PointerPte >= LastPte) break;
2499 
2500  /* Get the requested protection from the image header */
2501  SectionProtection = Section->Characteristics & ProtectionMask;
2502  if (SectionProtection == CurrentProtection)
2503  {
2504  /* Same protection, so merge the request */
2505  CurrentAddress = BaseAddress + Size - 1;
2506 
2507  /* Next */
2508  Sections--;
2509  Section++;
2510  continue;
2511  }
2512 
2513  /* This is now a new section, so close up the old one */
2514  CurrentPte = MiAddressToPte(CurrentAddress);
2515 
2516  /* Check for overlap */
2517  if (CurrentPte == PointerPte)
2518  {
2519  /* Skip the last PTE, since it overlaps with us */
2520  CurrentPte--;
2521 
2522  /* And set the PTE we will merge with */
2523  ASSERT((ComboPte == NULL) || (ComboPte == PointerPte));
2524  ComboPte = PointerPte;
2525 
2526  /* Get the most flexible protection by merging both */
2527  CombinedMask |= (SectionProtection | CurrentProtection);
2528  }
2529 
2530  /* Loop any PTEs left */
2531  if (CurrentPte >= StartPte)
2532  {
2533  /* Sanity check */
2534  ASSERT(StartPte < LastPte);
2535 
2536  /* Make sure we don't overflow past the last PTE in the driver */
2537  if (CurrentPte >= LastPte) CurrentPte = LastPte - 1;
2538  ASSERT(CurrentPte >= StartPte);
2539 
2540  /* Compute the protection and set it */
2541  CurrentMask = MiComputeDriverProtection(FALSE, CurrentProtection);
2542  MiSetSystemCodeProtection(StartPte, CurrentPte, CurrentMask);
2543  }
2544 
2545  /* Set new state */
2546  StartPte = PointerPte;
2547  CurrentAddress = BaseAddress + Size - 1;
2548  CurrentProtection = SectionProtection;
2549 
2550  /* Next */
2551  Sections--;
2552  Section++;
2553  }
2554 
2555  /* Is there a leftover section to merge? */
2556  if (ComboPte)
2557  {
2558  /* Compute and set the protection */
2559  CombinedMask = MiComputeDriverProtection(FALSE, CombinedProtection);
2560  MiSetSystemCodeProtection(ComboPte, ComboPte, CombinedMask);
2561 
2562  /* Handle overlap */
2563  if (ComboPte == StartPte) StartPte++;
2564  }
2565 
2566  /* Finally, handle the last section */
2567  CurrentPte = MiAddressToPte(CurrentAddress);
2568  if ((StartPte < LastPte) && (CurrentPte >= StartPte))
2569  {
2570  /* Handle overlap */
2571  if (CurrentPte >= LastPte) CurrentPte = LastPte - 1;
2572  ASSERT(CurrentPte >= StartPte);
2573 
2574  /* Compute and set the protection */
2575  CurrentMask = MiComputeDriverProtection(FALSE, CurrentProtection);
2576  MiSetSystemCodeProtection(StartPte, CurrentPte, CurrentMask);
2577  }
2578 }
2579 
2580 VOID
2581 NTAPI
2583  IN PMMPTE LastPte)
2584 {
2585  PVOID ImageBase;
2586  PETHREAD CurrentThread = PsGetCurrentThread();
2587  PFN_COUNT PageCount = 0;
2588  PFN_NUMBER PageFrameIndex;
2589  PMMPFN Pfn1;
2590  PAGED_CODE();
2591 
2592  /* The page fault handler is broken and doesn't page back in! */
2593  DPRINT1("WARNING: MiSetPagingOfDriver() called, but paging is broken! ignoring!\n");
2594  return;
2595 
2596  /* Get the driver's base address */
2597  ImageBase = MiPteToAddress(PointerPte);
2598  ASSERT(MI_IS_SESSION_IMAGE_ADDRESS(ImageBase) == FALSE);
2599 
2600  /* If this is a large page, it's stuck in physical memory */
2601  if (MI_IS_PHYSICAL_ADDRESS(ImageBase)) return;
2602 
2603  /* Lock the working set */
2604  MiLockWorkingSet(CurrentThread, &MmSystemCacheWs);
2605 
2606  /* Loop the PTEs */
2607  while (PointerPte <= LastPte)
2608  {
2609  /* Check for valid PTE */
2610  if (PointerPte->u.Hard.Valid == 1)
2611  {
2612  PageFrameIndex = PFN_FROM_PTE(PointerPte);
2613  Pfn1 = MiGetPfnEntry(PageFrameIndex);
2614  ASSERT(Pfn1->u2.ShareCount == 1);
2615 
2616  /* No working sets in ReactOS yet */
2617  PageCount++;
2618  }
2619 
2620  ImageBase = (PVOID)((ULONG_PTR)ImageBase + PAGE_SIZE);
2621  PointerPte++;
2622  }
2623 
2624  /* Release the working set */
2625  MiUnlockWorkingSet(CurrentThread, &MmSystemCacheWs);
2626 
2627  /* Do we have any driver pages? */
2628  if (PageCount)
2629  {
2630  /* Update counters */
2632  }
2633 }
2634 
2635 VOID
2636 NTAPI
2638 {
2639  ULONG_PTR ImageBase;
2640  PIMAGE_NT_HEADERS NtHeaders;
2641  ULONG Sections, Alignment, Size;
2642  PIMAGE_SECTION_HEADER Section;
2643  PMMPTE PointerPte = NULL, LastPte = NULL;
2644  if (MmDisablePagingExecutive) return;
2645 
2646  /* Get the driver base address and its NT header */
2647  ImageBase = (ULONG_PTR)LdrEntry->DllBase;
2648  NtHeaders = RtlImageNtHeader((PVOID)ImageBase);
2649  if (!NtHeaders) return;
2650 
2651  /* Get the sections and their alignment */
2652  Sections = NtHeaders->FileHeader.NumberOfSections;
2653  Alignment = NtHeaders->OptionalHeader.SectionAlignment - 1;
2654 
2655  /* Loop each section */
2656  Section = IMAGE_FIRST_SECTION(NtHeaders);
2657  while (Sections)
2658  {
2659  /* Find PAGE or .edata */
2660  if ((*(PULONG)Section->Name == 'EGAP') ||
2661  (*(PULONG)Section->Name == 'ade.'))
2662  {
2663  /* Had we already done some work? */
2664  if (!PointerPte)
2665  {
2666  /* Nope, setup the first PTE address */
2667  PointerPte = MiAddressToPte(ROUND_TO_PAGES(ImageBase +
2668  Section->
2669  VirtualAddress));
2670  }
2671 
2672  /* Compute the size */
2673  Size = max(Section->SizeOfRawData, Section->Misc.VirtualSize);
2674 
2675  /* Find the last PTE that maps this section */
2676  LastPte = MiAddressToPte(ImageBase +
2677  Section->VirtualAddress +
2678  Alignment +
2679  Size -
2680  PAGE_SIZE);
2681  }
2682  else
2683  {
2684  /* Had we found a section before? */
2685  if (PointerPte)
2686  {
2687  /* Mark it as pageable */
2688  MiSetPagingOfDriver(PointerPte, LastPte);
2689  PointerPte = NULL;
2690  }
2691  }
2692 
2693  /* Keep searching */
2694  Sections--;
2695  Section++;
2696  }
2697 
2698  /* Handle the straggler */
2699  if (PointerPte) MiSetPagingOfDriver(PointerPte, LastPte);
2700 }
2701 
2702 BOOLEAN
2703 NTAPI
2705 {
2706  PIMAGE_NT_HEADERS NtHeader;
2707  PAGED_CODE();
2708 
2709  /* Get NT Headers */
2710  NtHeader = RtlImageNtHeader(BaseAddress);
2711  if (NtHeader)
2712  {
2713  /* Check if this image is only safe for UP while we have 2+ CPUs */
2714  if ((KeNumberProcessors > 1) &&
2716  {
2717  /* Fail */
2718  return FALSE;
2719  }
2720  }
2721 
2722  /* Otherwise, it's safe */
2723  return TRUE;
2724 }
2725 
2726 NTSTATUS
2727 NTAPI
2729  IN BOOLEAN PurgeSection)
2730 {
2731  NTSTATUS Status;
2732  HANDLE SectionHandle;
2733  PVOID ViewBase = NULL;
2734  SIZE_T ViewSize = 0;
2736  FILE_STANDARD_INFORMATION FileStandardInfo;
2738  PIMAGE_NT_HEADERS NtHeaders;
2740  PAGED_CODE();
2741 
2742  /* Setup the object attributes */
2743  InitializeObjectAttributes(&ObjectAttributes,
2744  NULL,
2746  NULL,
2747  NULL);
2748 
2749  /* Create a section for the DLL */
2750  Status = ZwCreateSection(&SectionHandle,
2752  &ObjectAttributes,
2753  NULL,
2754  PAGE_EXECUTE,
2755  SEC_IMAGE,
2756  ImageHandle);
2757  if (!NT_SUCCESS(Status))
2758  {
2759  DPRINT1("ZwCreateSection failed with status 0x%x\n", Status);
2760  return Status;
2761  }
2762 
2763  /* Make sure we're in the system process */
2765 
2766  /* Map it */
2767  Status = ZwMapViewOfSection(SectionHandle,
2768  NtCurrentProcess(),
2769  &ViewBase,
2770  0,
2771  0,
2772  NULL,
2773  &ViewSize,
2774  ViewShare,
2775  0,
2776  PAGE_EXECUTE);
2777  if (!NT_SUCCESS(Status))
2778  {
2779  /* We failed, close the handle and return */
2780  DPRINT1("ZwMapViewOfSection failed with status 0x%x\n", Status);
2781  KeUnstackDetachProcess(&ApcState);
2782  ZwClose(SectionHandle);
2783  return Status;
2784  }
2785 
2786  /* Now query image information */
2787  Status = ZwQueryInformationFile(ImageHandle,
2788  &IoStatusBlock,
2789  &FileStandardInfo,
2790  sizeof(FileStandardInfo),
2792  if (NT_SUCCESS(Status))
2793  {
2794  /* First, verify the checksum */
2796  ViewSize,
2797  FileStandardInfo.
2798  EndOfFile.LowPart))
2799  {
2800  /* Set checksum failure */
2802  goto Fail;
2803  }
2804 
2805  /* Make sure it's a real image */
2806  NtHeaders = RtlImageNtHeader(ViewBase);
2807  if (!NtHeaders)
2808  {
2809  /* Set checksum failure */
2811  goto Fail;
2812  }
2813 
2814  /* Make sure it's for the correct architecture */
2815  if ((NtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_NATIVE) ||
2817  {
2818  /* Set protection failure */
2820  goto Fail;
2821  }
2822 
2823  /* Check that it's a valid SMP image if we have more then one CPU */
2824  if (!MmVerifyImageIsOkForMpUse(ViewBase))
2825  {
2826  /* Otherwise it's not the right image */
2827  Status = STATUS_IMAGE_MP_UP_MISMATCH;
2828  }
2829  }
2830 
2831  /* Unmap the section, close the handle, and return status */
2832 Fail:
2833  ZwUnmapViewOfSection(NtCurrentProcess(), ViewBase);
2834  KeUnstackDetachProcess(&ApcState);
2835  ZwClose(SectionHandle);
2836  return Status;
2837 }
2838 
2839 NTSTATUS
2840 NTAPI
2842  IN PUNICODE_STRING NamePrefix OPTIONAL,
2843  IN PUNICODE_STRING LoadedName OPTIONAL,
2844  IN ULONG Flags,
2845  OUT PVOID *ModuleObject,
2846  OUT PVOID *ImageBaseAddress)
2847 {
2848  PVOID ModuleLoadBase = NULL;
2849  NTSTATUS Status;
2853  PIMAGE_NT_HEADERS NtHeader;
2854  UNICODE_STRING BaseName, BaseDirectory, PrefixName, UnicodeTemp;
2855  PLDR_DATA_TABLE_ENTRY LdrEntry = NULL;
2856  ULONG EntrySize, DriverSize;
2857  PLOAD_IMPORTS LoadedImports = MM_SYSLDR_NO_IMPORTS;
2858  PCHAR MissingApiName, Buffer;
2859  PWCHAR MissingDriverName;
2860  HANDLE SectionHandle;
2862  PVOID Section = NULL;
2863  BOOLEAN LockOwned = FALSE;
2864  PLIST_ENTRY NextEntry;
2865  IMAGE_INFO ImageInfo;
2866  STRING AnsiTemp;
2867  PAGED_CODE();
2868 
2869  /* Detect session-load */
2870  if (Flags)
2871  {
2872  /* Sanity checks */
2873  ASSERT(NamePrefix == NULL);
2874  ASSERT(LoadedName == NULL);
2875 
2876  /* Make sure the process is in session too */
2877  if (!PsGetCurrentProcess()->ProcessInSession) return STATUS_NO_MEMORY;
2878  }
2879 
2880  /* Allocate a buffer we'll use for names */
2882  if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
2883 
2884  /* Check for a separator */
2885  if (FileName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
2886  {
2887  PWCHAR p;
2888  ULONG BaseLength;
2889 
2890  /* Loop the path until we get to the base name */
2891  p = &FileName->Buffer[FileName->Length / sizeof(WCHAR)];
2892  while (*(p - 1) != OBJ_NAME_PATH_SEPARATOR) p--;
2893 
2894  /* Get the length */
2895  BaseLength = (ULONG)(&FileName->Buffer[FileName->Length / sizeof(WCHAR)] - p);
2896  BaseLength *= sizeof(WCHAR);
2897 
2898  /* Setup the string */
2899  BaseName.Length = (USHORT)BaseLength;
2900  BaseName.Buffer = p;
2901  }
2902  else
2903  {
2904  /* Otherwise, we already have a base name */
2905  BaseName.Length = FileName->Length;
2906  BaseName.Buffer = FileName->Buffer;
2907  }
2908 
2909  /* Setup the maximum length */
2910  BaseName.MaximumLength = BaseName.Length;
2911 
2912  /* Now compute the base directory */
2913  BaseDirectory = *FileName;
2914  BaseDirectory.Length -= BaseName.Length;
2915  BaseDirectory.MaximumLength = BaseDirectory.Length;
2916 
2917  /* And the prefix, which for now is just the name itself */
2918  PrefixName = *FileName;
2919 
2920  /* Check if we have a prefix */
2921  if (NamePrefix) DPRINT1("Prefixed images are not yet supported!\n");
2922 
2923  /* Check if we already have a name, use it instead */
2924  if (LoadedName) BaseName = *LoadedName;
2925 
2926  /* Check for loader snap debugging */
2928  {
2929  /* Print out standard string */
2930  DPRINT1("MM:SYSLDR Loading %wZ (%wZ) %s\n",
2931  &PrefixName, &BaseName, Flags ? "in session space" : "");
2932  }
2933 
2934  /* Acquire the load lock */
2935 LoaderScan:
2936  ASSERT(LockOwned == FALSE);
2937  LockOwned = TRUE;
2939  KeWaitForSingleObject(&MmSystemLoadLock,
2941  KernelMode,
2942  FALSE,
2943  NULL);
2944 
2945  /* Scan the module list */
2946  NextEntry = PsLoadedModuleList.Flink;
2947  while (NextEntry != &PsLoadedModuleList)
2948  {
2949  /* Get the entry and compare the names */
2950  LdrEntry = CONTAINING_RECORD(NextEntry,
2952  InLoadOrderLinks);
2953  if (RtlEqualUnicodeString(&PrefixName, &LdrEntry->FullDllName, TRUE))
2954  {
2955  /* Found it, break out */
2956  break;
2957  }
2958 
2959  /* Keep scanning */
2960  NextEntry = NextEntry->Flink;
2961  }
2962 
2963  /* Check if we found the image */
2964  if (NextEntry != &PsLoadedModuleList)
2965  {
2966  /* Check if we had already mapped a section */
2967  if (Section)
2968  {
2969  /* Dereference and clear */
2970  ObDereferenceObject(Section);
2971  Section = NULL;
2972  }
2973 
2974  /* Check if this was supposed to be a session load */
2975  if (!Flags)
2976  {
2977  /* It wasn't, so just return the data */
2978  *ModuleObject = LdrEntry;
2979  *ImageBaseAddress = LdrEntry->DllBase;
2980  Status = STATUS_IMAGE_ALREADY_LOADED;
2981  }
2982  else
2983  {
2984  /* We don't support session loading yet */
2985  UNIMPLEMENTED_DBGBREAK("Unsupported Session-Load!\n");
2986  Status = STATUS_NOT_IMPLEMENTED;
2987  }
2988 
2989  /* Do cleanup */
2990  goto Quickie;
2991  }
2992  else if (!Section)
2993  {
2994  /* It wasn't loaded, and we didn't have a previous attempt */
2995  KeReleaseMutant(&MmSystemLoadLock, 1, FALSE, FALSE);
2997  LockOwned = FALSE;
2998 
2999  /* Check if KD is enabled */
3001  {
3002  /* FIXME: Attempt to get image from KD */
3003  }
3004 
3005  /* We don't have a valid entry */
3006  LdrEntry = NULL;
3007 
3008  /* Setup image attributes */
3009  InitializeObjectAttributes(&ObjectAttributes,
3010  FileName,
3012  NULL,
3013  NULL);
3014 
3015  /* Open the image */
3016  Status = ZwOpenFile(&FileHandle,
3017  FILE_EXECUTE,
3018  &ObjectAttributes,
3019  &IoStatusBlock,
3021  0);
3022  if (!NT_SUCCESS(Status))
3023  {
3024  DPRINT1("ZwOpenFile failed for '%wZ' with status 0x%x\n",
3025  FileName, Status);
3026  goto Quickie;
3027  }
3028 
3029  /* Validate it */
3030  Status = MmCheckSystemImage(FileHandle, FALSE);
3031  if ((Status == STATUS_IMAGE_CHECKSUM_MISMATCH) ||
3032  (Status == STATUS_IMAGE_MP_UP_MISMATCH) ||
3033  (Status == STATUS_INVALID_IMAGE_PROTECT))
3034  {
3035  /* Fail loading */
3036  goto Quickie;
3037  }
3038 
3039  /* Check if this is a session-load */
3040  if (Flags)
3041  {
3042  /* Then we only need read and execute */
3043  DesiredAccess = SECTION_MAP_READ | SECTION_MAP_EXECUTE;
3044  }
3045  else
3046  {
3047  /* Otherwise, we can allow write access */
3048  DesiredAccess = SECTION_ALL_ACCESS;
3049  }
3050 
3051  /* Initialize the attributes for the section */
3052  InitializeObjectAttributes(&ObjectAttributes,
3053  NULL,
3055  NULL,
3056  NULL);
3057 
3058  /* Create the section */
3059  Status = ZwCreateSection(&SectionHandle,
3060  DesiredAccess,
3061  &ObjectAttributes,
3062  NULL,
3063  PAGE_EXECUTE,
3064  SEC_IMAGE,
3065  FileHandle);
3066  if (!NT_SUCCESS(Status))
3067  {
3068  DPRINT1("ZwCreateSection failed with status 0x%x\n", Status);
3069  goto Quickie;
3070  }
3071 
3072  /* Now get the section pointer */
3073  Status = ObReferenceObjectByHandle(SectionHandle,
3076  KernelMode,
3077  &Section,
3078  NULL);
3079  ZwClose(SectionHandle);
3080  if (!NT_SUCCESS(Status)) goto Quickie;
3081 
3082  /* Check if this was supposed to be a session-load */
3083  if (Flags)
3084  {
3085  /* We don't support session loading yet */
3086  UNIMPLEMENTED_DBGBREAK("Unsupported Session-Load!\n");
3087  goto Quickie;
3088  }
3089 
3090  /* Check the loader list again, we should end up in the path below */
3091  goto LoaderScan;
3092  }
3093  else
3094  {
3095  /* We don't have a valid entry */
3096  LdrEntry = NULL;
3097  }
3098 
3099  /* Load the image */
3100  Status = MiLoadImageSection(&Section,
3101  &ModuleLoadBase,
3102  FileName,
3103  FALSE,
3104  NULL);
3105  ASSERT(Status != STATUS_ALREADY_COMMITTED);
3106 
3107  /* Get the size of the driver */
3108  DriverSize = ((PROS_SECTION_OBJECT)Section)->ImageSection->ImageInformation.ImageFileSize;
3109 
3110  /* Make sure we're not being loaded into session space */
3111  if (!Flags)
3112  {
3113  /* Check for success */
3114  if (NT_SUCCESS(Status))
3115  {
3116  /* Support large pages for drivers */
3117  MiUseLargeDriverPage(DriverSize / PAGE_SIZE,
3118  &ModuleLoadBase,
3119  &BaseName,
3120  TRUE);
3121  }
3122 
3123  /* Dereference the section */
3124  ObDereferenceObject(Section);
3125  Section = NULL;
3126  }
3127 
3128  /* Check for failure of the load earlier */
3129  if (!NT_SUCCESS(Status))
3130  {
3131  DPRINT1("MiLoadImageSection failed with status 0x%x\n", Status);
3132  goto Quickie;
3133  }
3134 
3135  /* Relocate the driver */
3136  Status = LdrRelocateImageWithBias(ModuleLoadBase,
3137  0,
3138  "SYSLDR",
3142  if (!NT_SUCCESS(Status))
3143  {
3144  DPRINT1("LdrRelocateImageWithBias failed with status 0x%x\n", Status);
3145  goto Quickie;
3146  }
3147 
3148  /* Get the NT Header */
3149  NtHeader = RtlImageNtHeader(ModuleLoadBase);
3150 
3151  /* Calculate the size we'll need for the entry and allocate it */
3152  EntrySize = sizeof(LDR_DATA_TABLE_ENTRY) +
3153  BaseName.Length +
3154  sizeof(UNICODE_NULL);
3155 
3156  /* Allocate the entry */
3157  LdrEntry = ExAllocatePoolWithTag(NonPagedPool, EntrySize, TAG_MODULE_OBJECT);
3158  if (!LdrEntry)
3159  {
3160  /* Fail */
3162  goto Quickie;
3163  }
3164 
3165  /* Setup the entry */
3166  LdrEntry->Flags = LDRP_LOAD_IN_PROGRESS;
3167  LdrEntry->LoadCount = 1;
3168  LdrEntry->LoadedImports = LoadedImports;
3169  LdrEntry->PatchInformation = NULL;
3170 
3171  /* Check the version */
3172  if ((NtHeader->OptionalHeader.MajorOperatingSystemVersion >= 5) &&
3173  (NtHeader->OptionalHeader.MajorImageVersion >= 5))
3174  {
3175  /* Mark this image as a native image */
3176  LdrEntry->Flags |= LDRP_ENTRY_NATIVE;
3177  }
3178 
3179  /* Setup the rest of the entry */
3180  LdrEntry->DllBase = ModuleLoadBase;
3181  LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)ModuleLoadBase +
3183  LdrEntry->SizeOfImage = DriverSize;
3184  LdrEntry->CheckSum = NtHeader->OptionalHeader.CheckSum;
3185  LdrEntry->SectionPointer = Section;
3186 
3187  /* Now write the DLL name */
3188  LdrEntry->BaseDllName.Buffer = (PVOID)(LdrEntry + 1);
3189  LdrEntry->BaseDllName.Length = BaseName.Length;
3190  LdrEntry->BaseDllName.MaximumLength = BaseName.Length;
3191 
3192  /* Copy and null-terminate it */
3193  RtlCopyMemory(LdrEntry->BaseDllName.Buffer,
3194  BaseName.Buffer,
3195  BaseName.Length);
3196  LdrEntry->BaseDllName.Buffer[BaseName.Length / sizeof(WCHAR)] = UNICODE_NULL;
3197 
3198  /* Now allocate the full name */
3200  PrefixName.Length +
3201  sizeof(UNICODE_NULL),
3202  TAG_LDR_WSTR);
3203  if (!LdrEntry->FullDllName.Buffer)
3204  {
3205  /* Don't fail, just set it to zero */
3206  LdrEntry->FullDllName.Length = 0;
3207  LdrEntry->FullDllName.MaximumLength = 0;
3208  }
3209  else
3210  {
3211  /* Set it up */
3212  LdrEntry->FullDllName.Length = PrefixName.Length;
3213  LdrEntry->FullDllName.MaximumLength = PrefixName.Length;
3214 
3215  /* Copy and null-terminate */
3216  RtlCopyMemory(LdrEntry->FullDllName.Buffer,
3217  PrefixName.Buffer,
3218  PrefixName.Length);
3219  LdrEntry->FullDllName.Buffer[PrefixName.Length / sizeof(WCHAR)] = UNICODE_NULL;
3220  }
3221 
3222  /* Add the entry */
3223  MiProcessLoaderEntry(LdrEntry, TRUE);
3224 
3225  /* Resolve imports */
3226  MissingApiName = Buffer;
3227  MissingDriverName = NULL;
3228  Status = MiResolveImageReferences(ModuleLoadBase,
3229  &BaseDirectory,
3230  NULL,
3231  &MissingApiName,
3232  &MissingDriverName,
3233  &LoadedImports);
3234  if (!NT_SUCCESS(Status))
3235  {
3236  BOOLEAN NeedToFreeString = FALSE;
3237 
3238  /* If the lowest bit is set to 1, this is a hint that we need to free */
3239  if (*(ULONG_PTR*)&MissingDriverName & 1)
3240  {
3241  NeedToFreeString = TRUE;
3242  *(ULONG_PTR*)&MissingDriverName &= ~1;
3243  }
3244 
3245  DPRINT1("MiResolveImageReferences failed with status 0x%x\n", Status);
3246  DPRINT1(" Missing driver '%ls', missing API '%s'\n",
3247  MissingDriverName, MissingApiName);
3248 
3249  if (NeedToFreeString)
3250  {
3251  ExFreePoolWithTag(MissingDriverName, TAG_LDR_WSTR);
3252  }
3253 
3254  /* Fail */
3255  MiProcessLoaderEntry(LdrEntry, FALSE);
3256 
3257  /* Check if we need to free the name */
3258  if (LdrEntry->FullDllName.Buffer)
3259  {
3260  /* Free it */
3262  }
3263 
3264  /* Free the entry itself */
3266  LdrEntry = NULL;
3267  goto Quickie;
3268  }
3269 
3270  /* Update the loader entry */
3271  LdrEntry->Flags |= (LDRP_SYSTEM_MAPPED |
3273  LDRP_MM_LOADED);
3274  LdrEntry->Flags &= ~LDRP_LOAD_IN_PROGRESS;
3275  LdrEntry->LoadedImports = LoadedImports;
3276 
3277  /* FIXME: Call driver verifier's loader function */
3278 
3279  /* Write-protect the system image */
3281 
3282  /* Check if notifications are enabled */
3284  {
3285  /* Fill out the notification data */
3286  ImageInfo.Properties = 0;
3288  ImageInfo.SystemModeImage = TRUE;
3289  ImageInfo.ImageSize = LdrEntry->SizeOfImage;
3290  ImageInfo.ImageBase = LdrEntry->DllBase;
3291  ImageInfo.ImageSectionNumber = ImageInfo.ImageSelector = 0;
3292 
3293  /* Send the notification */
3294  PspRunLoadImageNotifyRoutines(FileName, NULL, &ImageInfo);
3295  }
3296 
3297 #if defined(KDBG) || defined(_WINKD_)
3298  /* MiCacheImageSymbols doesn't detect rossym */
3299  if (TRUE)
3300 #else
3301  /* Check if there's symbols */
3302  if (MiCacheImageSymbols(LdrEntry->DllBase))
3303 #endif
3304  {
3305  /* Check if the system root is present */
3306  if ((PrefixName.Length > (11 * sizeof(WCHAR))) &&
3307  !(_wcsnicmp(PrefixName.Buffer, L"\\SystemRoot", 11)))
3308  {
3309  /* Add the system root */
3310  UnicodeTemp = PrefixName;
3311  UnicodeTemp.Buffer += 11;
3312  UnicodeTemp.Length -= (11 * sizeof(WCHAR));
3313  sprintf_nt(Buffer,
3314  "%ws%wZ",
3315  &SharedUserData->NtSystemRoot[2],
3316  &UnicodeTemp);
3317  }
3318  else
3319  {
3320  /* Build the name */
3321  sprintf_nt(Buffer, "%wZ", &BaseName);
3322  }
3323 
3324  /* Setup the ansi string */
3325  RtlInitString(&AnsiTemp, Buffer);
3326 
3327  /* Notify the debugger */
3328  DbgLoadImageSymbols(&AnsiTemp,
3329  LdrEntry->DllBase,
3331  LdrEntry->Flags |= LDRP_DEBUG_SYMBOLS_LOADED;
3332  }
3333 
3334  /* Page the driver */
3335  ASSERT(Section == NULL);
3336  MiEnablePagingOfDriver(LdrEntry);
3337 
3338  /* Return pointers */
3339  *ModuleObject = LdrEntry;
3340  *ImageBaseAddress = LdrEntry->DllBase;
3341 
3342 Quickie:
3343  /* Check if we have the lock acquired */
3344  if (LockOwned)
3345  {
3346  /* Release the lock */
3347  KeReleaseMutant(&MmSystemLoadLock, 1, FALSE, FALSE);
3349  LockOwned = FALSE;
3350  }
3351 
3352  /* If we have a file handle, close it */
3353  if (FileHandle) ZwClose(FileHandle);
3354 
3355  /* Check if we had a prefix (not supported yet - PrefixName == *FileName now) */
3356  /* if (NamePrefix) ExFreePool(PrefixName.Buffer); */
3357 
3358  /* Free the name buffer and return status */
3360  return Status;
3361 }
3362 
3364 NTAPI
3366 {
3367  PLDR_DATA_TABLE_ENTRY LdrEntry, FoundEntry = NULL;
3368  PLIST_ENTRY NextEntry;
3369  PAGED_CODE();
3370 
3371  /* Loop entries */
3372  NextEntry = PsLoadedModuleList.Flink;
3373  do
3374  {
3375  /* Get the loader entry */
3376  LdrEntry = CONTAINING_RECORD(NextEntry,
3378  InLoadOrderLinks);
3379 
3380  /* Check if the address matches */
3381  if ((Address >= LdrEntry->DllBase) &&
3382  (Address < (PVOID)((ULONG_PTR)LdrEntry->DllBase +
3383  LdrEntry->SizeOfImage)))
3384  {
3385  /* Found a match */
3386  FoundEntry = LdrEntry;
3387  break;
3388  }
3389 
3390  /* Move on */
3391  NextEntry = NextEntry->Flink;
3392  } while(NextEntry != &PsLoadedModuleList);
3393 
3394  /* Return the entry */
3395  return FoundEntry;
3396 }
3397 
3398 /* PUBLIC FUNCTIONS ***********************************************************/
3399 
3400 /*
3401  * @implemented
3402  */
3403 PVOID
3404 NTAPI
3405 MmPageEntireDriver(IN PVOID AddressWithinSection)
3406 {
3407  PMMPTE StartPte, EndPte;
3408  PLDR_DATA_TABLE_ENTRY LdrEntry;
3409  PAGED_CODE();
3410 
3411  /* Get the loader entry */
3412  LdrEntry = MiLookupDataTableEntry(AddressWithinSection);
3413  if (!LdrEntry) return NULL;
3414 
3415  /* Check if paging of kernel mode is disabled or if the driver is mapped as an image */
3416  if ((MmDisablePagingExecutive) || (LdrEntry->SectionPointer))
3417  {
3418  /* Don't do anything, just return the base address */
3419  return LdrEntry->DllBase;
3420  }
3421 
3422  /* Wait for active DPCs to finish before we page out the driver */
3424 
3425  /* Get the PTE range for the whole driver image */
3426  StartPte = MiAddressToPte((ULONG_PTR)LdrEntry->DllBase);
3427  EndPte = MiAddressToPte((ULONG_PTR)LdrEntry->DllBase + LdrEntry->SizeOfImage);
3428 
3429  /* Enable paging for the PTE range */
3430  ASSERT(MI_IS_SESSION_IMAGE_ADDRESS(AddressWithinSection) == FALSE);
3431  MiSetPagingOfDriver(StartPte, EndPte);
3432 
3433  /* Return the base address */
3434  return LdrEntry->DllBase;
3435 }
3436 
3437 /*
3438  * @unimplemented
3439  */
3440 VOID
3441 NTAPI
3442 MmResetDriverPaging(IN PVOID AddressWithinSection)
3443 {
3444  UNIMPLEMENTED;
3445 }
3446 
3447 /*
3448  * @implemented
3449  */
3450 PVOID
3451 NTAPI
3453 {
3454  PVOID ProcAddress = NULL;
3455  ANSI_STRING AnsiRoutineName;
3456  NTSTATUS Status;
3457  PLIST_ENTRY NextEntry;
3458  PLDR_DATA_TABLE_ENTRY LdrEntry;
3459  BOOLEAN Found = FALSE;
3460  UNICODE_STRING KernelName = RTL_CONSTANT_STRING(L"ntoskrnl.exe");
3462  ULONG Modules = 0;
3463 
3464  /* Convert routine to ansi name */
3465  Status = RtlUnicodeStringToAnsiString(&AnsiRoutineName,
3466  SystemRoutineName,
3467  TRUE);
3468  if (!NT_SUCCESS(Status)) return NULL;
3469 
3470  /* Lock the list */
3473 
3474  /* Loop the loaded module list */
3475  NextEntry = PsLoadedModuleList.Flink;
3476  while (NextEntry != &PsLoadedModuleList)
3477  {
3478  /* Get the entry */
3479  LdrEntry = CONTAINING_RECORD(NextEntry,
3481  InLoadOrderLinks);
3482 
3483  /* Check if it's the kernel or HAL */
3484  if (RtlEqualUnicodeString(&KernelName, &LdrEntry->BaseDllName, TRUE))
3485  {
3486  /* Found it */
3487  Found = TRUE;
3488  Modules++;
3489  }
3490  else if (RtlEqualUnicodeString(&HalName, &LdrEntry->BaseDllName, TRUE))
3491  {
3492  /* Found it */
3493  Found = TRUE;
3494  Modules++;
3495  }
3496 
3497  /* Check if we found a valid binary */
3498  if (Found)
3499  {
3500  /* Find the procedure name */
3501  ProcAddress = MiFindExportedRoutineByName(LdrEntry->DllBase,
3502  &AnsiRoutineName);
3503 
3504  /* Break out if we found it or if we already tried both modules */
3505  if (ProcAddress) break;
3506  if (Modules == 2) break;
3507  }
3508 
3509  /* Keep looping */
3510  NextEntry = NextEntry->Flink;
3511  }
3512 
3513  /* Release the lock */
3516 
3517  /* Free the string and return */
3518  RtlFreeAnsiString(&AnsiRoutineName);
3519  return ProcAddress;
3520 }
3521 
3522 /* EOF */
DWORD *typedef PVOID
Definition: winlogon.h:52
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define LDRP_LOAD_IN_PROGRESS
Definition: ldrtypes.h:40
NTSTATUS NTAPI MmCallDllInitialize(IN PLDR_DATA_TABLE_ENTRY LdrEntry, IN PLIST_ENTRY ListHead)
Definition: sysldr.c:309
#define STATUS_SUCCESS
Definition: contextmenu.cpp:55
union _IMAGE_THUNK_DATA32::@1903 u1
#define LDRP_ENTRY_PROCESSED
Definition: ldrtypes.h:42
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
ERESOURCE PsLoadedModuleResource
Definition: sysldr.c:37
VOID NTAPI MiInitializePfn(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified)
Definition: pfnlist.c:969
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define IN
Definition: typedefs.h:39
VOID NTAPI MiProcessLoaderEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry, IN BOOLEAN Insert)
Definition: sysldr.c:565
#define max(a, b)
Definition: svc.c:63
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint 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 GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble const GLfloat const GLdouble const GLfloat GLenum GLint GLint GLint GLint GLint GLint j
Definition: glfuncs.h:98
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
KAPC_STATE
Definition: ketypes.h:1258
PVOID ULONG Address
Definition: oprghdlr.h:14
PMMPTE MiKernelResourceEndPte
Definition: sysldr.c:49
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
ULONG_PTR MmPoolCodeStart
Definition: sysldr.c:50
PLDR_DATA_TABLE_ENTRY Entry[1]
Definition: ldrtypes.h:171
NTSTATUS NTAPI MmUnloadSystemImage(IN PVOID ImageHandle)
Definition: sysldr.c:911
union _IMAGE_SECTION_HEADER::@1388 Misc
NTSTATUS(NTAPI * PMM_DLL_INITIALIZE)(_In_ PUNICODE_STRING RegistryPath)
Definition: iotypes.h:2489
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
ULONG ImageAddressingMode
Definition: pstypes.h:200
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: bidi.c:75
VOID NTAPI MiWriteProtectSystemImage(IN PVOID ImageBase)
Definition: sysldr.c:2392
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
ULONG PFN_COUNT
Definition: mmtypes.h:102
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
ULONG_PTR PsNtosImageBase
Definition: sysldr.c:38
LIST_ENTRY PsLoadedModuleList
Definition: sysldr.c:34
__wchar_t WCHAR
Definition: xmlstorage.h:180
PMMPTE NTAPI MiReserveSystemPtes(IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:246
#define MI_IS_SESSION_ADDRESS(Address)
Definition: miarm.h:138
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
ULONG ImageSelector
Definition: pstypes.h:208
#define CR4_PSE
Definition: ketypes.h:88
VOID NTAPI INIT_FUNCTION MiFindInitializationCode(OUT PVOID *StartVa, OUT PVOID *EndVa)
Definition: sysldr.c:1450
PVOID ImageBase
Definition: pstypes.h:207
IN OUT PIRP IN ULONG IN WMIENABLEDISABLECONTROL Function
Definition: wmilib.h:37
PFN_NUMBER MmTotalSystemDriverPages
Definition: sysldr.c:41
char CHAR
Definition: xmlstorage.h:175
LIST_ENTRY MiLargePageDriverList
Definition: largepag.c:26
ULONG NTAPI MiComputeDriverProtection(IN BOOLEAN SessionSpace, IN ULONG SectionProtection)
Definition: sysldr.c:2334
SIZE_T ImageSize
Definition: pstypes.h:209
ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes]
Definition: syspte.c:25
struct _LOAD_IMPORTS * PLOAD_IMPORTS
#define MM_SYSLDR_SINGLE_ENTRY
Definition: miarm.h:174
VOID NTAPI MiSetPagingOfDriver(IN PMMPTE PointerPte, IN PMMPTE LastPte)
Definition: sysldr.c:2582
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2327
ULONG_PTR MmPoolCodeEnd
Definition: sysldr.c:50
NTSTATUS NTAPI MiDereferenceImports(IN PLOAD_IMPORTS ImportList)
Definition: sysldr.c:395
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
#define MM_READWRITE
Definition: miarm.h:49
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:209
VOID NTAPI INIT_FUNCTION MiUpdateThunks(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PVOID OldBase, IN PVOID NewBase, IN ULONG Size)
Definition: sysldr.c:592
#define IMAGE_SCN_MEM_READ
Definition: ntimage.h:240
ULONG SizeOfImage
Definition: ldrtypes.h:141
#define MM_NOACCESS
Definition: miarm.h:67
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
#define STATUS_DRIVER_ORDINAL_NOT_FOUND
Definition: ntstatus.h:721
#define snprintf
Definition: wintirpc.h:48
USHORT Modified
Definition: mm.h:292
#define FLG_ENABLE_KDEBUG_SYMBOL_LOAD
Definition: pstypes.h:74
Definition: strmini.h:380
ULONG KeFeatureBits
Definition: krnlinit.c:22
struct _IMAGE_IMPORT_BY_NAME * PIMAGE_IMPORT_BY_NAME
#define TAG_LDR_IMPORTS
Definition: tag.h:111
VOID NTAPI INIT_FUNCTION MiLocateKernelSections(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: sysldr.c:2127
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:267
uint16_t * PWCHAR
Definition: typedefs.h:55
NTSTATUS(NTAPI * PMM_DLL_UNLOAD)(VOID)
Definition: iotypes.h:2493
IN POBJECT_ATTRIBUTES PortAttributes IN ACCESS_MASK DesiredAccess
Definition: creport.c:28
#define InsertTailList(ListHead, Entry)
#define LDRP_DRIVER_DEPENDENT_DLL
Definition: ldrtypes.h:54
#define WCHAR
Definition: msvc.h:43
_In_ UCHAR EntrySize
Definition: iofuncs.h:640
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
PVOID NTAPI MiCacheImageSymbols(IN PVOID BaseAddress)
Definition: sysldr.c:57
VOID NTAPI MiClearImports(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: sysldr.c:470
BOOLEAN NTAPI LdrVerifyMappedImageMatchesChecksum(_In_ PVOID BaseAddress, _In_ SIZE_T NumberOfBytes, _In_ ULONG FileLength)
UNICODE_STRING BaseName
Definition: miarm.h:375
#define MAXIMUM_FILENAME_LENGTH
Definition: env_spec_w32.h:41
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
#define FILE_SHARE_READ
Definition: compat.h:125
KSPIN_LOCK PsLoadedModuleSpinLock
Definition: sysldr.c:36
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
Definition: fs_rec.h:186
#define STATUS_DRIVER_ENTRYPOINT_NOT_FOUND
Definition: ntstatus.h:722
DWORD AddressOfNameOrdinals
Definition: compat.h:155
WORD MajorOperatingSystemVersion
Definition: ntddk_ex.h:160
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
uint32_t ULONG_PTR
Definition: typedefs.h:64
NTSTRSAFEAPI RtlStringCbCopyA(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:163
#define STATUS_ALREADY_COMMITTED
Definition: ntstatus.h:256
#define ERROR_FATAL(...)
Definition: debug.h:237
#define OBJ_NAME_PATH_SEPARATOR
Definition: nt_native.h:1240
ULONG_PTR MmPteCodeStart
Definition: sysldr.c:51
#define KF_LARGE_PAGE
Definition: ketypes.h:148
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
PVOID DllBase
Definition: ldrtypes.h:139
VOID NTAPI MmFreeDriverInitialization(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: sysldr.c:1615
PMM_IMAGE_SECTION_OBJECT ImageSection
Definition: mm.h:198
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:329
VOID NTAPI MiFreeInitializationCode(IN PVOID InitStart, IN PVOID InitEnd)
Definition: sysldr.c:1427
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1293
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
GLenum GLclampf GLint i
Definition: glfuncs.h:14
#define MiAddressToPte(x)
Definition: mmx86.c:19
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:388
ULONG PFN_NUMBER
Definition: ke.h:8
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define va_end(ap)
Definition: acmsvcex.h:90
#define TAG_LDR_WSTR
Definition: tag.h:110
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:914
#define UNICODE_NULL
#define ANSI_NULL
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:649
ULONG_PTR ShareCount
Definition: mm.h:322
#define IMAGE_FIRST_SECTION(NtHeader)
Definition: ntimage.h:427
PVOID NTAPI MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName)
Definition: sysldr.c:3452
long LONG
Definition: pedump.c:60
LIST_ENTRY MmLoadedUserImageList
Definition: sysldr.c:35
#define _SEH2_END
Definition: pseh2_64.h:7
PVOID EntryPoint
Definition: ntddk_ex.h:207
PWCHAR HalName
Definition: halacpi.c:45
_Check_return_ _CRTIMP int __cdecl _strnicmp(_In_reads_or_z_(_MaxCount) const char *_Str1, _In_reads_or_z_(_MaxCount) const char *_Str2, _In_ size_t _MaxCount)
#define ERROR_DBGBREAK(...)
Definition: debug.h:220
union Alignment_ Alignment
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:251
#define STATUS_IMAGE_MP_UP_MISMATCH
Definition: ntstatus.h:703
MMSUPPORT MmSystemCacheWs
Definition: init.c:55
smooth NULL
Definition: ftsmooth.c:513
PVOID FORCEINLINE MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:185
BOOLEAN KdDebuggerEnabled
Definition: kdmain.c:16
#define PAGE_EXECUTE
Definition: nt_native.h:1306
char * va_list
Definition: acmsvcex.h:78
void DPRINT(...)
Definition: polytest.cpp:61
_Check_return_ _CRTIMP _CONST_RETURN wchar_t *__cdecl wcsrchr(_In_z_ const wchar_t *_Str, _In_ wchar_t _Ch)
FORCEINLINE VOID MiUnlockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1247
Definition: bufpool.h:45
struct _FileName FileName
ULONG_PTR MmPteCodeEnd
Definition: sysldr.c:51
#define MI_SET_USAGE(x)
Definition: mm.h:253
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSTATUS NTAPI MmMapViewOfSection(IN PVOID SectionObject, IN PEPROCESS Process, 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:4491
Definition: miarm.h:372
IMAGE_FILE_HEADER FileHeader
Definition: ntddk_ex.h:183
#define InterlockedExchangeAdd
Definition: interlocked.h:181
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER SectionOffset
Definition: mmfuncs.h:404
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define STATUS_IMAGE_CHECKSUM_MISMATCH
Definition: ntstatus.h:663
UINTN Size
Definition: acefiex.h:550
#define MM_ZERO_ACCESS
Definition: miarm.h:45
#define UNIMPLEMENTED_DBGBREAK(...)
Definition: debug.h:226
PVOID PatchInformation
Definition: ldrtypes.h:162
#define STATUS_INVALID_IMAGE_PROTECT
Definition: ntstatus.h:526
USHORT MaximumLength
Definition: env_spec_w32.h:377
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
#define PDE_MAPPED_VA
Definition: miarm.h:20
VOID NTAPI DbgUnLoadImageSymbols(_In_ PSTRING Name, _In_ PVOID Base, _In_ ULONG_PTR ProcessId)
NTSTATUS NTAPI MmUnmapViewOfSection(IN PEPROCESS Process, IN PVOID BaseAddress)
Definition: section.c:3049
unsigned char BOOLEAN
static VOID sprintf_nt(IN PCHAR Buffer, IN PCHAR Format, IN...)
Definition: sysldr.c:22
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
ULONG SystemModeImage
Definition: pstypes.h:201
ULONG_PTR ExPoolCodeStart
Definition: sysldr.c:50
PVOID MmUnloadedDrivers
Definition: sysldr.c:43
#define STATUS_INVALID_IMAGE_FORMAT
Definition: ntstatus.h:345
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
union _MMPFN::@1577 u2
#define MM_EXECUTE
Definition: miarm.h:47
if(!(yy_init))
Definition: macro.lex.yy.c:704
BOOLEAN NTAPI INIT_FUNCTION MiInitializeLoadedModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: sysldr.c:2188
BOOLEAN PsImageNotifyEnabled
Definition: psnotify.c:18
#define LDRP_ENTRY_NATIVE
Definition: ldrtypes.h:55
NTSTATUS NTAPI MiLoadImageSection(IN OUT PVOID *SectionPtr, OUT PVOID *ImageBase, IN PUNICODE_STRING FileName, IN BOOLEAN SessionLoad, IN PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: sysldr.c:84
PVOID LoadedImports
Definition: ldrtypes.h:159
NTSTATUS NTAPI MmCheckSystemImage(IN HANDLE ImageHandle, IN BOOLEAN PurgeSection)
Definition: sysldr.c:2728
struct _LDR_DATA_TABLE_ENTRY LDR_DATA_TABLE_ENTRY
ULONG64 Valid
Definition: mmtypes.h:150
ULONG CheckSum
Definition: ntddk_ex.h:218
#define MAX_PATH
Definition: compat.h:26
PVOID NTAPI MmPageEntireDriver(IN PVOID AddressWithinSection)
Definition: sysldr.c:3405
#define LDRP_DEBUG_SYMBOLS_LOADED
Definition: ldrtypes.h:48
unsigned short * PUSHORT
Definition: retypes.h:2
struct _ROS_SECTION_OBJECT * PROS_SECTION_OBJECT
NTSYSAPI VOID NTAPI RtlFreeAnsiString(PANSI_STRING AnsiString)
void(* Func)(int)
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
BOOLEAN MiLargePageAllDrivers
Definition: largepag.c:27
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:75
#define PAGED_CODE()
Definition: video.h:57
MMPTE ValidKernelPte
Definition: init.c:31
POBJECT_TYPE MmSectionObjectType
Definition: section.c:136
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
KMUTANT MmSystemLoadLock
Definition: sysldr.c:39
UINTN VOID * Buffer
Definition: acefiex.h:370
VOID NTAPI MmResetDriverPaging(IN PVOID AddressWithinSection)
Definition: sysldr.c:3442
Definition: strmini.h:378
PVOID MmLastUnloadedDrivers
Definition: sysldr.c:44
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
LONG NTAPI KeReleaseMutant(IN PKMUTANT Mutant, IN KPRIORITY Increment, IN BOOLEAN Abandon, IN BOOLEAN Wait)
Definition: mutex.c:98
BOOLEAN NTAPI MmVerifyImageIsOkForMpUse(IN PVOID BaseAddress)
Definition: sysldr.c:2704
std::wstring STRING
Definition: fontsub.cpp:33
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
FORCEINLINE VOID PspRunLoadImageNotifyRoutines(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INFO ImageInfo)
Definition: ps_x.h:84
_In_ PUNICODE_STRING Name
Definition: mrx.h:218
#define IMAGE_SCN_MEM_WRITE
Definition: ntimage.h:241
NTSYSAPI NTSTATUS NTAPI ZwOpenFile(_Out_ PHANDLE FileHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG ShareAccess, _In_ ULONG OpenOptions)
#define SharedUserData
#define BYTES_TO_PAGES(Size)
#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH
Definition: ntstatus.h:128
ULONG_PTR ExPoolCodeEnd
Definition: sysldr.c:50
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define RtlImageDirectoryEntryToData
Definition: compat.h:460
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
#define IMAGE_FILE_UP_SYSTEM_ONLY
Definition: pedump.c:170
NTSTATUS NTAPI MiResolveImageReferences(IN PVOID ImageBase, IN PUNICODE_STRING ImageFileDirectory, IN PUNICODE_STRING NamePrefix OPTIONAL, OUT PCHAR *MissingApi, OUT PWCHAR *MissingDriver, OUT PLOAD_IMPORTS *LoadImports)
Definition: sysldr.c:1000
#define SECTION_MAP_READ
Definition: compat.h:128
#define FILE_EXECUTE
Definition: nt_native.h:642
#define KeEnterCriticalRegion()
Definition: ke_x.h:83
Definition: mm.h:305
Definition: ntddk_ex.h:202
NTSTATUS NTAPI MmLoadSystemImage(IN PUNICODE_STRING FileName, IN PUNICODE_STRING NamePrefix OPTIONAL, IN PUNICODE_STRING LoadedName OPTIONAL, IN ULONG Flags, OUT PVOID *ModuleObject, OUT PVOID *ImageBaseAddress)
Definition: sysldr.c:2841
ULONG ExpInitializationPhase
Definition: init.c:65
NTSTATUS NTAPI INIT_FUNCTION MiBuildImportsForBootDrivers(VOID)
Definition: sysldr.c:1862
ULONG ImageSectionNumber
Definition: pstypes.h:210
GLenum GLsizei len
Definition: glext.h:6722
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:118
_In_ ULONG _In_ BOOLEAN _Must_inspect_result_ PVOID * VirtualAddress
Definition: ndis.h:3772
KPROCESS Pcb
Definition: pstypes.h:1194
BOOLEAN NTAPI MiCallDllUnloadAndUnloadDll(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: sysldr.c:370
ACPI_EFI_HANDLE ACPI_EFI_DEVICE_PATH VOID UINTN ACPI_EFI_HANDLE * ImageHandle
Definition: acefiex.h:463
__INTRIN_INLINE unsigned long __readcr4(void)
Definition: intrin_x86.h:1608
#define MM_SYSLDR_BOOT_LOADED
Definition: miarm.h:172
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
#define IMAGE_DIRECTORY_ENTRY_IAT
Definition: pedump.c:271
#define IMAGE_DIRECTORY_ENTRY_EXPORT
Definition: compat.h:140
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:877
CCHAR KeNumberProcessors
Definition: krnlinit.c:35
NTSYSAPI VOID NTAPI RtlInitString(PSTRING DestinationString, PCSZ SourceString)
SIZE_T Count
Definition: ldrtypes.h:170
Status
Definition: gdiplustypes.h:24
#define MM_SYSLDR_NO_IMPORTS
Definition: miarm.h:171
#define MM_EXECUTE_READWRITE
Definition: miarm.h:51
LIST_ENTRY InLoadOrderLinks
Definition: ldrtypes.h:136
PFN_COUNT NTAPI MiDeleteSystemPageableVm(IN PMMPTE PointerPte, IN PFN_NUMBER PageCount, IN ULONG Flags, OUT PPFN_NUMBER ValidPages)
Definition: virtual.c:297
Definition: hiveinit.c:368
PVOID SectionPointer
Definition: ntddk_ex.h:217
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:475
static HANDLE FileHandle
Definition: cabinet.c:47
ULONG_PTR SIZE_T
Definition: typedefs.h:79
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define NT_SUCCESS(StatCode)
Definition: cmd.c:149
DWORD *typedef HANDLE
Definition: winlogon.h:52
LONG NTSTATUS
Definition: DriverTester.h:11
#define KeLeaveCriticalRegion()
Definition: ke_x.h:114
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
LOGICAL NTAPI MiUseLargeDriverPage(IN ULONG NumberOfPtes, IN OUT PVOID *ImageBaseAddress, IN PUNICODE_STRING BaseImageName, IN BOOLEAN BootDriver)
Definition: sysldr.c:2277
NTSYSAPI ULONG NTAPI LdrRelocateImageWithBias(_In_ PVOID NewAddress, _In_ LONGLONG AdditionalBias, _In_ PCCH LoaderName, _In_ ULONG Success, _In_ ULONG Conflict, _In_ ULONG Invalid)
#define IMAGE_SNAP_BY_ORDINAL(Ordinal)
Definition: ntimage.h:567
BOOLEAN MmEnforceWriteProtection
Definition: sysldr.c:47
#define ROUND_TO_PAGES(Size)
unsigned short USHORT
Definition: pedump.c:61
#define IMAGE_DIRECTORY_ENTRY_DEBUG
Definition: compat.h:141
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:701
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
int __cdecl vsprintf(char *_Dest, const char *_Format, va_list _Args)
Definition: sprintf.c:733
static ULONG Delta
Definition: xboxvideo.c:28
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
#define _SEH2_TRY
Definition: pseh2_64.h:5
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1415
UNICODE_STRING FullDllName
Definition: ldrtypes.h:142
UNICODE_STRING BaseDllName
Definition: ldrtypes.h:143
USHORT Rom
Definition: mm.h:300
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
#define va_start(ap, A)
Definition: acmsvcex.h:91
HANDLE NTAPI PsGetCurrentProcessId(VOID)
Definition: process.c:1123
#define IMAGE_DIRECTORY_ENTRY_BASERELOC
Definition: pedump.c:264
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define STATUS_PROCEDURE_NOT_FOUND
Definition: ntstatus.h:344
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]
Definition: pedump.c:281
KIRQL FASTCALL KeAcquireSpinLockRaiseToSynch(PKSPIN_LOCK SpinLock)
Definition: spinlock.c:62
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
VOID NTAPI DbgLoadImageSymbols(_In_ PSTRING Name, _In_ PVOID Base, _In_ ULONG_PTR ProcessId)
#define IMAGE_NT_OPTIONAL_HDR_MAGIC
Definition: ntimage.h:387
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define DPRINT1
Definition: precomp.h:8
#define RtlImageNtHeader
Definition: compat.h:457
PVOID NTAPI MiLocateExportName(IN PVOID DllBase, IN PCHAR ExportName)
Definition: sysldr.c:232
#define IMAGE_DIRECTORY_ENTRY_IMPORT
Definition: pedump.c:260
BOOLEAN MmMakeLowMemory
Definition: sysldr.c:46
#define MI_IS_SESSION_IMAGE_ADDRESS(Address)
Definition: miarm.h:135
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
signed char * PCHAR
Definition: retypes.h:7
VOID NTAPI MiEnablePagingOfDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: sysldr.c:2637
SECTION_IMAGE_INFORMATION ImageInformation
Definition: mm.h:182
void int int ULONGLONG int va_list * ap
Definition: winesup.h:32
#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
#define TAG_MODULE_OBJECT
Definition: tag.h:109
ULONG Flags
Definition: ntddk_ex.h:211
union _MMPFN::@1578 u3
ULONG ERESOURCE
Definition: env_spec_w32.h:594
unsigned int ULONG
Definition: retypes.h:1
#define SECTION_MAP_EXECUTE
Definition: nt_native.h:1290
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define IMAGE_FILE_RELOCS_STRIPPED
Definition: pedump.c:159
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define UNIMPLEMENTED
Definition: debug.h:114
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
uint32_t * PULONG_PTR
Definition: typedefs.h:64
#define SEC_IMAGE
Definition: mmtypes.h:96
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
VOID NTAPI MiSetSystemCodeProtection(IN PMMPTE FirstPte, IN PMMPTE LastPte, IN ULONG ProtectionMask)
Definition: sysldr.c:2382
#define MM_READONLY
Definition: miarm.h:46
#define IMAGE_ADDRESSING_MODE_32BIT
Definition: pstypes.h:194
#define __FUNCTION__
Definition: compiler.h:205
static BOOLEAN LoadSymbols
Definition: kdb_symbols.c:29
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
PVOID NTAPI MiFindExportedRoutineByName(IN PVOID DllBase, IN PANSI_STRING ExportName)
Definition: sysldr.c:490
union _MMPTE::@2063 u
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1097
#define IMAGE_ORDINAL(Ordinal)
Definition: pedump.c:337
FORCEINLINE VOID MiLockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1203
GLfloat GLfloat p
Definition: glext.h:8902
UCHAR MmDisablePagingExecutive
Definition: mminit.c:30
#define STATUS_CONFLICTING_ADDRESSES
Definition: ntstatus.h:247
ULONG NtGlobalFlag
Definition: init.c:51
VOID NTAPI INIT_FUNCTION MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: sysldr.c:1673
FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
Definition: miarm.h:900
signed int * PLONG
Definition: retypes.h:5
PMMPTE MiKernelResourceStartPte
Definition: sysldr.c:49
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define LDRP_MM_LOADED
Definition: ldrtypes.h:58
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define PFN_FROM_PTE(v)
Definition: mm.h:82
VOID NTAPI KeFlushQueuedDpcs(VOID)
Definition: dpc.c:918
#define MmSystemRangeStart
Definition: mm.h:25
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
IN HDEVINFO IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
Definition: devinst.c:44
BOOLEAN KdDebuggerNotPresent
Definition: kdmain.c:18
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define STATUS_NOT_FOUND
Definition: udferr_usr.h:181
PLDR_DATA_TABLE_ENTRY NTAPI MiLookupDataTableEntry(IN PVOID Address)
Definition: sysldr.c:3365
ULONG Properties
Definition: pstypes.h:198
CHAR MI_PFN_CURRENT_PROCESS_NAME[16]
Definition: pfnlist.c:64
USHORT LoadCount
Definition: ntddk_ex.h:212
#define FLG_SHOW_LDR_SNAPS
Definition: pstypes.h:57
NTSTATUS NTAPI MiSnapThunk(IN PVOID DllBase, IN PVOID ImageBase, IN PIMAGE_THUNK_DATA Name, IN PIMAGE_THUNK_DATA Address, IN PIMAGE_EXPORT_DIRECTORY ExportDirectory, IN ULONG ExportSize, IN BOOLEAN SnapForwarder, OUT PCHAR *MissingApi)
Definition: sysldr.c:691
#define IMAGE_SCN_MEM_EXECUTE
Definition: ntimage.h:239
#define STATUS_IMAGE_ALREADY_LOADED
Definition: ntstatus.h:492
#define INIT_FUNCTION
Definition: ntoskrnl.h:11
#define LDRP_SYSTEM_MAPPED
Definition: ldrtypes.h:52
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define IMAGE_SCN_MEM_DISCARDABLE
Definition: ntimage.h:235