* PROJECT: ReactOS Runtime Library
* PURPOSE: Activation Context Support
* FILE: lib/rtl/actctx.c
- * PROGRAMERS:
+ * PROGRAMERS:
* Jon Griffiths
* Eric Pouech
* Jacek Caban for CodeWeavers
BOOLEAN RtlpNotAllowingMultipleActivation;
-#define QUERY_ACTCTX_FLAG_ACTIVE (0x00000001)
-
#define ACTCTX_FLAGS_ALL (\
ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
ACTCTX_FLAG_LANGID_VALID |\
static const WCHAR iidW[] = {'i','i','d',0};
static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
-static const WCHAR nameW[] = {'n','a','m','e',0};
+static const WCHAR g_nameW[] = {'n','a','m','e',0};
static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
-static const WCHAR xmlW[] = {'?','x','m','l',0};
+static const WCHAR g_xmlW[] = {'?','x','m','l',0};
static const WCHAR manifestv1W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','1',0};
static const WCHAR manifestv3W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','3',0};
UNICODE_STRING res;
res.Buffer = (PWSTR)xmlstr->ptr;
- res.Length = res.MaximumLength = xmlstr->len * sizeof(WCHAR);
+ res.Length = res.MaximumLength = (USHORT)xmlstr->len * sizeof(WCHAR);
return res;
}
{',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
static const WCHAR public_keyW[] =
{',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
- static const WCHAR typeW[] =
- {',','t','y','p','e','=',0};
- static const WCHAR versionW[] =
- {',','v','e','r','s','i','o','n','=',0};
WCHAR version[64], *ret;
SIZE_T size = 0;
sprintfW( version, version_formatW,
ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
- if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
+ if (ai->name) size += strlenW(ai->name);
if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
- if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2;
- size += strlenW(versionW) + strlenW(version) + 2;
+ if (ai->type) size += 1 + strlenW(typeW) + 1 + strlenW(ai->type) + 2;
+ size += 1+ strlenW(versionW) + 1 + strlenW(version) + 2;
if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
return NULL;
if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
name->ptr = xmlbuf->ptr;
- name->len = ptr-xmlbuf->ptr;
+ name->len = (ULONG)(ptr - xmlbuf->ptr);
xmlbuf->ptr = ptr;
ptr++;
return FALSE;
}
- value->len = ptr - value->ptr;
+ value->len = (ULONG)(ptr - value->ptr);
xmlbuf->ptr = ptr + 1;
if (xmlbuf->ptr == xmlbuf->end) return FALSE;
ptr++;
elem->ptr = xmlbuf->ptr;
- elem->len = ptr - xmlbuf->ptr;
+ elem->len = (ULONG)(ptr - xmlbuf->ptr);
xmlbuf->ptr = ptr;
return xmlbuf->ptr != xmlbuf->end;
}
if (!ptr) return FALSE;
content->ptr = xmlbuf->ptr;
- content->len = ptr - xmlbuf->ptr;
+ content->len = (ULONG)(ptr - xmlbuf->ptr);
xmlbuf->ptr = ptr;
return TRUE;
while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
{
- if (xmlstr_cmp(&attr_name, nameW))
+ if (xmlstr_cmp(&attr_name, g_nameW))
{
if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
}
{
if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
}
- if (xmlstr_cmp(&attr_name, nameW))
+ if (xmlstr_cmp(&attr_name, g_nameW))
{
if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
}
{
if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
}
- if (xmlstr_cmp(&attr_name, nameW))
+ if (xmlstr_cmp(&attr_name, g_nameW))
{
if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
}
while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
{
- if (xmlstr_cmp(&attr_name, nameW))
+ if (xmlstr_cmp(&attr_name, g_nameW))
{
if (!(entity->u.clrclass.name = xmlstrdupW(&attr_value))) return FALSE;
}
while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
{
- if (xmlstr_cmp(&attr_name, nameW))
+ if (xmlstr_cmp(&attr_name, g_nameW))
{
if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
}
attr_nameU = xmlstr2unicode(&attr_name);
attr_valueU = xmlstr2unicode(&attr_value);
- if (xmlstr_cmp(&attr_name, nameW))
+ if (xmlstr_cmp(&attr_name, g_nameW))
{
if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
DPRINT("name=%wZ\n", &attr_valueU);
if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
- if (xmlstr_cmp(&elem, xmlW) &&
+ if (xmlstr_cmp(&elem, g_xmlW) &&
(!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
return STATUS_SXS_CANT_GEN_ACTCTX;
: ACTIVATION_CONTEXT_PATH_TYPE_NONE;
unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
- if (RtlIsTextUnicode( (PVOID) buffer, size, &unicode_tests ))
+ if (RtlIsTextUnicode((PVOID)buffer, (ULONG)size, &unicode_tests ))
{
xmlbuf.ptr = buffer;
xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
}
else
{
- /* let's assume utf-8 for now */
- int len;
- WCHAR *new_buff;
+ /* TODO: this doesn't handle arbitrary encodings */
+ ANSI_STRING xmlA;
+ UNICODE_STRING xmlW;
+
+ ASSERT(size < MAXUSHORT);
+ xmlA.Buffer = (PCHAR)buffer;
+ xmlA.Length = xmlA.MaximumLength = (USHORT)size;
_SEH2_TRY
{
- len = mbstowcs( NULL, buffer, size);
+ status = RtlAnsiStringToUnicodeString(&xmlW, &xmlA, TRUE);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
}
_SEH2_END;
- DPRINT("len = %x\n", len);
-
- if (len == -1)
+ if (!NT_SUCCESS(status))
{
- DPRINT1( "utf-8 conversion failed\n" );
+ DPRINT1("RtlAnsiStringToUnicodeString failed with %lx\n", status);
return STATUS_SXS_CANT_GEN_ACTCTX;
}
- if (!(new_buff = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, len)))
- return STATUS_NO_MEMORY;
-
- mbstowcs( new_buff, buffer, size);
- xmlbuf.ptr = new_buff;
+ ASSERT(xmlW.Buffer != NULL);
- xmlbuf.end = xmlbuf.ptr + len / sizeof(WCHAR);
+ xmlbuf.ptr = xmlW.Buffer;
+ xmlbuf.end = xmlbuf.ptr + xmlW.Length / sizeof(WCHAR);
status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
- RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff );
+ RtlFreeUnicodeString(&xmlW);
}
return status;
}
return NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
}
-static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
+static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, USHORT extra_len )
{
NTSTATUS status;
ULONG magic;
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))
{
status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileStandardInformation);
if (status == STATUS_SUCCESS)
- status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
+ status = parse_manifest(acl, ai, filename, directory, shared, base, (SIZE_T)info.EndOfFile.QuadPart);
NtUnmapViewOfSection( NtCurrentProcess(), base );
NtClose( mapping );
WCHAR *tmp;
ULONG build, revision;
- data_len = io.Information;
+ data_len = (ULONG)io.Information;
for (;;)
{
NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
FileBothDirectoryInformation, FALSE, &lookup_us, FALSE );
if (io.Status != STATUS_SUCCESS) break;
- data_len = io.Information;
+ data_len = (ULONG)io.Information;
data_pos = 0;
}
dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
revision = atoiW(tmp);
if (build == ai->version.build && revision < ai->version.revision)
continue;
- ai->version.build = build;
- ai->version.revision = revision;
+ ai->version.build = (USHORT)build;
+ ai->version.revision = (USHORT)revision;
if ((ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info->FileNameLength * sizeof(WCHAR) )))
{
if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
- if (!(path = RtlAllocateHeap( RtlGetProcessHeap(), 0,
+ if (!(path = RtlAllocateHeap( RtlGetProcessHeap(), 0,
((strlenW(SharedUserData->NtSystemRoot) + 1) *sizeof(WCHAR)) + sizeof(manifest_dirW) )))
return STATUS_NO_MEMORY;
UNICODE_STRING nameW;
HANDLE file;
- DPRINT1( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
+ DPRINT( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
ai->name, ai->version.major, ai->version.minor, ai->version.build, ai->version.revision, ai->arch );
if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
}
NTSTATUS
-NTAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
+NTAPI RtlActivateActivationContextEx( ULONG flags, PTEB tebAddress, HANDLE handle, PULONG_PTR cookie )
{
RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
if (!(frame = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame) )))
return STATUS_NO_MEMORY;
- frame->Previous = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
+ frame->Previous = tebAddress->ActivationContextStackPointer->ActiveFrame;
frame->ActivationContext = handle;
frame->Flags = 0;
- NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame;
+ tebAddress->ActivationContextStackPointer->ActiveFrame = frame;
RtlAddRefActivationContext( handle );
*cookie = (ULONG_PTR)frame;
}
+NTSTATUS
+NTAPI RtlActivateActivationContext( ULONG flags, HANDLE handle, PULONG_PTR cookie )
+{
+ return RtlActivateActivationContextEx(flags, NtCurrentTeb(), handle, cookie);
+}
+
NTSTATUS
NTAPI
RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
}
VOID
-NTAPI RtlFreeThreadActivationContextStack(void)
+NTAPI
+RtlFreeActivationContextStack(PACTIVATION_CONTEXT_STACK Stack)
{
- RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
+ PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, PrevFrame;
- frame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
- while (frame)
+ /* 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)
{
- RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
- RtlReleaseActivationContext( frame->ActivationContext );
- RtlFreeHeap( RtlGetProcessHeap(), 0, frame );
- frame = prev;
+ PrevFrame = ActiveFrame->Previous;
+ RtlReleaseActivationContext(ActiveFrame->ActivationContext);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveFrame);
+ ActiveFrame = PrevFrame;
}
- NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NULL;
+
+ /* 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)
+{
+ RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer);
+ NtCurrentTeb()->ActivationContextStackPointer = NULL;
}
acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
acdi->ulAssemblyCount = actctx->num_assemblies;
acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
- acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
+ acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? (DWORD)manifest_len - 1 : 0;
acdi->ulRootConfigurationPathType = actctx->config.type;
- acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
+ acdi->ulRootConfigurationPathChars = actctx->config.info ? (DWORD)config_len - 1 : 0;
acdi->ulAppDirPathType = actctx->appdir.type;
- acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
+ acdi->ulAppDirPathChars = actctx->appdir.info ? (DWORD)appdir_len - 1 : 0;
ptr = (LPWSTR)(acdi + 1);
if (manifest_len)
{
}
afdi->ulFlags = 0; /* FIXME */
- afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
+ afdi->ulEncodedAssemblyIdentityLength = (DWORD)(id_len - 1) * sizeof(WCHAR);
afdi->ulManifestPathType = assembly->manifest.type;
- afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
+ afdi->ulManifestPathLength = assembly->manifest.info ? (DWORD)(path_len - 1) * sizeof(WCHAR) : 0;
/* FIXME afdi->liManifestLastWriteTime = 0; */
afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
afdi->ulPolicyPathLength = 0;
afdi->ulManifestVersionMinor = 0;
afdi->ulPolicyVersionMajor = 0; /* FIXME */
afdi->ulPolicyVersionMinor = 0; /* FIXME */
- afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
+ afdi->ulAssemblyDirectoryNameLength = ad_len ? (DWORD)(ad_len - 1) * sizeof(WCHAR) : 0;
ptr = (LPWSTR)(afdi + 1);
afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
}
if (retlen) *retlen = 0; /* yes that's what native does !! */
afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
- afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
+ afdi->ulFilenameLength = dll_len ? (DWORD)(dll_len - 1) * sizeof(WCHAR) : 0;
afdi->ulPathLength = 0; /* FIXME */
ptr = (LPWSTR)(afdi + 1);
if (dll_len)
return STATUS_SUCCESS;
}
+NTSTATUS
+NTAPI
+RtlQueryInformationActiveActivationContext(ULONG ulInfoClass,
+ PVOID pvBuffer,
+ SIZE_T cbBuffer OPTIONAL,
+ SIZE_T *pcbWrittenOrRequired OPTIONAL)
+{
+ return RtlQueryInformationActivationContext(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX,
+ NULL,
+ NULL,
+ ulInfoClass,
+ pvBuffer,
+ cbBuffer,
+ pcbWrittenOrRequired);
+}
+
#define FIND_ACTCTX_RETURN_FLAGS 0x00000002
#define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004
#define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
status = STATUS_SXS_KEY_NOT_FOUND;
+ /* if there is no data, but params are valid,
+ we return that sxs key is not found to be at least somehow compatible */
+ if (!data) return status;
+
ASSERT(NtCurrentTeb());
ASSERT(NtCurrentTeb()->ActivationContextStackPointer);
RtlAllocateActivationContextStack(IN PVOID *Context)
{
PACTIVATION_CONTEXT_STACK ContextStack;
+
+ /* 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;
- /* FIXME: Documentation on MSDN reads that activation contexts are only created
- for modules that have a valid manifest file or resource */
- actctx_init();
-
return STATUS_SUCCESS;
}
/* Return pointer to the activation frame */
return &Frame->Frame;
#else
- return NULL;
+
+ RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame = &Frame->Frame;
+
+ frame->Previous = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
+ frame->ActivationContext = Context;
+ frame->Flags = 0;
+
+ NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame;
+
+ return STATUS_SUCCESS;
#endif
}
FASTCALL
RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame)
{
-#if NEW_NTDLL_LOADER
- RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
+ RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
+ //RTL_ACTIVATION_CONTEXT_STACK_FRAME *top;
/* find the right frame */
- top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
+ //top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
frame = &Frame->Frame;
if (!frame)
+ {
+ DPRINT1("No top frame!\n");
RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
+ }
/* pop everything up to and including frame */
NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous;
return frame;
-#else
- return NULL;
-#endif
}