Sync with trunk (r48545)
[reactos.git] / dll / win32 / fusion / asmname.c
index 3c014ea..bcf49a7 100644 (file)
@@ -43,6 +43,7 @@ typedef struct {
     LPWSTR displayname;
     LPWSTR name;
     LPWSTR culture;
+    LPWSTR procarch;
 
     WORD version[4];
     DWORD versize;
@@ -53,6 +54,16 @@ typedef struct {
     LONG ref;
 } IAssemblyNameImpl;
 
+static const WCHAR separator[] = {',',' ',0};
+static const WCHAR version[] = {'V','e','r','s','i','o','n',0};
+static const WCHAR culture[] = {'C','u','l','t','u','r','e',0};
+static const WCHAR pubkey[] =
+    {'P','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
+static const WCHAR procarch[] = {'p','r','o','c','e','s','s','o','r',
+    'A','r','c','h','i','t','e','c','t','u','r','e',0};
+
+#define CHARS_PER_PUBKEY 16
+
 static HRESULT WINAPI IAssemblyNameImpl_QueryInterface(IAssemblyName *iface,
                                                        REFIID riid, LPVOID *ppobj)
 {
@@ -208,16 +219,120 @@ static HRESULT WINAPI IAssemblyNameImpl_GetDisplayName(IAssemblyName *iface,
                                                        DWORD dwDisplayFlags)
 {
     IAssemblyNameImpl *name = (IAssemblyNameImpl *)iface;
+    WCHAR verstr[30];
+    DWORD size;
+    LPWSTR cultureval = 0;
+
+    static const WCHAR equals[] = {'=',0};
 
     TRACE("(%p, %p, %p, %d)\n", iface, szDisplayName,
           pccDisplayName, dwDisplayFlags);
 
-    if (!name->displayname || !*name->displayname)
+    if (dwDisplayFlags == 0)
+    {
+        if (!name->displayname || !*name->displayname)
+            return FUSION_E_INVALID_NAME;
+
+        size = min(*pccDisplayName, lstrlenW(name->displayname) + 1);
+
+        lstrcpynW(szDisplayName, name->displayname, size);
+        *pccDisplayName = size;
+
+        return S_OK;
+    }
+
+    if (!name->name || !*name->name)
         return FUSION_E_INVALID_NAME;
 
-    lstrcpyW(szDisplayName, name->displayname);
-    *pccDisplayName = lstrlenW(szDisplayName) + 1;
+    /* Verify buffer size is sufficient */
+    size = lstrlenW(name->name) + 1;
+
+    if ((dwDisplayFlags & ASM_DISPLAYF_VERSION) && (name->versize > 0))
+    {
+        static const WCHAR spec[] = {'%','d',0};
+        static const WCHAR period[] = {'.',0};
+        int i;
+
+        wsprintfW(verstr, spec, name->version[0]);
+
+        for (i = 1; i < name->versize; i++)
+        {
+            WCHAR value[6];
+            wsprintfW(value, spec, name->version[i]);
+
+            lstrcatW(verstr, period);
+            lstrcatW(verstr, value);
+        }
+
+        size += lstrlenW(separator) + lstrlenW(version) + lstrlenW(equals) + lstrlenW(verstr);
+    }
+
+    if ((dwDisplayFlags & ASM_DISPLAYF_CULTURE) && (name->culture))
+    {
+        static const WCHAR neutral[] = {'n','e','u','t','r','a','l', 0};
+
+        cultureval = (lstrlenW(name->culture) == 2) ? name->culture : (LPWSTR) neutral;
+        size += lstrlenW(separator) + lstrlenW(culture) + lstrlenW(equals) + lstrlenW(cultureval);
+    }
+
+    if ((dwDisplayFlags & ASM_DISPLAYF_PUBLIC_KEY_TOKEN) && (name->haspubkey))
+        size += lstrlenW(separator) + lstrlenW(pubkey) + lstrlenW(equals) + CHARS_PER_PUBKEY;
+
+    if ((dwDisplayFlags & ASM_DISPLAYF_PROCESSORARCHITECTURE) && (name->procarch))
+        size += lstrlenW(separator) + lstrlenW(procarch) + lstrlenW(equals) + lstrlenW(name->procarch);
 
+    if (size > *pccDisplayName)
+        return S_FALSE;
+
+    /* Construct the string */
+    lstrcpyW(szDisplayName, name->name);
+
+    if ((dwDisplayFlags & ASM_DISPLAYF_VERSION) && (name->versize > 0))
+    {
+        lstrcatW(szDisplayName, separator);
+
+        lstrcatW(szDisplayName, version);
+        lstrcatW(szDisplayName, equals);
+        lstrcatW(szDisplayName, verstr);
+    }
+
+    if ((dwDisplayFlags & ASM_DISPLAYF_CULTURE) && (name->culture))
+    {
+        lstrcatW(szDisplayName, separator);
+
+        lstrcatW(szDisplayName, culture);
+        lstrcatW(szDisplayName, equals);
+        lstrcatW(szDisplayName, cultureval);
+    }
+
+    if ((dwDisplayFlags & ASM_DISPLAYF_PUBLIC_KEY_TOKEN) && (name->haspubkey))
+    {
+        WCHAR pkt[CHARS_PER_PUBKEY + 1];
+        static const WCHAR spec[] = {'%','0','x','%','0','x','%','0','x',
+            '%','0','x','%','0','x','%','0','x','%','0','x','%','0','x',0};
+
+        lstrcatW(szDisplayName, separator);
+
+        lstrcatW(szDisplayName, pubkey);
+        lstrcatW(szDisplayName, equals);
+
+        wsprintfW(pkt, spec, name->pubkey[0], name->pubkey[1], name->pubkey[2],
+            name->pubkey[3], name->pubkey[4], name->pubkey[5], name->pubkey[6],
+            name->pubkey[7]);
+
+        lstrcatW(szDisplayName, pkt);
+    }
+
+    if ((dwDisplayFlags & ASM_DISPLAYF_PROCESSORARCHITECTURE) && (name->procarch))
+    {
+        lstrcatW(szDisplayName, separator);
+
+        lstrcatW(szDisplayName, procarch);
+        lstrcatW(szDisplayName, equals);
+        lstrcatW(szDisplayName, name->procarch);
+    }
+
+    *pccDisplayName = size;
     return S_OK;
 }
 
@@ -347,8 +462,6 @@ static HRESULT parse_culture(IAssemblyNameImpl *name, LPWSTR culture)
     return S_OK;
 }
 
-#define CHARS_PER_PUBKEY 16
-
 static BOOL is_hex(WCHAR c)
 {
     return ((c >= 'a' && c <= 'f') ||
@@ -397,12 +510,6 @@ static HRESULT parse_display_name(IAssemblyNameImpl *name, LPCWSTR szAssemblyNam
     HRESULT hr = S_OK;
     BOOL done = FALSE;
 
-    static const WCHAR separator[] = {',',' ',0};
-    static const WCHAR version[] = {'V','e','r','s','i','o','n',0};
-    static const WCHAR culture[] = {'C','u','l','t','u','r','e',0};
-    static const WCHAR pubkey[] =
-        {'P','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
-
     if (!szAssemblyName)
         return S_OK;
 
@@ -462,6 +569,11 @@ static HRESULT parse_display_name(IAssemblyNameImpl *name, LPCWSTR szAssemblyNam
             hr = parse_culture(name, ptr);
         else if (!lstrcmpW(str, pubkey))
             hr = parse_pubkey(name, ptr);
+        else if (!lstrcmpW(str, procarch))
+        {
+            name->procarch = strdupW(ptr);
+            hr = S_OK;
+        }
 
         if (FAILED(hr))
             goto done;