* 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 );
/* FUNCTIONS *****************************************************************/
RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
}
LoadCount = Module->LoadCount;
- if (Module->LoadCount > 0 && Module->LoadCount != LDRP_PROCESS_CREATION_TIME)
- {
+ if (Module->LoadCount > 0 && Module->LoadCount != LDRP_PROCESS_CREATION_TIME)
+ {
Module->LoadCount--;
- }
+ }
if (!Locked)
{
RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
}
LoadCount = Module->LoadCount;
- if (Module->LoadCount != LDRP_PROCESS_CREATION_TIME)
- {
+ if (Module->LoadCount != LDRP_PROCESS_CREATION_TIME)
+ {
Module->LoadCount++;
- }
+ }
if (!Locked)
{
RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
/* Copy it to the heap allocd memory */
Path = RtlAllocateHeap(RtlGetProcessHeap(),
0,
- wcslen(SearchPathBuffer) * sizeof(WCHAR));
+ (wcslen(SearchPathBuffer) + 1) * sizeof(WCHAR));
if (!Path)
{
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;
}
MAX_PATH,
DosName,
NULL) == 0)
- return STATUS_DLL_NOT_FOUND;
+ {
+ /* try to find active context dll */
+ Status = find_actctx_dll(DllName->Buffer, DosName);
+ if(Status == STATUS_SUCCESS)
+ DPRINT("found %S for %S\n", DosName,DllName->Buffer);
+ else
+ return STATUS_DLL_NOT_FOUND;
+ }
if (!RtlDosPathNameToNtPathName_U (DosName,
&FullNtFileName,
NULL,
NULL))
+ {
+ DPRINT("Dll %wZ not found!\n", DllName);
return STATUS_DLL_NOT_FOUND;
+ }
DPRINT("FullNtFileName %wZ\n", &FullNtFileName);
{
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)))
ULONG Count, ProtectSize, OldProtect, OldProtect2;
PVOID Page, ProtectPage, ProtectPage2;
PUSHORT TypeOffset;
- ULONG_PTR Delta;
+ LONG_PTR Delta;
NTSTATUS Status;
if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
if (Load && !NT_SUCCESS(Status))
{
Status = LdrpLoadModule(SearchPath,
- 0,
+ 0,
&DllName,
Module,
- NULL);
+ NULL);
if (NT_SUCCESS(Status))
{
Status = LdrFindEntryForName (&DllName, Module, FALSE);
if (!NT_SUCCESS(Status))
{
ULONG ErrorResponse;
- ULONG_PTR ErrorParameter = (ULONG_PTR)&DllName;
+ ULONG_PTR ErrorParameter = (ULONG_PTR)&AnsiDllName;
DPRINT1("failed to load %wZ\n", &DllName);
+
NtRaiseHardError(STATUS_DLL_NOT_FOUND,
1,
1,
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*);
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;
ULONG Size;
+ ULONG_PTR cookie;
DPRINT("LdrFixupImports(SearchPath %S, Module %p)\n", SearchPath, Module);
}
}
+ if (!create_module_activation_context( Module ))
+ {
+ if (Module->EntryPointActivationContext == NULL)
+ {
+ DPRINT("EntryPointActivationContext has not be allocated\n");
+ DPRINT("Module->DllBaseName %wZ\n", Module->BaseDllName);
+ }
+ RtlActivateActivationContext( 0, Module->EntryPointActivationContext, &cookie );
+ }
+
/*
* Process each import module.
*/
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)
LdrpAcquireTlsSlot(Module, TlsSize, FALSE);
}
+ if (Module->EntryPointActivationContext) RtlDeactivateActivationContext( 0, cookie );
+
return STATUS_SUCCESS;
}
PIMAGE_DOS_HEADER DosHeader;
PIMAGE_NT_HEADERS NTHeaders;
PLDR_DATA_TABLE_ENTRY tmpModule;
+ PVOID ActivationContextStack;
DPRINT("LdrPEStartup(ImageBase %p SectionHandle %p)\n",
ImageBase, SectionHandle);
(*Module)->Flags |= LDRP_IMAGE_NOT_AT_BASE;
}
+ /* Allocate memory for the ActivationContextStack */
+ /* FIXME: Verify RtlAllocateActivationContextStack behavior */
+ Status = RtlAllocateActivationContextStack(&ActivationContextStack);
+ if (NT_SUCCESS(Status))
+ {
+ DPRINT("ActivationContextStack %x\n",ActivationContextStack);
+ DPRINT("ActiveFrame %x\n", ((PACTIVATION_CONTEXT_STACK)ActivationContextStack)->ActiveFrame);
+ NtCurrentTeb()->ActivationContextStackPointer = ActivationContextStack;
+ NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NULL;
+ }
+ else
+ DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
+
/*
* If the DLL's imports symbols from other
* modules, fixup the imported calls entry points.
/* Map the dll into the process */
ViewSize = 0;
ImageBase = 0;
- ArbitraryUserPointer = NtCurrentTeb()->Tib.ArbitraryUserPointer;
- NtCurrentTeb()->Tib.ArbitraryUserPointer = FullDosName.Buffer;
+ ArbitraryUserPointer = NtCurrentTeb()->NtTib.ArbitraryUserPointer;
+ NtCurrentTeb()->NtTib.ArbitraryUserPointer = FullDosName.Buffer;
Status = NtMapViewOfSection(SectionHandle,
NtCurrentProcess(),
&ImageBase,
ViewShare,
0,
PAGE_READONLY);
- NtCurrentTeb()->Tib.ArbitraryUserPointer = ArbitraryUserPointer;
+ NtCurrentTeb()->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
if (!NT_SUCCESS(Status))
{
DPRINT1("map view of section failed (Status 0x%08lx)\n", Status);
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;
}
PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent;
PCHAR ImportedName;
PLDR_DATA_TABLE_ENTRY ImportedModule;
- NTSTATUS Status;
+ NTSTATUS Status = 0;
LONG LoadCount;
ULONG Size;
OUT PULONG ReturnedLength OPTIONAL)
{
PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
+ CHAR KeyInfoBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 32];
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING ValueNameString;
UNICODE_STRING KeyName;
return Status;
}
- KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 32;
- KeyInfo = RtlAllocateHeap (RtlGetProcessHeap(),
- HEAP_ZERO_MEMORY,
- KeyInfoSize);
- if (KeyInfo == NULL)
- {
- NtClose (KeyHandle);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
+ KeyInfoSize = sizeof(KeyInfoBuffer);
+ KeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfoBuffer;
RtlInitUnicodeString (&ValueNameString,
(PWSTR)ValueName);
&ResultSize);
if (Status == STATUS_BUFFER_OVERFLOW)
{
+ /* We can allocate only if there is a process heap already */
+ if (!RtlGetProcessHeap())
+ {
+ NtClose (KeyHandle);
+ return STATUS_NO_MEMORY;
+ }
KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + KeyInfo->DataLength;
- RtlFreeHeap (RtlGetProcessHeap(),
- 0,
- KeyInfo);
KeyInfo = RtlAllocateHeap (RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
KeyInfoSize);
if (!NT_SUCCESS(Status))
{
- if (KeyInfo != NULL)
+ if ((PCHAR)KeyInfo != KeyInfoBuffer)
{
RtlFreeHeap (RtlGetProcessHeap(),
0,
if (KeyInfo->Type != Type)
{
- RtlFreeHeap (RtlGetProcessHeap(),
- 0,
- KeyInfo);
+ if ((PCHAR)KeyInfo != KeyInfoBuffer)
+ {
+ RtlFreeHeap (RtlGetProcessHeap(),
+ 0,
+ KeyInfo);
+ }
return STATUS_OBJECT_TYPE_MISMATCH;
}
&KeyInfo->Data,
ResultSize);
- RtlFreeHeap (RtlGetProcessHeap(),
- 0,
- KeyInfo);
+ if ((PCHAR)KeyInfo != KeyInfoBuffer)
+ {
+ RtlFreeHeap (RtlGetProcessHeap(),
+ 0,
+ KeyInfo);
+ }
if (ReturnedLength != NULL)
{
}
-PIMAGE_BASE_RELOCATION NTAPI
-LdrProcessRelocationBlock(IN ULONG_PTR Address,
- IN ULONG Count,
- IN PUSHORT TypeOffset,
- IN LONG_PTR Delta)
+PIMAGE_BASE_RELOCATION
+NTAPI
+LdrProcessRelocationBlock(
+ IN ULONG_PTR Address,
+ IN ULONG Count,
+ IN PUSHORT TypeOffset,
+ IN LONG_PTR Delta)
{
- SHORT Offset;
- USHORT Type;
- USHORT i;
- PUSHORT ShortPtr;
- PULONG LongPtr;
-
- for (i = 0; i < Count; i++)
- {
- Offset = *TypeOffset & 0xFFF;
- Type = *TypeOffset >> 12;
-
- switch (Type)
- {
- case IMAGE_REL_BASED_ABSOLUTE:
- break;
-
- case IMAGE_REL_BASED_HIGH:
- ShortPtr = (PUSHORT)((ULONG_PTR)Address + Offset);
- *ShortPtr += HIWORD(Delta);
- break;
-
- case IMAGE_REL_BASED_LOW:
- ShortPtr = (PUSHORT)((ULONG_PTR)Address + Offset);
- *ShortPtr += LOWORD(Delta);
- break;
-
- case IMAGE_REL_BASED_HIGHLOW:
- LongPtr = (PULONG)((ULONG_PTR)Address + Offset);
- *LongPtr += Delta;
- break;
-
- case IMAGE_REL_BASED_HIGHADJ:
- case IMAGE_REL_BASED_MIPS_JMPADDR:
- default:
- DPRINT1("Unknown/unsupported fixup type %hu.\n", Type);
- return NULL;
- }
-
- TypeOffset++;
- }
-
- return (PIMAGE_BASE_RELOCATION)TypeOffset;
+ return LdrProcessRelocationBlockLongLong(Address, Count, TypeOffset, Delta);
}
NTSTATUS