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 versioned=\"yes\">wndClass1</windowClass>"
|
||||||
"<windowClass>wndClass2</windowClass>"
|
"<windowClass>wndClass2</windowClass>"
|
||||||
"</file>"
|
"</file>"
|
||||||
|
"<file name=\"testlib1_2.dll\" />"
|
||||||
"</assembly>";
|
"</assembly>";
|
||||||
|
|
||||||
static const char manifest_wndcls2[] =
|
static const char manifest_wndcls2[] =
|
||||||
|
@ -117,6 +118,7 @@ static const char manifest_wndcls2[] =
|
||||||
"<windowClass versioned=\"no\">wndClass3</windowClass>"
|
"<windowClass versioned=\"no\">wndClass3</windowClass>"
|
||||||
"<windowClass>wndClass4</windowClass>"
|
"<windowClass>wndClass4</windowClass>"
|
||||||
"</file>"
|
"</file>"
|
||||||
|
"<file name=\"testlib2_2.dll\" />"
|
||||||
"</assembly>";
|
"</assembly>";
|
||||||
|
|
||||||
static const char manifest_wndcls_main[] =
|
static const char manifest_wndcls_main[] =
|
||||||
|
@ -754,101 +756,17 @@ static void test_create_fail(void)
|
||||||
test_create_and_fail(manifest2, wrong_depmanifest1, 0 );
|
test_create_and_fail(manifest2, wrong_depmanifest1, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dllredirect_keyed_data
|
struct strsection_header
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
DWORD magic;
|
DWORD magic;
|
||||||
DWORD unk1[4];
|
ULONG size;
|
||||||
|
DWORD unk1[3];
|
||||||
ULONG count;
|
ULONG count;
|
||||||
ULONG index_offset;
|
ULONG index_offset;
|
||||||
DWORD unk2[4];
|
DWORD unk2[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wndclass_index
|
struct string_index
|
||||||
{
|
{
|
||||||
ULONG hash;
|
ULONG hash;
|
||||||
ULONG name_offset;
|
ULONG name_offset;
|
||||||
|
@ -868,10 +786,82 @@ struct wndclass_redirect_data
|
||||||
ULONG module_offset;/* container name offset */
|
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)
|
static void test_find_window_class(HANDLE handle, LPCWSTR clsname, ULONG exid, int line)
|
||||||
{
|
{
|
||||||
struct wndclass_redirect_data *wnddata;
|
struct wndclass_redirect_data *wnddata;
|
||||||
struct wndclass_header *header;
|
struct strsection_header *header;
|
||||||
ACTCTX_SECTION_KEYED_DATA data;
|
ACTCTX_SECTION_KEYED_DATA data;
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
|
||||||
|
@ -885,7 +875,7 @@ static void test_find_window_class(HANDLE handle, LPCWSTR clsname, ULONG exid, i
|
||||||
wine_dbgstr_w(clsname));
|
wine_dbgstr_w(clsname));
|
||||||
if (!ret) return;
|
if (!ret) return;
|
||||||
|
|
||||||
header = (struct wndclass_header*)data.lpSectionBase;
|
header = (struct strsection_header*)data.lpSectionBase;
|
||||||
wnddata = (struct wndclass_redirect_data*)data.lpData;
|
wnddata = (struct wndclass_redirect_data*)data.lpData;
|
||||||
|
|
||||||
ok_(__FILE__, line)(header->magic == 0x64487353, "got wrong magic 0x%08x\n", header->magic);
|
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};
|
static const WCHAR cls1W[] = {'1','.','2','.','3','.','4','!','w','n','d','C','l','a','s','s','1',0};
|
||||||
ACTCTX_SECTION_KEYED_DATA data, data2;
|
ACTCTX_SECTION_KEYED_DATA data, data2;
|
||||||
struct wndclass_redirect_data *classdata;
|
struct wndclass_redirect_data *classdata;
|
||||||
|
struct strsection_header *section;
|
||||||
ULONG_PTR cookie;
|
ULONG_PTR cookie;
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
WCHAR *ptrW;
|
WCHAR *ptrW;
|
||||||
|
@ -1176,6 +1167,10 @@ static void test_wndclass_section(void)
|
||||||
wndClass3W, &data2);
|
wndClass3W, &data2);
|
||||||
ok(ret, "got %d\n", ret);
|
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 */
|
/* 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.lpSectionBase == data2.lpSectionBase, "got %p, %p\n", data.lpSectionBase, data2.lpSectionBase);
|
||||||
ok(data.ulSectionTotalLength == data2.ulSectionTotalLength, "got %u, %u\n", data.ulSectionTotalLength,
|
ok(data.ulSectionTotalLength == data2.ulSectionTotalLength, "got %u, %u\n", data.ulSectionTotalLength,
|
||||||
|
@ -1196,6 +1191,59 @@ static void test_wndclass_section(void)
|
||||||
pReleaseActCtx(handle);
|
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)
|
static void test_actctx(void)
|
||||||
{
|
{
|
||||||
ULONG_PTR cookie;
|
ULONG_PTR cookie;
|
||||||
|
@ -1415,6 +1463,7 @@ static void test_actctx(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
test_wndclass_section();
|
test_wndclass_section();
|
||||||
|
test_dllredirect_section();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_app_manifest(void)
|
static void test_app_manifest(void)
|
||||||
|
|
|
@ -94,19 +94,20 @@ struct assembly_identity
|
||||||
BOOL optional;
|
BOOL optional;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wndclass_header
|
struct strsection_header
|
||||||
{
|
{
|
||||||
DWORD magic;
|
DWORD magic;
|
||||||
DWORD unk1[4];
|
ULONG size;
|
||||||
|
DWORD unk1[3];
|
||||||
ULONG count;
|
ULONG count;
|
||||||
ULONG index_offset;
|
ULONG index_offset;
|
||||||
DWORD unk2[4];
|
DWORD unk2[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wndclass_index
|
struct string_index
|
||||||
{
|
{
|
||||||
ULONG hash; /* original class name hash */
|
ULONG hash; /* key string hash */
|
||||||
ULONG name_offset; /* original class name offset */
|
ULONG name_offset;
|
||||||
ULONG name_len;
|
ULONG name_len;
|
||||||
ULONG data_offset; /* redirect data offset */
|
ULONG data_offset; /* redirect data offset */
|
||||||
ULONG data_len;
|
ULONG data_len;
|
||||||
|
@ -123,8 +124,24 @@ struct wndclass_redirect_data
|
||||||
ULONG module_offset;/* container name offset */
|
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>
|
<section header>
|
||||||
<index[]>
|
<index[]>
|
||||||
|
@ -133,16 +150,25 @@ struct wndclass_redirect_data
|
||||||
<versioned name>
|
<versioned name>
|
||||||
<module name>
|
<module name>
|
||||||
|
|
||||||
Header is fixed length structure - struct wndclass_header,
|
Header is fixed length structure - struct strsection_header,
|
||||||
contains redirected classes count;
|
contains redirected classes count;
|
||||||
|
|
||||||
Index is an array of fixed length index records, each record is
|
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.
|
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),
|
Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
|
||||||
others are relative to section itself.
|
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
|
struct entity
|
||||||
|
@ -218,7 +244,8 @@ struct assembly
|
||||||
|
|
||||||
enum context_sections
|
enum context_sections
|
||||||
{
|
{
|
||||||
WINDOWCLASS_SECTION = 1
|
WINDOWCLASS_SECTION = 1,
|
||||||
|
DLLREDIRECT_SECTION = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _ACTIVATION_CONTEXT
|
typedef struct _ACTIVATION_CONTEXT
|
||||||
|
@ -232,7 +259,8 @@ typedef struct _ACTIVATION_CONTEXT
|
||||||
unsigned int allocated_assemblies;
|
unsigned int allocated_assemblies;
|
||||||
/* section data */
|
/* section data */
|
||||||
DWORD sections;
|
DWORD sections;
|
||||||
struct wndclass_header *wndclass_section;
|
struct strsection_header *wndclass_section;
|
||||||
|
struct strsection_header *dllredirect_section;
|
||||||
} ACTIVATION_CONTEXT;
|
} ACTIVATION_CONTEXT;
|
||||||
|
|
||||||
struct actctx_loader
|
struct actctx_loader
|
||||||
|
@ -704,6 +732,7 @@ static void actctx_release( ACTIVATION_CONTEXT *actctx )
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
|
RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
|
RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
|
RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
|
||||||
|
RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
|
RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
|
||||||
actctx->magic = 0;
|
actctx->magic = 0;
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, actctx );
|
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;
|
if (error || !dll->name) return FALSE;
|
||||||
|
|
||||||
|
acl->actctx->sections |= DLLREDIRECT_SECTION;
|
||||||
|
|
||||||
if (end) return TRUE;
|
if (end) return TRUE;
|
||||||
|
|
||||||
while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
|
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;
|
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;
|
unsigned int i, j, total_len = 0, dll_count = 0;
|
||||||
data->lpData = v1;
|
struct strsection_header *header;
|
||||||
data->ulLength = 20; /* FIXME */
|
struct dllredirect_data *data;
|
||||||
data->lpSectionGlobalData = NULL; /* FIXME */
|
struct string_index *index;
|
||||||
data->ulSectionGlobalDataLength = 0; /* FIXME */
|
ULONG name_offset;
|
||||||
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;
|
|
||||||
|
|
||||||
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,
|
/* each entry needs index, data and string data */
|
||||||
PACTCTX_SECTION_KEYED_DATA data)
|
total_len += sizeof(*index);
|
||||||
{
|
total_len += sizeof(*data);
|
||||||
unsigned int i, j, snlen = section_name->Length / sizeof(WCHAR);
|
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++)
|
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++)
|
for (j = 0; j < assembly->num_dlls; j++)
|
||||||
{
|
{
|
||||||
struct dll_redirect *dll = &assembly->dlls[j];
|
struct dll_redirect *dll = &assembly->dlls[j];
|
||||||
if (!strncmpiW(section_name->Buffer, dll->name, snlen) && !dll->name[snlen])
|
UNICODE_STRING str;
|
||||||
return fill_keyed_data(data, dll, assembly, i);
|
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);
|
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)
|
static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
|
||||||
{
|
|
||||||
return (assembly - actctx->assemblies) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct wndclass_header **section)
|
|
||||||
{
|
{
|
||||||
unsigned int i, j, k, total_len = 0, class_count = 0;
|
unsigned int i, j, k, total_len = 0, class_count = 0;
|
||||||
struct wndclass_redirect_data *data;
|
struct wndclass_redirect_data *data;
|
||||||
struct wndclass_header *header;
|
struct strsection_header *header;
|
||||||
struct wndclass_index *index;
|
struct string_index *index;
|
||||||
ULONG name_offset;
|
ULONG name_offset;
|
||||||
|
|
||||||
/* compute section length */
|
/* compute section length */
|
||||||
|
@ -2281,8 +2428,8 @@ static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct wndcla
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
/* each class entry needs index, data and string data */
|
/* each class entry needs index, data and string data */
|
||||||
total_len += sizeof(struct wndclass_index);
|
total_len += sizeof(*index);
|
||||||
total_len += sizeof(struct wndclass_redirect_data);
|
total_len += sizeof(*data);
|
||||||
/* original name is stored separately */
|
/* original name is stored separately */
|
||||||
total_len += aligned_string_len(class_len*sizeof(WCHAR));
|
total_len += aligned_string_len(class_len*sizeof(WCHAR));
|
||||||
/* versioned name and module name are stored one after another */
|
/* 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));
|
memset(header, 0, sizeof(*header));
|
||||||
header->magic = SECTION_MAGIC;
|
header->magic = SECTION_MAGIC;
|
||||||
|
header->size = sizeof(*header);
|
||||||
header->count = class_count;
|
header->count = class_count;
|
||||||
header->index_offset = sizeof(*header);
|
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);
|
name_offset = header->index_offset + header->count*sizeof(*index);
|
||||||
|
|
||||||
for (i = 0; i < actctx->num_assemblies; i++)
|
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->name_len = str.Length;
|
||||||
index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
|
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->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 */
|
/* setup data */
|
||||||
data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
|
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,
|
static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
|
||||||
PACTCTX_SECTION_KEYED_DATA data)
|
PACTCTX_SECTION_KEYED_DATA data)
|
||||||
{
|
{
|
||||||
struct wndclass_index *iter, *index = NULL;
|
struct string_index *iter, *index = NULL;
|
||||||
struct wndclass_redirect_data *class;
|
struct wndclass_redirect_data *class;
|
||||||
ULONG hash;
|
ULONG hash;
|
||||||
int i;
|
int i;
|
||||||
|
@ -2406,7 +2554,7 @@ static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRI
|
||||||
|
|
||||||
if (!actctx->wndclass_section)
|
if (!actctx->wndclass_section)
|
||||||
{
|
{
|
||||||
struct wndclass_header *section;
|
struct strsection_header *section;
|
||||||
|
|
||||||
NTSTATUS status = build_wndclass_section(actctx, §ion);
|
NTSTATUS status = build_wndclass_section(actctx, §ion);
|
||||||
if (status) return status;
|
if (status) return status;
|
||||||
|
|
Loading…
Reference in New Issue