implemented a reference count on LdrLoadDll
[reactos.git] / reactos / lib / ntdll / ldr / utils.c
1 /* $Id: utils.c,v 1.12 1999/10/17 18:16:31 ariadne Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: lib/ntdll/ldr/startup.c
6 * PURPOSE: Process startup for PE executables
7 * PROGRAMMERS: Jean Michault
8 * Rex Jolliff (rex@lvcablemodem.com)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <reactos/config.h>
14 #define WIN32_NO_STATUS
15 #define WIN32_NO_PEHDR
16 #include <windows.h>
17 #include <ddk/ntddk.h>
18 #include <pe.h>
19 #include <string.h>
20 #include <internal/string.h>
21 #include <wchar.h>
22 #include <ntdll/ldr.h>
23
24 #ifdef DBG_NTDLL_LDR_UTILS
25 #define NDEBUG
26 #endif
27 #include <ntdll/ntdll.h>
28
29 /* FUNCTIONS *****************************************************************/
30
31
32 /* Type for a DLL's entry point */
33 typedef
34 WINBOOL
35 STDCALL
36 (* PDLLMAIN_FUNC) (
37 HANDLE hInst,
38 ULONG ul_reason_for_call,
39 LPVOID lpReserved
40 );
41
42 static
43 NTSTATUS
44 LdrFindDll (PDLL* Dll,PCHAR Name);
45
46 /**********************************************************************
47 * NAME
48 * LdrLoadDll
49 *
50 * DESCRIPTION
51 *
52 * ARGUMENTS
53 *
54 * RETURN VALUE
55 *
56 * REVISIONS
57 *
58 * NOTE
59 *
60 */
61
62 NTSTATUS
63 LdrLoadDll (
64 PDLL * Dll,
65 PCHAR Name
66 )
67 {
68 char fqname [255] = "\\??\\C:\\reactos\\system32\\";
69 ANSI_STRING AnsiString;
70 UNICODE_STRING UnicodeString;
71 OBJECT_ATTRIBUTES FileObjectAttributes;
72 char BlockBuffer [1024];
73 PIMAGE_DOS_HEADER DosHeader;
74 NTSTATUS Status;
75 PIMAGE_NT_HEADERS NTHeaders;
76 PEPFUNC DllStartupAddr;
77 ULONG ImageSize;
78 ULONG InitialViewSize;
79 PVOID ImageBase;
80 HANDLE FileHandle;
81 HANDLE SectionHandle;
82 PDLLMAIN_FUNC Entrypoint;
83
84
85 DPRINT("LdrLoadDll(Base %x, Name \"%s\")\n", Dll, Name);
86
87 if ( LdrFindDll(Dll,Name) == STATUS_SUCCESS )
88 return STATUS_SUCCESS;
89
90 /*
91 * Build the DLL's absolute name
92 */
93 strcat(fqname, Name);
94
95 DPRINT("fqname \"%s\"\n", fqname);
96 /*
97 * Open the DLL's image file.
98 */
99 RtlInitAnsiString(
100 & AnsiString,
101 fqname
102 );
103 RtlAnsiStringToUnicodeString(
104 & UnicodeString,
105 & AnsiString,
106 TRUE
107 );
108
109 InitializeObjectAttributes(
110 & FileObjectAttributes,
111 & UnicodeString,
112 0,
113 NULL,
114 NULL
115 );
116
117 DPRINT("Opening dll \"%s\"\n", fqname);
118
119 Status = ZwOpenFile(
120 & FileHandle,
121 FILE_ALL_ACCESS,
122 & FileObjectAttributes,
123 NULL,
124 0,
125 0
126 );
127 if (!NT_SUCCESS(Status))
128 {
129 DPRINT("Dll open failed: Status = 0x%08x\n", Status);
130 return Status;
131 }
132 Status = ZwReadFile(
133 FileHandle,
134 0,
135 0,
136 0,
137 0,
138 BlockBuffer,
139 sizeof BlockBuffer,
140 0,
141 0
142 );
143 if (!NT_SUCCESS(Status))
144 {
145 DPRINT("Dll header read failed: Status = 0x%08x\n", Status);
146 ZwClose(FileHandle);
147 return Status;
148 }
149 /*
150 * Overlay DOS and NT headers structures to the
151 * buffer with DLL's header raw data.
152 */
153 DosHeader = (PIMAGE_DOS_HEADER) BlockBuffer;
154 NTHeaders = (PIMAGE_NT_HEADERS) (BlockBuffer + DosHeader->e_lfanew);
155 /*
156 * Check it is a PE image file.
157 */
158 if ( (DosHeader->e_magic != IMAGE_DOS_MAGIC)
159 || (DosHeader->e_lfanew == 0L)
160 // || (*(PULONG)((PUCHAR)BlockBuffer + DosHeader->e_lfanew) != IMAGE_PE_MAGIC)
161 || (*(PULONG)(NTHeaders) != IMAGE_PE_MAGIC)
162 )
163 {
164 DPRINT("NTDLL format invalid\n");
165 ZwClose(FileHandle);
166
167 return STATUS_UNSUCCESSFUL;
168 }
169
170 // NTHeaders = (PIMAGE_NT_HEADERS) (BlockBuffer + DosHeader->e_lfanew);
171 ImageBase = (PVOID) NTHeaders->OptionalHeader.ImageBase;
172 ImageSize = NTHeaders->OptionalHeader.SizeOfImage;
173
174 DPRINT("ImageBase 0x%08x\n", ImageBase);
175
176 DllStartupAddr =
177 (PEPFUNC) (
178 ImageBase
179 + NTHeaders->OptionalHeader.AddressOfEntryPoint
180 );
181 /*
182 * Create a section for NTDLL.
183 */
184 Status = ZwCreateSection(
185 & SectionHandle,
186 SECTION_ALL_ACCESS,
187 NULL,
188 NULL,
189 PAGE_READWRITE,
190 MEM_COMMIT,
191 FileHandle
192 );
193 if (!NT_SUCCESS(Status))
194 {
195 DPRINT("NTDLL create section failed: Status = 0x%08x\n", Status);
196 ZwClose(FileHandle);
197 return Status;
198 }
199 /*
200 * Map the NTDLL into the process.
201 */
202 InitialViewSize =
203 DosHeader->e_lfanew
204 + sizeof (IMAGE_NT_HEADERS)
205 + sizeof (IMAGE_SECTION_HEADER) * NTHeaders->FileHeader.NumberOfSections;
206 Status = ZwMapViewOfSection(
207 SectionHandle,
208 NtCurrentProcess(),
209 (PVOID *) & ImageBase,
210 0,
211 InitialViewSize,
212 NULL,
213 & InitialViewSize,
214 0,
215 MEM_COMMIT,
216 PAGE_READWRITE
217 );
218 if (!NT_SUCCESS(Status))
219 {
220 DPRINT("NTDLL.LDR: map view of section failed ");
221 ZwClose(FileHandle);
222
223 return Status;
224 }
225 ZwClose(FileHandle);
226
227 (*Dll) = RtlAllocateHeap(
228 RtlGetProcessHeap(),
229 0,
230 sizeof (DLL)
231 );
232 (*Dll)->Headers = NTHeaders;
233 (*Dll)->BaseAddress = (PVOID)ImageBase;
234 (*Dll)->Next = LdrDllListHead.Next;
235 (*Dll)->Prev = & LdrDllListHead;
236 (*Dll)->ReferenceCount = 1;
237 LdrDllListHead.Next->Prev = (*Dll);
238 LdrDllListHead.Next = (*Dll);
239
240 Entrypoint =
241 (PDLLMAIN_FUNC) LdrPEStartup(
242 ImageBase,
243 SectionHandle
244 );
245 if (Entrypoint != NULL)
246 {
247 DPRINT("Calling entry point at 0x%08x\n", Entrypoint);
248 if (FALSE == Entrypoint(
249 Dll,
250 DLL_PROCESS_ATTACH,
251 NULL
252 ))
253 {
254 DPRINT("NTDLL.LDR: DLL \"%s\" failed to initialize\n", fqname);
255 /* FIXME: should clean up and fail */
256 }
257 else
258 {
259 DPRINT("NTDLL.LDR: DLL \"%s\" initialized successfully\n", fqname);
260 }
261 }
262 else
263 {
264 DPRINT("NTDLL.LDR: Entrypoint is NULL for \"%s\"\n", fqname);
265 }
266
267 return STATUS_SUCCESS;
268 }
269
270
271 /**********************************************************************
272 * NAME LOCAL
273 * LdrFindDll
274 *
275 * DESCRIPTION
276 *
277 * ARGUMENTS
278 *
279 * RETURN VALUE
280 *
281 * REVISIONS
282 *
283 * NOTE
284 *
285 */
286 static
287 NTSTATUS
288 LdrFindDll (
289 PDLL * Dll,
290 PCHAR Name
291 )
292 {
293 PIMAGE_EXPORT_DIRECTORY ExportDir;
294 DLL * current;
295 PIMAGE_OPTIONAL_HEADER OptionalHeader;
296
297
298 DPRINT("NTDLL.LdrFindDll(Name %s)\n", Name);
299
300 current = & LdrDllListHead;
301 do
302 {
303 OptionalHeader = & current->Headers->OptionalHeader;
304 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
305 OptionalHeader->DataDirectory[
306 IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
307 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
308 ((ULONG)ExportDir + (ULONG)current->BaseAddress);
309
310 DPRINT("Scanning %x %x %x\n",
311 ExportDir->Name,
312 current->BaseAddress,
313 (ExportDir->Name + current->BaseAddress)
314 );
315 DPRINT("Scanning %s\n",
316 ExportDir->Name + current->BaseAddress
317 );
318 if (strcmp(ExportDir->Name + current->BaseAddress, Name) == 0)
319 {
320 *Dll = current;
321 current->ReferenceCount++;
322 return STATUS_SUCCESS;
323 }
324
325 current = current->Next;
326
327 } while (current != & LdrDllListHead);
328
329 dprintf("Failed to find dll %s\n",Name);
330
331 return -1;
332 }
333
334
335 /**********************************************************************
336 * NAME
337 * LdrMapSections
338 *
339 * DESCRIPTION
340 *
341 * ARGUMENTS
342 *
343 * RETURN VALUE
344 *
345 * REVISIONS
346 *
347 * NOTE
348 *
349 */
350 NTSTATUS
351 LdrMapSections (
352 HANDLE ProcessHandle,
353 PVOID ImageBase,
354 HANDLE SectionHandle,
355 PIMAGE_NT_HEADERS NTHeaders
356 )
357 {
358 ULONG i;
359 NTSTATUS Status;
360
361
362 for ( i = 0;
363 (i < NTHeaders->FileHeader.NumberOfSections);
364 i++
365 )
366 {
367 PIMAGE_SECTION_HEADER Sections;
368 LARGE_INTEGER Offset;
369 ULONG Base;
370
371 Sections = (PIMAGE_SECTION_HEADER) SECHDROFFSET(ImageBase);
372 Base = (ULONG) (Sections[i].VirtualAddress + ImageBase);
373 Offset.u.LowPart = Sections[i].PointerToRawData;
374 Offset.u.HighPart = 0;
375 Status = ZwMapViewOfSection(
376 SectionHandle,
377 ProcessHandle,
378 (PVOID *) & Base,
379 0,
380 Sections[i].Misc.VirtualSize,
381 & Offset,
382 (PULONG) & Sections[i].Misc.VirtualSize,
383 0,
384 MEM_COMMIT,
385 PAGE_READWRITE
386 );
387 if (!NT_SUCCESS(Status))
388 {
389 return Status;
390 }
391 }
392 return STATUS_SUCCESS;
393 }
394
395
396 /**********************************************************************
397 * NAME LOCAL
398 * LdrGetExportByOrdinal
399 *
400 * DESCRIPTION
401 *
402 * ARGUMENTS
403 *
404 * RETURN VALUE
405 *
406 * REVISIONS
407 *
408 * NOTE
409 *
410 */
411
412 PVOID
413 LdrGetExportByOrdinal (
414 PDLL Module,
415 ULONG Ordinal
416 )
417 {
418 PIMAGE_EXPORT_DIRECTORY ExportDir;
419 PDWORD * ExFunctions;
420 USHORT * ExOrdinals;
421
422 ExportDir = (
423 Module->BaseAddress
424 + (Module->Headers->OptionalHeader
425 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
426 .VirtualAddress
427 )
428 );
429
430 ExOrdinals = (USHORT *)
431 RVA(
432 Module->BaseAddress,
433 ExportDir->AddressOfNameOrdinals
434 );
435 ExFunctions = (PDWORD *)
436 RVA(
437 Module->BaseAddress,
438 ExportDir->AddressOfFunctions
439 );
440 dprintf(
441 "LdrGetExportByOrdinal(Ordinal %d) = %x\n",
442 Ordinal,
443 ExFunctions[ExOrdinals[Ordinal - ExportDir->Base]]
444 );
445 return(ExFunctions[ExOrdinals[Ordinal - ExportDir->Base]]);
446 }
447
448
449 /**********************************************************************
450 * NAME LOCAL
451 * LdrGetExportByName
452 *
453 * DESCRIPTION
454 *
455 * ARGUMENTS
456 *
457 * RETURN VALUE
458 *
459 * REVISIONS
460 *
461 * NOTE
462 *
463 */
464
465 PVOID
466 LdrGetExportByName (
467 PDLL Module,
468 PUCHAR SymbolName
469 )
470 {
471 PIMAGE_EXPORT_DIRECTORY ExportDir;
472 PDWORD * ExFunctions;
473 PDWORD * ExNames;
474 USHORT * ExOrdinals;
475 ULONG i;
476 PVOID ExName;
477 ULONG Ordinal;
478
479 DPRINT(
480 "LdrFindExport(Module %x, SymbolName %s)\n",
481 Module,
482 SymbolName
483 );
484
485 ExportDir = (
486 Module->BaseAddress
487 + (Module->Headers->OptionalHeader
488 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
489 .VirtualAddress
490 )
491 );
492 /*
493 * Get header pointers
494 */
495 ExNames = (PDWORD *)
496 RVA(
497 Module->BaseAddress,
498 ExportDir->AddressOfNames
499 );
500 ExOrdinals = (USHORT *)
501 RVA(
502 Module->BaseAddress,
503 ExportDir->AddressOfNameOrdinals
504 );
505 ExFunctions = (PDWORD *)
506 RVA(
507 Module->BaseAddress,
508 ExportDir->AddressOfFunctions
509 );
510 for ( i = 0;
511 ( i < ExportDir->NumberOfFunctions);
512 i++
513 )
514 {
515 ExName = RVA(
516 Module->BaseAddress,
517 ExNames[i]
518 );
519 DPRINT(
520 "Comparing '%s' '%s'\n",
521 ExName,
522 SymbolName
523 );
524 if (strcmp(ExName,SymbolName) == 0)
525 {
526 Ordinal = ExOrdinals[i];
527 return(RVA(Module->BaseAddress, ExFunctions[Ordinal]));
528 }
529 }
530
531 dprintf("LdrGetExportByName() = failed to find %s\n",SymbolName);
532
533 return NULL;
534 }
535
536
537 /**********************************************************************
538 * NAME LOCAL
539 * LdrPerformRelocations
540 *
541 * DESCRIPTION
542 * Relocate a DLL's memory image.
543 *
544 * ARGUMENTS
545 *
546 * RETURN VALUE
547 *
548 * REVISIONS
549 *
550 * NOTE
551 *
552 */
553 static
554 NTSTATUS
555 LdrPerformRelocations (
556 PIMAGE_NT_HEADERS NTHeaders,
557 PVOID ImageBase
558 )
559 {
560 USHORT NumberOfEntries;
561 PUSHORT pValue16;
562 ULONG RelocationRVA;
563 ULONG Delta32;
564 ULONG Offset;
565 PULONG pValue32;
566 PRELOCATION_DIRECTORY RelocationDir;
567 PRELOCATION_ENTRY RelocationBlock;
568 int i;
569
570
571 RelocationRVA =
572 NTHeaders->OptionalHeader
573 .DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]
574 .VirtualAddress;
575 if (RelocationRVA)
576 {
577 RelocationDir = (PRELOCATION_DIRECTORY)
578 ((PCHAR)ImageBase + RelocationRVA);
579
580 while (RelocationDir->SizeOfBlock)
581 {
582 Delta32 = (unsigned long) (
583 ImageBase
584 - NTHeaders->OptionalHeader.ImageBase
585 );
586 RelocationBlock = (PRELOCATION_ENTRY) (
587 RelocationRVA
588 + ImageBase
589 + sizeof (RELOCATION_DIRECTORY)
590 );
591 NumberOfEntries = (
592 RelocationDir->SizeOfBlock
593 - sizeof (RELOCATION_DIRECTORY)
594 )
595 / sizeof (RELOCATION_ENTRY);
596
597 for ( i = 0;
598 (i < NumberOfEntries);
599 i++
600 )
601 {
602 Offset = (
603 RelocationBlock[i].TypeOffset
604 & 0xfff
605 )
606 + RelocationDir->VirtualAddress;
607 /*
608 * What kind of relocations should we perform
609 * for the current entry?
610 */
611 switch (RelocationBlock[i].TypeOffset >> 12)
612 {
613 case TYPE_RELOC_ABSOLUTE:
614 break;
615
616 case TYPE_RELOC_HIGH:
617 pValue16 = (PUSHORT) (ImageBase + Offset);
618 *pValue16 += Delta32 >> 16;
619 break;
620
621 case TYPE_RELOC_LOW:
622 pValue16 = (PUSHORT)(ImageBase + Offset);
623 *pValue16 += Delta32 & 0xffff;
624 break;
625
626 case TYPE_RELOC_HIGHLOW:
627 pValue32 = (PULONG) (ImageBase + Offset);
628 *pValue32 += Delta32;
629 break;
630
631 case TYPE_RELOC_HIGHADJ:
632 /* FIXME: do the highadjust fixup */
633 DPRINT(
634 "TYPE_RELOC_HIGHADJ fixup not implemented"
635 ", sorry\n"
636 );
637 return(STATUS_UNSUCCESSFUL);
638
639 default:
640 DPRINT("unexpected fixup type\n");
641 return STATUS_UNSUCCESSFUL;
642 }
643 }
644 RelocationRVA += RelocationDir->SizeOfBlock;
645 RelocationDir = (PRELOCATION_DIRECTORY) (
646 ImageBase
647 + RelocationRVA
648 );
649 }
650 }
651 return STATUS_SUCCESS;
652 }
653
654
655 /**********************************************************************
656 * NAME LOCAL
657 * LdrFixupImports
658 *
659 * DESCRIPTION
660 * Compute the entry point for every symbol the DLL imports
661 * from other modules.
662 *
663 * ARGUMENTS
664 *
665 * RETURN VALUE
666 *
667 * REVISIONS
668 *
669 * NOTE
670 *
671 */
672 static
673 NTSTATUS
674 LdrFixupImports (
675 PIMAGE_NT_HEADERS NTHeaders,
676 PVOID ImageBase
677 )
678 {
679 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
680 ULONG Ordinal;
681 PDLL Module;
682 NTSTATUS Status;
683
684
685 /*
686 * Process each import module.
687 */
688 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY) (
689 ImageBase
690 + NTHeaders->OptionalHeader
691 .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
692 .VirtualAddress
693 );
694 while (ImportModuleDirectory->dwRVAModuleName)
695 {
696 PVOID * ImportAddressList;
697 PULONG FunctionNameList;
698 DWORD pName;
699 PWORD pHint;
700
701 Status = LdrLoadDll(
702 & Module,
703 (PCHAR) (
704 ImageBase
705 + ImportModuleDirectory->dwRVAModuleName
706 )
707 );
708 if (!NT_SUCCESS(Status))
709 {
710 return Status;
711 }
712 /*
713 * Get the import address list.
714 */
715 ImportAddressList = (PVOID *) (
716 NTHeaders->OptionalHeader.ImageBase
717 + ImportModuleDirectory->dwRVAFunctionAddressList
718 );
719 /*
720 * Get the list of functions to import.
721 */
722 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
723 {
724 FunctionNameList = (PULONG) (
725 ImageBase
726 + ImportModuleDirectory->dwRVAFunctionNameList
727 );
728 }
729 else
730 {
731 FunctionNameList = (PULONG) (
732 ImageBase
733 + ImportModuleDirectory->dwRVAFunctionAddressList
734 );
735 }
736 /*
737 * Walk through function list and fixup addresses.
738 */
739 while (*FunctionNameList != 0L)
740 {
741 if ((*FunctionNameList) & 0x80000000)
742 {
743 Ordinal = (*FunctionNameList) & 0x7fffffff;
744 *ImportAddressList =
745 LdrGetExportByOrdinal(
746 Module,
747 Ordinal
748 );
749 }
750 else
751 {
752 pName = (DWORD) (
753 ImageBase
754 + *FunctionNameList
755 + 2
756 );
757 pHint = (PWORD) (
758 ImageBase
759 + *FunctionNameList
760 );
761
762 *ImportAddressList =
763 LdrGetExportByName(
764 Module,
765 (PUCHAR) pName
766 );
767 if ((*ImportAddressList) == NULL)
768 {
769 return STATUS_UNSUCCESSFUL;
770 }
771 }
772 ImportAddressList++;
773 FunctionNameList++;
774 }
775 ImportModuleDirectory++;
776 }
777 return STATUS_SUCCESS;
778 }
779
780
781 /**********************************************************************
782 * NAME
783 * LdrPEStartup
784 *
785 * DESCRIPTION
786 * 1. Map the DLL's sections into memory.
787 * 2. Relocate, if needed the DLL.
788 * 3. Fixup any imported symbol.
789 * 4. Compute the DLL's entry point.
790 *
791 * ARGUMENTS
792 * ImageBase
793 * Address at which the DLL's image
794 * is loaded.
795 *
796 * SectionHandle
797 * Handle of the section that contains
798 * the DLL's image.
799 *
800 * RETURN VALUE
801 * NULL on error; otherwise the entry point
802 * to call for initializing the DLL.
803 *
804 * REVISIONS
805 *
806 * NOTE
807 *
808 */
809 PEPFUNC
810 LdrPEStartup (
811 PVOID ImageBase,
812 HANDLE SectionHandle
813 )
814 {
815 NTSTATUS Status;
816 PEPFUNC EntryPoint;
817 PIMAGE_DOS_HEADER DosHeader;
818 PIMAGE_NT_HEADERS NTHeaders;
819
820
821 /*
822 * Overlay DOS and WNT headers structures
823 * to the DLL's image.
824 */
825 DosHeader = (PIMAGE_DOS_HEADER) ImageBase;
826 NTHeaders = (PIMAGE_NT_HEADERS) (ImageBase + DosHeader->e_lfanew);
827 /*
828 * Initialize image sections.
829 */
830 LdrMapSections(
831 NtCurrentProcess(),
832 ImageBase,
833 SectionHandle,
834 NTHeaders
835 );
836 /*
837 * If the base address is different from the
838 * one the DLL is actually loaded, perform any
839 * relocation.
840 */
841 if (ImageBase != (PVOID) NTHeaders->OptionalHeader.ImageBase)
842 {
843 Status = LdrPerformRelocations(
844 NTHeaders,
845 ImageBase
846 );
847 if (!NT_SUCCESS(Status))
848 {
849 dprintf("LdrPerformRelocations() failed\n");
850 return NULL;
851 }
852 }
853 /*
854 * If the DLL's imports symbols from other
855 * modules, fixup the imported calls entry points.
856 */
857 if (NTHeaders->OptionalHeader
858 .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
859 .VirtualAddress != 0)
860 {
861 Status = LdrFixupImports(
862 NTHeaders,
863 ImageBase
864 );
865 if (!NT_SUCCESS(Status))
866 {
867 dprintf("LdrFixupImports() failed\n");
868 return NULL;
869 }
870 }
871 /*
872 * Compute the DLL's entry point's address.
873 */
874 EntryPoint = (PEPFUNC) (
875 ImageBase
876 + NTHeaders->OptionalHeader.AddressOfEntryPoint
877 );
878 dprintf("LdrPEStartup() = %x\n",EntryPoint);
879 return EntryPoint;
880 }
881
882 NTSTATUS LdrUnloadDll(PDLL Dll)
883 {
884
885 PDLLMAIN_FUNC Entrypoint;
886 NTSTATUS Status;
887
888
889 if ( Dll->ReferenceCount > 1 ) {
890 Dll->ReferenceCount--;
891 return STATUS_SUCCESS;
892 }
893
894 Entrypoint =
895 (PDLLMAIN_FUNC) LdrPEStartup(
896 Dll->BaseAddress,
897 Dll->SectionHandle
898 );
899 if (Entrypoint != NULL)
900 {
901 DPRINT("Calling entry point at 0x%08x\n", Entrypoint);
902 if (FALSE == Entrypoint(
903 Dll,
904 DLL_PROCESS_DETACH,
905 NULL
906 ))
907 {
908 DPRINT("NTDLL.LDR: DLL failed to detach\n");
909 return -1;
910 }
911 else
912 {
913 DPRINT("NTDLL.LDR: DLL detached successfully\n");
914 }
915 }
916 else
917 {
918 DPRINT("NTDLL.LDR: Entrypoint is NULL for \n");
919 }
920
921
922 Status = ZwUnmapViewOfSection(
923 NtCurrentProcess(),
924 Dll->BaseAddress
925 );
926
927 ZwClose(Dll->SectionHandle);
928
929 return Status;
930 }
931
932 /* EOF */