- Make the NDK compatible with the MSDDK again.
[reactos.git] / reactos / ntoskrnl / ldr / rtl.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ldr/rtl.c
6 * PURPOSE: Loader utilities
7 *
8 * PROGRAMMERS: Jean Michault
9 * Rex Jolliff (rex@lvcablemodem.com)
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ntoskrnl.h>
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 /* FUNCTIONS ****************************************************************/
19
20 NTSTATUS STDCALL
21 LdrGetProcedureAddress (IN PVOID BaseAddress,
22 IN PANSI_STRING Name,
23 IN ULONG Ordinal,
24 OUT PVOID *ProcedureAddress)
25 {
26 PIMAGE_EXPORT_DIRECTORY ExportDir;
27 ULONG ExportDirSize = 0;
28 PUSHORT OrdinalPtr;
29 PULONG NamePtr;
30 PCHAR CurrentNamePtr;
31 PULONG AddressPtr;
32
33 if (ProcedureAddress == NULL)
34 return STATUS_INVALID_PARAMETER;
35
36 /* get the pointer to the export directory */
37 ExportDir = RtlImageDirectoryEntryToData(BaseAddress, TRUE,
38 IMAGE_DIRECTORY_ENTRY_EXPORT,
39 &ExportDirSize);
40
41 if (ExportDir == NULL || ExportDirSize == 0)
42 return STATUS_INVALID_PARAMETER;
43
44 AddressPtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfFunctions);
45
46 if (Name && Name->Length)
47 {
48 LONG minn, maxn, mid, res;
49
50 /* Search for export by name */
51
52 /*
53 * NOTE: Exports are always sorted and so we can apply binary search.
54 * Also the function names are _case sensitive_, so respect that.
55 * -- Filip Navara, August 1st, 2005
56 */
57
58 OrdinalPtr = (PUSHORT)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
59 NamePtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfNames);
60
61 minn = 0; maxn = ExportDir->NumberOfNames - 1;
62 while (minn <= maxn)
63 {
64 mid = (minn + maxn) / 2;
65 CurrentNamePtr = (PCHAR)RVA(BaseAddress, NamePtr[mid]);
66 res = strncmp(CurrentNamePtr, Name->Buffer, Name->Length);
67 if (res == 0)
68 {
69 /*
70 * Check if the beginning of the name matched, but it's still
71 * not the whole name.
72 */
73 if (CurrentNamePtr[Name->Length] != 0)
74 {
75 res = -1;
76 }
77 else
78 {
79 *ProcedureAddress = (PVOID)RVA(BaseAddress, AddressPtr[OrdinalPtr[mid]]);
80 return STATUS_SUCCESS;
81 }
82 }
83 if (res > 0)
84 maxn = mid - 1;
85 else
86 minn = mid + 1;
87 }
88
89 CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
90 }
91 else
92 {
93 /* Search for export by ordinal */
94
95 Ordinal &= 0x0000FFFF;
96 if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions)
97 {
98 *ProcedureAddress = (PVOID)RVA(BaseAddress, AddressPtr[Ordinal - ExportDir->Base]);
99 return STATUS_SUCCESS;
100 }
101
102 CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n", Ordinal);
103 }
104
105 return STATUS_PROCEDURE_NOT_FOUND;
106 }
107
108 /* EOF */