Nikolay Sivov : ntdll: Support optional 'versioned' attribute for windowClass sections.

Alexandre Julliard julliard at winehq.org
Thu Aug 15 13:12:46 CDT 2013


Module: wine
Branch: master
Commit: cddea89d22e5d433b10367b213e4ecc4017d1af1
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=cddea89d22e5d433b10367b213e4ecc4017d1af1

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Sat Aug  3 06:40:27 2013 +0400

ntdll: Support optional 'versioned' attribute for windowClass sections.

---

 dlls/kernel32/tests/actctx.c |   16 ++++++++++-
 dlls/ntdll/actctx.c          |   56 +++++++++++++++++++++++++++++++++---------
 2 files changed, 58 insertions(+), 14 deletions(-)

diff --git a/dlls/kernel32/tests/actctx.c b/dlls/kernel32/tests/actctx.c
index ae82a07..234fa9d 100644
--- a/dlls/kernel32/tests/actctx.c
+++ b/dlls/kernel32/tests/actctx.c
@@ -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());
 
diff --git a/dlls/ntdll/actctx.c b/dlls/ntdll/actctx.c
index 1561db8..d5f7055 100644
--- a/dlls/ntdll/actctx.c
+++ b/dlls/ntdll/actctx.c
@@ -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 */
-                    versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
+                    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);
-                    get_assembly_version(assembly, ptrW);
-                    strcatW(ptrW, exclW);
-                    strcatW(ptrW, entity->u.class.name);
+                    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));




More information about the wine-cvs mailing list