ntdll: Implement compatible section for dll redirects.

This commit is contained in:
Nikolay Sivov 2013-08-04 18:21:09 +04:00 committed by Alexandre Julliard
parent cddea89d22
commit 2a5a8bc4a3
2 changed files with 334 additions and 137 deletions

View File

@ -108,6 +108,7 @@ static const char manifest_wndcls1[] =
"<windowClass versioned=\"yes\">wndClass1</windowClass>"
"<windowClass>wndClass2</windowClass>"
"</file>"
"<file name=\"testlib1_2.dll\" />"
"</assembly>";
static const char manifest_wndcls2[] =
@ -117,6 +118,7 @@ static const char manifest_wndcls2[] =
"<windowClass versioned=\"no\">wndClass3</windowClass>"
"<windowClass>wndClass4</windowClass>"
"</file>"
"<file name=\"testlib2_2.dll\" />"
"</assembly>";
static const char manifest_wndcls_main[] =
@ -754,101 +756,17 @@ static void test_create_fail(void)
test_create_and_fail(manifest2, wrong_depmanifest1, 0 );
}
struct dllredirect_keyed_data
{
ULONG size;
ULONG unk;
DWORD res[3];
};
static void test_find_dll_redirection(HANDLE handle, LPCWSTR libname, ULONG exid, int line)
{
ACTCTX_SECTION_KEYED_DATA data;
BOOL ret;
memset(&data, 0xfe, sizeof(data));
data.cbSize = sizeof(data);
ret = pFindActCtxSectionStringW(0, NULL,
ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
libname, &data);
ok_(__FILE__, line)(ret, "FindActCtxSectionStringW failed: %u\n", GetLastError());
if(!ret)
{
skip("couldn't find %s\n",strw(libname));
return;
}
ok_(__FILE__, line)(data.cbSize == sizeof(data), "data.cbSize=%u\n", data.cbSize);
ok_(__FILE__, line)(data.ulDataFormatVersion == 1, "data.ulDataFormatVersion=%u\n", data.ulDataFormatVersion);
ok_(__FILE__, line)(data.lpData != NULL, "data.lpData == NULL\n");
ok_(__FILE__, line)(data.ulLength == 20, "data.ulLength=%u\n", data.ulLength);
if (data.lpData)
{
struct dllredirect_keyed_data *dlldata = (struct dllredirect_keyed_data*)data.lpData;
todo_wine
ok_(__FILE__, line)(dlldata->size == data.ulLength, "got wrong size %d\n", dlldata->size);
if (dlldata->size == data.ulLength)
{
ok_(__FILE__, line)(dlldata->unk == 2, "got wrong field value %d\n", dlldata->unk);
ok_(__FILE__, line)(dlldata->res[0] == 0, "got wrong res[0] value %d\n", dlldata->res[0]);
ok_(__FILE__, line)(dlldata->res[1] == 0, "got wrong res[1] value %d\n", dlldata->res[1]);
ok_(__FILE__, line)(dlldata->res[2] == 0, "got wrong res[2] value %d\n", dlldata->res[2]);
}
}
ok_(__FILE__, line)(data.lpSectionGlobalData == NULL, "data.lpSectionGlobalData != NULL\n");
ok_(__FILE__, line)(data.ulSectionGlobalDataLength == 0, "data.ulSectionGlobalDataLength=%u\n",
data.ulSectionGlobalDataLength);
ok_(__FILE__, line)(data.lpSectionBase != NULL, "data.lpSectionBase == NULL\n");
/* ok_(__FILE__, line)(data.ulSectionTotalLength == ??, "data.ulSectionTotalLength=%u\n",
data.ulSectionTotalLength); */
ok_(__FILE__, line)(data.hActCtx == NULL, "data.hActCtx=%p\n", data.hActCtx);
ok_(__FILE__, line)(data.ulAssemblyRosterIndex == exid, "data.ulAssemblyRosterIndex=%u, expected %u\n",
data.ulAssemblyRosterIndex, exid);
memset(&data, 0xfe, sizeof(data));
data.cbSize = sizeof(data);
ret = pFindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL,
ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
libname, &data);
ok_(__FILE__, line)(ret, "FindActCtxSectionStringW failed: %u\n", GetLastError());
if(!ret)
{
skip("couldn't find\n");
return;
}
ok_(__FILE__, line)(data.cbSize == sizeof(data), "data.cbSize=%u\n", data.cbSize);
ok_(__FILE__, line)(data.ulDataFormatVersion == 1, "data.ulDataFormatVersion=%u\n", data.ulDataFormatVersion);
ok_(__FILE__, line)(data.lpData != NULL, "data.lpData == NULL\n");
ok_(__FILE__, line)(data.ulLength == 20, "data.ulLength=%u\n", data.ulLength);
ok_(__FILE__, line)(data.lpSectionGlobalData == NULL, "data.lpSectionGlobalData != NULL\n");
ok_(__FILE__, line)(data.ulSectionGlobalDataLength == 0, "data.ulSectionGlobalDataLength=%u\n",
data.ulSectionGlobalDataLength);
ok_(__FILE__, line)(data.lpSectionBase != NULL, "data.lpSectionBase == NULL\n");
/* ok_(__FILE__, line)(data.ulSectionTotalLength == ?? , "data.ulSectionTotalLength=%u\n",
data.ulSectionTotalLength); */
ok_(__FILE__, line)(data.hActCtx == handle, "data.hActCtx=%p\n", data.hActCtx);
ok_(__FILE__, line)(data.ulAssemblyRosterIndex == exid, "data.ulAssemblyRosterIndex=%u, expected %u\n",
data.ulAssemblyRosterIndex, exid);
pReleaseActCtx(handle);
}
struct wndclass_header
struct strsection_header
{
DWORD magic;
DWORD unk1[4];
ULONG size;
DWORD unk1[3];
ULONG count;
ULONG index_offset;
DWORD unk2[4];
};
struct wndclass_index
struct string_index
{
ULONG hash;
ULONG name_offset;
@ -868,10 +786,82 @@ struct wndclass_redirect_data
ULONG module_offset;/* container name offset */
};
struct dllredirect_data
{
ULONG size;
ULONG unk;
DWORD res[3];
};
static void test_find_dll_redirection(HANDLE handle, LPCWSTR libname, ULONG exid, int line)
{
ACTCTX_SECTION_KEYED_DATA data;
BOOL ret;
memset(&data, 0xfe, sizeof(data));
data.cbSize = sizeof(data);
ret = pFindActCtxSectionStringW(0, NULL,
ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
libname, &data);
ok_(__FILE__, line)(ret, "FindActCtxSectionStringW failed: %u\n", GetLastError());
if (!ret) return;
ok_(__FILE__, line)(data.cbSize == sizeof(data), "data.cbSize=%u\n", data.cbSize);
ok_(__FILE__, line)(data.ulDataFormatVersion == 1, "data.ulDataFormatVersion=%u\n", data.ulDataFormatVersion);
ok_(__FILE__, line)(data.lpData != NULL, "data.lpData == NULL\n");
ok_(__FILE__, line)(data.ulLength == 20, "data.ulLength=%u\n", data.ulLength);
if (data.lpData)
{
struct dllredirect_data *dlldata = (struct dllredirect_data*)data.lpData;
ok_(__FILE__, line)(dlldata->size == data.ulLength, "got wrong size %d\n", dlldata->size);
ok_(__FILE__, line)(dlldata->unk == 2, "got wrong field value %d\n", dlldata->unk);
ok_(__FILE__, line)(dlldata->res[0] == 0, "got wrong res[0] value %d\n", dlldata->res[0]);
ok_(__FILE__, line)(dlldata->res[1] == 0, "got wrong res[1] value %d\n", dlldata->res[1]);
ok_(__FILE__, line)(dlldata->res[2] == 0, "got wrong res[2] value %d\n", dlldata->res[2]);
}
ok_(__FILE__, line)(data.lpSectionGlobalData == NULL, "data.lpSectionGlobalData != NULL\n");
ok_(__FILE__, line)(data.ulSectionGlobalDataLength == 0, "data.ulSectionGlobalDataLength=%u\n",
data.ulSectionGlobalDataLength);
ok_(__FILE__, line)(data.lpSectionBase != NULL, "data.lpSectionBase == NULL\n");
ok_(__FILE__, line)(data.ulSectionTotalLength > 0, "data.ulSectionTotalLength=%u\n",
data.ulSectionTotalLength);
ok_(__FILE__, line)(data.hActCtx == NULL, "data.hActCtx=%p\n", data.hActCtx);
ok_(__FILE__, line)(data.ulAssemblyRosterIndex == exid, "data.ulAssemblyRosterIndex=%u, expected %u\n",
data.ulAssemblyRosterIndex, exid);
memset(&data, 0xfe, sizeof(data));
data.cbSize = sizeof(data);
ret = pFindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL,
ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
libname, &data);
ok_(__FILE__, line)(ret, "FindActCtxSectionStringW failed: %u\n", GetLastError());
if (!ret) return;
ok_(__FILE__, line)(data.cbSize == sizeof(data), "data.cbSize=%u\n", data.cbSize);
ok_(__FILE__, line)(data.ulDataFormatVersion == 1, "data.ulDataFormatVersion=%u\n", data.ulDataFormatVersion);
ok_(__FILE__, line)(data.lpData != NULL, "data.lpData == NULL\n");
ok_(__FILE__, line)(data.ulLength == 20, "data.ulLength=%u\n", data.ulLength);
ok_(__FILE__, line)(data.lpSectionGlobalData == NULL, "data.lpSectionGlobalData != NULL\n");
ok_(__FILE__, line)(data.ulSectionGlobalDataLength == 0, "data.ulSectionGlobalDataLength=%u\n",
data.ulSectionGlobalDataLength);
ok_(__FILE__, line)(data.lpSectionBase != NULL, "data.lpSectionBase == NULL\n");
ok_(__FILE__, line)(data.ulSectionTotalLength > 0, "data.ulSectionTotalLength=%u\n",
data.ulSectionTotalLength);
ok_(__FILE__, line)(data.hActCtx == handle, "data.hActCtx=%p\n", data.hActCtx);
ok_(__FILE__, line)(data.ulAssemblyRosterIndex == exid, "data.ulAssemblyRosterIndex=%u, expected %u\n",
data.ulAssemblyRosterIndex, exid);
pReleaseActCtx(handle);
}
static void test_find_window_class(HANDLE handle, LPCWSTR clsname, ULONG exid, int line)
{
struct wndclass_redirect_data *wnddata;
struct wndclass_header *header;
struct strsection_header *header;
ACTCTX_SECTION_KEYED_DATA data;
BOOL ret;
@ -885,7 +875,7 @@ static void test_find_window_class(HANDLE handle, LPCWSTR clsname, ULONG exid, i
wine_dbgstr_w(clsname));
if (!ret) return;
header = (struct wndclass_header*)data.lpSectionBase;
header = (struct strsection_header*)data.lpSectionBase;
wnddata = (struct wndclass_redirect_data*)data.lpData;
ok_(__FILE__, line)(header->magic == 0x64487353, "got wrong magic 0x%08x\n", header->magic);
@ -1143,6 +1133,7 @@ static void test_wndclass_section(void)
static const WCHAR cls1W[] = {'1','.','2','.','3','.','4','!','w','n','d','C','l','a','s','s','1',0};
ACTCTX_SECTION_KEYED_DATA data, data2;
struct wndclass_redirect_data *classdata;
struct strsection_header *section;
ULONG_PTR cookie;
HANDLE handle;
WCHAR *ptrW;
@ -1176,6 +1167,10 @@ static void test_wndclass_section(void)
wndClass3W, &data2);
ok(ret, "got %d\n", ret);
section = (struct strsection_header*)data.lpSectionBase;
ok(section->count == 4, "got %d\n", section->count);
ok(section->size == sizeof(*section), "got %d\n", section->size);
/* For both string same section is returned, meaning it's one wndclass section per context */
ok(data.lpSectionBase == data2.lpSectionBase, "got %p, %p\n", data.lpSectionBase, data2.lpSectionBase);
ok(data.ulSectionTotalLength == data2.ulSectionTotalLength, "got %u, %u\n", data.ulSectionTotalLength,
@ -1196,6 +1191,59 @@ static void test_wndclass_section(void)
pReleaseActCtx(handle);
}
static void test_dllredirect_section(void)
{
static const WCHAR testlib1W[] = {'t','e','s','t','l','i','b','1','.','d','l','l',0};
static const WCHAR testlib2W[] = {'t','e','s','t','l','i','b','2','.','d','l','l',0};
ACTCTX_SECTION_KEYED_DATA data, data2;
struct strsection_header *section;
ULONG_PTR cookie;
HANDLE handle;
BOOL ret;
/* use two dependent manifests, 4 'files' total */
create_manifest_file("testdep1.manifest", manifest_wndcls1, -1, NULL, NULL);
create_manifest_file("testdep2.manifest", manifest_wndcls2, -1, NULL, NULL);
create_manifest_file("main_wndcls.manifest", manifest_wndcls_main, -1, NULL, NULL);
handle = test_create("main_wndcls.manifest");
DeleteFileA("testdep1.manifest");
DeleteFileA("testdep2.manifest");
DeleteFileA("main_wndcls.manifest");
ret = pActivateActCtx(handle, &cookie);
ok(ret, "ActivateActCtx failed: %u\n", GetLastError());
memset(&data, 0, sizeof(data));
memset(&data2, 0, sizeof(data2));
data.cbSize = sizeof(data);
data2.cbSize = sizeof(data2);
/* get data for two files from different assemblies */
ret = pFindActCtxSectionStringW(0, NULL,
ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
testlib1W, &data);
ok(ret, "got %d\n", ret);
ret = pFindActCtxSectionStringW(0, NULL,
ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
testlib2W, &data2);
ok(ret, "got %d\n", ret);
section = (struct strsection_header*)data.lpSectionBase;
ok(section->count == 4, "got %d\n", section->count);
ok(section->size == sizeof(*section), "got %d\n", section->size);
/* For both string same section is returned, meaning it's one dll redirect section per context */
ok(data.lpSectionBase == data2.lpSectionBase, "got %p, %p\n", data.lpSectionBase, data2.lpSectionBase);
ok(data.ulSectionTotalLength == data2.ulSectionTotalLength, "got %u, %u\n", data.ulSectionTotalLength,
data2.ulSectionTotalLength);
ret = pDeactivateActCtx(0, cookie);
ok(ret, "DeactivateActCtx failed: %u\n", GetLastError());
pReleaseActCtx(handle);
}
static void test_actctx(void)
{
ULONG_PTR cookie;
@ -1415,6 +1463,7 @@ static void test_actctx(void)
}
test_wndclass_section();
test_dllredirect_section();
}
static void test_app_manifest(void)

