mirror of
https://github.com/reactos/reactos.git
synced 2024-10-01 23:14:53 +00:00
[ACTCTX]
- Improve and rewrite a few active context support functions in RTL, making them more close to their real functionality and throwing away wineisms. - Uncomment a line in RtlAllocateActivationContextStack() which was causing it to always allocate a new activation context stack even if there was one. Thanks to my previous commit in kernel32 counterpart, this hack is not needed anymore and memory won't be wasted. - Since we have mostly Wine's code in our activation context implementation, it makes sense to use it properly until it's rewritten, so first of all: - Properly initialize current process's activation context support by calling actctx_init() from LdrpInitializeProcess instead of calling it all the time when a new context is created. - Bring in create_module_activation_context and find_actctx_dll (newer version from Wine which supports manifests/assmeblies in local directories) and use it. Every place where it's used is marked as a HACK so it will be easy to detach it later. - Remove actctx-related hack LdrpInitializeThread, now it works properly. - Fix a typo in LdrpMapDll found by rafalh. Now the error-detection condition will be correctly evaluated. See issue #6611 for more details. svn path=/trunk/; revision=54623
This commit is contained in:
parent
c3ae29cc85
commit
417b739dbe
|
@ -87,6 +87,7 @@ ULONG RtlpDisableHeapLookaside; // TODO: Move to heap.c
|
|||
ULONG RtlpShutdownProcessFlags; // TODO: Use it
|
||||
|
||||
NTSTATUS LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders, PVOID ImageBase);
|
||||
void actctx_init(void);
|
||||
|
||||
#ifdef _WIN64
|
||||
#define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll
|
||||
|
@ -504,19 +505,11 @@ LdrpInitializeThread(IN PCONTEXT Context)
|
|||
NtCurrentTeb()->RealClientId.UniqueThread);
|
||||
|
||||
/* Allocate an Activation Context Stack */
|
||||
/* FIXME: This is a hack for Wine's actctx stuff */
|
||||
DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer);
|
||||
if (!(NtCurrentTeb()->ActivationContextStackPointer))
|
||||
Status = RtlAllocateActivationContextStack((PVOID*)&NtCurrentTeb()->ActivationContextStackPointer);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
Status = RtlAllocateActivationContextStack((PVOID*)&NtCurrentTeb()->ActivationContextStackPointer);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer);
|
||||
DPRINT("ActiveFrame %p\n", ((PACTIVATION_CONTEXT_STACK)NtCurrentTeb()->ActivationContextStackPointer)->ActiveFrame);
|
||||
NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NULL;
|
||||
}
|
||||
else
|
||||
DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
|
||||
DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
|
||||
}
|
||||
|
||||
/* Make sure we are not shutting down */
|
||||
|
@ -1946,6 +1939,9 @@ LdrpInitializeProcess(IN PCONTEXT Context,
|
|||
InsertHeadList(&Peb->Ldr->InInitializationOrderModuleList,
|
||||
&LdrpNtDllDataTableEntry->InInitializationOrderModuleList);
|
||||
|
||||
/* Initialize Wine's active context implementation for the current process */
|
||||
actctx_init();
|
||||
|
||||
/* Set the current directory */
|
||||
Status = RtlSetCurrentDirectory_U(&CurrentDirectory);
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
|
|
@ -20,6 +20,122 @@ BOOLEAN g_ShimsEnabled;
|
|||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
/* NOTE: Remove those two once our actctx support becomes better */
|
||||
NTSTATUS create_module_activation_context( LDR_DATA_TABLE_ENTRY *module )
|
||||
{
|
||||
NTSTATUS status;
|
||||
LDR_RESOURCE_INFO info;
|
||||
IMAGE_RESOURCE_DATA_ENTRY *entry;
|
||||
|
||||
info.Type = (ULONG)RT_MANIFEST;
|
||||
info.Name = (ULONG)ISOLATIONAWARE_MANIFEST_RESOURCE_ID;
|
||||
info.Language = 0;
|
||||
if (!(status = LdrFindResource_U( module->DllBase, &info, 3, &entry )))
|
||||
{
|
||||
ACTCTXW ctx;
|
||||
ctx.cbSize = sizeof(ctx);
|
||||
ctx.lpSource = NULL;
|
||||
ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
|
||||
ctx.hModule = module->DllBase;
|
||||
ctx.lpResourceName = (LPCWSTR)ISOLATIONAWARE_MANIFEST_RESOURCE_ID;
|
||||
status = RtlCreateActivationContext( &module->EntryPointActivationContext, &ctx );
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS find_actctx_dll( LPCWSTR libname, WCHAR *fullname )
|
||||
{
|
||||
static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\',0};
|
||||
static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
|
||||
|
||||
ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *info;
|
||||
ACTCTX_SECTION_KEYED_DATA data;
|
||||
UNICODE_STRING nameW;
|
||||
NTSTATUS status;
|
||||
SIZE_T needed, size = 1024;
|
||||
WCHAR *p;
|
||||
|
||||
RtlInitUnicodeString( &nameW, libname );
|
||||
data.cbSize = sizeof(data);
|
||||
status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL,
|
||||
ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
|
||||
&nameW, &data );
|
||||
if (status != STATUS_SUCCESS) return status;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!(info = RtlAllocateHeap( RtlGetProcessHeap(), 0, size )))
|
||||
{
|
||||
status = STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
status = RtlQueryInformationActivationContext( 0, data.hActCtx, &data.ulAssemblyRosterIndex,
|
||||
AssemblyDetailedInformationInActivationContext,
|
||||
info, size, &needed );
|
||||
if (status == STATUS_SUCCESS) break;
|
||||
if (status != STATUS_BUFFER_TOO_SMALL) goto done;
|
||||
RtlFreeHeap( RtlGetProcessHeap(), 0, info );
|
||||
size = needed;
|
||||
}
|
||||
|
||||
DPRINT("manifestpath === %S\n", info->lpAssemblyManifestPath);
|
||||
DPRINT("DirectoryName === %S\n", info->lpAssemblyDirectoryName);
|
||||
if (!info->lpAssemblyManifestPath || !info->lpAssemblyDirectoryName)
|
||||
{
|
||||
status = STATUS_SXS_KEY_NOT_FOUND;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((p = wcsrchr( info->lpAssemblyManifestPath, '\\' )))
|
||||
{
|
||||
DWORD dirlen = info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
|
||||
|
||||
p++;
|
||||
if (_wcsnicmp( p, info->lpAssemblyDirectoryName, dirlen ) || wcsicmp( p + dirlen, dotManifestW ))
|
||||
{
|
||||
/* manifest name does not match directory name, so it's not a global
|
||||
* windows/winsxs manifest; use the manifest directory name instead */
|
||||
dirlen = p - info->lpAssemblyManifestPath;
|
||||
needed = (dirlen + 1) * sizeof(WCHAR) + nameW.Length;
|
||||
|
||||
p = fullname;
|
||||
/*if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed )))
|
||||
{
|
||||
status = STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}*/
|
||||
memcpy( p, info->lpAssemblyManifestPath, dirlen * sizeof(WCHAR) );
|
||||
p += dirlen;
|
||||
wcscpy( p, libname );
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
needed = (wcslen(SharedUserData->NtSystemRoot) * sizeof(WCHAR) +
|
||||
sizeof(winsxsW) + info->ulAssemblyDirectoryNameLength + nameW.Length + 2*sizeof(WCHAR));
|
||||
|
||||
//if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed )))
|
||||
//{
|
||||
//status = STATUS_NO_MEMORY;
|
||||
//goto done;
|
||||
//}
|
||||
wcscpy( p, SharedUserData->NtSystemRoot );
|
||||
p += wcslen(p);
|
||||
memcpy( p, winsxsW, sizeof(winsxsW) );
|
||||
p += sizeof(winsxsW) / sizeof(WCHAR);
|
||||
memcpy( p, info->lpAssemblyDirectoryName, info->ulAssemblyDirectoryNameLength );
|
||||
p += info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
|
||||
*p++ = '\\';
|
||||
wcscpy( p, libname );
|
||||
|
||||
done:
|
||||
RtlFreeHeap( RtlGetProcessHeap(), 0, info );
|
||||
RtlReleaseActivationContext( data.hActCtx );
|
||||
DPRINT("%S\n", fullname);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LdrpAllocateUnicodeString(IN OUT PUNICODE_STRING StringOut,
|
||||
|
@ -559,6 +675,7 @@ LdrpResolveDllName(PWSTR DllPath,
|
|||
PWCHAR NameBuffer, p1, p2 = 0;
|
||||
ULONG Length;
|
||||
ULONG BufSize = 500;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Allocate space for full DLL name */
|
||||
FullDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufSize + sizeof(UNICODE_NULL));
|
||||
|
@ -573,14 +690,25 @@ LdrpResolveDllName(PWSTR DllPath,
|
|||
|
||||
if (!Length || Length > BufSize)
|
||||
{
|
||||
if (ShowSnaps)
|
||||
/* HACK: Try to find active context dll */
|
||||
Status = find_actctx_dll(DllName, FullDllName->Buffer);
|
||||
if(Status == STATUS_SUCCESS)
|
||||
{
|
||||
DPRINT1("LDR: LdrResolveDllName - Unable to find ");
|
||||
DPRINT1("%ws from %ws\n", DllName, DllPath ? DllPath : LdrpDefaultPath.Buffer);
|
||||
Length = wcslen(FullDllName->Buffer) * sizeof(WCHAR);
|
||||
DPRINT1("found %S for %S\n", FullDllName->Buffer, DllName);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NOTE: This code should remain after removing the hack */
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: LdrResolveDllName - Unable to find ");
|
||||
DPRINT1("%ws from %ws\n", DllName, DllPath ? DllPath : LdrpDefaultPath.Buffer);
|
||||
}
|
||||
|
||||
RtlFreeUnicodeString(FullDllName);
|
||||
return FALSE;
|
||||
RtlFreeUnicodeString(FullDllName);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct full DLL name */
|
||||
|
@ -1269,7 +1397,7 @@ SkipCheck:
|
|||
}
|
||||
|
||||
/* Check if this was a non-relocatable DLL or a known dll */
|
||||
if (!RelocatableDll && KnownDll)
|
||||
if (!RelocatableDll || KnownDll)
|
||||
{
|
||||
/* Setup for hard error */
|
||||
HardErrorParameters[0] = (ULONG_PTR)&IllegalDll;
|
||||
|
@ -1847,7 +1975,7 @@ LdrpCheckForLoadedDll(IN PWSTR DllPath,
|
|||
PVOID ViewBase = NULL;
|
||||
SIZE_T ViewSize = 0;
|
||||
PIMAGE_NT_HEADERS NtHeader, NtHeader2;
|
||||
DPRINT("LdrpCheckForLoadedDll('%S' '%wZ' %d %d %p)\n", DllPath, DllName, Flag, RedirectedDll, LdrEntry);
|
||||
DPRINT("LdrpCheckForLoadedDll('%S' '%wZ' %d %d %p)\n", DllPath ? ((ULONG_PTR)DllPath == 1 ? L"" : DllPath) : L"", DllName, Flag, RedirectedDll, LdrEntry);
|
||||
|
||||
/* Check if a dll name was provided */
|
||||
if (!(DllName->Buffer) || !(DllName->Buffer[0])) return FALSE;
|
||||
|
@ -1910,6 +2038,16 @@ lookinhash:
|
|||
/* Check if that was successful */
|
||||
if (!(Length) || (Length > (sizeof(NameBuf) - sizeof(UNICODE_NULL))))
|
||||
{
|
||||
/* HACK: Try to find active context dll */
|
||||
Status = find_actctx_dll(DllName->Buffer, FullDllName.Buffer);
|
||||
if(Status == STATUS_SUCCESS)
|
||||
{
|
||||
Length = wcslen(FullDllName.Buffer) * sizeof(WCHAR);
|
||||
DPRINT1("found %S for %S\n", FullDllName.Buffer, DllName->Buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: LdrpCheckForLoadedDll - Unable To Locate %ws: 0x%08x\n",
|
||||
|
@ -1918,6 +2056,7 @@ lookinhash:
|
|||
|
||||
/* Return failure */
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Full dll name is found */
|
||||
|
|
|
@ -1659,6 +1659,9 @@ static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assemb
|
|||
IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
|
||||
void *ptr;
|
||||
|
||||
//DPRINT( "looking for res %s in module %p %s\n", resname,
|
||||
// hModule, filename );
|
||||
|
||||
#if 0
|
||||
if (TRACE_ON(actctx))
|
||||
{
|
||||
|
@ -2427,20 +2430,42 @@ RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
RtlFreeActivationContextStack(PACTIVATION_CONTEXT_STACK Stack)
|
||||
{
|
||||
PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, PrevFrame;
|
||||
|
||||
/* Nothing to do if there is no stack */
|
||||
if (!Stack) return;
|
||||
|
||||
/* Get the current active frame */
|
||||
ActiveFrame = Stack->ActiveFrame;
|
||||
|
||||
/* Go through them in backwards order and release */
|
||||
while (ActiveFrame)
|
||||
{
|
||||
PrevFrame = ActiveFrame->Previous;
|
||||
RtlReleaseActivationContext(ActiveFrame->ActivationContext);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveFrame);
|
||||
ActiveFrame = PrevFrame;
|
||||
}
|
||||
|
||||
/* Zero out the active frame */
|
||||
Stack->ActiveFrame = NULL;
|
||||
|
||||
/* TODO: Empty the Frame List Cache */
|
||||
ASSERT(IsListEmpty(&Stack->FrameListCache));
|
||||
|
||||
/* Free activation stack memory */
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, Stack);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI RtlFreeThreadActivationContextStack(void)
|
||||
{
|
||||
RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
|
||||
|
||||
frame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
|
||||
while (frame)
|
||||
{
|
||||
RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
|
||||
RtlReleaseActivationContext( frame->ActivationContext );
|
||||
RtlFreeHeap( RtlGetProcessHeap(), 0, frame );
|
||||
frame = prev;
|
||||
}
|
||||
NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NULL;
|
||||
RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer);
|
||||
NtCurrentTeb()->ActivationContextStackPointer = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2757,17 +2782,22 @@ RtlAllocateActivationContextStack(IN PVOID *Context)
|
|||
{
|
||||
PACTIVATION_CONTEXT_STACK ContextStack;
|
||||
|
||||
/* FIXME: Check if it's already allocated */
|
||||
//if (*Context) return STATUS_SUCCESS;
|
||||
/* Check if it's already allocated */
|
||||
if (*Context) return STATUS_SUCCESS;
|
||||
|
||||
/* Allocate space for the context stack */
|
||||
ContextStack = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (ACTIVATION_CONTEXT_STACK) );
|
||||
if (!ContextStack)
|
||||
{
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
ContextStack->ActiveFrame = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
|
||||
if (!ContextStack->ActiveFrame) return STATUS_NO_MEMORY;
|
||||
/* Initialize the context stack */
|
||||
ContextStack->Flags = 0;
|
||||
ContextStack->ActiveFrame = NULL;
|
||||
InitializeListHead(&ContextStack->FrameListCache);
|
||||
ContextStack->NextCookieSequenceNumber = 1;
|
||||
ContextStack->StackId = 1; //TODO: Timer-based
|
||||
|
||||
*Context = ContextStack;
|
||||
|
||||
|
|
Loading…
Reference in a new issue