diff --git a/dlls/kernel32/tests/actctx.c b/dlls/kernel32/tests/actctx.c
index 234fa9d937f..ed38571d4df 100644
--- a/dlls/kernel32/tests/actctx.c
+++ b/dlls/kernel32/tests/actctx.c
@@ -108,6 +108,7 @@ static const char manifest_wndcls1[] =
"wndClass1"
"wndClass2"
""
+""
"";
static const char manifest_wndcls2[] =
@@ -117,6 +118,7 @@ static const char manifest_wndcls2[] =
"wndClass3"
"wndClass4"
""
+""
"";
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)
diff --git a/dlls/ntdll/actctx.c b/dlls/ntdll/actctx.c
index d5f7055d96e..7280b4cb9a2 100644
--- a/dlls/ntdll/actctx.c
+++ b/dlls/ntdll/actctx.c
@@ -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:
@@ -133,16 +150,25 @@ struct wndclass_redirect_data
- 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:
+
+
+
+ ---
+
+
+ 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, §ion);
+ 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, §ion);
if (status) return status;