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=54623&r1=54622&r2=54623&view=diff
==============================================================================
--- 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?rev=54623&r1=54622&r2=54623&view=diff
==============================================================================
--- 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&r1=54622&r2=54623&view=diff
==============================================================================
--- 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;
 


Reply via email to