[PATCH v2 1/6] shell32: Fix the icon sizes of the shell imagelists.

Huw Davies huw at codeweavers.com
Tue May 2 09:13:13 CDT 2017


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/shell32/iconcache.c       | 42 ++++++++++++++++++++++++++----
 dlls/shell32/tests/shelllink.c | 58 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 95 insertions(+), 5 deletions(-)

diff --git a/dlls/shell32/iconcache.c b/dlls/shell32/iconcache.c
index 737f4d5023..59fd8fb104 100644
--- a/dlls/shell32/iconcache.c
+++ b/dlls/shell32/iconcache.c
@@ -73,6 +73,11 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
 };
 static CRITICAL_SECTION SHELL32_SicCS = { &critsect_debug, -1, 0, 0, 0, 0 };
 
+
+static const WCHAR WindowMetrics[] = {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','D','e','s','k','t','o','p','\\',
+                                      'W','i','n','d','o','w','M','e','t','r','i','c','s',0};
+static const WCHAR ShellIconSize[] = {'S','h','e','l','l',' ','I','c','o','n',' ','S','i','z','e',0};
+
 /*****************************************************************************
  * SIC_CompareEntries
  *
@@ -361,6 +366,24 @@ static INT SIC_LoadIcon (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags)
         return ret;
 }
 
+static int get_shell_icon_size(void)
+{
+    WCHAR buf[32];
+    DWORD value = 32, size = sizeof(buf), type;
+    HKEY key;
+
+    if (!RegOpenKeyW( HKEY_CURRENT_USER, WindowMetrics, &key ))
+    {
+        if (!RegQueryValueExW( key, ShellIconSize, NULL, &type, (BYTE *)buf, &size ) && type == REG_SZ)
+        {
+            if (size == sizeof(buf)) buf[size / sizeof(WCHAR) - 1] = 0;
+            value = atoiW( buf );
+        }
+        RegCloseKey( key );
+    }
+    return value;
+}
+
 /*****************************************************************************
  * SIC_Initialize			[internal]
  */
