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?re…
==============================================================================
--- 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?r…
==============================================================================
--- 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;