* PURPOSE: Process startup for PE executables
* PROGRAMMERS: Jean Michault
* Rex Jolliff (rex@lvcablemodem.com)
+ * Michael Martin
*/
/*
OUT PVOID *BaseAddress OPTIONAL);
static NTSTATUS LdrpAttachProcess(VOID);
static VOID LdrpDetachProcess(BOOLEAN UnloadAll);
+static NTSTATUS LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module, BOOLEAN Unload);
NTSTATUS find_actctx_dll( LPCWSTR libname, WCHAR *fulldosname );
NTSTATUS create_module_activation_context( LDR_DATA_TABLE_ENTRY *module );
ASSERT(Module);
memset(Module, 0, sizeof(LDR_DATA_TABLE_ENTRY));
Module->DllBase = (PVOID)ImageBase;
- Module->EntryPoint = (PVOID)(ULONG_PTR)NTHeaders->OptionalHeader.AddressOfEntryPoint;
+ Module->EntryPoint = (PVOID)NTHeaders->OptionalHeader.AddressOfEntryPoint;
if (Module->EntryPoint != 0)
Module->EntryPoint = (PVOID)((ULONG_PTR)Module->EntryPoint + (ULONG_PTR)Module->DllBase);
Module->SizeOfImage = LdrpGetResidentSize(NTHeaders);
IN BOOLEAN MapAsDataFile,
OUT PHANDLE SectionHandle)
{
- WCHAR SearchPathBuffer[MAX_PATH];
+ WCHAR *SearchPathBuffer = NULL;
+ WCHAR *ImagePathNameBufferPtr = NULL;
WCHAR DosName[MAX_PATH];
UNICODE_STRING FullNtFileName;
+ UNICODE_STRING PathEnvironmentVar_U;
+ UNICODE_STRING PathName_U;
OBJECT_ATTRIBUTES FileObjectAttributes;
HANDLE FileHandle;
char BlockBuffer [1024];
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
ULONG len;
+ ULONG ImagePathLen;
DPRINT("LdrpMapDllImageFile() called\n");
if (SearchPath == NULL)
{
/* get application running path */
+ ImagePathNameBufferPtr = NtCurrentPeb()->ProcessParameters->ImagePathName.Buffer;
- wcscpy (SearchPathBuffer, NtCurrentPeb()->ProcessParameters->ImagePathName.Buffer);
+ /* Length of ImagePathName */
+ ImagePathLen = wcslen(ImagePathNameBufferPtr);
- len = wcslen (SearchPathBuffer);
+ /* Subtract application name leaveing only the directory length */
+ while (ImagePathLen && ImagePathNameBufferPtr[ImagePathLen - 1] != L'\\')
+ ImagePathLen--;
- while (len && SearchPathBuffer[len - 1] != L'\\')
- len--;
+ /* Length of directory + semicolon */
+ len = ImagePathLen + 1;
- if (len) SearchPathBuffer[len-1] = L'\0';
+ /* Length of SystemRoot + "//system32" + semicolon*/
+ len += wcslen(SharedUserData->NtSystemRoot) + 10;
+ /* Length of SystemRoot + semicolon */
+ len += wcslen(SharedUserData->NtSystemRoot) + 1;
- wcscat (SearchPathBuffer, L";");
+ RtlInitUnicodeString (&PathName_U, L"PATH");
+ PathEnvironmentVar_U.Length = 0;
+ PathEnvironmentVar_U.MaximumLength = 0;
+ PathEnvironmentVar_U.Buffer = NULL;
+
+ /* Get the path environment variable */
+ Status = RtlQueryEnvironmentVariable_U(NULL, &PathName_U, &PathEnvironmentVar_U);
+
+ /* Check that valid information was returned */
+ if ((Status == STATUS_BUFFER_TOO_SMALL) && (PathEnvironmentVar_U.Length > 0))
+ {
+ /* Allocate memory for the path env var */
+ PathEnvironmentVar_U.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, PathEnvironmentVar_U.Length + sizeof(WCHAR));
+ if (!PathEnvironmentVar_U.Buffer)
+ {
+ DPRINT1("Fatal! Out of Memory!!\n");
+ return STATUS_NO_MEMORY;
+ }
+ PathEnvironmentVar_U.MaximumLength = PathEnvironmentVar_U.Length + sizeof(WCHAR);
+
+ /* Retry */
+ Status = RtlQueryEnvironmentVariable_U(NULL, &PathName_U, &PathEnvironmentVar_U);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Unable to get path environment string!\n");
+ ASSERT(FALSE);
+ }
+ /* Length of path evn var + semicolon */
+ len += (PathEnvironmentVar_U.Length / sizeof(WCHAR)) + 1;
+ }
+ /* Allocate the size needed to hold all the above paths + period */
+ SearchPathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, (len + 2) * sizeof(WCHAR));
+ if (!SearchPathBuffer)
+ {
+ DPRINT1("Fatal! Out of Memory!!\n");
+ return STATUS_NO_MEMORY;
+ }
+
+ wcsncpy(SearchPathBuffer, ImagePathNameBufferPtr, ImagePathLen);
+ wcscat (SearchPathBuffer, L";");
wcscat (SearchPathBuffer, SharedUserData->NtSystemRoot);
wcscat (SearchPathBuffer, L"\\system32;");
wcscat (SearchPathBuffer, SharedUserData->NtSystemRoot);
- wcscat (SearchPathBuffer, L";.");
+ wcscat (SearchPathBuffer, L";");
+
+ if (PathEnvironmentVar_U.Buffer)
+ {
+ wcscat (SearchPathBuffer, PathEnvironmentVar_U.Buffer);
+ wcscat (SearchPathBuffer, L";");
+ RtlFreeHeap(RtlGetProcessHeap(), 0, PathEnvironmentVar_U.Buffer);
+ }
+ wcscat (SearchPathBuffer, L".");
SearchPath = SearchPathBuffer;
}
if(Status == STATUS_SUCCESS)
DPRINT("found %S for %S\n", DosName,DllName->Buffer);
else
- return STATUS_DLL_NOT_FOUND;
+ return STATUS_DLL_NOT_FOUND;
}
if (!RtlDosPathNameToNtPathName_U (DosName,
{
NTSTATUS Status;
PLDR_DATA_TABLE_ENTRY Module;
-
+ ULONG_PTR cookie;
PPEB Peb = NtCurrentPeb();
- TRACE_LDR("LdrLoadDll, loading %wZ%s%S\n",
+ TRACE_LDR("LdrLoadDll loading %wZ%S%S with flags %d\n",
Name,
SearchPath ? L" from " : L"",
- SearchPath ? SearchPath : L"");
+ SearchPath ? SearchPath : L"",
+ LoadFlags ? *LoadFlags : 0);
Status = LdrpLoadModule(SearchPath, LoadFlags ? *LoadFlags : 0, Name, &Module, BaseAddress);
if (NT_SUCCESS(Status) &&
(!LoadFlags || 0 == (*LoadFlags & LOAD_LIBRARY_AS_DATAFILE)))
{
+ if (!create_module_activation_context( Module ))
+ {
+ RtlActivateActivationContext(0, Module->EntryPointActivationContext, &cookie);
+ }
+
if (!(Module->Flags & LDRP_PROCESS_ATTACH_CALLED))
{
RtlEnterCriticalSection(Peb->LoaderLock);
Status = LdrpAttachProcess();
RtlLeaveCriticalSection(Peb->LoaderLock);
}
+ if (Module->EntryPointActivationContext) RtlDeactivateActivationContext(0, cookie);
}
if ((!Module) && (NT_SUCCESS(Status)))
? RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base] )
: NULL);
- if (((ULONG_PTR)Function >= (ULONG_PTR)ExportDir) &&
- ((ULONG_PTR)Function < (ULONG_PTR)ExportDir + (ULONG_PTR)ExportDirSize))
+ if (((ULONG)Function >= (ULONG)ExportDir) &&
+ ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize))
{
DPRINT("Forward: %s\n", (PCHAR)Function);
Function = LdrFixupForward((PCHAR)Function);
{
Ordinal = ExOrdinals[Hint];
Function = RVA(BaseAddress, ExFunctions[Ordinal]);
- if (((ULONG_PTR)Function >= (ULONG_PTR)ExportDir) &&
- ((ULONG_PTR)Function < (ULONG_PTR)ExportDir + (ULONG_PTR)ExportDirSize))
+ if (((ULONG)Function >= (ULONG)ExportDir) &&
+ ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize))
{
DPRINT("Forward: %s\n", (PCHAR)Function);
Function = LdrFixupForward((PCHAR)Function);
{
Ordinal = ExOrdinals[mid];
Function = RVA(BaseAddress, ExFunctions[Ordinal]);
- if (((ULONG_PTR)Function >= (ULONG_PTR)ExportDir) &&
- ((ULONG_PTR)Function < (ULONG_PTR)ExportDir + (ULONG_PTR)ExportDirSize))
+ if (((ULONG)Function >= (ULONG)ExportDir) &&
+ ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize))
{
DPRINT("Forward: %s\n", (PCHAR)Function);
Function = LdrFixupForward((PCHAR)Function);
{
PIMAGE_DATA_DIRECTORY RelocationDDir;
PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
- ULONG Count, OldProtect, OldProtect2;
- SIZE_T ProtectSize;
+ ULONG Count, ProtectSize, OldProtect, OldProtect2;
PVOID Page, ProtectPage, ProtectPage2;
PUSHORT TypeOffset;
ULONG_PTR Delta;
if (Load && !NT_SUCCESS(Status))
{
Status = LdrpLoadModule(SearchPath,
- 0,
+ 0,
&DllName,
Module,
- NULL);
+ NULL);
if (NT_SUCCESS(Status))
{
Status = LdrFindEntryForName (&DllName, Module, FALSE);
PVOID IATBase;
ULONG OldProtect;
ULONG Ordinal;
- SIZE_T IATSize;
+ ULONG IATSize;
if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0)
{
IATSize++;
}
+ /* No need to fixup anything if IAT is empty */
+ if (IATSize == 0) return STATUS_SUCCESS;
+
/* Unprotect the region we are about to write into. */
IATBase = (PVOID)ImportAddressList;
IATSize *= sizeof(PVOID*);
PVOID IATBase;
ULONG OldProtect;
ULONG Offset;
- SIZE_T IATSize;
+ ULONG IATSize;
PIMAGE_NT_HEADERS NTHeaders;
PCHAR Name;
ULONG Size;
PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent;
PIMAGE_TLS_DIRECTORY TlsDirectory;
ULONG TlsSize = 0;
- NTSTATUS Status;
+ NTSTATUS Status = STATUS_SUCCESS;
PLDR_DATA_TABLE_ENTRY ImportedModule;
PCHAR ImportedName;
PWSTR ModulePath;
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to load %s\n", ImportedName);
- return Status;
+ break;
}
Success:
if (Module == ImportedModule)
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to import %s\n", ImportedName);
- return Status;
+ break;
}
ImportModuleDirectoryCurrent++;
}
+
+ if (!NT_SUCCESS(Status))
+ {
+ NTSTATUS errorStatus = Status;
+
+ while (ImportModuleDirectoryCurrent >= ImportModuleDirectory)
+ {
+ ImportedName = (PCHAR)Module->DllBase + ImportModuleDirectoryCurrent->Name;
+
+ Status = LdrpGetOrLoadModule(NULL, ImportedName, &ImportedModule, FALSE);
+ if (NT_SUCCESS(Status) && Module != ImportedModule)
+ {
+ Status = LdrpUnloadModule(ImportedModule, FALSE);
+ if (!NT_SUCCESS(Status)) DPRINT1("unable to unload %s\n", ImportedName);
+ }
+ ImportModuleDirectoryCurrent--;
+ }
+ return errorStatus;
+ }
}
if (TlsDirectory && TlsSize > 0)
if (!NT_SUCCESS(Status))
{
DPRINT1("LdrFixupImports failed for %wZ, status=%x\n", &(*Module)->BaseDllName, Status);
+ NtUnmapViewOfSection (NtCurrentProcess (), ImageBase);
+ NtClose (SectionHandle);
+ RtlFreeUnicodeString (&FullDosName);
+ RtlFreeUnicodeString (&(*Module)->FullDllName);
+ RtlFreeUnicodeString (&(*Module)->BaseDllName);
+ RemoveEntryList (&(*Module)->InLoadOrderLinks);
+ RtlFreeHeap (RtlGetProcessHeap (), 0, Module);
return Status;
}
RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
InsertTailList(&NtCurrentPeb()->Ldr->InInitializationOrderModuleList,
- &(*Module)->InInitializationOrderLinks);
+ &(*Module)->InInitializationOrderModuleList);
RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
}
return STATUS_SUCCESS;
PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent;
PCHAR ImportedName;
PLDR_DATA_TABLE_ENTRY ImportedModule;
- NTSTATUS Status;
+ NTSTATUS Status = 0;
LONG LoadCount;
ULONG Size;
Entry = ModuleListHead->Blink;
while (Entry != ModuleListHead)
{
- Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
+ Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
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 == LDRP_PROCESS_CREATION_TIME ? 1 : 0));
+ LdrpCallDllEntry(Module, DLL_PROCESS_DETACH, (PVOID)(Module->LoadCount == LDRP_PROCESS_CREATION_TIME ? 1 : 0));
}
else
{
Entry = ModuleListHead->Blink;
while (Entry != ModuleListHead)
{
- Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
+ Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
Entry = Entry->Blink;
if (Module->Flags & LDRP_UNLOAD_IN_PROGRESS &&
((UnloadAll && Module->LoadCount != LDRP_PROCESS_CREATION_TIME) || Module->LoadCount == 0))
{
/* remove the module entry from the list */
RemoveEntryList (&Module->InLoadOrderLinks);
- RemoveEntryList (&Module->InInitializationOrderLinks);
+ RemoveEntryList (&Module->InInitializationOrderModuleList);
NtUnmapViewOfSection (NtCurrentProcess (), Module->DllBase);
NtClose (Module->SectionPointer);
Entry = ModuleListHead->Flink;
while (Entry != ModuleListHead)
{
- Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
+ Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
if (!(Module->Flags & (LDRP_LOAD_IN_PROGRESS|LDRP_UNLOAD_IN_PROGRESS|LDRP_ENTRY_PROCESSED)))
{
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 == LDRP_PROCESS_CREATION_TIME ? 1 : 0));
+ Result = LdrpCallDllEntry(Module, DLL_PROCESS_ATTACH, (PVOID)(Module->LoadCount == LDRP_PROCESS_CREATION_TIME ? 1 : 0));
if (!Result)
{
Status = STATUS_DLL_INIT_FAILED;
while (Entry != ModuleListHead)
{
- Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
+ Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
if (Module->Flags & LDRP_PROCESS_ATTACH_CALLED &&
!(Module->Flags & LDRP_DONT_CALL_FOR_THREADS) &&
!(Module->Flags & LDRP_UNLOAD_IN_PROGRESS))
Entry = ModuleListHead->Blink;
while (Entry != ModuleListHead)
{
- Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
+ Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
if (Module->Flags & LDRP_PROCESS_ATTACH_CALLED &&
!(Module->Flags & LDRP_DONT_CALL_FOR_THREADS) &&
LongPtr = (PULONG)((ULONG_PTR)Address + Offset);
*LongPtr += Delta;
break;
-#ifdef _WIN64
- case IMAGE_REL_BASED_DIR64:
- LongPtr = (PULONG)((ULONG_PTR)Address + Offset);
- *LongPtr += Delta;
- break;
-#endif
case IMAGE_REL_BASED_HIGHADJ:
case IMAGE_REL_BASED_MIPS_JMPADDR:
*Cookie = 0;
CookieSet = TRUE;
if (Disposition) *Disposition = 0;
-}
+ }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
if (CookieSet)
}
/* FIXME: Cookie is based on part of the thread id */
- *Cookie = (ULONG_PTR)NtCurrentTeb()->RealClientId.UniqueThread;
+ *Cookie = (ULONG)NtCurrentTeb()->RealClientId.UniqueThread;
return Status;
}
if (Flags != 0x01)
return STATUS_INVALID_PARAMETER_1;
- if (Cookie != (ULONG_PTR)NtCurrentTeb()->RealClientId.UniqueThread)
+ if (Cookie != (ULONG)NtCurrentTeb()->RealClientId.UniqueThread)
return STATUS_INVALID_PARAMETER_2;
RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);