View File

@ -94,19 +94,20 @@ struct assembly_identity
BOOL optional;
};
struct wndclass_header
struct strsection_header
{
DWORD magic;
DWORD unk1[4];
ULONG size;
DWORD unk1[3];
ULONG count;
ULONG index_offset;
DWORD unk2[4];
};
struct wndclass_index
struct string_index
{
ULONG hash; /* original class name hash */
ULONG name_offset; /* original class name offset */
ULONG hash; /* key string hash */
ULONG name_offset;
ULONG name_len;
ULONG data_offset; /* redirect data offset */
ULONG data_len;
@ -123,8 +124,24 @@ struct wndclass_redirect_data
ULONG module_offset;/* container name offset */
};
struct dllredirect_data
{
ULONG size;
ULONG unk;
DWORD res[3];
};
/*
Window class redirection section is a plain buffer with following format:
Sections structure.
Sections are accessible by string or guid key, that defines two types of sections.
All sections of each type have same magic value and header structure, index
data could be of two possible types too. So every string based section uses
the same index format, same applies to guid sections - they share same guid index
format.
- window class redirection section is a plain buffer with following format:
<section header>
<index[]>
@ -133,16 +150,25 @@ struct wndclass_redirect_data
<versioned name>
<module name>
Header is fixed length structure - struct wndclass_header,
Header is fixed length structure - struct strsection_header,
contains redirected classes count;
Index is an array of fixed length index records, each record is
struct wndclass_index.
struct string_index.
All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
others are relative to section itself.
- dll redirect section format:
<section header>
<index[]>
<data[]> --- <dll name>
<data>
This section doesn't seem to carry any payload data except dll names.
*/
struct entity
@ -218,7 +244,8 @@ struct assembly
enum context_sections
{
WINDOWCLASS_SECTION = 1
WINDOWCLASS_SECTION = 1,
DLLREDIRECT_SECTION = 2
};
typedef struct _ACTIVATION_CONTEXT
@ -232,7 +259,8 @@ typedef struct _ACTIVATION_CONTEXT
unsigned int allocated_assemblies;
/* section data */
DWORD sections;
struct wndclass_header *wndclass_section;
struct strsection_header *wndclass_section;
struct strsection_header *dllredirect_section;
} ACTIVATION_CONTEXT;
struct actctx_loader
@ -704,6 +732,7 @@ static void actctx_release( ACTIVATION_CONTEXT *actctx )
RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
actctx->magic = 0;
RtlFreeHeap( GetProcessHeap(), 0, actctx );
@ -1415,6 +1444,9 @@ static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct
}
if (error || !dll->name) return FALSE;
acl->actctx->sections |= DLLREDIRECT_SECTION;
if (end) return TRUE;
while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
@ -2208,26 +2240,43 @@ static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
return status;
}
static NTSTATUS fill_keyed_data(PACTCTX_SECTION_KEYED_DATA data, PVOID v1, PVOID v2, unsigned int i)
static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
{
data->ulDataFormatVersion = 1;
data->lpData = v1;
data->ulLength = 20; /* FIXME */
data->lpSectionGlobalData = NULL; /* FIXME */
data->ulSectionGlobalDataLength = 0; /* FIXME */
data->lpSectionBase = v2;
data->ulSectionTotalLength = 0; /* FIXME */
data->hActCtx = NULL;
if (data->cbSize >= offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
data->ulAssemblyRosterIndex = i + 1;
unsigned int i, j, total_len = 0, dll_count = 0;
struct strsection_header *header;
struct dllredirect_data *data;
struct string_index *index;
ULONG name_offset;
return STATUS_SUCCESS;
}
/* 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];
static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name,
PACTCTX_SECTION_KEYED_DATA data)
{
unsigned int i, j, snlen = section_name->Length / sizeof(WCHAR);
/* each entry needs index, data and string data */
total_len += sizeof(*index);
total_len += sizeof(*data);
total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
}
dll_count += assembly->num_dlls;
}
total_len += sizeof(*header);
header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
if (!header) return STATUS_NO_MEMORY;
memset(header, 0, sizeof(*header));
header->magic = SECTION_MAGIC;
header->size = sizeof(*header);
header->count = dll_count;
header->index_offset = sizeof(*header);
index = (struct string_index*)((BYTE*)header + header->index_offset);
name_offset = header->index_offset + header->count*sizeof(*index);
for (i = 0; i < actctx->num_assemblies; i++)
{
@ -2235,34 +2284,132 @@ static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_S
for (j = 0; j < assembly->num_dlls; j++)
{
struct dll_redirect *dll = &assembly->dlls[j];
if (!strncmpiW(section_name->Buffer, dll->name, snlen) && !dll->name[snlen])
return fill_keyed_data(data, dll, assembly, i);
UNICODE_STRING str;
WCHAR *ptrW;
/* setup new index entry */
str.Buffer = dll->name;
str.Length = strlenW(dll->name)*sizeof(WCHAR);
str.MaximumLength = str.Length + sizeof(WCHAR);
/* hash original class name */
RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
index->name_offset = name_offset;
index->name_len = str.Length;
index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
index->data_len = sizeof(*data);
index->rosterindex = i + 1;
/* setup data */
data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
data->size = sizeof(*data);
data->unk = 2; /* FIXME: seems to be constant */
memset(data->res, 0, sizeof(data->res));
/* dll name */
ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
memcpy(ptrW, dll->name, index->name_len);
ptrW[index->name_len/sizeof(WCHAR)] = 0;
name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
index++;
}
}
return STATUS_SXS_KEY_NOT_FOUND;
*section = header;
return STATUS_SUCCESS;
}
static inline struct wndclass_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
{
return (struct wndclass_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
struct string_index *iter, *index = NULL;
ULONG hash = 0, i;
RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
iter = (struct string_index*)((BYTE*)section + section->index_offset);
for (i = 0; i < section->count; i++)
{
if (iter->hash == hash)
{
const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
if (!strcmpW(nameW, name->Buffer))
{
index = iter;
break;
}
else
WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
}
iter++;
}
return index;
}
static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct wndclass_index *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);
}
static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
PACTCTX_SECTION_KEYED_DATA data)
{
struct dllredirect_data *dll;
struct string_index *index;
if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
if (!actctx->dllredirect_section)
{
struct strsection_header *section;
NTSTATUS status = build_dllredirect_section(actctx, &section);
if (status) return status;
if (interlocked_cmpxchg_ptr((void**)&actctx->dllredirect_section, section, NULL))
RtlFreeHeap(GetProcessHeap(), 0, section);
}
index = find_string_index(actctx->dllredirect_section, name);
if (!index) return STATUS_SXS_KEY_NOT_FOUND;
dll = get_dllredirect_data(actctx, index);
data->ulDataFormatVersion = 1;
data->lpData = dll;
data->ulLength = dll->size;
data->lpSectionGlobalData = NULL;
data->ulSectionGlobalDataLength = 0;
data->lpSectionBase = actctx->dllredirect_section;
data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
data->hActCtx = NULL;
if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
data->ulAssemblyRosterIndex = index->rosterindex;
return STATUS_SUCCESS;
}
static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
{
return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
}
static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
{
return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
}
static inline ULONG get_assembly_rosterindex(ACTIVATION_CONTEXT *actctx, const struct assembly* assembly)
{
return (assembly - actctx->assemblies) + 1;
}
static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct wndclass_header **section)
static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
{
unsigned int i, j, k, total_len = 0, class_count = 0;
struct wndclass_redirect_data *data;
struct wndclass_header *header;
struct wndclass_index *index;
struct strsection_header *header;
struct string_index *index;
ULONG name_offset;
/* compute section length */
@ -2281,8 +2428,8 @@ static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct wndcla
int len;
/* each class entry needs index, data and string data */
total_len += sizeof(struct wndclass_index);
total_len += sizeof(struct wndclass_redirect_data);
total_len += sizeof(*index);
total_len += sizeof(*data);
/* original name is stored separately */
total_len += aligned_string_len(class_len*sizeof(WCHAR));
/* versioned name and module name are stored one after another */
@ -2306,9 +2453,10 @@ static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct wndcla
memset(header, 0, sizeof(*header));
header->magic = SECTION_MAGIC;
header->size = sizeof(*header);
header->count = class_count;
header->index_offset = sizeof(*header);
index = (struct wndclass_index*)((BYTE*)header + header->index_offset);
index = (struct string_index*)((BYTE*)header + header->index_offset);
name_offset = header->index_offset + header->count*sizeof(*index);
for (i = 0; i < actctx->num_assemblies; i++)
@ -2345,7 +2493,7 @@ static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct wndcla
index->name_len = str.Length;
index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
index->rosterindex = get_assembly_rosterindex(actctx, assembly);
index->rosterindex = i + 1;
/* setup data */
data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
@ -2397,7 +2545,7 @@ static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct wndcla
static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
PACTCTX_SECTION_KEYED_DATA data)
{
struct wndclass_index *iter, *index = NULL;
struct string_index *iter, *index = NULL;
struct wndclass_redirect_data *class;
ULONG hash;
int i;
@ -2406,7 +2554,7 @@ static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRI
if (!actctx->wndclass_section)
{
struct wndclass_header *section;
struct strsection_header *section;
NTSTATUS status = build_wndclass_section(actctx, &section);
if (status) return status;