more work on loader
[reactos.git] / reactos / ntoskrnl / ldr / loader.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ldr/loader.c
5 * PURPOSE: Loaders for PE executables
6 * PROGRAMMERS: Jean Michault
7 * Rex Jolliff (rex@lvcablemodem.com)
8 * UPDATE HISTORY:
9 * DW 22/05/98 Created
10 * RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE
11 * RJJ 10/12/98 Built driver loader function and added hooks for PE/COFF
12 * RJJ 10/12/98 Rolled in David's code to load COFF drivers
13 * JM 14/12/98 Built initail PE user module loader
14 */
15
16 /* INCLUDES *****************************************************************/
17
18 #include <internal/i386/segment.h>
19 #include <internal/kernel.h>
20 #include <internal/linkage.h>
21 #include <internal/module.h>
22 #include <internal/ob.h>
23 #include <internal/string.h>
24 #include <internal/symbol.h>
25
26 #include <ddk/ntddk.h>
27
28 //#define NDEBUG
29 #include <internal/debug.h>
30
31 /* MACROS ********************************************************************/
32
33 /* GLOBALS *******************************************************************/
34
35 POBJECT_TYPE ObModuleType = NULL;
36
37 /* FORWARD DECLARATIONS ******************************************************/
38
39 NTSTATUS LdrProcessDriver(PVOID ModuleLoadBase);
40
41 /* PE Driver load support */
42 static NTSTATUS LdrPEProcessDriver(PVOID ModuleLoadBase);
43
44 /* COFF Driver load support */
45 static NTSTATUS LdrCOFFProcessDriver(PVOID ModuleLoadBase);
46 static BOOLEAN LdrCOFFDoRelocations(module *Module, unsigned int SectionIndex);
47 static BOOLEAN LdrCOFFDoAddr32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation);
48 static BOOLEAN LdrCOFFDoReloc32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation);
49 static void LdrCOFFGetSymbolName(module *Module, unsigned int Idx, char *Name);
50 static unsigned int LdrCOFFGetSymbolValue(module *Module, unsigned int Idx);
51 static unsigned int LdrCOFFGetKernelSymbolAddr(char *Name);
52 static unsigned int LdrCOFFGetSymbolValueByName(module *Module, char *SymbolName, unsigned int Idx);
53
54 /* Image loader forward delcarations */
55 static NTSTATUS LdrProcessMZImage(HANDLE ProcessHandle, HANDLE ModuleHandle, HANDLE FileHandle);
56 static NTSTATUS LdrProcessPEImage(HANDLE ProcessHandle, HANDLE ModuleHandle, HANDLE FileHandle);
57 static NTSTATUS LdrProcessBinImage(HANDLE ProcessHandle, HANDLE ModuleHandle, HANDLE FileHandle);
58
59 /* FUNCTIONS *****************************************************************/
60
61 VOID LdrInitModuleManagment(VOID)
62 {
63 ANSI_STRING AnsiString;
64
65 /* Register the process object type */
66 ObModuleType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
67 ObModuleType->TotalObjects = 0;
68 ObModuleType->TotalHandles = 0;
69 ObModuleType->MaxObjects = ULONG_MAX;
70 ObModuleType->MaxHandles = ULONG_MAX;
71 ObModuleType->PagedPoolCharge = 0;
72 ObModuleType->NonpagedPoolCharge = sizeof(MODULE);
73 ObModuleType->Dump = NULL;
74 ObModuleType->Open = NULL;
75 ObModuleType->Close = NULL;
76 ObModuleType->Delete = NULL;
77 ObModuleType->Parse = NULL;
78 ObModuleType->Security = NULL;
79 ObModuleType->QueryName = NULL;
80 ObModuleType->OkayToClose = NULL;
81 RtlInitAnsiString(&AnsiString, "Module");
82 RtlAnsiStringToUnicodeString(&ObModuleType->TypeName, &AnsiString, TRUE);
83 }
84
85 /*
86 * FUNCTION: Loads a kernel driver
87 * ARGUMENTS:
88 * FileName = Driver to load
89 * RETURNS: Status
90 */
91
92 NTSTATUS
93 LdrLoadDriver(PUNICODE_STRING Filename)
94 {
95 PVOID ModuleLoadBase;
96 NTSTATUS Status;
97 HANDLE FileHandle;
98 OBJECT_ATTRIBUTES FileObjectAttributes;
99 FILE_STANDARD_INFORMATION FileStdInfo;
100
101 DbgPrint("Loading Driver %W...\n", Filename);
102
103 /* Open the Driver */
104 InitializeObjectAttributes(&FileObjectAttributes,
105 Filename,
106 0,
107 NULL,
108 NULL);
109 CHECKPOINT;
110 Status = ZwOpenFile(&FileHandle,
111 FILE_ALL_ACCESS,
112 &FileObjectAttributes,
113 NULL, 0, 0);
114 CHECKPOINT;
115 if (!NT_SUCCESS(Status))
116 {
117 return Status;
118 }
119 CHECKPOINT;
120
121 /* Get the size of the file */
122 Status = ZwQueryInformationFile(FileHandle,
123 NULL,
124 &FileStdInfo,
125 sizeof(FileStdInfo),
126 FileStandardInformation);
127 if (!NT_SUCCESS(Status))
128 {
129 return Status;
130 }
131 CHECKPOINT;
132
133 /* Allocate nonpageable memory for driver */
134 ModuleLoadBase = ExAllocatePool(NonPagedPool,
135 GET_LARGE_INTEGER_LOW_PART(FileStdInfo.EndOfFile));
136 if (ModuleLoadBase == NULL)
137 {
138 return STATUS_INSUFFICIENT_RESOURCES;
139 }
140 CHECKPOINT;
141
142 /* Load driver into memory chunk */
143 Status = ZwReadFile(FileHandle,
144 0, 0, 0, 0,
145 ModuleLoadBase,
146 GET_LARGE_INTEGER_LOW_PART(FileStdInfo.EndOfFile),
147 0, 0);
148 if (!NT_SUCCESS(Status))
149 {
150 ExFreePool(ModuleLoadBase);
151 return Status;
152 }
153 CHECKPOINT;
154
155 ZwClose(FileHandle);
156
157 Status = LdrProcessDriver(ModuleLoadBase);
158
159 /* Cleanup */
160 ExFreePool(ModuleLoadBase);
161
162 return STATUS_SUCCESS;
163 }
164
165 NTSTATUS
166 LdrProcessDriver(PVOID ModuleLoadBase)
167 {
168 PIMAGE_DOS_HEADER PEDosHeader;
169
170 /* If MZ header exists */
171 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
172 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
173 {
174 return LdrPEProcessDriver(ModuleLoadBase);
175 }
176 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC)
177 {
178 return STATUS_NOT_IMPLEMENTED;
179 }
180 else /* Assume COFF format and load */
181 {
182 return LdrCOFFProcessDriver(ModuleLoadBase);
183 }
184 }
185
186 NTSTATUS
187 LdrPEProcessDriver(PVOID ModuleLoadBase)
188 {
189 unsigned int DriverSize, Idx;
190 long int RelocDelta, NumRelocs;
191 PVOID DriverBase, RelocBase;
192 PULONG PEMagic;
193 PIMAGE_DOS_HEADER PEDosHeader;
194 PIMAGE_FILE_HEADER PEFileHeader;
195 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
196 PIMAGE_SECTION_HEADER PESectionHeaders;
197 PRELOCATION_DIRECTORY RelocDir;
198 PRELOCATION_ENTRY RelocEntry;
199
200 DPRINT("Processing PE Driver at module base:%08lx\n", ModuleLoadBase);
201
202 /* Get header pointers */
203 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
204 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
205 PEDosHeader->e_lfanew);
206 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
207 PEDosHeader->e_lfanew + sizeof(ULONG));
208 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
209 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
210 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
211 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
212 sizeof(IMAGE_OPTIONAL_HEADER));
213 CHECKPOINT;
214
215 /* Check file magic numbers */
216 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
217 {
218 DPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
219 return STATUS_UNSUCCESSFUL;
220 }
221 if (PEDosHeader->e_lfanew == 0)
222 {
223 DPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
224 return STATUS_UNSUCCESSFUL;
225 }
226 if (*PEMagic != IMAGE_PE_MAGIC)
227 {
228 DPRINT("Incorrect PE magic: %08x\n", *PEMagic);
229 return STATUS_UNSUCCESSFUL;
230 }
231 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
232 {
233 DPRINT("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
234 return STATUS_UNSUCCESSFUL;
235 }
236 CHECKPOINT;
237
238 /* FIXME: if image is fixed-address load, then fail */
239
240 /* FIXME: check/verify OS version number */
241
242 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
243 PEOptionalHeader->Magic,
244 PEOptionalHeader->MajorLinkerVersion,
245 PEOptionalHeader->MinorLinkerVersion);
246 DPRINT("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
247 CHECKPOINT;
248
249 /* Determine the size of the module */
250 DPRINT("Sections: (section align:%08lx)\n",
251 PEOptionalHeader->SectionAlignment);
252 DriverSize = 0;
253 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
254 {
255 DPRINT("Name: %-8.8s VA:%08lx RawSize:%6d Offset:%08lx CHAR:%08lx OfsAdr: %08lx\n",
256 PESectionHeaders[Idx].Name,
257 PESectionHeaders[Idx].VirtualAddress,
258 PESectionHeaders[Idx].SizeOfRawData,
259 PESectionHeaders[Idx].PointerToRawData,
260 PESectionHeaders[Idx].Characteristics,
261 DriverSize);
262 DriverSize += ROUND_UP(PESectionHeaders[Idx].SizeOfRawData,
263 PEOptionalHeader->SectionAlignment);
264 }
265 DPRINT("DriverSize computed by using section headers: %d(%08lx)\n",
266 DriverSize,
267 DriverSize);
268
269 #if 0
270 /* Allocate a virtual section for the module */
271 DriverBase = MmAllocateSection(DriverSize);
272 if (DriverBase == 0)
273 {
274 DbgPrint("Failed to allocate a virtual section for driver\n");
275 return STATUS_INSUFFICIENT_RESOURCES;
276 }
277 CHECKPOINT;
278
279 CurrentBase = ModuleLoadBase;
280 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
281 {
282 /* Copy current section into current offset of virtual section */
283 if (PESectionHeaders[Idx].Characteristics &
284 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
285 {
286 memcpy(CurrentBase,
287 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
288 PESectionHeaders[Idx].SizeOfRawData);
289 }
290 else
291 {
292 memset(CurrentBase, '\0', PESectionHeaders[Idx].SizeOfRawData);
293 }
294 CurrentSize += ROUND_UP(PESectionHeaders[Idx].SizeOfRawData,
295 PEOptionalHeader->SectionAlignment);
296 }
297
298 #else
299 DriverBase = ModuleLoadBase;
300 #endif
301
302 /* FIXME: Perform relocation fixups */
303 RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase;
304 RelocDir = (PRELOCATION_DIRECTORY) ((DWORD)ModuleLoadBase +
305 PEOptionalHeader->DataDirectory[
306 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
307 DPRINT("Relocs: ModuleLoadBase: %08lx RelocDelta %08lx\n",
308 ModuleLoadBase,
309 RelocDelta);
310 while (RelocDir->SizeOfBlock != 0)
311 {
312 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
313 sizeof(WORD);
314 DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
315 RelocDir,
316 RelocDir->VirtualAddress,
317 NumRelocs);
318 RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir +
319 sizeof(RELOCATION_DIRECTORY));
320 for (Idx = 0; Idx < NumRelocs; Idx++)
321 {
322 DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
323 DriverBase + RelocDir->VirtualAddress +
324 (RelocEntry[Idx].TypeOffset & 0x0fff),
325 (RelocEntry[Idx].TypeOffset >> 12) & 0xf,
326 (RelocEntry[Idx].TypeOffset >> 12) & 0xf ? "HIGHLOW" : "ABS",
327 *(PDWORD)((DWORD) DriverBase + RelocDir->VirtualAddress +
328 (RelocEntry[Idx].TypeOffset & 0x0fff)),
329 (*(PDWORD)((DWORD) DriverBase + RelocDir->VirtualAddress +
330 (RelocEntry[Idx].TypeOffset & 0x0fff))) + RelocDelta);
331 }
332 RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
333 RelocDir->SizeOfBlock);
334 getchar();
335 }
336
337 #if 0
338
339 /* FIXME: perform import fixups */
340 /* FIXME: compute address of entry point */
341
342 #endif
343
344 /* return InitializeLoadedDriver(EntryPoint); */
345 return STATUS_NOT_IMPLEMENTED;
346 }
347
348 NTSTATUS
349 LdrCOFFProcessDriver(PVOID ModuleLoadBase)
350 {
351 BOOLEAN FoundEntry;
352 char SymbolName[255];
353 int i;
354 ULONG EntryOffset;
355 FILHDR *FileHeader;
356 AOUTHDR *AOUTHeader;
357 module *Module;
358 PDRIVER_INITIALIZE EntryRoutine;
359
360 /* Get header pointers */
361 FileHeader = ModuleLoadBase;
362 AOUTHeader = ModuleLoadBase + FILHSZ;
363 CHECKPOINT;
364
365 /* Check COFF magic value */
366 if (I386BADMAG(*FileHeader))
367 {
368 DbgPrint("Module has bad magic value (%x)\n",
369 FileHeader->f_magic);
370 return STATUS_UNSUCCESSFUL;
371 }
372 CHECKPOINT;
373
374 /* Allocate and initialize a module definition structure */
375 Module = (module *) ExAllocatePool(NonPagedPool, sizeof(module));
376 if (Module == NULL)
377 {
378 return STATUS_INSUFFICIENT_RESOURCES;
379 }
380 Module->sym_list = (SYMENT *)(ModuleLoadBase + FileHeader->f_symptr);
381 Module->str_tab = (char *)(ModuleLoadBase + FileHeader->f_symptr +
382 FileHeader->f_nsyms * SYMESZ);
383 Module->scn_list = (SCNHDR *)(ModuleLoadBase + FILHSZ +
384 FileHeader->f_opthdr);
385 Module->size = 0;
386 Module->raw_data_off = (ULONG) ModuleLoadBase;
387 Module->nsyms = FileHeader->f_nsyms;
388 CHECKPOINT;
389
390 /* Determine the length of the module */
391 for (i = 0; i < FileHeader->f_nscns; i++)
392 {
393 DPRINT("Section name: %.8s\n", Module->scn_list[i].s_name);
394 DPRINT("size %x vaddr %x size %x\n",
395 Module->size,
396 Module->scn_list[i].s_vaddr,
397 Module->scn_list[i].s_size);
398 if (Module->scn_list[i].s_flags & STYP_TEXT)
399 {
400 Module->text_base = Module->scn_list[i].s_vaddr;
401 }
402 if (Module->scn_list[i].s_flags & STYP_DATA)
403 {
404 Module->data_base = Module->scn_list[i].s_vaddr;
405 }
406 if (Module->scn_list[i].s_flags & STYP_BSS)
407 {
408 Module->bss_base = Module->scn_list[i].s_vaddr;
409 }
410 if (Module->size <
411 (Module->scn_list[i].s_vaddr + Module->scn_list[i].s_size))
412 {
413 Module->size = Module->size + Module->scn_list[i].s_vaddr +
414 Module->scn_list[i].s_size;
415 }
416 }
417 CHECKPOINT;
418
419 /* Allocate a section for the module */
420 Module->base = (unsigned int) MmAllocateSection(Module->size);
421 if (Module->base == 0)
422 {
423 DbgPrint("Failed to alloc section for module\n");
424 ExFreePool(Module);
425 return STATUS_INSUFFICIENT_RESOURCES;
426 }
427 CHECKPOINT;
428
429 /* Adjust section vaddrs for allocated area */
430 Module->data_base = Module->data_base + Module->base;
431 Module->text_base = Module->text_base + Module->base;
432 Module->bss_base = Module->bss_base + Module->base;
433
434 /* Relocate module and fixup imports */
435 for (i = 0; i < FileHeader->f_nscns; i++)
436 {
437 if (Module->scn_list[i].s_flags & STYP_TEXT ||
438 Module->scn_list[i].s_flags & STYP_DATA)
439 {
440 memcpy((PVOID)(Module->base + Module->scn_list[i].s_vaddr),
441 (PVOID)(ModuleLoadBase + Module->scn_list[i].s_scnptr),
442 Module->scn_list[i].s_size);
443 if (!LdrCOFFDoRelocations(Module, i))
444 {
445 DPRINT("Relocation failed for section %s\n",
446 Module->scn_list[i].s_name);
447
448 /* FIXME: unallocate all sections here */
449
450 ExFreePool(Module);
451
452 return STATUS_UNSUCCESSFUL;
453 }
454 }
455 if (Module->scn_list[i].s_flags & STYP_BSS)
456 {
457 memset((PVOID)(Module->base + Module->scn_list[i].s_vaddr),
458 0,
459 Module->scn_list[i].s_size);
460 }
461 }
462
463 DbgPrint("Module base: %x\n", Module->base);
464
465 /* Find the entry point */
466 EntryOffset = 0L;
467 FoundEntry = FALSE;
468 for (i = 0; i < FileHeader->f_nsyms; i++)
469 {
470 LdrCOFFGetSymbolName(Module, i, SymbolName);
471 if (!strcmp(SymbolName, "_DriverEntry"))
472 {
473 EntryOffset = Module->sym_list[i].e_value;
474 FoundEntry = TRUE;
475 DPRINT("Found entry at %x\n", EntryOffset);
476 }
477 }
478 if (!FoundEntry)
479 {
480 DbgPrint("No module entry point defined\n");
481 ExFreePool(Module);
482
483 /* FIXME: unallocate all sections here */
484
485 return STATUS_UNSUCCESSFUL;
486 }
487
488 /* Get the address of the module initalization routine */
489 EntryRoutine = (PDRIVER_INITIALIZE)(Module->base + EntryOffset);
490
491 /* Cleanup */
492 ExFreePool(Module);
493
494 return InitalizeLoadedDriver(EntryRoutine);
495 }
496
497 /* LdrCOFFDoRelocations
498 * FUNCTION: Do the relocations for a module section
499 * ARGUMENTS:
500 * Module = Pointer to the module
501 * SectionIndex = Index of the section to be relocated
502 * RETURNS: Success or failure
503 */
504
505 static BOOLEAN
506 LdrCOFFDoRelocations(module *Module, unsigned int SectionIndex)
507 {
508 SCNHDR *Section = &Module->scn_list[SectionIndex];
509 RELOC *Relocation = (RELOC *)(Module->raw_data_off + Section->s_relptr);
510 int j;
511
512 DPRINT("SectionIndex %d Name %.8s Relocs %d\n",
513 SectionIndex,
514 Module->scn_list[SectionIndex].s_name,
515 Section->s_nreloc);
516
517 for (j = 0; j < Section->s_nreloc; j++)
518 {
519 DPRINT("vaddr %x symndex %x",
520 Relocation->r_vaddr,
521 Relocation->r_symndx);
522
523 switch (Relocation->r_type)
524 {
525 case RELOC_ADDR32:
526 if (!LdrCOFFDoAddr32Reloc(Module, Section, Relocation))
527 {
528 return FALSE;
529 }
530 break;
531
532 case RELOC_REL32:
533 if (!LdrCOFFDoReloc32Reloc(Module, Section, Relocation))
534 {
535 return FALSE;
536 }
537 break;
538
539 default:
540 DPRINT("%.8s: Unknown relocation type %x at %d in module\n",
541 Module->scn_list[SectionIndex].s_name,
542 Relocation->r_type,
543 j);
544 return FALSE;
545 }
546 Relocation++;
547 }
548 DPRINT("%.8s: relocations done\n", Module->scn_list[SectionIndex].s_name);
549
550 return TRUE;
551 }
552
553 /*
554 * FUNCTION: Performs a addr32 relocation on a loaded module
555 * ARGUMENTS:
556 * mod = module to perform the relocation on
557 * scn = Section to perform the relocation in
558 * reloc = Pointer to a data structure describing the relocation
559 * RETURNS: Success or failure
560 * NOTE: This fixes up a relocation needed when changing the base address of a
561 * module
562 */
563
564 static BOOLEAN
565 LdrCOFFDoAddr32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation)
566 {
567 unsigned int Value;
568 unsigned int *Location;
569
570 Value = LdrCOFFGetSymbolValue(Module, Relocation->r_symndx);
571 Location = (unsigned int *)(Module->base + Relocation->r_vaddr);
572 DPRINT("ADDR32 loc %x value %x *loc %x\n", Location, Value, *Location);
573 *Location = (*Location) + Module->base;
574
575 return TRUE;
576 }
577
578 /*
579 * FUNCTION: Performs a reloc32 relocation on a loaded module
580 * ARGUMENTS:
581 * mod = module to perform the relocation on
582 * scn = Section to perform the relocation in
583 * reloc = Pointer to a data structure describing the relocation
584 * RETURNS: Success or failure
585 * NOTE: This fixes up an undefined reference to a kernel function in a module
586 */
587
588 static BOOLEAN
589 LdrCOFFDoReloc32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation)
590 {
591 char Name[255];
592 unsigned int Value;
593 unsigned int *Location;
594
595 memset(Name, 0, 255);
596 LdrCOFFGetSymbolName(Module, Relocation->r_symndx, Name);
597 Value = (unsigned int) LdrCOFFGetKernelSymbolAddr(Name);
598 if (Value == 0L)
599 {
600 Value = LdrCOFFGetSymbolValueByName(Module, Name, Relocation->r_symndx);
601 if (Value == 0L)
602 {
603 DbgPrint("Undefined symbol %s in module\n", Name);
604 return FALSE;
605 }
606 Location = (unsigned int *)(Module->base + Relocation->r_vaddr);
607 // (*Location) = (*Location) + Value + Module->base - Section->s_vaddr;
608 (*Location) = (*Location);
609 DPRINT("Module->base %x Section->s_vaddr %x\n",
610 Module->base,
611 Section->s_vaddr);
612 }
613 else
614 {
615 DPRINT("REL32 value %x name %s\n", Value, Name);
616 Location = (unsigned int *)(Module->base + Relocation->r_vaddr);
617 DPRINT("old %x ", *Location);
618 DPRINT("Module->base %x Section->s_vaddr %x\n",
619 Module->base,
620 Section->s_vaddr);
621 (*Location) = (*Location) + Value - Module->base + Section->s_vaddr;
622 DPRINT("new %x\n", *Location);
623 }
624
625 return TRUE;
626 }
627
628 /*
629 * FUNCTION: Get the name of a symbol from a loaded module by ordinal
630 * ARGUMENTS:
631 * mod = module
632 * i = index of symbol
633 * name (OUT) = pointer to a string where the symbol name will be
634 * stored
635 */
636
637 static void
638 LdrCOFFGetSymbolName(module *Module, unsigned int Idx, char *Name)
639 {
640 if (Module->sym_list[Idx].e.e_name[0] != 0)
641 {
642 strncpy(Name, Module->sym_list[Idx].e.e_name, 8);
643 Name[8] = '\0';
644 }
645 else
646 {
647 strcpy(Name, &Module->str_tab[Module->sym_list[Idx].e.e.e_offset]);
648 }
649 }
650
651 /*
652 * FUNCTION: Get the value of a module defined symbol
653 * ARGUMENTS:
654 * mod = module
655 * i = index of symbol
656 * RETURNS: The value of the symbol
657 * NOTE: This fixes up references to known sections
658 */
659
660 static unsigned int
661 LdrCOFFGetSymbolValue(module *Module, unsigned int Idx)
662 {
663 char Name[255];
664
665 LdrCOFFGetSymbolName(Module, Idx, Name);
666 DPRINT("name %s ", Name);
667
668 /* Check if the symbol is a section we have relocated */
669 if (strcmp(Name, ".text") == 0)
670 {
671 return Module->text_base;
672 }
673 if (strcmp(Name, ".data") == 0)
674 {
675 return Module->data_base;
676 }
677 if (strcmp(Name, ".bss") == 0)
678 {
679 return Module->bss_base;
680 }
681
682 return Module->sym_list[Idx].e_value;
683 }
684
685 /*
686 * FUNCTION: Get the address of a kernel symbol
687 * ARGUMENTS:
688 * name = symbol name
689 * RETURNS: The address of the symbol on success
690 * NULL on failure
691 */
692
693 static unsigned int
694 LdrCOFFGetKernelSymbolAddr(char *Name)
695 {
696 int i = 0;
697
698 while (symbol_table[i].name != NULL)
699 {
700 if (strcmp(symbol_table[i].name, Name) == 0)
701 {
702 return symbol_table[i].value;
703 }
704 i++;
705 }
706
707 return 0L;
708 }
709
710 static unsigned int
711 LdrCOFFGetSymbolValueByName(module *Module,
712 char *SymbolName,
713 unsigned int Idx)
714 {
715 unsigned int i;
716 char Name[255];
717
718 DPRINT("LdrCOFFGetSymbolValueByName(sname %s, idx %x)\n", SymbolName, Idx);
719
720 for (i = 0; i < Module->nsyms; i++)
721 {
722 LdrCOFFGetSymbolName(Module, i, Name);
723 DPRINT("Scanning %s Value %x\n", Name, Module->sym_list[i].e_value);
724 if (strcmp(Name, SymbolName) == 0)
725 {
726 DPRINT("Returning %x\n", Module->sym_list[i].e_value);
727 return Module->sym_list[i].e_value;
728 }
729 }
730
731 return 0L;
732 }
733
734 NTSTATUS LdrLoadLibrary(HANDLE ProcessHandle,
735 PHANDLE ModuleHandle,
736 PCHAR Name)
737 {
738 #if 0
739 NTSTATUS Status;
740 ANSI_STRING afilename;
741 UNICODE_STRING ufilename,umodName;
742 PMODULE *Library, *Module;
743 OBJECT_ATTRIBUTES attr;
744 PWSTR Ignored;
745 char name2[512];
746
747 /* FIXME: this is broke */
748 /* FIXME: check for module already loaded */
749 /* FIXME: otherwise load module */
750 /* FIXME: we need to fix how modules are loaded so that they can
751 be shared... :( */
752
753 /* If module is already loaded, get a reference and return it */
754 strcpy(name2, "\\modules\\");
755 strcat(name2, Name);
756 RtlInitAnsiString(&afilename, name2);
757 RtlAnsiStringToUnicodeString(&umodName, &afilename, TRUE);
758 InitializeObjectAttributes(&attr, &umodName, 0, NULL, NULL);
759 Status = ObOpenObjectByName(&attr, (PVOID *) &Library, &Ignored);
760 DPRINT("LoadLibrary : Status=%x,pLibrary=%x\n",Status, Library);
761 if (!NT_SUCCESS(Status) || Library == NULL)
762 {
763 strcpy(name2, "\\??\\C:\\reactos\\system\\");
764 strcat(name2, name);
765 RtlInitAnsiString(&afilename, name2);
766 RtlAnsiStringToUnicodeString(&ufilename, &afilename, TRUE);
767 DPRINT("LoadLibrary,load %s\n", name2);
768 Library = LdrLoadImage(&ufilename);
769 /* FIXME: execute start code ? */
770 Module = ObGenericCreateObject(NULL, PROCESS_ALL_ACCESS, &attr, ObModuleType);
771 if (Module)
772 {
773 memcpy(Module, Library, PMODULE);
774 }
775 else
776 {
777 DbgPrint("library object not created\n");
778 }
779 RtlFreeUnicodeString(&ufilename);
780 Status = ObOpenObjectByName(&attr, (PVOID *)&Library, &Ignored);
781 }
782 else
783 {
784 DPRINT("Library already loaded\n");
785 *Module = Library
786 }
787 RtlFreeUnicodeString(&umodName);
788
789 return STATUS_SUCCESS;
790 #endif
791 UNIMPLEMENTED;
792 }
793
794 /* LdrLoadImage
795 * FUNCTION:
796 * Loads a module into the specified process
797 * ARGUMENTS:
798 * HANDLE ProcessHandle handle of the process to load the module into
799 * PHANDLE ModuleHandle handle of the loaded module
800 * PUNICODE_STRING Filename name of the module to load
801 * RETURNS:
802 * NTSTATUS
803 */
804
805 NTSTATUS
806 LdrLoadImage(HANDLE ProcessHandle,
807 PHANDLE ModuleHandle,
808 PUNICODE_STRING Filename)
809 {
810 char BlockBuffer[1024];
811 NTSTATUS Status;
812 OBJECT_ATTRIBUTES FileObjectAttributes;
813 HANDLE FileHandle;
814 PMODULE Module;
815 PIMAGE_DOS_HEADER PEDosHeader;
816
817 /* FIXME: should DLLs be named sections? */
818
819 /* Open the image file */
820 InitializeObjectAttributes(&FileObjectAttributes,
821 Filename,
822 0,
823 NULL,
824 NULL);
825 Status = ZwOpenFile(&FileHandle, 0, &FileObjectAttributes, NULL, 0, 0);
826 if (!NT_SUCCESS(Status))
827 {
828 return Status;
829 }
830
831 /* Build a module structure for the image */
832 Module = ObGenericCreateObject(ModuleHandle,
833 PROCESS_ALL_ACCESS,
834 NULL,
835 ObModuleType);
836 if (Module == NULL)
837 {
838 ZwClose(FileHandle);
839 return Status;
840 }
841
842 /* Read first block of image to determine type */
843 Status = ZwReadFile(FileHandle, 0, 0, 0, 0, BlockBuffer, 1024, 0, 0);
844 if (!NT_SUCCESS(Status))
845 {
846 ObDereferenceObject(*ModuleHandle);
847 *ModuleHandle = NULL;
848 ZwClose(FileHandle);
849
850 return Status;
851 }
852
853 /* If MZ header exists */
854 PEDosHeader = (PIMAGE_DOS_HEADER) BlockBuffer;
855 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC &&
856 PEDosHeader->e_lfanew != 0L &&
857 *(PULONG)((PUCHAR)BlockBuffer + PEDosHeader->e_lfanew) == IMAGE_PE_MAGIC)
858 {
859 Status = LdrProcessPEImage(ProcessHandle,
860 ModuleHandle,
861 FileHandle);
862 }
863 else if (PEDosHeader->e_magic == 0x54AD)
864 {
865 Status = LdrProcessMZImage(ProcessHandle,
866 ModuleHandle,
867 FileHandle);
868 }
869 else /* Assume bin format and load */
870 {
871 Status = LdrProcessBinImage(ProcessHandle,
872 ModuleHandle,
873 FileHandle);
874 }
875 /* FIXME: {else} could check for a.out, ELF, COFF, etc. images here... */
876
877 /* FIXME: should we unconditionally dereference the module handle here? */
878 if (!NT_SUCCESS(Status))
879 {
880 ObDereferenceObject(*ModuleHandle);
881 *ModuleHandle = NULL;
882 }
883 ZwClose(FileHandle);
884
885 return Status;
886 }
887
888 static NTSTATUS
889 LdrProcessMZImage(HANDLE ProcessHandle,
890 HANDLE ModuleHandle,
891 HANDLE FileHandle)
892 {
893
894 /* FIXME: map VDM into low memory */
895 /* FIXME: Build/Load image sections */
896
897 return STATUS_NOT_IMPLEMENTED;
898 }
899
900 static NTSTATUS
901 LdrProcessPEImage(HANDLE ProcessHandle,
902 HANDLE ModuleHandle,
903 HANDLE FileHandle)
904 {
905 int i;
906 NTSTATUS Status;
907 PVOID BaseSection;
908 PIMAGE_DOS_HEADER DosHeader;
909 PIMAGE_NT_HEADERS NTHeaders;
910 PMODULE Module;
911 LARGE_INTEGER SectionOffset;
912
913 /* Allocate memory for headers */
914 Module = HEADER_TO_BODY(ModuleHandle);
915 if (Module == NULL)
916 {
917 return STATUS_UNSUCCESSFUL;
918 }
919 DosHeader = (PIMAGE_DOS_HEADER)ExAllocatePool(NonPagedPool,
920 sizeof(IMAGE_DOS_HEADER) +
921 sizeof(IMAGE_NT_HEADERS));
922 if (DosHeader == NULL)
923 {
924 return STATUS_UNSUCCESSFUL;
925 }
926 NTHeaders = (PIMAGE_NT_HEADERS)((PUCHAR) DosHeader + sizeof(IMAGE_DOS_HEADER));
927
928 /* Read the headers into memory */
929 memset(Module, '\0', sizeof(PMODULE));
930 Status = ZwReadFile(FileHandle,
931 NULL, NULL, NULL, NULL,
932 DosHeader,
933 sizeof(IMAGE_DOS_HEADER),
934 0, 0);
935 if (!NT_SUCCESS(Status))
936 {
937 ExFreePool(DosHeader);
938 return Status;
939 }
940 SET_LARGE_INTEGER_HIGH_PART(SectionOffset, 0);
941 SET_LARGE_INTEGER_LOW_PART(SectionOffset, DosHeader->e_lfanew);
942 Status = ZwReadFile(FileHandle,
943 NULL, NULL, NULL, NULL,
944 NTHeaders,
945 sizeof(IMAGE_NT_HEADERS),
946 &SectionOffset,
947 0);
948 if (!NT_SUCCESS(Status))
949 {
950 ExFreePool(DosHeader);
951 return Status;
952 }
953
954 /* Allocate memory in process for image */
955 Module->Flags = MODULE_FLAG_PE;
956 Module->Base = (PVOID) NTHeaders->OptionalHeader.ImageBase;
957 Module->Size = NTHeaders->OptionalHeader.SizeOfImage;
958 Status = ZwAllocateVirtualMemory(ProcessHandle,
959 &Module->Base,
960 0,
961 NULL,
962 MEM_COMMIT,
963 PAGE_READWRITE);
964 if (!NT_SUCCESS(Status))
965 {
966 ExFreePool(DosHeader);
967 return Status;
968 }
969
970 /* Load headers into virtual memory */
971 Status = ZwReadFile(FileHandle,
972 NULL, NULL, NULL, NULL,
973 Module->Base,
974 NTHeaders->OptionalHeader.SizeOfHeaders,
975 0, 0);
976 if (!NT_SUCCESS(Status))
977 {
978 ZwFreeVirtualMemory(ProcessHandle,
979 Module->Base,
980 0,
981 MEM_RELEASE);
982 ExFreePool(DosHeader);
983 return Status;
984 }
985
986 /* Adjust module pointers into virtual memory */
987 DosHeader = (PIMAGE_DOS_HEADER) Module->Base;
988 NTHeaders = (PIMAGE_NT_HEADERS) ((PUCHAR)Module->Base +
989 DosHeader->e_lfanew);
990 Module->Image.PE.FileHeader = (PIMAGE_FILE_HEADER) ((PUCHAR)NTHeaders +
991 sizeof(DWORD));
992 Module->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
993 ((PUCHAR)Module->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
994 Module->Image.PE.SectionList = (PCOFF_SECTION_HEADER) ((PUCHAR)NTHeaders +
995 sizeof(IMAGE_NT_HEADERS));
996
997 /* Build Image Sections */
998 /* FIXME: should probably use image directory to load sections. */
999 for (i = 0; i < Module->Image.PE.FileHeader->NumberOfSections; i++)
1000 {
1001 DPRINT("section %d\n", i);
1002 BaseSection = (PVOID)((PCHAR) Module->Base +
1003 Module->Image.PE.SectionList[i].s_vaddr);
1004
1005 /* Load code and initialized data sections from disk */
1006 if ((Module->Image.PE.SectionList[i].s_flags & STYP_TEXT) ||
1007 (Module->Image.PE.SectionList[i].s_flags & STYP_DATA))
1008 {
1009 SET_LARGE_INTEGER_HIGH_PART(SectionOffset, 0);
1010 SET_LARGE_INTEGER_LOW_PART(SectionOffset,
1011 Module->Image.PE.SectionList[i].s_scnptr);
1012
1013 /* FIXME: should probably map sections into sections */
1014 Status = ZwReadFile(FileHandle,
1015 NULL, NULL, NULL, NULL,
1016 Module->Base + Module->Image.PE.SectionList[i].s_vaddr,
1017 min(Module->Image.PE.SectionList[i].s_size,
1018 Module->Image.PE.SectionList[i].s_paddr),
1019 &SectionOffset, 0);
1020 if (!NT_SUCCESS(Status))
1021 {
1022 ZwFreeVirtualMemory(ProcessHandle,
1023 Module->Base,
1024 0,
1025 MEM_RELEASE);
1026 ExFreePool(DosHeader);
1027 return Status;
1028 }
1029 }
1030 else if (Module->Image.PE.SectionList[i].s_flags & STYP_BSS)
1031 {
1032 memset((PVOID)(Module->Base +
1033 Module->Image.PE.SectionList[i].s_vaddr),
1034 0,
1035 Module->Image.PE.SectionList[i].s_size);
1036 }
1037 }
1038
1039 /* Resolve Import Library references */
1040 if (Module->Image.PE.OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1041 {
1042 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1043
1044 /* Process each import module */
1045 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1046 ((PUCHAR)Module->Base + Module->Image.PE.OptionalHeader->
1047 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1048 while (ImportModuleDirectory->dwRVAModuleName)
1049 {
1050 PMODULE Library;
1051 PVOID *LibraryExports;
1052 PVOID *ImportAddressList; // was pImpAddr
1053 PULONG FunctionNameList;
1054 DWORD pName;
1055 PWORD pHint;
1056
1057 /* Load the library module into the process */
1058 /* FIXME: this should take a UNICODE string */
1059 Status = LdrLoadLibrary(ProcessHandle,
1060 &Library,
1061 (PCHAR)(Module->Base +
1062 ImportModuleDirectory->dwRVAModuleName));
1063 if (!NT_SUCCESS(Status))
1064 {
1065 /* FIXME: Dereference all loaded modules */
1066 ZwFreeVirtualMemory(ProcessHandle,
1067 Module->Base,
1068 0,
1069 MEM_RELEASE);
1070 ExFreePool(DosHeader);
1071
1072 return Status;
1073 }
1074
1075 /* Get the address of the export list for the library */
1076 LibraryExports = (PVOID *)(Library->Base +
1077 Library->Image.PE.OptionalHeader->
1078 DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress +
1079 sizeof(IMAGE_EXPORT_DIRECTORY));
1080
1081 /* Get the import address list */
1082 ImportAddressList = (PVOID *)
1083 ((PCHAR)Module->Image.PE.OptionalHeader->ImageBase +
1084 ImportModuleDirectory->dwRVAFunctionAddressList);
1085
1086 /* Get the list of functions to import */
1087 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1088 {
1089 FunctionNameList = (PULONG) ((PCHAR)Module->Base +
1090 ImportModuleDirectory->dwRVAFunctionNameList);
1091 }
1092 else
1093 {
1094 FunctionNameList = (PULONG) ((PCHAR)Module->Base +
1095 ImportModuleDirectory->dwRVAFunctionAddressList);
1096 }
1097
1098 /* Walk through function list and fixup addresses */
1099 while(*FunctionNameList != 0L)
1100 {
1101 if ((*FunctionNameList) & 0x80000000) // hint
1102 {
1103 *ImportAddressList = LibraryExports[(*FunctionNameList) & 0x7fffffff];
1104 }
1105 else // hint-name
1106 {
1107 pName = (DWORD)((PCHAR)Module->Base + *FunctionNameList + 2);
1108 pHint = (PWORD)((PCHAR)Module->Base + *FunctionNameList);
1109
1110 /* FIXME: verify name */
1111
1112 *ImportAddressList = LibraryExports[*pHint];
1113 }
1114
1115 /* FIXME: verify value of hint */
1116
1117 ImportAddressList++;
1118 FunctionNameList++;
1119 }
1120 ImportModuleDirectory++;
1121 }
1122 }
1123
1124 /* Do fixups */
1125 if (Module->Base != (PVOID)Module->Image.PE.OptionalHeader->ImageBase)
1126 {
1127 USHORT NumberOfEntries;
1128 PUSHORT pValue16;
1129 ULONG RelocationRVA;
1130 ULONG Delta32, Offset;
1131 PULONG pValue32;
1132 PRELOCATION_DIRECTORY RelocationDir;
1133 PRELOCATION_ENTRY RelocationBlock;
1134
1135 RelocationRVA = NTHeaders->OptionalHeader.DataDirectory[
1136 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
1137 if (RelocationRVA)
1138 {
1139 RelocationDir = (PRELOCATION_DIRECTORY)
1140 ((PCHAR)Module->Base + RelocationRVA);
1141 while (RelocationDir->SizeOfBlock)
1142 {
1143 Delta32 = (unsigned long)(Module->Base - NTHeaders->OptionalHeader.ImageBase);
1144 RelocationBlock = (PRELOCATION_ENTRY)
1145 (RelocationRVA + Module->Base + sizeof(RELOCATION_DIRECTORY));
1146 NumberOfEntries =
1147 (RelocationDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1148 sizeof(RELOCATION_ENTRY);
1149 for (i = 0; i < NumberOfEntries; i++)
1150 {
1151 Offset = (RelocationBlock[i].TypeOffset & 0xfff) + RelocationDir->VirtualAddress;
1152 switch (RelocationBlock[i].TypeOffset >> 12)
1153 {
1154 case TYPE_RELOC_ABSOLUTE:
1155 break;
1156
1157 case TYPE_RELOC_HIGH:
1158 pValue16 = (PUSHORT) (Module->Base + Offset);
1159 *pValue16 += Delta32 >> 16;
1160 break;
1161
1162 case TYPE_RELOC_LOW:
1163 pValue16 = (PUSHORT)(Module->Base + Offset);
1164 *pValue16 += Delta32 & 0xffff;
1165 break;
1166
1167 case TYPE_RELOC_HIGHLOW:
1168 pValue32 = (PULONG) (Module->Base + Offset);
1169 *pValue32 += Delta32;
1170 break;
1171
1172 case TYPE_RELOC_HIGHADJ:
1173 /* FIXME: do the highadjust fixup */
1174 DbgPrint("TYPE_RELOC_HIGHADJ fixup not implemented, sorry\n");
1175 // break;
1176
1177 default:
1178 DbgPrint("unexpected fixup type\n");
1179
1180 /* FIXME: Dereference all loaded modules */
1181
1182 ZwFreeVirtualMemory(ProcessHandle,
1183 Module->Base,
1184 0,
1185 MEM_RELEASE);
1186 ExFreePool(DosHeader);
1187 return STATUS_UNSUCCESSFUL;
1188 }
1189 }
1190 RelocationRVA += RelocationDir->SizeOfBlock;
1191 RelocationDir = (PRELOCATION_DIRECTORY)((PCHAR)Module->Base +
1192 RelocationRVA);
1193 }
1194 }
1195 }
1196
1197 /* FIXME: Create the stack for the process */
1198 /* FIXME: Setup the context for the initial thread */
1199 /* FIXME: Create the initial thread */
1200
1201 // fail: ZwFreeVirtualMemory(ProcessHandle, Module->ImageBase, 0, MEM_RELEASE);
1202 ExFreePool(DosHeader);
1203
1204 return STATUS_NOT_IMPLEMENTED;
1205 }
1206
1207 NTSTATUS
1208 LdrProcessBinImage(HANDLE ProcessHandle,
1209 HANDLE ModuleHandle,
1210 HANDLE FileHandle)
1211 {
1212 NTSTATUS Status;
1213 FILE_STANDARD_INFORMATION FileStdInfo;
1214 ULONG SectionSize;
1215 HANDLE ThreadHandle;
1216 CONTEXT Context;
1217 HANDLE SectionHandle;
1218 PVOID BaseAddress;
1219
1220 /* FIXME: should set module pointers */
1221
1222 /* Get the size of the file for the section */
1223 Status = ZwQueryInformationFile(FileHandle,
1224 NULL,
1225 &FileStdInfo,
1226 sizeof(FileStdInfo),
1227 FileStandardInformation);
1228 if (!NT_SUCCESS(Status))
1229 {
1230 return Status;
1231 }
1232
1233 /* Create the section for the code */
1234 Status = ZwCreateSection(&SectionHandle,
1235 SECTION_ALL_ACCESS,
1236 NULL,
1237 NULL,
1238 PAGE_READWRITE,
1239 MEM_COMMIT,
1240 FileHandle);
1241 if (!NT_SUCCESS(Status))
1242 {
1243 return Status;
1244 }
1245
1246 /* Map a view of the section into the desired process */
1247 BaseAddress = (PVOID)0x10000;
1248 SectionSize = GET_LARGE_INTEGER_LOW_PART(FileStdInfo.AllocationSize);
1249 Status = ZwMapViewOfSection(SectionHandle,
1250 ProcessHandle,
1251 &BaseAddress,
1252 0,
1253 SectionSize,
1254 NULL,
1255 &SectionSize,
1256 0,
1257 MEM_COMMIT,
1258 PAGE_READWRITE);
1259 if (!NT_SUCCESS(Status))
1260 {
1261 /* FIXME: destroy the section here */
1262 return Status;
1263 }
1264
1265 /* Setup the context for the initial thread */
1266 memset(&Context,0,sizeof(CONTEXT));
1267 Context.SegSs = USER_DS;
1268 Context.Esp = 0x2000;
1269 Context.EFlags = 0x202;
1270 Context.SegCs = USER_CS;
1271 Context.Eip = 0x10000;
1272 Context.SegDs = USER_DS;
1273 Context.SegEs = USER_DS;
1274 Context.SegFs = USER_DS;
1275 Context.SegGs = USER_DS;
1276
1277 /* Create the stack for the process */
1278 BaseAddress = (PVOID) 0x1000;
1279 SectionSize = 0x1000;
1280 Status = ZwAllocateVirtualMemory(ProcessHandle,
1281 &BaseAddress,
1282 0,
1283 &SectionSize,
1284 MEM_COMMIT,
1285 PAGE_READWRITE);
1286 if (!NT_SUCCESS(Status))
1287 {
1288 /* FIXME: unmap the section here */
1289 /* FIXME: destroy the section here */
1290
1291 return Status;
1292 }
1293
1294 /* Create the initial thread */
1295 Status = ZwCreateThread(&ThreadHandle,
1296 THREAD_ALL_ACCESS,
1297 NULL,
1298 ProcessHandle,
1299 NULL,
1300 &Context,
1301 NULL,
1302 FALSE);
1303 if (!NT_SUCCESS(Status))
1304 {
1305 /* FIXME: destroy the stack memory block here */
1306 /* FIXME: unmap the section here */
1307 /* FIXME: destroy the section here */
1308 return Status;
1309 }
1310
1311 return STATUS_SUCCESS;
1312 }
1313
1314