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)
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
16 /* INCLUDES *****************************************************************/
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>
26 #include <ddk/ntddk.h>
29 #include <internal/debug.h>
31 /* MACROS ********************************************************************/
33 /* GLOBALS *******************************************************************/
35 POBJECT_TYPE ObModuleType
= NULL
;
37 /* FORWARD DECLARATIONS ******************************************************/
39 NTSTATUS
LdrLoadDriver(PUNICODE_STRING Filename
);
40 NTSTATUS
LdrProcessDriver(PVOID ModuleLoadBase
);
42 /* PE Driver load support */
43 static NTSTATUS
LdrPEProcessDriver(PVOID ModuleLoadBase
);
44 static unsigned int LdrGetKernelSymbolAddr(char *Name
);
46 /* COFF Driver load support */
47 static NTSTATUS
LdrCOFFProcessDriver(PVOID ModuleLoadBase
);
48 static BOOLEAN
LdrCOFFDoRelocations(module
*Module
, unsigned int SectionIndex
);
49 static BOOLEAN
LdrCOFFDoAddr32Reloc(module
*Module
, SCNHDR
*Section
, RELOC
*Relocation
);
50 static BOOLEAN
LdrCOFFDoReloc32Reloc(module
*Module
, SCNHDR
*Section
, RELOC
*Relocation
);
51 static void LdrCOFFGetSymbolName(module
*Module
, unsigned int Idx
, char *Name
);
52 static unsigned int LdrCOFFGetSymbolValue(module
*Module
, unsigned int Idx
);
53 static unsigned int LdrCOFFGetSymbolValueByName(module
*Module
, char *SymbolName
, unsigned int Idx
);
55 /* Image loader forward delcarations */
56 static NTSTATUS
LdrProcessMZImage(HANDLE ProcessHandle
, HANDLE ModuleHandle
, HANDLE FileHandle
);
57 static NTSTATUS
LdrProcessPEImage(HANDLE ProcessHandle
, HANDLE ModuleHandle
, HANDLE FileHandle
);
58 static NTSTATUS
LdrProcessBinImage(HANDLE ProcessHandle
, HANDLE ModuleHandle
, HANDLE FileHandle
);
60 /* FUNCTIONS *****************************************************************/
62 VOID
LdrInitModuleManagement(VOID
)
64 ANSI_STRING AnsiString
;
66 /* Register the process object type */
67 ObModuleType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
68 ObModuleType
->TotalObjects
= 0;
69 ObModuleType
->TotalHandles
= 0;
70 ObModuleType
->MaxObjects
= ULONG_MAX
;
71 ObModuleType
->MaxHandles
= ULONG_MAX
;
72 ObModuleType
->PagedPoolCharge
= 0;
73 ObModuleType
->NonpagedPoolCharge
= sizeof(MODULE
);
74 ObModuleType
->Dump
= NULL
;
75 ObModuleType
->Open
= NULL
;
76 ObModuleType
->Close
= NULL
;
77 ObModuleType
->Delete
= NULL
;
78 ObModuleType
->Parse
= NULL
;
79 ObModuleType
->Security
= NULL
;
80 ObModuleType
->QueryName
= NULL
;
81 ObModuleType
->OkayToClose
= NULL
;
82 RtlInitAnsiString(&AnsiString
, "Module");
83 RtlAnsiStringToUnicodeString(&ObModuleType
->TypeName
, &AnsiString
, TRUE
);
87 * load the auto config drivers.
89 VOID
LdrLoadAutoConfigDrivers(VOID
)
92 ANSI_STRING AnsiDriverName
;
93 UNICODE_STRING DriverName
;
95 RtlInitAnsiString(&AnsiDriverName
,"\\??\\C:\\reactos\\system\\drivers\\keyboard.o");
96 RtlAnsiStringToUnicodeString(&DriverName
, &AnsiDriverName
, TRUE
);
97 Status
= LdrLoadDriver(&DriverName
);
98 RtlFreeUnicodeString(&DriverName
);
99 if (!NT_SUCCESS(Status
))
101 DbgPrint("driver load failed, status;%d(%x)\n", Status
, Status
);
102 DbgPrintErrorMessage(Status
);
104 RtlInitAnsiString(&AnsiDriverName
,"\\??\\C:\\reactos\\system\\drivers\\blues.o");
105 RtlAnsiStringToUnicodeString(&DriverName
, &AnsiDriverName
, TRUE
);
106 Status
= LdrLoadDriver(&DriverName
);
107 RtlFreeUnicodeString(&DriverName
);
108 if (!NT_SUCCESS(Status
))
110 DbgPrint("driver load failed, status;%d(%x)\n", Status
, Status
);
111 DbgPrintErrorMessage(Status
);
117 * FUNCTION: Loads a kernel driver
119 * FileName = Driver to load
124 LdrLoadDriver(PUNICODE_STRING Filename
)
126 PVOID ModuleLoadBase
;
129 OBJECT_ATTRIBUTES FileObjectAttributes
;
130 FILE_STANDARD_INFORMATION FileStdInfo
;
132 DbgPrint("Loading Driver %W...\n", Filename
);
134 /* Open the Driver */
135 InitializeObjectAttributes(&FileObjectAttributes
,
141 Status
= ZwOpenFile(&FileHandle
,
143 &FileObjectAttributes
,
146 if (!NT_SUCCESS(Status
))
152 /* Get the size of the file */
153 Status
= ZwQueryInformationFile(FileHandle
,
157 FileStandardInformation
);
158 if (!NT_SUCCESS(Status
))
164 /* Allocate nonpageable memory for driver */
165 ModuleLoadBase
= ExAllocatePool(NonPagedPool
,
166 GET_LARGE_INTEGER_LOW_PART(FileStdInfo
.EndOfFile
));
167 if (ModuleLoadBase
== NULL
)
169 return STATUS_INSUFFICIENT_RESOURCES
;
173 /* Load driver into memory chunk */
174 Status
= ZwReadFile(FileHandle
,
177 GET_LARGE_INTEGER_LOW_PART(FileStdInfo
.EndOfFile
),
179 if (!NT_SUCCESS(Status
))
181 ExFreePool(ModuleLoadBase
);
188 Status
= LdrProcessDriver(ModuleLoadBase
);
191 ExFreePool(ModuleLoadBase
);
193 return STATUS_SUCCESS
;
197 LdrProcessDriver(PVOID ModuleLoadBase
)
199 PIMAGE_DOS_HEADER PEDosHeader
;
201 /* If MZ header exists */
202 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
203 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
&& PEDosHeader
->e_lfanew
!= 0L)
205 return LdrPEProcessDriver(ModuleLoadBase
);
207 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
)
209 return STATUS_NOT_IMPLEMENTED
;
211 else /* Assume COFF format and load */
213 return LdrCOFFProcessDriver(ModuleLoadBase
);
218 LdrPEProcessDriver(PVOID ModuleLoadBase
)
220 unsigned int DriverSize
, Idx
;
221 long int RelocDelta
, NumRelocs
;
223 PVOID DriverBase
, CurrentBase
, EntryPoint
;
225 PIMAGE_DOS_HEADER PEDosHeader
;
226 PIMAGE_FILE_HEADER PEFileHeader
;
227 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
228 PIMAGE_SECTION_HEADER PESectionHeaders
;
229 PRELOCATION_DIRECTORY RelocDir
;
230 PRELOCATION_ENTRY RelocEntry
;
232 PVOID
*ImportAddressList
;
233 PULONG FunctionNameList
;
234 PCHAR pName
, SymbolNameBuf
;
237 /* FIXME: this could be used to load kernel DLLs also, however */
238 /* the image headers should be preserved in such a case */
240 DPRINT("Processing PE Driver at module base:%08lx\n", ModuleLoadBase
);
242 /* Get header pointers */
243 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
244 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
245 PEDosHeader
->e_lfanew
);
246 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
247 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
248 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
249 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
250 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
251 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
252 sizeof(IMAGE_OPTIONAL_HEADER
));
255 /* Check file magic numbers */
256 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
258 DPRINT("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
259 return STATUS_UNSUCCESSFUL
;
261 if (PEDosHeader
->e_lfanew
== 0)
263 DPRINT("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
264 return STATUS_UNSUCCESSFUL
;
266 if (*PEMagic
!= IMAGE_PE_MAGIC
)
268 DPRINT("Incorrect PE magic: %08x\n", *PEMagic
);
269 return STATUS_UNSUCCESSFUL
;
271 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
273 DPRINT("Incorrect Architechture: %04x\n", PEFileHeader
->Machine
);
274 return STATUS_UNSUCCESSFUL
;
278 /* FIXME: if image is fixed-address load, then fail */
280 /* FIXME: check/verify OS version number */
282 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
283 PEOptionalHeader
->Magic
,
284 PEOptionalHeader
->MajorLinkerVersion
,
285 PEOptionalHeader
->MinorLinkerVersion
);
286 DPRINT("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
289 /* Determine the size of the module */
290 DPRINT("Sections: (section align:%08lx)\n",
291 PEOptionalHeader
->SectionAlignment
);
292 DriverSize
= PESectionHeaders
[0].PointerToRawData
;
293 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
295 DPRINT("Name:%-8.8s VA:%08lx RawSz:%6d Offs:%08lx CHAR:%08lx OfsA: %08lx\n",
296 PESectionHeaders
[Idx
].Name
,
297 PESectionHeaders
[Idx
].VirtualAddress
,
298 PESectionHeaders
[Idx
].SizeOfRawData
,
299 PESectionHeaders
[Idx
].PointerToRawData
,
300 PESectionHeaders
[Idx
].Characteristics
,
302 DriverSize
+= ROUND_UP(PESectionHeaders
[Idx
].SizeOfRawData
,
303 PEOptionalHeader
->SectionAlignment
);
305 DPRINT("DriverSize computed by using section headers: %d(%08lx)\n",
309 /* Allocate a virtual section for the module */
310 DriverBase
= MmAllocateSection(DriverSize
);
313 DbgPrint("Failed to allocate a virtual section for driver\n");
314 return STATUS_INSUFFICIENT_RESOURCES
;
318 /* Copy image sections into virtual section */
319 memcpy(DriverBase
, ModuleLoadBase
, PESectionHeaders
[0].PointerToRawData
);
320 CurrentBase
= (PVOID
) ((DWORD
)DriverBase
+ PESectionHeaders
[0].PointerToRawData
);
321 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
323 /* Copy current section into current offset of virtual section */
324 if (PESectionHeaders
[Idx
].Characteristics
&
325 (IMAGE_SECTION_CHAR_CODE
| IMAGE_SECTION_CHAR_DATA
))
328 (PVOID
)(ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
329 PESectionHeaders
[Idx
].SizeOfRawData
);
333 memset(CurrentBase
, '\0', PESectionHeaders
[Idx
].SizeOfRawData
);
335 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].SizeOfRawData
,
336 PEOptionalHeader
->SectionAlignment
);
337 CurrentBase
= (PVOID
)((DWORD
)CurrentBase
+
338 ROUND_UP(PESectionHeaders
[Idx
].SizeOfRawData
,
339 PEOptionalHeader
->SectionAlignment
));
342 /* Perform relocation fixups */
343 RelocDelta
= (DWORD
) DriverBase
- PEOptionalHeader
->ImageBase
;
344 RelocDir
= (PRELOCATION_DIRECTORY
) ((DWORD
)ModuleLoadBase
+
345 PEOptionalHeader
->DataDirectory
[
346 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
347 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
349 PEOptionalHeader
->ImageBase
,
351 while (RelocDir
->SizeOfBlock
!= 0)
353 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
355 DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
357 RelocDir
->VirtualAddress
,
359 RelocEntry
= (PRELOCATION_ENTRY
) ((DWORD
)RelocDir
+
360 sizeof(RELOCATION_DIRECTORY
));
361 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
363 DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
364 DriverBase
+ RelocDir
->VirtualAddress
+
365 (RelocEntry
[Idx
].TypeOffset
& 0x0fff),
366 (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf,
367 (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf ? "HIGHLOW" : "ABS",
368 *(PDWORD
)((DWORD
) DriverBase
+ RelocDir
->VirtualAddress
+
369 (RelocEntry
[Idx
].TypeOffset
& 0x0fff)),
370 (*(PDWORD
)((DWORD
) DriverBase
+ RelocDir
->VirtualAddress
+
371 (RelocEntry
[Idx
].TypeOffset
& 0x0fff))) + RelocDelta
);
372 if (((RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf) == 3)
374 (*(PDWORD
)((DWORD
) DriverBase
+ RelocDir
->VirtualAddress
+
375 (RelocEntry
[Idx
].TypeOffset
& 0x0fff))) += RelocDelta
;
377 else if (((RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf) != 0)
379 DPRINT("Unknown relocation type %x\n",
380 (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf);
381 return STATUS_UNSUCCESSFUL
;
384 RelocDir
= (PRELOCATION_DIRECTORY
)((DWORD
)RelocDir
+
385 RelocDir
->SizeOfBlock
);
388 /* Perform import fixups */
389 if (PEOptionalHeader
->DataDirectory
[
390 IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
392 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
394 SymbolNameBuf
= ExAllocatePool(NonPagedPool
, 512);
396 /* Process each import module */
397 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
398 ((DWORD
)ModuleLoadBase
+ PEOptionalHeader
->
399 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
400 while (ImportModuleDirectory
->dwRVAModuleName
)
402 /* FIXME: handle kernel mode DLLs */
404 /* Check to make sure that import lib is kernel */
406 pName
= (PCHAR
) ModuleLoadBase
+
407 ImportModuleDirectory
->dwRVAModuleName
;
408 DPRINT("Import module: %s\n", pName
);
409 if (strcmp(pName
, "ntoskrnl.exe") &&
410 strcmp(pName
, "HAL.dll"))
412 DPRINT("Kernel mode DLLs are currently unsupported\n");
415 /* Get the import address list */
416 ImportAddressList
= (PVOID
*) ((DWORD
)ModuleLoadBase
+
417 ImportModuleDirectory
->dwRVAFunctionAddressList
);
419 /* Get the list of functions to import */
420 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
422 FunctionNameList
= (PULONG
) ((DWORD
)ModuleLoadBase
+
423 ImportModuleDirectory
->dwRVAFunctionNameList
);
427 FunctionNameList
= (PULONG
) ((DWORD
)ModuleLoadBase
+
428 ImportModuleDirectory
->dwRVAFunctionAddressList
);
431 /* Walk through function list and fixup addresses */
432 while(*FunctionNameList
!= 0L)
434 if ((*FunctionNameList
) & 0x80000000) // hint
436 DPRINT(" Hint: %08lx\n", *FunctionNameList
);
439 DPRINT("Hints for kernel symbols are not handled.\n");
440 *ImportAddressList
= 0;
445 pName
= (PCHAR
)((DWORD
)ModuleLoadBase
+
446 *FunctionNameList
+ 2);
447 pHint
= (PWORD
)((DWORD
)ModuleLoadBase
+ *FunctionNameList
);
448 DPRINT(" Hint:%04x Name:%s\n", pHint
, pName
);
450 /* Get address for symbol */
453 *SymbolNameBuf
= '_';
454 strcpy(SymbolNameBuf
+ 1, pName
);
455 *ImportAddressList
= (PVOID
) LdrGetKernelSymbolAddr(SymbolNameBuf
); if (*ImportAddressList
== 0L)
457 DPRINT("Unresolved kernel symbol: %s\n", pName
);
464 ImportModuleDirectory
++;
467 ExFreePool(SymbolNameBuf
);
470 /* Compute address of entry point */
471 EntryPoint
= (PVOID
) ((DWORD
)DriverBase
+ PEOptionalHeader
->AddressOfEntryPoint
);
473 return InitializeLoadedDriver(EntryPoint
);
477 LdrCOFFProcessDriver(PVOID ModuleLoadBase
)
480 char SymbolName
[255];
486 PDRIVER_INITIALIZE EntryRoutine
;
488 /* Get header pointers */
489 FileHeader
= ModuleLoadBase
;
490 AOUTHeader
= ModuleLoadBase
+ FILHSZ
;
493 /* Check COFF magic value */
494 if (I386BADMAG(*FileHeader
))
496 DbgPrint("Module has bad magic value (%x)\n",
497 FileHeader
->f_magic
);
498 return STATUS_UNSUCCESSFUL
;
502 /* Allocate and initialize a module definition structure */
503 Module
= (module
*) ExAllocatePool(NonPagedPool
, sizeof(module
));
506 return STATUS_INSUFFICIENT_RESOURCES
;
508 Module
->sym_list
= (SYMENT
*)(ModuleLoadBase
+ FileHeader
->f_symptr
);
509 Module
->str_tab
= (char *)(ModuleLoadBase
+ FileHeader
->f_symptr
+
510 FileHeader
->f_nsyms
* SYMESZ
);
511 Module
->scn_list
= (SCNHDR
*)(ModuleLoadBase
+ FILHSZ
+
512 FileHeader
->f_opthdr
);
514 Module
->raw_data_off
= (ULONG
) ModuleLoadBase
;
515 Module
->nsyms
= FileHeader
->f_nsyms
;
518 /* Determine the length of the module */
519 for (i
= 0; i
< FileHeader
->f_nscns
; i
++)
521 DPRINT("Section name: %.8s\n", Module
->scn_list
[i
].s_name
);
522 DPRINT("size %x vaddr %x size %x\n",
524 Module
->scn_list
[i
].s_vaddr
,
525 Module
->scn_list
[i
].s_size
);
526 if (Module
->scn_list
[i
].s_flags
& STYP_TEXT
)
528 Module
->text_base
= Module
->scn_list
[i
].s_vaddr
;
530 if (Module
->scn_list
[i
].s_flags
& STYP_DATA
)
532 Module
->data_base
= Module
->scn_list
[i
].s_vaddr
;
534 if (Module
->scn_list
[i
].s_flags
& STYP_BSS
)
536 Module
->bss_base
= Module
->scn_list
[i
].s_vaddr
;
539 (Module
->scn_list
[i
].s_vaddr
+ Module
->scn_list
[i
].s_size
))
541 Module
->size
= Module
->size
+ Module
->scn_list
[i
].s_vaddr
+
542 Module
->scn_list
[i
].s_size
;
547 /* Allocate a section for the module */
548 Module
->base
= (unsigned int) MmAllocateSection(Module
->size
);
549 if (Module
->base
== 0)
551 DbgPrint("Failed to alloc section for module\n");
553 return STATUS_INSUFFICIENT_RESOURCES
;
557 /* Adjust section vaddrs for allocated area */
558 Module
->data_base
= Module
->data_base
+ Module
->base
;
559 Module
->text_base
= Module
->text_base
+ Module
->base
;
560 Module
->bss_base
= Module
->bss_base
+ Module
->base
;
562 /* Relocate module and fixup imports */
563 for (i
= 0; i
< FileHeader
->f_nscns
; i
++)
565 if (Module
->scn_list
[i
].s_flags
& STYP_TEXT
||
566 Module
->scn_list
[i
].s_flags
& STYP_DATA
)
568 memcpy((PVOID
)(Module
->base
+ Module
->scn_list
[i
].s_vaddr
),
569 (PVOID
)(ModuleLoadBase
+ Module
->scn_list
[i
].s_scnptr
),
570 Module
->scn_list
[i
].s_size
);
571 if (!LdrCOFFDoRelocations(Module
, i
))
573 DPRINT("Relocation failed for section %s\n",
574 Module
->scn_list
[i
].s_name
);
576 /* FIXME: unallocate all sections here */
580 return STATUS_UNSUCCESSFUL
;
583 if (Module
->scn_list
[i
].s_flags
& STYP_BSS
)
585 memset((PVOID
)(Module
->base
+ Module
->scn_list
[i
].s_vaddr
),
587 Module
->scn_list
[i
].s_size
);
591 DbgPrint("Module base: %x\n", Module
->base
);
593 /* Find the entry point */
596 for (i
= 0; i
< FileHeader
->f_nsyms
; i
++)
598 LdrCOFFGetSymbolName(Module
, i
, SymbolName
);
599 if (!strcmp(SymbolName
, "_DriverEntry"))
601 EntryOffset
= Module
->sym_list
[i
].e_value
;
603 DPRINT("Found entry at %x\n", EntryOffset
);
608 DbgPrint("No module entry point defined\n");
611 /* FIXME: unallocate all sections here */
613 return STATUS_UNSUCCESSFUL
;
616 /* Get the address of the module initalization routine */
617 EntryRoutine
= (PDRIVER_INITIALIZE
)(Module
->base
+ EntryOffset
);
622 return InitializeLoadedDriver(EntryRoutine
);
625 /* LdrCOFFDoRelocations
626 * FUNCTION: Do the relocations for a module section
628 * Module = Pointer to the module
629 * SectionIndex = Index of the section to be relocated
630 * RETURNS: Success or failure
634 LdrCOFFDoRelocations(module
*Module
, unsigned int SectionIndex
)
636 SCNHDR
*Section
= &Module
->scn_list
[SectionIndex
];
637 RELOC
*Relocation
= (RELOC
*)(Module
->raw_data_off
+ Section
->s_relptr
);
640 DPRINT("SectionIndex %d Name %.8s Relocs %d\n",
642 Module
->scn_list
[SectionIndex
].s_name
,
645 for (j
= 0; j
< Section
->s_nreloc
; j
++)
647 DPRINT("vaddr %x symndex %x",
649 Relocation
->r_symndx
);
651 switch (Relocation
->r_type
)
654 if (!LdrCOFFDoAddr32Reloc(Module
, Section
, Relocation
))
661 if (!LdrCOFFDoReloc32Reloc(Module
, Section
, Relocation
))
668 DPRINT("%.8s: Unknown relocation type %x at %d in module\n",
669 Module
->scn_list
[SectionIndex
].s_name
,
676 DPRINT("%.8s: relocations done\n", Module
->scn_list
[SectionIndex
].s_name
);
682 * FUNCTION: Performs a addr32 relocation on a loaded module
684 * mod = module to perform the relocation on
685 * scn = Section to perform the relocation in
686 * reloc = Pointer to a data structure describing the relocation
687 * RETURNS: Success or failure
688 * NOTE: This fixes up a relocation needed when changing the base address of a
693 LdrCOFFDoAddr32Reloc(module
*Module
, SCNHDR
*Section
, RELOC
*Relocation
)
696 unsigned int *Location
;
698 Value
= LdrCOFFGetSymbolValue(Module
, Relocation
->r_symndx
);
699 Location
= (unsigned int *)(Module
->base
+ Relocation
->r_vaddr
);
700 DPRINT("ADDR32 loc %x value %x *loc %x\n", Location
, Value
, *Location
);
701 *Location
= (*Location
) + Module
->base
;
707 * FUNCTION: Performs a reloc32 relocation on a loaded module
709 * mod = module to perform the relocation on
710 * scn = Section to perform the relocation in
711 * reloc = Pointer to a data structure describing the relocation
712 * RETURNS: Success or failure
713 * NOTE: This fixes up an undefined reference to a kernel function in a module
717 LdrCOFFDoReloc32Reloc(module
*Module
, SCNHDR
*Section
, RELOC
*Relocation
)
721 unsigned int *Location
;
723 memset(Name
, 0, 255);
724 LdrCOFFGetSymbolName(Module
, Relocation
->r_symndx
, Name
);
725 Value
= (unsigned int) LdrGetKernelSymbolAddr(Name
);
728 Value
= LdrCOFFGetSymbolValueByName(Module
, Name
, Relocation
->r_symndx
);
731 DbgPrint("Undefined symbol %s in module\n", Name
);
734 Location
= (unsigned int *)(Module
->base
+ Relocation
->r_vaddr
);
735 // (*Location) = (*Location) + Value + Module->base - Section->s_vaddr;
736 (*Location
) = (*Location
);
737 DPRINT("Module->base %x Section->s_vaddr %x\n",
743 DPRINT("REL32 value %x name %s\n", Value
, Name
);
744 Location
= (unsigned int *)(Module
->base
+ Relocation
->r_vaddr
);
745 DPRINT("old %x ", *Location
);
746 DPRINT("Module->base %x Section->s_vaddr %x\n",
749 (*Location
) = (*Location
) + Value
- Module
->base
+ Section
->s_vaddr
;
750 DPRINT("new %x\n", *Location
);
757 * FUNCTION: Get the name of a symbol from a loaded module by ordinal
760 * i = index of symbol
761 * name (OUT) = pointer to a string where the symbol name will be
766 LdrCOFFGetSymbolName(module
*Module
, unsigned int Idx
, char *Name
)
768 if (Module
->sym_list
[Idx
].e
.e_name
[0] != 0)
770 strncpy(Name
, Module
->sym_list
[Idx
].e
.e_name
, 8);
775 strcpy(Name
, &Module
->str_tab
[Module
->sym_list
[Idx
].e
.e
.e_offset
]);
780 * FUNCTION: Get the value of a module defined symbol
783 * i = index of symbol
784 * RETURNS: The value of the symbol
785 * NOTE: This fixes up references to known sections
789 LdrCOFFGetSymbolValue(module
*Module
, unsigned int Idx
)
793 LdrCOFFGetSymbolName(Module
, Idx
, Name
);
794 DPRINT("name %s ", Name
);
796 /* Check if the symbol is a section we have relocated */
797 if (strcmp(Name
, ".text") == 0)
799 return Module
->text_base
;
801 if (strcmp(Name
, ".data") == 0)
803 return Module
->data_base
;
805 if (strcmp(Name
, ".bss") == 0)
807 return Module
->bss_base
;
810 return Module
->sym_list
[Idx
].e_value
;
814 * FUNCTION: Get the address of a kernel symbol
817 * RETURNS: The address of the symbol on success
822 LdrGetKernelSymbolAddr(char *Name
)
826 while (symbol_table
[i
].name
!= NULL
)
828 if (strcmp(symbol_table
[i
].name
, Name
) == 0)
830 return symbol_table
[i
].value
;
839 LdrCOFFGetSymbolValueByName(module
*Module
,
846 DPRINT("LdrCOFFGetSymbolValueByName(sname %s, idx %x)\n", SymbolName
, Idx
);
848 for (i
= 0; i
< Module
->nsyms
; i
++)
850 LdrCOFFGetSymbolName(Module
, i
, Name
);
851 DPRINT("Scanning %s Value %x\n", Name
, Module
->sym_list
[i
].e_value
);
852 if (strcmp(Name
, SymbolName
) == 0)
854 DPRINT("Returning %x\n", Module
->sym_list
[i
].e_value
);
855 return Module
->sym_list
[i
].e_value
;
862 NTSTATUS
LdrLoadLibrary(HANDLE ProcessHandle
,
863 PHANDLE ModuleHandle
,
868 ANSI_STRING afilename
;
869 UNICODE_STRING ufilename
,umodName
;
870 PMODULE
*Library
, *Module
;
871 OBJECT_ATTRIBUTES attr
;
875 /* FIXME: this is broke */
876 /* FIXME: check for module already loaded */
877 /* FIXME: otherwise load module */
878 /* FIXME: we need to fix how modules are loaded so that they can
881 /* If module is already loaded, get a reference and return it */
882 strcpy(name2
, "\\modules\\");
884 RtlInitAnsiString(&afilename
, name2
);
885 RtlAnsiStringToUnicodeString(&umodName
, &afilename
, TRUE
);
886 InitializeObjectAttributes(&attr
, &umodName
, 0, NULL
, NULL
);
887 Status
= ObOpenObjectByName(&attr
, (PVOID
*) &Library
, &Ignored
);
888 DPRINT("LoadLibrary : Status=%x,pLibrary=%x\n",Status
, Library
);
889 if (!NT_SUCCESS(Status
) || Library
== NULL
)
891 strcpy(name2
, "\\??\\C:\\reactos\\system\\");
893 RtlInitAnsiString(&afilename
, name2
);
894 RtlAnsiStringToUnicodeString(&ufilename
, &afilename
, TRUE
);
895 DPRINT("LoadLibrary,load %s\n", name2
);
896 Library
= LdrLoadImage(&ufilename
);
897 /* FIXME: execute start code ? */
898 Module
= ObGenericCreateObject(NULL
, PROCESS_ALL_ACCESS
, &attr
, ObModuleType
);
901 memcpy(Module
, Library
, PMODULE
);
905 DbgPrint("library object not created\n");
907 RtlFreeUnicodeString(&ufilename
);
908 Status
= ObOpenObjectByName(&attr
, (PVOID
*)&Library
, &Ignored
);
912 DPRINT("Library already loaded\n");
915 RtlFreeUnicodeString(&umodName
);
917 return STATUS_SUCCESS
;
924 * Loads a module into the specified process
926 * HANDLE ProcessHandle handle of the process to load the module into
927 * PHANDLE ModuleHandle handle of the loaded module
928 * PUNICODE_STRING Filename name of the module to load
934 LdrLoadImage(HANDLE ProcessHandle
,
935 PHANDLE ModuleHandle
,
936 PUNICODE_STRING Filename
)
938 char BlockBuffer
[1024];
940 OBJECT_ATTRIBUTES FileObjectAttributes
;
943 PIMAGE_DOS_HEADER PEDosHeader
;
945 /* FIXME: should DLLs be named sections? */
947 /* Open the image file */
948 InitializeObjectAttributes(&FileObjectAttributes
,
953 Status
= ZwOpenFile(&FileHandle
, 0, &FileObjectAttributes
, NULL
, 0, 0);
954 if (!NT_SUCCESS(Status
))
959 /* Build a module structure for the image */
960 Module
= ObGenericCreateObject(ModuleHandle
,
970 /* Read first block of image to determine type */
971 Status
= ZwReadFile(FileHandle
, 0, 0, 0, 0, BlockBuffer
, 1024, 0, 0);
972 if (!NT_SUCCESS(Status
))
974 ObDereferenceObject(*ModuleHandle
);
975 *ModuleHandle
= NULL
;
981 /* If MZ header exists */
982 PEDosHeader
= (PIMAGE_DOS_HEADER
) BlockBuffer
;
983 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
&&
984 PEDosHeader
->e_lfanew
!= 0L &&
985 *(PULONG
)((PUCHAR
)BlockBuffer
+ PEDosHeader
->e_lfanew
) == IMAGE_PE_MAGIC
)
987 Status
= LdrProcessPEImage(ProcessHandle
,
991 else if (PEDosHeader
->e_magic
== 0x54AD)
993 Status
= LdrProcessMZImage(ProcessHandle
,
997 else /* Assume bin format and load */
999 Status
= LdrProcessBinImage(ProcessHandle
,
1003 /* FIXME: {else} could check for a.out, ELF, COFF, etc. images here... */
1005 /* FIXME: should we unconditionally dereference the module handle here? */
1006 if (!NT_SUCCESS(Status
))
1008 ObDereferenceObject(*ModuleHandle
);
1009 *ModuleHandle
= NULL
;
1011 ZwClose(FileHandle
);
1017 LdrProcessMZImage(HANDLE ProcessHandle
,
1018 HANDLE ModuleHandle
,
1022 /* FIXME: map VDM into low memory */
1023 /* FIXME: Build/Load image sections */
1025 return STATUS_NOT_IMPLEMENTED
;
1029 LdrProcessPEImage(HANDLE ProcessHandle
,
1030 HANDLE ModuleHandle
,
1036 PIMAGE_DOS_HEADER DosHeader
;
1037 PIMAGE_NT_HEADERS NTHeaders
;
1039 LARGE_INTEGER SectionOffset
;
1040 HANDLE SectionHandle
;
1042 /* Allocate memory for headers */
1043 Module
= HEADER_TO_BODY(ModuleHandle
);
1046 return STATUS_UNSUCCESSFUL
;
1048 DosHeader
= (PIMAGE_DOS_HEADER
)ExAllocatePool(NonPagedPool
,
1049 sizeof(IMAGE_DOS_HEADER
) +
1050 sizeof(IMAGE_NT_HEADERS
));
1051 if (DosHeader
== NULL
)
1053 return STATUS_UNSUCCESSFUL
;
1055 NTHeaders
= (PIMAGE_NT_HEADERS
)((PUCHAR
) DosHeader
+ sizeof(IMAGE_DOS_HEADER
));
1057 /* Read the headers into memory */
1058 memset(Module
, '\0', sizeof(PMODULE
));
1059 Status
= ZwReadFile(FileHandle
,
1060 NULL
, NULL
, NULL
, NULL
,
1062 sizeof(IMAGE_DOS_HEADER
),
1064 if (!NT_SUCCESS(Status
))
1066 ExFreePool(DosHeader
);
1069 SET_LARGE_INTEGER_HIGH_PART(SectionOffset
, 0);
1070 SET_LARGE_INTEGER_LOW_PART(SectionOffset
, DosHeader
->e_lfanew
);
1071 Status
= ZwReadFile(FileHandle
,
1072 NULL
, NULL
, NULL
, NULL
,
1074 sizeof(IMAGE_NT_HEADERS
),
1077 if (!NT_SUCCESS(Status
))
1079 ExFreePool(DosHeader
);
1083 /* Create the section for the code */
1084 Status
= ZwCreateSection(&SectionHandle
,
1091 if (!NT_SUCCESS(Status
))
1096 /* Map the Image into the process */
1097 Module
->Flags
= MODULE_FLAG_PE
;
1098 Module
->Base
= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
;
1099 Module
->Size
= NTHeaders
->OptionalHeader
.SizeOfImage
;
1100 Status
= ZwMapViewOfSection(SectionHandle
,
1110 if (!NT_SUCCESS(Status
))
1112 /* FIXME: destroy the section here */
1113 ExFreePool(DosHeader
);
1117 /* FIXME: create stack and other BSS sections */
1118 /* FIXME: if actual load address is different from ImageBase, then reloc */
1119 /* FIXME: do import fixups/load required libraries */
1122 /* Load headers into virtual memory */
1123 Status
= ZwReadFile(FileHandle
,
1124 NULL
, NULL
, NULL
, NULL
,
1126 NTHeaders
->OptionalHeader
.SizeOfHeaders
,
1128 if (!NT_SUCCESS(Status
))
1130 ZwFreeVirtualMemory(ProcessHandle
,
1134 ExFreePool(DosHeader
);
1138 /* Adjust module pointers into virtual memory */
1139 DosHeader
= (PIMAGE_DOS_HEADER
) Module
->Base
;
1140 NTHeaders
= (PIMAGE_NT_HEADERS
) ((PUCHAR
)Module
->Base
+
1141 DosHeader
->e_lfanew
);
1142 Module
->Image
.PE
.FileHeader
= (PIMAGE_FILE_HEADER
) ((PUCHAR
)NTHeaders
+
1144 Module
->Image
.PE
.OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
1145 ((PUCHAR
)Module
->Image
.PE
.FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
1146 Module
->Image
.PE
.SectionList
= (PCOFF_SECTION_HEADER
) ((PUCHAR
)NTHeaders
+
1147 sizeof(IMAGE_NT_HEADERS
));
1149 /* Build Image Sections */
1150 /* FIXME: should probably use image directory to load sections. */
1151 for (i
= 0; i
< Module
->Image
.PE
.FileHeader
->NumberOfSections
; i
++)
1153 DPRINT("section %d\n", i
);
1154 BaseSection
= (PVOID
)((PCHAR
) Module
->Base
+
1155 Module
->Image
.PE
.SectionList
[i
].s_vaddr
);
1157 /* Load code and initialized data sections from disk */
1158 if ((Module
->Image
.PE
.SectionList
[i
].s_flags
& STYP_TEXT
) ||
1159 (Module
->Image
.PE
.SectionList
[i
].s_flags
& STYP_DATA
))
1161 SET_LARGE_INTEGER_HIGH_PART(SectionOffset
, 0);
1162 SET_LARGE_INTEGER_LOW_PART(SectionOffset
,
1163 Module
->Image
.PE
.SectionList
[i
].s_scnptr
);
1165 /* FIXME: should probably map sections into sections */
1166 Status
= ZwReadFile(FileHandle
,
1167 NULL
, NULL
, NULL
, NULL
,
1168 Module
->Base
+ Module
->Image
.PE
.SectionList
[i
].s_vaddr
,
1169 min(Module
->Image
.PE
.SectionList
[i
].s_size
,
1170 Module
->Image
.PE
.SectionList
[i
].s_paddr
),
1172 if (!NT_SUCCESS(Status
))
1174 ZwFreeVirtualMemory(ProcessHandle
,
1178 ExFreePool(DosHeader
);
1182 else if (Module
->Image
.PE
.SectionList
[i
].s_flags
& STYP_BSS
)
1184 memset((PVOID
)(Module
->Base
+
1185 Module
->Image
.PE
.SectionList
[i
].s_vaddr
),
1187 Module
->Image
.PE
.SectionList
[i
].s_size
);
1191 /* Resolve Import Library references */
1192 if (Module
->Image
.PE
.OptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
1194 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
1196 /* Process each import module */
1197 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
1198 ((PUCHAR
)Module
->Base
+ Module
->Image
.PE
.OptionalHeader
->
1199 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
1200 while (ImportModuleDirectory
->dwRVAModuleName
)
1203 PVOID
*LibraryExports
;
1204 PVOID
*ImportAddressList
; // was pImpAddr
1205 PULONG FunctionNameList
;
1209 /* Load the library module into the process */
1210 /* FIXME: this should take a UNICODE string */
1211 Status
= LdrLoadLibrary(ProcessHandle
,
1213 (PCHAR
)(Module
->Base
+
1214 ImportModuleDirectory
->dwRVAModuleName
));
1215 if (!NT_SUCCESS(Status
))
1217 /* FIXME: Dereference all loaded modules */
1218 ZwFreeVirtualMemory(ProcessHandle
,
1222 ExFreePool(DosHeader
);
1227 /* Get the address of the export list for the library */
1228 LibraryExports
= (PVOID
*)(Library
->Base
+
1229 Library
->Image
.PE
.OptionalHeader
->
1230 DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
+
1231 sizeof(IMAGE_EXPORT_DIRECTORY
));
1233 /* Get the import address list */
1234 ImportAddressList
= (PVOID
*)
1235 ((PCHAR
)Module
->Image
.PE
.OptionalHeader
->ImageBase
+
1236 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1238 /* Get the list of functions to import */
1239 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
1241 FunctionNameList
= (PULONG
) ((PCHAR
)Module
->Base
+
1242 ImportModuleDirectory
->dwRVAFunctionNameList
);
1246 FunctionNameList
= (PULONG
) ((PCHAR
)Module
->Base
+
1247 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1250 /* Walk through function list and fixup addresses */
1251 while(*FunctionNameList
!= 0L)
1253 if ((*FunctionNameList
) & 0x80000000) // hint
1255 *ImportAddressList
= LibraryExports
[(*FunctionNameList
) & 0x7fffffff];
1259 pName
= (DWORD
)((PCHAR
)Module
->Base
+ *FunctionNameList
+ 2);
1260 pHint
= (PWORD
)((PCHAR
)Module
->Base
+ *FunctionNameList
);
1262 /* FIXME: verify name */
1264 *ImportAddressList
= LibraryExports
[*pHint
];
1267 /* FIXME: verify value of hint */
1269 ImportAddressList
++;
1272 ImportModuleDirectory
++;
1277 if (Module
->Base
!= (PVOID
)Module
->Image
.PE
.OptionalHeader
->ImageBase
)
1279 USHORT NumberOfEntries
;
1281 ULONG RelocationRVA
;
1282 ULONG Delta32
, Offset
;
1284 PRELOCATION_DIRECTORY RelocationDir
;
1285 PRELOCATION_ENTRY RelocationBlock
;
1287 RelocationRVA
= NTHeaders
->OptionalHeader
.DataDirectory
[
1288 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
1291 RelocationDir
= (PRELOCATION_DIRECTORY
)
1292 ((PCHAR
)Module
->Base
+ RelocationRVA
);
1293 while (RelocationDir
->SizeOfBlock
)
1295 Delta32
= (unsigned long)(Module
->Base
- NTHeaders
->OptionalHeader
.ImageBase
);
1296 RelocationBlock
= (PRELOCATION_ENTRY
)
1297 (RelocationRVA
+ Module
->Base
+ sizeof(RELOCATION_DIRECTORY
));
1299 (RelocationDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
1300 sizeof(RELOCATION_ENTRY
);
1301 for (i
= 0; i
< NumberOfEntries
; i
++)
1303 Offset
= (RelocationBlock
[i
].TypeOffset
& 0xfff) + RelocationDir
->VirtualAddress
;
1304 switch (RelocationBlock
[i
].TypeOffset
>> 12)
1306 case TYPE_RELOC_ABSOLUTE
:
1309 case TYPE_RELOC_HIGH
:
1310 pValue16
= (PUSHORT
) (Module
->Base
+ Offset
);
1311 *pValue16
+= Delta32
>> 16;
1314 case TYPE_RELOC_LOW
:
1315 pValue16
= (PUSHORT
)(Module
->Base
+ Offset
);
1316 *pValue16
+= Delta32
& 0xffff;
1319 case TYPE_RELOC_HIGHLOW
:
1320 pValue32
= (PULONG
) (Module
->Base
+ Offset
);
1321 *pValue32
+= Delta32
;
1324 case TYPE_RELOC_HIGHADJ
:
1325 /* FIXME: do the highadjust fixup */
1326 DbgPrint("TYPE_RELOC_HIGHADJ fixup not implemented, sorry\n");
1330 DbgPrint("unexpected fixup type\n");
1332 /* FIXME: Dereference all loaded modules */
1334 ZwFreeVirtualMemory(ProcessHandle
,
1338 ExFreePool(DosHeader
);
1339 return STATUS_UNSUCCESSFUL
;
1342 RelocationRVA
+= RelocationDir
->SizeOfBlock
;
1343 RelocationDir
= (PRELOCATION_DIRECTORY
)((PCHAR
)Module
->Base
+
1350 /* FIXME: Create the stack for the process */
1351 /* FIXME: Setup the context for the initial thread */
1352 /* FIXME: Create the initial thread */
1354 // fail: ZwFreeVirtualMemory(ProcessHandle, Module->ImageBase, 0, MEM_RELEASE);
1355 ExFreePool(DosHeader
);
1357 return STATUS_NOT_IMPLEMENTED
;
1361 LdrProcessBinImage(HANDLE ProcessHandle
,
1362 HANDLE ModuleHandle
,
1366 FILE_STANDARD_INFORMATION FileStdInfo
;
1368 HANDLE ThreadHandle
;
1370 HANDLE SectionHandle
;
1373 /* FIXME: should set module pointers */
1375 /* Get the size of the file for the section */
1376 Status
= ZwQueryInformationFile(FileHandle
,
1379 sizeof(FileStdInfo
),
1380 FileStandardInformation
);
1381 if (!NT_SUCCESS(Status
))
1386 /* Create the section for the code */
1387 Status
= ZwCreateSection(&SectionHandle
,
1394 if (!NT_SUCCESS(Status
))
1399 /* Map a view of the section into the desired process */
1400 BaseAddress
= (PVOID
)0x10000;
1401 SectionSize
= GET_LARGE_INTEGER_LOW_PART(FileStdInfo
.AllocationSize
);
1402 Status
= ZwMapViewOfSection(SectionHandle
,
1412 if (!NT_SUCCESS(Status
))
1414 /* FIXME: destroy the section here */
1418 /* Setup the context for the initial thread */
1419 memset(&Context
,0,sizeof(CONTEXT
));
1420 Context
.SegSs
= USER_DS
;
1421 Context
.Esp
= 0x2000;
1422 Context
.EFlags
= 0x202;
1423 Context
.SegCs
= USER_CS
;
1424 Context
.Eip
= 0x10000;
1425 Context
.SegDs
= USER_DS
;
1426 Context
.SegEs
= USER_DS
;
1427 Context
.SegFs
= USER_DS
;
1428 Context
.SegGs
= USER_DS
;
1430 /* Create the stack for the process */
1431 BaseAddress
= (PVOID
) 0x1000;
1432 SectionSize
= 0x1000;
1433 Status
= ZwAllocateVirtualMemory(ProcessHandle
,
1439 if (!NT_SUCCESS(Status
))
1441 /* FIXME: unmap the section here */
1442 /* FIXME: destroy the section here */
1447 /* Create the initial thread */
1448 Status
= ZwCreateThread(&ThreadHandle
,
1456 if (!NT_SUCCESS(Status
))
1458 /* FIXME: destroy the stack memory block here */
1459 /* FIXME: unmap the section here */
1460 /* FIXME: destroy the section here */
1464 return STATUS_SUCCESS
;