@@ -370,12 +393,21 @@ static BOOL WINAPI SIC_Initialize( INIT_ONCE *once, void *param, void **context
 	int		cx_small, cy_small;
 	int		cx_large, cy_large;
 
-	cx_small = GetSystemMetrics(SM_CXSMICON);
-	cy_small = GetSystemMetrics(SM_CYSMICON);
-	cx_large = GetSystemMetrics(SM_CXICON);
-	cy_large = GetSystemMetrics(SM_CYICON);
+        if (!IsProcessDPIAware())
+        {
+            cx_large = cy_large = get_shell_icon_size();
+            cx_small = GetSystemMetrics( SM_CXSMICON );
+            cy_small = GetSystemMetrics( SM_CYSMICON );
+        }
+        else
+        {
+            cx_large = GetSystemMetrics( SM_CXICON );
+            cy_large = GetSystemMetrics( SM_CYICON );
+            cx_small = cx_large / 2;
+            cy_small = cy_large / 2;
+        }
 
-	TRACE("\n");
+        TRACE("large %dx%d small %dx%d\n", cx_large, cy_large, cx_small, cx_small);
 
 	sic_hdpa = DPA_Create(16);
 
diff --git a/dlls/shell32/tests/shelllink.c b/dlls/shell32/tests/shelllink.c
index db15ccd7ed..ad254c8349 100644
--- a/dlls/shell32/tests/shelllink.c
+++ b/dlls/shell32/tests/shelllink.c
@@ -44,6 +44,7 @@ static HRESULT (WINAPI *pSHGetStockIconInfo)(SHSTOCKICONID, UINT, SHSTOCKICONINF
 static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR, LPSTR, DWORD);
 static DWORD (WINAPI *pGetShortPathNameA)(LPCSTR, LPSTR, DWORD);
 static UINT (WINAPI *pSHExtractIconsW)(LPCWSTR, int, int, int, HICON *, UINT *, UINT, UINT);
+static BOOL (WINAPI *pIsProcessDPIAware)(void);
 
 static const GUID _IID_IShellLinkDataList = {
     0x45e2b4ae, 0xb1c3, 0x11d0,
@@ -1304,6 +1305,21 @@ todo_wine {
     DestroyIcon(hicon);
 }
 
+static int get_shell_icon_size(void)
+{
+    char buf[10];
+    DWORD value = 32, size = sizeof(buf), type;
+    HKEY key;
+
+    if (!RegOpenKeyA( HKEY_CURRENT_USER, "Control Panel\\Desktop\\WindowMetrics", &key ))
+    {
+        if (!RegQueryValueExA( key, "Shell Icon Size", NULL, &type, (BYTE *)buf, &size ) && type == REG_SZ)
+            value = atoi( buf );
+        RegCloseKey( key );
+    }
+    return value;
+}
+
 static void test_SHGetImageList(void)
 {
     HRESULT hr;
@@ -1311,6 +1327,8 @@ static void test_SHGetImageList(void)
     BOOL ret;
     HIMAGELIST lg, sm;
     ULONG start_refs, refs;
+    int i, width, height, expect;
+    BOOL dpi_aware = pIsProcessDPIAware && pIsProcessDPIAware();
 
     hr = SHGetImageList( SHIL_LARGE, &IID_IImageList, (void **)&list );
     ok( hr == S_OK, "got %08x\n", hr );
@@ -1340,6 +1358,44 @@ static void test_SHGetImageList(void)
 
     IImageList_Release( list2 );
     IImageList_Release( list );
+
+    /* Test the icon sizes */
+    for (i = 0; i <= SHIL_LAST; i++)
+    {
+        hr = SHGetImageList( i, &IID_IImageList, (void **)&list );
+        todo_wine_if(i == SHIL_EXTRALARGE || i == SHIL_JUMBO)
+            ok( hr == S_OK ||
+                broken( i == SHIL_JUMBO && hr == E_INVALIDARG ), /* XP and 2003 */
+                "%d: got %08x\n", i, hr );
+        if (FAILED(hr)) continue;
+        IImageList_GetIconSize( list, &width, &height );
+        switch (i)
+        {
+        case SHIL_LARGE:
+            if (dpi_aware) expect = GetSystemMetrics( SM_CXICON );
+            else expect = get_shell_icon_size();
+            break;
+        case SHIL_SMALL:
+            if (dpi_aware) expect = GetSystemMetrics( SM_CXICON ) / 2;
+            else expect = GetSystemMetrics( SM_CXSMICON );
+            break;
+        case SHIL_EXTRALARGE:
+            expect = (GetSystemMetrics( SM_CXICON ) * 3) / 2;
+            break;
+        case SHIL_SYSSMALL:
+            expect = GetSystemMetrics( SM_CXSMICON );
+            break;
+        case SHIL_JUMBO:
+            expect = 256;
+            break;
+        }
+        todo_wine_if(i == SHIL_SYSSMALL && dpi_aware && expect != GetSystemMetrics( SM_CXICON ) / 2)
+        {
+            ok( width == expect, "%d: got %d expect %d\n", i, width, expect );
+            ok( height == expect, "%d: got %d expect %d\n", i, height, expect );
+        }
+        IImageList_Release( list );
+    }
 }
 
 START_TEST(shelllink)
@@ -1347,6 +1403,7 @@ START_TEST(shelllink)
     HRESULT r;
     HMODULE hmod = GetModuleHandleA("shell32.dll");
     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
+    HMODULE huser32 = GetModuleHandleA("user32.dll");
 
     pILFree = (void *)GetProcAddress(hmod, (LPSTR)155);
     pILIsEqual = (void *)GetProcAddress(hmod, (LPSTR)21);
@@ -1356,6 +1413,7 @@ START_TEST(shelllink)
     pGetLongPathNameA = (void *)GetProcAddress(hkernel32, "GetLongPathNameA");
     pGetShortPathNameA = (void *)GetProcAddress(hkernel32, "GetShortPathNameA");
     pSHExtractIconsW = (void *)GetProcAddress(hmod, "SHExtractIconsW");
+    pIsProcessDPIAware = (void *)GetProcAddress(huser32, "IsProcessDPIAware");
 
     r = CoInitialize(NULL);
     ok(r == S_OK, "CoInitialize failed (0x%08x)\n", r);
-- 
2.12.0




More information about the wine-patches mailing list