Various LdrGetProcedureAddress fixes: - Fix the binary search limits. - Fix the comparsion of names (previously "XXX" and "XXXyyy" would be considered identical) and make it case sensitive. - Remove non-binary search, it's not needed. - Don't use ULONG to store pointers. Modified: trunk/reactos/ntoskrnl/ldr/rtl.c _____
Modified: trunk/reactos/ntoskrnl/ldr/rtl.c --- trunk/reactos/ntoskrnl/ldr/rtl.c 2005-08-01 13:34:33 UTC (rev 16954) +++ trunk/reactos/ntoskrnl/ldr/rtl.c 2005-08-01 13:50:07 UTC (rev 16955) @@ -24,84 +24,84 @@
OUT PVOID *ProcedureAddress) { PIMAGE_EXPORT_DIRECTORY ExportDir; + ULONG ExportDirSize = 0; PUSHORT OrdinalPtr; PULONG NamePtr; + PCHAR CurrentNamePtr; PULONG AddressPtr; - ULONG i = 0;
+ if (ProcedureAddress == NULL) + return STATUS_INVALID_PARAMETER; + /* get the pointer to the export directory */ - ExportDir = (PIMAGE_EXPORT_DIRECTORY) - RtlImageDirectoryEntryToData (BaseAddress, TRUE, - IMAGE_DIRECTORY_ENTRY_EXPORT, &i); + ExportDir = RtlImageDirectoryEntryToData(BaseAddress, TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &ExportDirSize);
- if (!ExportDir || !i || !ProcedureAddress) - { - return(STATUS_INVALID_PARAMETER); - } + if (ExportDir == NULL || ExportDirSize == 0) + return STATUS_INVALID_PARAMETER;
- AddressPtr = (PULONG)RVA((char*)BaseAddress, ExportDir->AddressOfFunctions); + AddressPtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfFunctions); + if (Name && Name->Length) - { - LONG minn, maxn; + { + LONG minn, maxn, mid, res;
- /* by name */ - OrdinalPtr = - (PUSHORT)RVA((char*)BaseAddress, ExportDir->AddressOfNameOrdinals); - NamePtr = (PULONG)RVA((char*)BaseAddress, ExportDir->AddressOfNames); + /* Search for export by name */
- minn = 0; maxn = ExportDir->NumberOfNames; - while (minn <= maxn) - { - LONG mid; - LONG res; + /* + * NOTE: Exports are always sorted and so we can apply binary search. + * Also the function names are _case sensitive_, so respect that. + * -- Filip Navara, August 1st, 2005 + */
- mid = (minn + maxn) / 2; - res = _strnicmp(Name->Buffer, (PCH)RVA((char*)BaseAddress, NamePtr[mid]), - Name->Length); - if (res == 0) - { - *ProcedureAddress = - (PVOID)RVA((char*)BaseAddress, AddressPtr[OrdinalPtr[mid]]); - return(STATUS_SUCCESS); - } - else if (res > 0) - { - maxn = mid - 1; - } - else - { - minn = mid + 1; - } - } + OrdinalPtr = (PUSHORT)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals); + NamePtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfNames);
- for (i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++) - { - if (!_strnicmp(Name->Buffer, - (char*)((char*)BaseAddress + *NamePtr), Name->Length)) - { - *ProcedureAddress = - (PVOID)((ULONG)BaseAddress + - (ULONG)AddressPtr[*OrdinalPtr]); - return STATUS_SUCCESS; - } - } - CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name); - } + minn = 0; maxn = ExportDir->NumberOfNames - 1; + while (minn <= maxn) + { + mid = (minn + maxn) / 2; + CurrentNamePtr = (PCHAR)RVA(BaseAddress, NamePtr[mid]); + res = strncmp(CurrentNamePtr, Name->Buffer, Name->Length); + if (res == 0) + { + /* + * Check if the beginning of the name matched, but it's still + * not the whole name. + */ + if (CurrentNamePtr[Name->Length] != 0) + { + res = -1; + } + else + { + *ProcedureAddress = (PVOID)RVA(BaseAddress, AddressPtr[OrdinalPtr[mid]]); + return STATUS_SUCCESS; + } + } + if (res > 0) + maxn = mid - 1; + else + minn = mid + 1; + } + + CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name); + } else - { - /* by ordinal */ - Ordinal &= 0x0000FFFF; - if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions) - { - *ProcedureAddress = - (PVOID)((ULONG)BaseAddress + - (ULONG)AddressPtr[Ordinal - ExportDir->Base]); - return STATUS_SUCCESS; - } - CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n", - Ordinal); - } + { + /* Search for export by ordinal */
+ Ordinal &= 0x0000FFFF; + if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions) + { + *ProcedureAddress = (PVOID)RVA(BaseAddress, AddressPtr[Ordinal - ExportDir->Base]); + return STATUS_SUCCESS; + } + + CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n", Ordinal); + } + return STATUS_PROCEDURE_NOT_FOUND; }