Author: fireball Date: Fri Dec 9 10:33:09 2011 New Revision: 54623
URL: http://svn.reactos.org/svn/reactos?rev=54623&view=rev Log: [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.
Modified: trunk/reactos/dll/ntdll/ldr/ldrinit.c trunk/reactos/dll/ntdll/ldr/ldrutils.c trunk/reactos/lib/rtl/actctx.c
Modified: trunk/reactos/dll/ntdll/ldr/ldrinit.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/ldr/ldrinit.c?rev... ============================================================================== --- trunk/reactos/dll/ntdll/ldr/ldrinit.c [iso-8859-1] (original) +++ trunk/reactos/dll/ntdll/ldr/ldrinit.c [iso-8859-1] Fri Dec 9 10:33:09 2011 @@ -87,6 +87,7 @@ 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 @@ 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)) - { - 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"); + Status = RtlAllocateActivationContextStack((PVOID*)&NtCurrentTeb()->ActivationContextStackPointer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Warning: Unable to allocate ActivationContextStack\n"); }
/* Make sure we are not shutting down */ @@ -1946,6 +1939,9 @@ 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))
Modified: trunk/reactos/dll/ntdll/ldr/ldrutils.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/ldr/ldrutils.c?re... ============================================================================== --- trunk/reactos/dll/ntdll/ldr/ldrutils.c [iso-8859-1] (original) +++ trunk/reactos/dll/ntdll/ldr/ldrutils.c [iso-8859-1] Fri Dec 9 10:33:09 2011 @@ -19,6 +19,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 @@ -559,6 +675,7 @@ 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 @@
if (!Length || Length > BufSize) { - if (ShowSnaps) - { - DPRINT1("LDR: LdrResolveDllName - Unable to find "); - DPRINT1("%ws from %ws\n", DllName, DllPath ? DllPath : LdrpDefaultPath.Buffer); - } - - RtlFreeUnicodeString(FullDllName); - return FALSE; + /* HACK: Try to find active context dll */ + Status = find_actctx_dll(DllName, FullDllName->Buffer); + if(Status == STATUS_SUCCESS) + { + 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; + } }
/* Construct full DLL name */ @@ -1269,7 +1397,7 @@ }
/* 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 @@ 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 @@ /* 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 @@
/* Return failure */ return FALSE; + } }
/* Full dll name is found */
Modified: trunk/reactos/lib/rtl/actctx.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/actctx.c?rev=54623&... ============================================================================== --- trunk/reactos/lib/rtl/actctx.c [iso-8859-1] (original) +++ trunk/reactos/lib/rtl/actctx.c [iso-8859-1] Fri Dec 9 10:33:09 2011 @@ -1659,6 +1659,9 @@ 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)) { @@ -2428,19 +2431,41 @@ }
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 @@ { 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;