#define NDEBUG
#include <debug.h>
-#define LDRP_PROCESS_CREATION_TIME 0x8000000
+#define LDRP_PROCESS_CREATION_TIME 0xffff
#define RVA(m, b) ((PVOID)((ULONG_PTR)(b) + (ULONG_PTR)(m)))
/* GLOBALS *******************************************************************/
#ifdef NDEBUG
-#if defined(__GNUC__)
-#define TRACE_LDR(args...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); }
-#elif defined(_MSC_VER)
-#define TRACE_LDR(args, ...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(__VA_ARGS__); }
-#endif /* __GNUC__ */
-#else
-#define TRACE_LDR(args...) do { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0)
+#define TRACE_LDR(...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(__VA_ARGS__); }
#endif
typedef struct _TLS_DATA
/* FUNCTIONS *****************************************************************/
-#if defined(DBG) || defined(KDBG)
+#if DBG || defined(KDBG)
VOID
LdrpLoadUserModuleSymbols(PLDR_DATA_TABLE_ENTRY LdrModule)
RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
}
LoadCount = Module->LoadCount;
- if (Module->LoadCount > 0 && Module->LoadCount != 0xFFFF)
+ if (Module->LoadCount > 0 && Module->LoadCount != LDRP_PROCESS_CREATION_TIME)
{
Module->LoadCount--;
}
RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
}
LoadCount = Module->LoadCount;
- if (Module->LoadCount != 0xFFFF)
+ if (Module->LoadCount != LDRP_PROCESS_CREATION_TIME)
{
Module->LoadCount++;
}
static __inline VOID LdrpTlsCallback(PLDR_DATA_TABLE_ENTRY Module, ULONG dwReason)
{
PIMAGE_TLS_CALLBACK *TlsCallback;
- if (Module->TlsIndex != 0xFFFF && Module->LoadCount == 0xFFFF)
+ if (Module->TlsIndex != 0xFFFF && Module->LoadCount == LDRP_PROCESS_CREATION_TIME)
{
TlsCallback = LdrpTlsArray[Module->TlsIndex].TlsAddressOfCallBacks;
if (TlsCallback)
return ((PDLLMAIN_FUNC)Module->EntryPoint)(Module->DllBase, dwReason, lpReserved);
}
+static PWSTR
+LdrpQueryAppPaths(IN PCWSTR ImageName)
+{
+ PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ WCHAR SearchPathBuffer[5*MAX_PATH];
+ UNICODE_STRING ValueNameString;
+ UNICODE_STRING KeyName;
+ WCHAR NameBuffer[MAX_PATH];
+ ULONG KeyInfoSize;
+ ULONG ResultSize;
+ PWCHAR Backslash;
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+ PWSTR Path = NULL;
+
+ _snwprintf(NameBuffer,
+ sizeof(NameBuffer) / sizeof(WCHAR),
+ L"\\Registry\\Machine\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s",
+ ImageName);
+
+ RtlInitUnicodeString(&KeyName, NameBuffer);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenKey(&KeyHandle,
+ KEY_READ,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT ("NtOpenKey() failed (Status %lx)\n", Status);
+ return NULL;
+ }
+
+ KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 256 * sizeof(WCHAR);
+
+ KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, KeyInfoSize);
+ if (KeyInfo == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ NtClose(KeyHandle);
+ return NULL;
+ }
+
+ RtlInitUnicodeString(&ValueNameString,
+ L"Path");
+
+ Status = NtQueryValueKey(KeyHandle,
+ &ValueNameString,
+ KeyValuePartialInformation,
+ KeyInfo,
+ KeyInfoSize,
+ &ResultSize);
+
+ if (!NT_SUCCESS(Status))
+ {
+ NtClose(KeyHandle);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
+ return NULL;
+ }
+
+ RtlCopyMemory(SearchPathBuffer,
+ &KeyInfo->Data,
+ KeyInfo->DataLength);
+
+ /* Free KeyInfo memory, we won't need it anymore */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
+
+ /* Close the key handle */
+ NtClose(KeyHandle);
+
+ /* get application running path */
+ wcscat(SearchPathBuffer, L";");
+ wcscat(SearchPathBuffer, NtCurrentPeb()->ProcessParameters->ImagePathName.Buffer); // FIXME: Don't rely on it being NULL-terminated!!!
+
+ /* Remove trailing backslash */
+ Backslash = wcsrchr(SearchPathBuffer, L'\\');
+ if (Backslash) Backslash = L'\0';
+
+ wcscat(SearchPathBuffer, L";");
+
+ wcscat(SearchPathBuffer, SharedUserData->NtSystemRoot);
+ wcscat(SearchPathBuffer, L"\\system32;");
+ wcscat(SearchPathBuffer, SharedUserData->NtSystemRoot);
+ wcscat(SearchPathBuffer, L";.");
+
+ /* Copy it to the heap allocd memory */
+ Path = RtlAllocateHeap(RtlGetProcessHeap(),
+ 0,
+ wcslen(SearchPathBuffer) * sizeof(WCHAR));
+
+ if (!Path)
+ {
+ DPRINT1("RtlAllocateHeap() failed\n");
+ return NULL;
+ }
+
+ wcscpy(Path, SearchPathBuffer);
+
+ return Path;
+}
+
static NTSTATUS
LdrpInitializeTlsForThread(VOID)
{
while (Entry != ModuleListHead)
{
Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
- if (Module->LoadCount == 0xFFFF &&
+ if (Module->LoadCount == LDRP_PROCESS_CREATION_TIME &&
Module->TlsIndex != 0xFFFF)
{
TlsDirectory = (PIMAGE_TLS_DIRECTORY)
* loading while app is initializing
* dll must not be unloaded
*/
- Module->LoadCount = 0xFFFF;
+ Module->LoadCount = LDRP_PROCESS_CREATION_TIME;
}
Module->Flags = 0;
PLDR_DATA_TABLE_ENTRY ModulePtr;
BOOLEAN ContainsPath;
UNICODE_STRING AdjustedName;
- unsigned i;
DPRINT("LdrFindEntryForName(Name %wZ)\n", Name);
return(STATUS_SUCCESS);
}
- LdrAdjustDllName (&AdjustedName, Name, FALSE);
-
- ContainsPath = (AdjustedName.Length >= 2 * sizeof(WCHAR) && L':' == AdjustedName.Buffer[1]);
- for (i = 0; ! ContainsPath && i < AdjustedName.Length / sizeof(WCHAR); i++)
- {
- ContainsPath = L'\\' == AdjustedName.Buffer[i] ||
- L'/' == AdjustedName.Buffer[i];
- }
+ ContainsPath = (Name->Length >= 2 * sizeof(WCHAR) && L':' == Name->Buffer[1]);
+ LdrAdjustDllName (&AdjustedName, Name, !ContainsPath);
if (LdrpLastModule)
{
0 == RtlCompareUnicodeString(&LdrpLastModule->FullDllName, &AdjustedName, TRUE)))
{
*Module = LdrpLastModule;
- if (Ref && (*Module)->LoadCount != 0xFFFF)
+ if (Ref && (*Module)->LoadCount != LDRP_PROCESS_CREATION_TIME)
{
(*Module)->LoadCount++;
}
0 == RtlCompareUnicodeString(&ModulePtr->FullDllName, &AdjustedName, TRUE)))
{
*Module = LdrpLastModule = ModulePtr;
- if (Ref && ModulePtr->LoadCount != 0xFFFF)
+ if (Ref && ModulePtr->LoadCount != LDRP_PROCESS_CREATION_TIME)
{
ModulePtr->LoadCount++;
}
*/
if (!NT_SUCCESS(Status))
{
- ULONG Flags = LDRP_PROCESS_CREATION_TIME;
Status = LdrLoadDll(NULL,
- &Flags,
+ NULL,
&DllName,
&BaseAddress);
if (NT_SUCCESS(Status))
if (Load && !NT_SUCCESS(Status))
{
Status = LdrpLoadModule(SearchPath,
- NtCurrentPeb()->Ldr->Initialized ? 0 : LDRP_PROCESS_CREATION_TIME,
+ 0,
&DllName,
Module,
- NULL);
+ NULL);
if (NT_SUCCESS(Status))
{
Status = LdrFindEntryForName (&DllName, Module, FALSE);
NTSTATUS Status;
PLDR_DATA_TABLE_ENTRY ImportedModule;
PCHAR ImportedName;
+ PWSTR ModulePath;
ULONG Size;
DPRINT("LdrFixupImports(SearchPath %S, Module %p)\n", SearchPath, Module);
ImportedName = (PCHAR)Module->DllBase + ImportModuleDirectoryCurrent->Name;
TRACE_LDR("%wZ imports functions from %s\n", &Module->BaseDllName, ImportedName);
+ if (SearchPath == NULL)
+ {
+ ModulePath = LdrpQueryAppPaths(Module->BaseDllName.Buffer);
+
+ Status = LdrpGetOrLoadModule(ModulePath, ImportedName, &ImportedModule, TRUE);
+ if (ModulePath != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, ModulePath);
+ if (NT_SUCCESS(Status)) goto Success;
+ }
+
Status = LdrpGetOrLoadModule(SearchPath, ImportedName, &ImportedModule, TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to load %s\n", ImportedName);
return Status;
}
+Success:
if (Module == ImportedModule)
{
LdrpDecrementLoadCount(Module, FALSE);
DPRINT1("LdrFixupImports failed for %wZ, status=%x\n", &(*Module)->BaseDllName, Status);
return Status;
}
-#if defined(DBG) || defined(KDBG)
+#if DBG || defined(KDBG)
LdrpLoadUserModuleSymbols(*Module);
#endif /* DBG || KDBG */
RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
IN ULONG Ordinal,
OUT PVOID *ProcedureAddress)
{
+ NTSTATUS Status = STATUS_PROCEDURE_NOT_FOUND;
if (Name && Name->Length)
{
TRACE_LDR("LdrGetProcedureAddress by NAME - %Z\n", Name);
DPRINT("LdrGetProcedureAddress (BaseAddress %p Name %Z Ordinal %lu ProcedureAddress %p)\n",
BaseAddress, Name, Ordinal, ProcedureAddress);
- if (Name && Name->Length)
+ _SEH2_TRY
+ {
+ if (Name && Name->Length)
{
/* by name */
*ProcedureAddress = LdrGetExportByName(BaseAddress, (PUCHAR)Name->Buffer, 0xffff);
if (*ProcedureAddress != NULL)
{
- return STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
}
DPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
}
- else
+ else
{
/* by ordinal */
Ordinal &= 0x0000FFFF;
*ProcedureAddress = LdrGetExportByOrdinal(BaseAddress, (WORD)Ordinal);
if (*ProcedureAddress)
{
- return STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
}
DPRINT("LdrGetProcedureAddress: Can't resolve symbol @%lu\n", Ordinal);
}
- return STATUS_PROCEDURE_NOT_FOUND;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = STATUS_DLL_NOT_FOUND;
+ }
+ _SEH2_END;
+
+ return Status;
}
/**********************************************************************
while (Entry != ModuleListHead)
{
Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
- if (((UnloadAll && Module->LoadCount == 0xFFFF) || Module->LoadCount == 0) &&
+ if (((UnloadAll && Module->LoadCount == LDRP_PROCESS_CREATION_TIME) || Module->LoadCount == 0) &&
Module->Flags & LDRP_ENTRY_PROCESSED &&
!(Module->Flags & LDRP_UNLOAD_IN_PROGRESS))
{
{
TRACE_LDR("Unload %wZ - Calling entry point at %x\n",
&Module->BaseDllName, Module->EntryPoint);
- LdrpCallDllEntry(Module, DLL_PROCESS_DETACH, (PVOID)(INT_PTR)(Module->LoadCount == 0xFFFF ? 1 : 0));
+ LdrpCallDllEntry(Module, DLL_PROCESS_DETACH, (PVOID)(INT_PTR)(Module->LoadCount == LDRP_PROCESS_CREATION_TIME ? 1 : 0));
}
else
{
Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
Entry = Entry->Blink;
if (Module->Flags & LDRP_UNLOAD_IN_PROGRESS &&
- ((UnloadAll && Module->LoadCount != 0xFFFF) || Module->LoadCount == 0))
+ ((UnloadAll && Module->LoadCount != LDRP_PROCESS_CREATION_TIME) || Module->LoadCount == 0))
{
/* remove the module entry from the list */
RemoveEntryList (&Module->InLoadOrderLinks);
Module->Flags |= LDRP_LOAD_IN_PROGRESS;
TRACE_LDR("%wZ loaded - Calling init routine at %x for process attaching\n",
&Module->BaseDllName, Module->EntryPoint);
- Result = LdrpCallDllEntry(Module, DLL_PROCESS_ATTACH, (PVOID)(INT_PTR)(Module->LoadCount == 0xFFFF ? 1 : 0));
+ Result = LdrpCallDllEntry(Module, DLL_PROCESS_ATTACH, (PVOID)(INT_PTR)(Module->LoadCount == LDRP_PROCESS_CREATION_TIME ? 1 : 0));
if (!Result)
{
Status = STATUS_DLL_INIT_FAILED;