Copy w32api from trunk
[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 #define RVA(m, b) ((ULONG)b + m)
21
22 NTSTATUS STDCALL
23 LdrGetProcedureAddress (IN PVOID BaseAddress,
24 IN PANSI_STRING Name,
25 IN ULONG Ordinal,
26 OUT PVOID *ProcedureAddress)
27 {
28 PIMAGE_EXPORT_DIRECTORY ExportDir;
29 PUSHORT OrdinalPtr;
30 PULONG NamePtr;
31 PULONG AddressPtr;
32 ULONG i = 0;
33
34 /* get the pointer to the export directory */
35 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
36 RtlImageDirectoryEntryToData (BaseAddress, TRUE,
37 IMAGE_DIRECTORY_ENTRY_EXPORT, &i);
38
39 if (!ExportDir || !i || !ProcedureAddress)
40 {
41 return(STATUS_INVALID_PARAMETER);
42 }
43
44 AddressPtr = (PULONG)RVA((char*)BaseAddress, ExportDir->AddressOfFunctions);
45 if (Name && Name->Length)
46 {
47 LONG minn, maxn;
48
49 /* by name */
50 OrdinalPtr =
51 (PUSHORT)RVA((char*)BaseAddress, ExportDir->AddressOfNameOrdinals);
52 NamePtr = (PULONG)RVA((char*)BaseAddress, ExportDir->AddressOfNames);
53
54 minn = 0; maxn = ExportDir->NumberOfNames;
55 while (minn <= maxn)
56 {
57 LONG mid;
58 LONG res;
59
60 mid = (minn + maxn) / 2;
61 res = _strnicmp(Name->Buffer, (PCH)RVA((char*)BaseAddress, NamePtr[mid]),
62 Name->Length);
63 if (res == 0)
64 {
65 *ProcedureAddress =
66 (PVOID)RVA((char*)BaseAddress, AddressPtr[OrdinalPtr[mid]]);
67 return(STATUS_SUCCESS);
68 }
69 else if (res > 0)
70 {
71 maxn = mid - 1;
72 }
73 else
74 {
75 minn = mid + 1;
76 }
77 }
78
79 for (i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++)
80 {
81 if (!_strnicmp(Name->Buffer,
82 (char*)((char*)BaseAddress + *NamePtr), Name->Length))
83 {
84 *ProcedureAddress =
85 (PVOID)((ULONG)BaseAddress +
86 (ULONG)AddressPtr[*OrdinalPtr]);
87 return STATUS_SUCCESS;
88 }
89 }
90 CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
91 }
92 else
93 {
94 /* by ordinal */
95 Ordinal &= 0x0000FFFF;
96 if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions)
97 {
98 *ProcedureAddress =
99 (PVOID)((ULONG)BaseAddress +
100 (ULONG)AddressPtr[Ordinal - ExportDir->Base]);
101 return STATUS_SUCCESS;
102 }
103 CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n",
104 Ordinal);
105 }
106
107 return STATUS_PROCEDURE_NOT_FOUND;
108 }
109
110 /* EOF */