ntdll: Implement compatible typelib section.
This commit is contained in:
parent
1ca7eb649c
commit
36acd61447
|
@ -1319,9 +1319,7 @@ static void test_typelib_section(void)
|
|||
ret = pFindActCtxSectionGuid(0, NULL,
|
||||
ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION,
|
||||
&IID_TlibTest, &data);
|
||||
todo_wine
|
||||
ok(ret, "got %d\n", ret);
|
||||
if (!ret) return;
|
||||
|
||||
ret = pFindActCtxSectionGuid(0, NULL,
|
||||
ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION,
|
||||
|
|
|
@ -51,7 +51,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(actctx);
|
|||
ACTCTX_FLAG_HMODULE_VALID )
|
||||
|
||||
#define ACTCTX_MAGIC 0xC07E3E11
|
||||
#define SECTION_MAGIC 0x64487353
|
||||
#define STRSECTION_MAGIC 0x64487353 /* dHsS */
|
||||
#define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
|
||||
|
||||
/* we don't want to include winuser.h */
|
||||
#define RT_MANIFEST ((ULONG_PTR)24)
|
||||
|
@ -122,6 +123,26 @@ struct string_index
|
|||
ULONG rosterindex;
|
||||
};
|
||||
|
||||
struct guidsection_header
|
||||
{
|
||||
DWORD magic;
|
||||
ULONG size;
|
||||
DWORD unk[3];
|
||||
ULONG count;
|
||||
ULONG index_offset;
|
||||
DWORD unk2;
|
||||
ULONG names_offset;
|
||||
ULONG names_len;
|
||||
};
|
||||
|
||||
struct guid_index
|
||||
{
|
||||
GUID guid;
|
||||
ULONG data_offset;
|
||||
ULONG data_len;
|
||||
ULONG rosterindex;
|
||||
};
|
||||
|
||||
struct wndclass_redirect_data
|
||||
{
|
||||
ULONG size;
|
||||
|
@ -139,6 +160,20 @@ struct dllredirect_data
|
|||
DWORD res[3];
|
||||
};
|
||||
|
||||
struct tlibredirect_data
|
||||
{
|
||||
ULONG size;
|
||||
DWORD res;
|
||||
ULONG name_len;
|
||||
ULONG name_offset;
|
||||
LANGID langid;
|
||||
WORD flags;
|
||||
ULONG help_len;
|
||||
ULONG help_offset;
|
||||
WORD major_version;
|
||||
WORD minor_version;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
Sections structure.
|
||||
|
@ -177,6 +212,21 @@ struct dllredirect_data
|
|||
<data>
|
||||
|
||||
This section doesn't seem to carry any payload data except dll names.
|
||||
|
||||
- typelib section format:
|
||||
|
||||
<section header>
|
||||
<module names[]>
|
||||
<index[]>
|
||||
<data[]> --- <data>
|
||||
<helpstring>
|
||||
|
||||
Header is fixed length, index is an array of fixed length 'struct guid_index'.
|
||||
All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
|
||||
4-bytes aligned as a whole.
|
||||
|
||||
Module name offsets are relative to section, helpstring offset is relative to data
|
||||
structure itself.
|
||||
*/
|
||||
|
||||
struct entity
|
||||
|
@ -254,8 +304,9 @@ struct assembly
|
|||
|
||||
enum context_sections
|
||||
{
|
||||
WINDOWCLASS_SECTION = 1,
|
||||
DLLREDIRECT_SECTION = 2
|
||||
WINDOWCLASS_SECTION = 1,
|
||||
DLLREDIRECT_SECTION = 2,
|
||||
TLIBREDIRECT_SECTION = 4
|
||||
};
|
||||
|
||||
typedef struct _ACTIVATION_CONTEXT
|
||||
|
@ -269,8 +320,9 @@ typedef struct _ACTIVATION_CONTEXT
|
|||
unsigned int allocated_assemblies;
|
||||
/* section data */
|
||||
DWORD sections;
|
||||
struct strsection_header *wndclass_section;
|
||||
struct strsection_header *dllredirect_section;
|
||||
struct strsection_header *wndclass_section;
|
||||
struct strsection_header *dllredirect_section;
|
||||
struct guidsection_header *tlib_section;
|
||||
} ACTIVATION_CONTEXT;
|
||||
|
||||
struct actctx_loader
|
||||
|
@ -1156,7 +1208,7 @@ error:
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
|
||||
static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
|
||||
{
|
||||
xmlstr_t attr_name, attr_value;
|
||||
BOOL end = FALSE, error;
|
||||
|
@ -1189,7 +1241,12 @@ static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
|
|||
}
|
||||
}
|
||||
|
||||
if (error || end) return end;
|
||||
if (error) return FALSE;
|
||||
|
||||
acl->actctx->sections |= TLIBREDIRECT_SECTION;
|
||||
|
||||
if (end) return TRUE;
|
||||
|
||||
return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
|
||||
}
|
||||
|
||||
|
@ -1555,7 +1612,7 @@ static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct
|
|||
}
|
||||
else if (xmlstr_cmp(&elem, typelibW))
|
||||
{
|
||||
ret = parse_typelib_elem(xmlbuf, dll);
|
||||
ret = parse_typelib_elem(xmlbuf, dll, acl);
|
||||
}
|
||||
else if (xmlstr_cmp(&elem, windowClassW))
|
||||
{
|
||||
|
@ -2355,7 +2412,7 @@ static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct str
|
|||
if (!header) return STATUS_NO_MEMORY;
|
||||
|
||||
memset(header, 0, sizeof(*header));
|
||||
header->magic = SECTION_MAGIC;
|
||||
header->magic = STRSECTION_MAGIC;
|
||||
header->size = sizeof(*header);
|
||||
header->count = dll_count;
|
||||
header->index_offset = sizeof(*header);
|
||||
|
@ -2434,6 +2491,26 @@ static struct string_index *find_string_index(const struct strsection_header *se
|
|||
return index;
|
||||
}
|
||||
|
||||
static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
|
||||
{
|
||||
struct guid_index *iter, *index = NULL;
|
||||
ULONG i;
|
||||
|
||||
iter = (struct guid_index*)((BYTE*)section + section->index_offset);
|
||||
|
||||
for (i = 0; i < section->count; i++)
|
||||
{
|
||||
if (!memcmp(guid, &iter->guid, sizeof(*guid)))
|
||||
{
|
||||
index = iter;
|
||||
break;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
|
||||
{
|
||||
return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
|
||||
|
@ -2536,7 +2613,7 @@ static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsec
|
|||
if (!header) return STATUS_NO_MEMORY;
|
||||
|
||||
memset(header, 0, sizeof(*header));
|
||||
header->magic = SECTION_MAGIC;
|
||||
header->magic = STRSECTION_MAGIC;
|
||||
header->size = sizeof(*header);
|
||||
header->count = class_count;
|
||||
header->index_offset = sizeof(*header);
|
||||
|
@ -2688,6 +2765,174 @@ static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRI
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
|
||||
{
|
||||
unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
|
||||
struct guidsection_header *header;
|
||||
ULONG module_offset, data_offset;
|
||||
struct tlibredirect_data *data;
|
||||
struct guid_index *index;
|
||||
|
||||
/* compute section length */
|
||||
for (i = 0; i < actctx->num_assemblies; i++)
|
||||
{
|
||||
struct assembly *assembly = &actctx->assemblies[i];
|
||||
for (j = 0; j < assembly->num_dlls; j++)
|
||||
{
|
||||
struct dll_redirect *dll = &assembly->dlls[j];
|
||||
for (k = 0; k < dll->entities.num; k++)
|
||||
{
|
||||
struct entity *entity = &dll->entities.base[k];
|
||||
if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
|
||||
{
|
||||
/* each entry needs index, data and string data for module name and help string */
|
||||
total_len += sizeof(*index);
|
||||
total_len += sizeof(*data);
|
||||
/* help string is stored separately */
|
||||
if (*entity->u.typelib.helpdir)
|
||||
total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
|
||||
|
||||
/* module names are packed one after another */
|
||||
names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
|
||||
|
||||
tlib_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
total_len += aligned_string_len(names_len);
|
||||
total_len += sizeof(*header);
|
||||
|
||||
header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
|
||||
if (!header) return STATUS_NO_MEMORY;
|
||||
|
||||
memset(header, 0, sizeof(*header));
|
||||
header->magic = GUIDSECTION_MAGIC;
|
||||
header->size = sizeof(*header);
|
||||
header->count = tlib_count;
|
||||
header->index_offset = sizeof(*header) + aligned_string_len(names_len);
|
||||
index = (struct guid_index*)((BYTE*)header + header->index_offset);
|
||||
module_offset = sizeof(*header);
|
||||
data_offset = header->index_offset + tlib_count*sizeof(*index);
|
||||
|
||||
for (i = 0; i < actctx->num_assemblies; i++)
|
||||
{
|
||||
struct assembly *assembly = &actctx->assemblies[i];
|
||||
for (j = 0; j < assembly->num_dlls; j++)
|
||||
{
|
||||
struct dll_redirect *dll = &assembly->dlls[j];
|
||||
for (k = 0; k < dll->entities.num; k++)
|
||||
{
|
||||
struct entity *entity = &dll->entities.base[k];
|
||||
if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
|
||||
{
|
||||
ULONG module_len, help_len;
|
||||
UNICODE_STRING str;
|
||||
WCHAR *ptrW;
|
||||
|
||||
if (*entity->u.typelib.helpdir)
|
||||
help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
|
||||
else
|
||||
help_len = 0;
|
||||
|
||||
module_len = strlenW(dll->name)*sizeof(WCHAR);
|
||||
|
||||
/* setup new index entry */
|
||||
RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
|
||||
RtlGUIDFromString(&str, &index->guid);
|
||||
index->data_offset = data_offset;
|
||||
index->data_len = sizeof(*data) + aligned_string_len(help_len);
|
||||
index->rosterindex = i + 1;
|
||||
|
||||
/* setup data */
|
||||
data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
|
||||
data->size = sizeof(*data);
|
||||
data->res = 0;
|
||||
data->name_len = module_len;
|
||||
data->name_offset = module_offset;
|
||||
/* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
|
||||
data->langid = 0;
|
||||
data->flags = entity->u.typelib.flags;
|
||||
data->help_len = help_len;
|
||||
data->help_offset = sizeof(*data);
|
||||
data->major_version = entity->u.typelib.major;
|
||||
data->minor_version = entity->u.typelib.minor;
|
||||
|
||||
/* module name */
|
||||
ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
|
||||
memcpy(ptrW, dll->name, data->name_len);
|
||||
ptrW[data->name_len/sizeof(WCHAR)] = 0;
|
||||
|
||||
/* help string */
|
||||
if (data->help_len)
|
||||
{
|
||||
ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
|
||||
memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
|
||||
ptrW[data->help_len/sizeof(WCHAR)] = 0;
|
||||
}
|
||||
|
||||
data_offset += sizeof(*data);
|
||||
if (help_len)
|
||||
data_offset += aligned_string_len(help_len + sizeof(WCHAR));
|
||||
|
||||
module_offset += module_len + sizeof(WCHAR);
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*section = header;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
|
||||
{
|
||||
return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
|
||||
}
|
||||
|
||||
static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
|
||||
{
|
||||
struct guid_index *index = NULL;
|
||||
struct tlibredirect_data *tlib;
|
||||
|
||||
if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
|
||||
|
||||
if (!actctx->tlib_section)
|
||||
{
|
||||
struct guidsection_header *section;
|
||||
|
||||
NTSTATUS status = build_tlib_section(actctx, §ion);
|
||||
if (status) return status;
|
||||
|
||||
if (interlocked_cmpxchg_ptr((void**)&actctx->tlib_section, section, NULL))
|
||||
RtlFreeHeap(GetProcessHeap(), 0, section);
|
||||
}
|
||||
|
||||
index = find_guid_index(actctx->tlib_section, guid);
|
||||
if (!index) return STATUS_SXS_KEY_NOT_FOUND;
|
||||
|
||||
tlib = get_tlib_data(actctx, index);
|
||||
|
||||
data->ulDataFormatVersion = 1;
|
||||
data->lpData = tlib;
|
||||
/* full length includes string length with nulls */
|
||||
data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
|
||||
data->lpSectionGlobalData = NULL;
|
||||
data->ulSectionGlobalDataLength = 0;
|
||||
data->lpSectionBase = actctx->tlib_section;
|
||||
data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
|
||||
data->hActCtx = NULL;
|
||||
|
||||
if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
|
||||
data->ulAssemblyRosterIndex = index->rosterindex;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
|
||||
const UNICODE_STRING *section_name,
|
||||
DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
|
||||
|
@ -2702,9 +2947,6 @@ static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
|
|||
case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
|
||||
status = find_window_class(actctx, section_name, data);
|
||||
break;
|
||||
case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
|
||||
case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
|
||||
case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
|
||||
case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
|
||||
case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
|
||||
case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
|
||||
|
@ -2725,6 +2967,35 @@ static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
|
||||
const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
switch (section_kind)
|
||||
{
|
||||
case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
|
||||
status = find_tlib_redirection(actctx, guid, data);
|
||||
break;
|
||||
case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
|
||||
case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
|
||||
FIXME("Unsupported yet section_kind %x\n", section_kind);
|
||||
return STATUS_SXS_SECTION_NOT_FOUND;
|
||||
default:
|
||||
WARN("Unknown section_kind %x\n", section_kind);
|
||||
return STATUS_SXS_SECTION_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (status != STATUS_SUCCESS) return status;
|
||||
|
||||
if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
|
||||
{
|
||||
actctx_addref(actctx);
|
||||
data->hActCtx = actctx;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* initialize the activation context for the current process */
|
||||
void actctx_init(void)
|
||||
{
|
||||
|
@ -3244,8 +3515,9 @@ NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *ex
|
|||
const GUID *guid, void *ptr )
|
||||
{
|
||||
ACTCTX_SECTION_KEYED_DATA *data = ptr;
|
||||
NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
|
||||
|
||||
FIXME("%08x %s %u %s %p: stub\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
|
||||
TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
|
||||
|
||||
if (extguid)
|
||||
{
|
||||
|
@ -3262,5 +3534,14 @@ NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *ex
|
|||
if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
|
||||
{
|
||||
ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
|
||||
if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
|
||||
}
|
||||
|
||||
if (status != STATUS_SUCCESS)
|
||||
status = find_guid( process_actctx, section_kind, guid, flags, data );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue