ntdll: Implement compatible section for dll redirects.
This commit is contained in:
parent
cddea89d22
commit
2a5a8bc4a3
|
@ -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)
|
||||
|
|
|
@ -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, §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;
|
||||
|
|
Loading…
Reference in New Issue