ntdll: Support optional 'versioned' attribute for windowClass sections.
This commit is contained in:
parent
1103a241db
commit
cddea89d22
|
@ -105,7 +105,7 @@ static const char manifest_wndcls1[] =
|
|||
"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
|
||||
"<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>"
|
||||
"<file name=\"testlib1.dll\">"
|
||||
"<windowClass>wndClass1</windowClass>"
|
||||
"<windowClass versioned=\"yes\">wndClass1</windowClass>"
|
||||
"<windowClass>wndClass2</windowClass>"
|
||||
"</file>"
|
||||
"</assembly>";
|
||||
|
@ -114,7 +114,7 @@ static const char manifest_wndcls2[] =
|
|||
"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
|
||||
"<assemblyIdentity version=\"4.3.2.1\" name=\"testdep2\" type=\"win32\" processorArchitecture=\"" ARCH "\" />"
|
||||
"<file name=\"testlib2.dll\">"
|
||||
"<windowClass>wndClass3</windowClass>"
|
||||
"<windowClass versioned=\"no\">wndClass3</windowClass>"
|
||||
"<windowClass>wndClass4</windowClass>"
|
||||
"</file>"
|
||||
"</assembly>";
|
||||
|
@ -1140,9 +1140,12 @@ todo_wine
|
|||
|
||||
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;
|
||||
ULONG_PTR cookie;
|
||||
HANDLE handle;
|
||||
WCHAR *ptrW;
|
||||
BOOL ret;
|
||||
|
||||
/* use two dependent manifests, each defines 2 window class redirects */
|
||||
|
@ -1178,6 +1181,15 @@ static void test_wndclass_section(void)
|
|||
ok(data.ulSectionTotalLength == data2.ulSectionTotalLength, "got %u, %u\n", data.ulSectionTotalLength,
|
||||
data2.ulSectionTotalLength);
|
||||
|
||||
/* wndClass1 is versioned, wndClass3 is not */
|
||||
classdata = (struct wndclass_redirect_data*)data.lpData;
|
||||
ptrW = (WCHAR*)((BYTE*)data.lpData + classdata->name_offset);
|
||||
ok(!lstrcmpW(ptrW, cls1W), "got %s\n", wine_dbgstr_w(ptrW));
|
||||
|
||||
classdata = (struct wndclass_redirect_data*)data2.lpData;
|
||||
ptrW = (WCHAR*)((BYTE*)data2.lpData + classdata->name_offset);
|
||||
ok(!lstrcmpW(ptrW, wndClass3W), "got %s\n", wine_dbgstr_w(ptrW));
|
||||
|
||||
ret = pDeactivateActCtx(0, cookie);
|
||||
ok(ret, "DeactivateActCtx failed: %u\n", GetLastError());
|
||||
|
||||
|
|
|
@ -167,6 +167,7 @@ struct entity
|
|||
struct
|
||||
{
|
||||
WCHAR *name;
|
||||
BOOL versioned;
|
||||
} class;
|
||||
struct
|
||||
{
|
||||
|
@ -279,6 +280,9 @@ static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
|
|||
static const WCHAR typeW[] = {'t','y','p','e',0};
|
||||
static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
|
||||
static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
|
||||
static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
|
||||
static const WCHAR yesW[] = {'y','e','s',0};
|
||||
static const WCHAR noW[] = {'n','o',0};
|
||||
|
||||
static const WCHAR xmlW[] = {'?','x','m','l',0};
|
||||
static const WCHAR manifestv1W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','1',0};
|
||||
|
@ -1093,15 +1097,30 @@ static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
|
|||
|
||||
static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
|
||||
{
|
||||
xmlstr_t elem, content;
|
||||
BOOL end = FALSE, ret = TRUE;
|
||||
xmlstr_t elem, content, attr_name, attr_value;
|
||||
BOOL end = FALSE, ret = TRUE, error;
|
||||
struct entity* entity;
|
||||
|
||||
if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
|
||||
return FALSE;
|
||||
|
||||
if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
|
||||
if (end) return FALSE;
|
||||
entity->u.class.versioned = TRUE;
|
||||
while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
|
||||
{
|
||||
if (xmlstr_cmp(&attr_name, versionedW))
|
||||
{
|
||||
if (xmlstr_cmpi(&attr_value, noW))
|
||||
entity->u.class.versioned = FALSE;
|
||||
else if (!xmlstr_cmpi(&attr_value, yesW))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
|
||||
}
|
||||
}
|
||||
|
||||
if (error || end) return end;
|
||||
|
||||
if (!parse_text_content(xmlbuf, &content)) return FALSE;
|
||||
|
||||
|
@ -1318,7 +1337,6 @@ static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
|
|||
{
|
||||
if (xmlstr_cmp(&attr_name, optionalW))
|
||||
{
|
||||
static const WCHAR yesW[] = {'y','e','s',0};
|
||||
optional = xmlstr_cmpi( &attr_value, yesW );
|
||||
TRACE("optional=%s\n", debugstr_xmlstr(&attr_value));
|
||||
}
|
||||
|
@ -2259,16 +2277,19 @@ static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct wndcla
|
|||
struct entity *entity = &dll->entities.base[k];
|
||||
if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
|
||||
{
|
||||
int class_len = strlenW(entity->u.class.name);
|
||||
int class_len = strlenW(entity->u.class.name) + 1;
|
||||
int len;
|
||||
|
||||
/* each class entry needs index, data and string data */
|
||||
total_len += sizeof(struct wndclass_index);
|
||||
total_len += sizeof(struct wndclass_redirect_data);
|
||||
/* original name is stored separately */
|
||||
total_len += aligned_string_len((class_len+1)*sizeof(WCHAR));
|
||||
total_len += aligned_string_len(class_len*sizeof(WCHAR));
|
||||
/* versioned name and module name are stored one after another */
|
||||
len = get_assembly_version(assembly, NULL) + class_len + 2 /* null terminator and '!' separator */;
|
||||
if (entity->u.class.versioned)
|
||||
len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
|
||||
else
|
||||
len = class_len;
|
||||
len += strlenW(dll->name) + 1;
|
||||
total_len += aligned_string_len(len*sizeof(WCHAR));
|
||||
|
||||
|
@ -2314,7 +2335,10 @@ static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct wndcla
|
|||
RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
|
||||
|
||||
/* include '!' separator too */
|
||||
if (entity->u.class.versioned)
|
||||
versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
|
||||
else
|
||||
versioned_len = str.Length;
|
||||
module_len = strlenW(dll->name)*sizeof(WCHAR);
|
||||
|
||||
index->name_offset = name_offset;
|
||||
|
@ -2344,9 +2368,17 @@ static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct wndcla
|
|||
|
||||
/* versioned name */
|
||||
ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
|
||||
if (entity->u.class.versioned)
|
||||
{
|
||||
get_assembly_version(assembly, ptrW);
|
||||
strcatW(ptrW, exclW);
|
||||
strcatW(ptrW, entity->u.class.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(ptrW, entity->u.class.name, index->name_len);
|
||||
ptrW[index->name_len/sizeof(WCHAR)] = 0;
|
||||
}
|
||||
|
||||
name_offset += sizeof(*data);
|
||||
name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
|
||||
|
|
Loading…
Reference in New Issue