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;