user: SetDesktopWallPaper() should call SystemParametersInfoA()

Andrew Ziem ahziem1 at mailbolt.com
Thu Jul 20 09:18:55 CDT 2006


changelog:
user: SetDesktopWallPaper() should call SystemParametersInfoA()

This patch improves a previous patch[1] based on advice from Dmitry
Timoshkov[2].

[1] http://www.winehq.org/pipermail/wine-patches/2006-July/028761.html
[2] http://winehq.org/pipermail/wine-devel/2006-July/049640.html

This uncommited patch (which adds tests) is still valid:
http://www.winehq.org/pipermail/wine-patches/2006-July/028495.html
---
 dlls/user/desktop.c   |  169 --------------------------------------
 dlls/user/sysparams.c |  217 ++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 215 insertions(+), 171 deletions(-)

diff --git a/dlls/user/desktop.c b/dlls/user/desktop.c
index 2252f99..212e339 100644
--- a/dlls/user/desktop.c
+++ b/dlls/user/desktop.c
@@ -33,10 +33,6 @@ #include "wingdi.h"
 #include "controls.h"
 #include "wine/winuser16.h"
 
-static HBRUSH hbrushPattern;
-static HBITMAP hbitmapWallPaper;
-static SIZE bitmapSize;
-static BOOL fTileWallPaper;
 
 static LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );
 
@@ -56,60 +52,6 @@ const struct builtin_class_descr DESKTOP
 };
 
 
-/***********************************************************************
- *           DESKTOP_LoadBitmap
- *
- * Load a bitmap from a file. Used by SetDeskWallPaper().
- */
-static HBITMAP DESKTOP_LoadBitmap( HDC hdc, const char *filename )
-{
-    BITMAPFILEHEADER *fileHeader;
-    BITMAPINFO *bitmapInfo;
-    HBITMAP hbitmap;
-    HFILE file;
-    LPSTR buffer;
-    LONG size;
-
-    /* Read all the file into memory */
-
-    if ((file = _lopen( filename, OF_READ )) == HFILE_ERROR)
-    {
-        UINT len = GetWindowsDirectoryA( NULL, 0 );
-        if (!(buffer = HeapAlloc( GetProcessHeap(), 0,
-                                  len + strlen(filename) + 2 )))
-            return 0;
-        GetWindowsDirectoryA( buffer, len + 1 );
-        strcat( buffer, "\\" );
-        strcat( buffer, filename );
-        file = _lopen( buffer, OF_READ );
-        HeapFree( GetProcessHeap(), 0, buffer );
-    }
-    if (file == HFILE_ERROR) return 0;
-    size = _llseek( file, 0, 2 );
-    if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size )))
-    {
-	_lclose( file );
-	return 0;
-    }
-    _llseek( file, 0, 0 );
-    size = _lread( file, buffer, size );
-    _lclose( file );
-    fileHeader = (BITMAPFILEHEADER *)buffer;
-    bitmapInfo = (BITMAPINFO *)(buffer + sizeof(BITMAPFILEHEADER));
-
-      /* Check header content */
-    if ((fileHeader->bfType != 0x4d42) || (size < fileHeader->bfSize))
-    {
-	HeapFree( GetProcessHeap(), 0, buffer );
-	return 0;
-    }
-    hbitmap = CreateDIBitmap( hdc, &bitmapInfo->bmiHeader, CBM_INIT,
-                                buffer + fileHeader->bfOffBits,
-                                bitmapInfo, DIB_RGB_COLORS );
-    HeapFree( GetProcessHeap(), 0, buffer );
-    return hbitmap;
-}
-
 
 
 /***********************************************************************
@@ -121,62 +63,6 @@ static LRESULT WINAPI DesktopWndProc( HW
     return 0;  /* all other messages are ignored */
 }
 
-/***********************************************************************
- *           PaintDesktop   (USER32.@)
- *
- */
-BOOL WINAPI PaintDesktop(HDC hdc)
-{
-    HWND hwnd = GetDesktopWindow();
-
-    /* check for an owning thread; otherwise don't paint anything (non-desktop mode) */
-    if (GetWindowThreadProcessId( hwnd, NULL ))
-    {
-        RECT rect;
-
-        GetClientRect( hwnd, &rect );
-
-        /* Paint desktop pattern (only if wall paper does not cover everything) */
-
-        if (!hbitmapWallPaper ||
-            (!fTileWallPaper && ((bitmapSize.cx < rect.right) || (bitmapSize.cy < rect.bottom))))
-        {
-            HBRUSH brush = hbrushPattern;
-            if (!brush) brush = (HBRUSH)GetClassLongPtrW( hwnd, GCLP_HBRBACKGROUND );
-            /* Set colors in case pattern is a monochrome bitmap */
-            SetBkColor( hdc, RGB(0,0,0) );
-            SetTextColor( hdc, GetSysColor(COLOR_BACKGROUND) );
-            FillRect( hdc, &rect, brush );
-        }
-
-        /* Paint wall paper */
-
-        if (hbitmapWallPaper)
-        {
-            INT x, y;
-            HDC hMemDC = CreateCompatibleDC( hdc );
-
-            SelectObject( hMemDC, hbitmapWallPaper );
-
-            if (fTileWallPaper)
-            {
-                for (y = 0; y < rect.bottom; y += bitmapSize.cy)
-                    for (x = 0; x < rect.right; x += bitmapSize.cx)
-                        BitBlt( hdc, x, y, bitmapSize.cx, bitmapSize.cy, hMemDC, 0, 0, SRCCOPY );
-            }
-            else
-            {
-                x = (rect.left + rect.right - bitmapSize.cx) / 2;
-                y = (rect.top + rect.bottom - bitmapSize.cy) / 2;
-                if (x < 0) x = 0;
-                if (y < 0) y = 0;
-                BitBlt( hdc, x, y, bitmapSize.cx, bitmapSize.cy, hMemDC, 0, 0, SRCCOPY );
-            }
-            DeleteDC( hMemDC );
-        }
-    }
-    return TRUE;
-}
 
 /***********************************************************************
  *           OldSetDeskPattern   (USER.279)
@@ -203,61 +89,8 @@ BOOL16 WINAPI SetDeskWallPaper16( LPCSTR
  */
 BOOL WINAPI SetDeskWallPaper( LPCSTR filename )
 {
-    HBITMAP hbitmap;
-    HDC hdc;
-    char buffer[256];
-
-    if (filename == (LPSTR)-1)
-    {
-	GetProfileStringA( "desktop", "WallPaper", "(None)", buffer, 256 );
-	filename = buffer;
-    }
-    hdc = GetDC( 0 );
-    hbitmap = DESKTOP_LoadBitmap( hdc, filename );
-    ReleaseDC( 0, hdc );
-    if (hbitmapWallPaper) DeleteObject( hbitmapWallPaper );
-    hbitmapWallPaper = hbitmap;
-    fTileWallPaper = GetProfileIntA( "desktop", "TileWallPaper", 0 );
-    if (hbitmap)
-    {
-	BITMAP bmp;
-	GetObjectA( hbitmap, sizeof(bmp), &bmp );
-	bitmapSize.cx = (bmp.bmWidth != 0) ? bmp.bmWidth : 1;
-	bitmapSize.cy = (bmp.bmHeight != 0) ? bmp.bmHeight : 1;
-    }
-    return TRUE;
+    return SystemParametersInfoA( SPI_SETDESKWALLPAPER, 0, (PVOID)filename, 0 );
 }
 
 
-/***********************************************************************
- *           DESKTOP_SetPattern
- *
- * Set the desktop pattern.
- */
-BOOL DESKTOP_SetPattern( LPCWSTR pattern )
-{
-    int pat[8];
-
-    if (hbrushPattern) DeleteObject( hbrushPattern );
-    hbrushPattern = 0;
-    memset( pat, 0, sizeof(pat) );
-    if (pattern)
-    {
-        char buffer[64];
-        WideCharToMultiByte( CP_ACP, 0, pattern, -1, buffer, sizeof(buffer), NULL, NULL );
-        if (sscanf( buffer, " %d %d %d %d %d %d %d %d",
-                    &pat[0], &pat[1], &pat[2], &pat[3],
-                    &pat[4], &pat[5], &pat[6], &pat[7] ))
-        {
-            WORD pattern[8];
-            HBITMAP hbitmap;
-            int i;
 
-            for (i = 0; i < 8; i++) pattern[i] = pat[i] & 0xffff;
-            hbitmap = CreateBitmap( 8, 8, 1, 1, (LPSTR)pattern );
-            hbrushPattern = CreatePatternBrush( hbitmap );
-            DeleteObject( hbitmap );
-        }
-    }
-    return TRUE;
-}
diff --git a/dlls/user/sysparams.c b/dlls/user/sysparams.c
index de0677f..2cb4415 100644
--- a/dlls/user/sysparams.c
+++ b/dlls/user/sysparams.c
@@ -355,6 +355,11 @@ static const WORD wPattern55AA[] = { 0x5
 
 HBRUSH SYSCOLOR_55AABrush = 0;
 
+static HBRUSH hbrushPattern;
+static HBITMAP hbitmapWallPaper; /* desktop wallpaper */
+static SIZE bitmapSize; /* size of desktop wallpaper */
+static BOOL fTileWallPaper;
+
 extern void __wine_make_gdi_object_system( HGDIOBJ handle, BOOL set );
 
 
@@ -744,6 +749,169 @@ static void SYSPARAMS_SetSysColor( int i
     __wine_make_gdi_object_system( SysColorPens[index], TRUE);
 }
 
+
+
+/***********************************************************************
+ *           SYSPARAMS_LoadBitmap
+ *
+ * Load a bitmap from a file. Used by 
+ * SystemParametersInfoW(SPI_SETDESKWALLPAPER,...)
+ */
+static HBITMAP SYSPARAMS_LoadBitmap( HDC hdc, LPCWSTR filename )
+{
+    BITMAPFILEHEADER *fileHeader;
+    BITMAPINFO *bitmapInfo;
+    HBITMAP hbitmap;
+    DWORD size;
+    HANDLE hFile;
+    LPBYTE bmimage;
+    HANDLE fmapping;
+    const WCHAR slash[] = { '\\', 0 };
+
+    /* Read all the file into memory */
+    hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+    if (INVALID_HANDLE_VALUE == hFile)
+    {
+	/* also look in Windows directory */
+        LPWSTR buffer;
+        UINT len = GetWindowsDirectoryW( NULL, 0 );
+        if (!(buffer = HeapAlloc( GetProcessHeap(), 0,
+                                  sizeof(WCHAR) * (len + lstrlenW(filename) + 2 ))))
+            return NULL;
+        GetWindowsDirectoryW( buffer, (len + 1) );
+        lstrcatW( buffer, slash );
+        lstrcatW( buffer, filename );
+        hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+        HeapFree( GetProcessHeap(), 0, buffer );
+    }
+    if (INVALID_HANDLE_VALUE == hFile)
+        return NULL;
+
+    size = GetFileSize(hFile, NULL);
+
+    /* Map the file */
+    fmapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
+    CloseHandle(hFile);
+    if (!fmapping)
+    {
+        WARN("CreateFileMapping error %ld\n", GetLastError() );
+        return NULL;
+    }
+
+    if (!(bmimage = MapViewOfFile(fmapping, FILE_MAP_READ, 0, 0, 0)))
+    {
+        WARN("MapViewOfFile error %ld\n", GetLastError() );
+        CloseHandle(fmapping);
+        return NULL;
+    }
+    CloseHandle(fmapping);
+
+    fileHeader = (BITMAPFILEHEADER *)bmimage;
+    bitmapInfo = (BITMAPINFO *)(bmimage + sizeof(BITMAPFILEHEADER));
+
+    /* Check header content */
+    if ((fileHeader->bfType != 0x4d42) || (size < fileHeader->bfSize))
+    {
+        UnmapViewOfFile(bmimage);
+	return 0;
+    }
+    hbitmap = CreateDIBitmap( hdc, &bitmapInfo->bmiHeader, CBM_INIT,
+                                bmimage + fileHeader->bfOffBits,
+                                bitmapInfo, DIB_RGB_COLORS );
+    UnmapViewOfFile(bmimage);
+    return hbitmap;
+}
+
+/***********************************************************************
+ *           PaintDesktop   (USER32.@)
+ *
+ */
+BOOL WINAPI PaintDesktop(HDC hdc)
+{
+    HWND hwnd = GetDesktopWindow();
+
+    /* check for an owning thread; otherwise don't paint anything (non-desktop mode) */
+    if (GetWindowThreadProcessId( hwnd, NULL ))
+    {
+        RECT rect;
+
+        GetClientRect( hwnd, &rect );
+
+        /* Paint desktop pattern (only if wall paper does not cover everything) */
+
+        if (!hbitmapWallPaper ||
+            (!fTileWallPaper && ((bitmapSize.cx < rect.right) || (bitmapSize.cy < rect.bottom))))
+        {
+            HBRUSH brush = hbrushPattern;
+            if (!brush) brush = (HBRUSH)GetClassLongPtrW( hwnd, GCLP_HBRBACKGROUND );
+            /* Set colors in case pattern is a monochrome bitmap */
+            SetBkColor( hdc, RGB(0,0,0) );
+            SetTextColor( hdc, GetSysColor(COLOR_BACKGROUND) );
+            FillRect( hdc, &rect, brush );
+        }
+
+        /* Paint wall paper */
+
+        if (hbitmapWallPaper)
+        {
+            INT x, y;
+            HDC hMemDC = CreateCompatibleDC( hdc );
+
+            SelectObject( hMemDC, hbitmapWallPaper );
+
+            if (fTileWallPaper)
+            {
+                for (y = 0; y < rect.bottom; y += bitmapSize.cy)
+                    for (x = 0; x < rect.right; x += bitmapSize.cx)
+                        BitBlt( hdc, x, y, bitmapSize.cx, bitmapSize.cy, hMemDC, 0, 0, SRCCOPY );
+            }
+            else
+            {
+                x = (rect.left + rect.right - bitmapSize.cx) / 2;
+                y = (rect.top + rect.bottom - bitmapSize.cy) / 2;
+                if (x < 0) x = 0;
+                if (y < 0) y = 0;
+                BitBlt( hdc, x, y, bitmapSize.cx, bitmapSize.cy, hMemDC, 0, 0, SRCCOPY );
+            }
+            DeleteDC( hMemDC );
+        }
+    }
+    return TRUE;
+}
+
+/***********************************************************************
+ *           SYSPARAMS_SetPattern
+ *
+ * Set the desktop pattern.
+ */
+BOOL SYSPARAMS_SetPattern( LPCWSTR pattern )
+{
+    int pat[8];
+
+    if (hbrushPattern) DeleteObject( hbrushPattern );
+    hbrushPattern = 0;
+    memset( pat, 0, sizeof(pat) );
+    if (pattern)
+    {
+        char buffer[64];
+        WideCharToMultiByte( CP_ACP, 0, pattern, -1, buffer, sizeof(buffer), NULL, NULL );
+        if (sscanf( buffer, " %d %d %d %d %d %d %d %d",
+                    &pat[0], &pat[1], &pat[2], &pat[3],
+                    &pat[4], &pat[5], &pat[6], &pat[7] ))
+        {
+            WORD pattern[8];
+            HBITMAP hbitmap;
+            int i;
+
+            for (i = 0; i < 8; i++) pattern[i] = pat[i] & 0xffff;
+            hbitmap = CreateBitmap( 8, 8, 1, 1, (LPSTR)pattern );
+            hbrushPattern = CreatePatternBrush( hbitmap );
+            DeleteObject( hbitmap );
+        }
+    }
+    return TRUE;
+}
+
 /* load a uint parameter from the registry */
 static BOOL get_uint_param( unsigned int idx, LPCWSTR regkey, LPCWSTR value,
                             UINT *value_ptr, UINT *ret_ptr )
@@ -1314,8 +1482,49 @@ #define WINE_SPI_WARN(x) \
         break;
 
     case SPI_SETDESKWALLPAPER:			/*     20 */
-        if (!pvParam || !SetDeskWallPaper( (LPSTR)pvParam )) return FALSE;
+    {
+        HBITMAP hbitmap;
+        HDC hdc;
+        WCHAR buffer[MAX_PATH];
+        const WCHAR desktop[] = {'d','e','s','k','t','o','p',0};
+        const WCHAR WallPaper[] = {'W','a','l','l','P','a','p','e','r',0};
+        const WCHAR None[] = {'(','n','o','n','e',')',0};
+        const WCHAR TileWallPaper[] = {'T','i','l','e','W','a','l','l','P','a','p','e','r',0};
+        int def = 0;
+
+        if ((LPCWSTR)NULL == pvParam || (LPCWSTR)SETWALLPAPER_DEFAULT == pvParam)
+        {
+            /* revert to default wallpaper */
+            GetProfileStringW( desktop, WallPaper, None, buffer, MAX_PATH );
+            pvParam = buffer;
+            def = 1;
+        }
+        else if ('\0' == ((LPCWSTR)pvParam)[0])
+        {
+            /* remove wallpaper*/
+            if (hbitmapWallPaper)
+               DeleteObject( hbitmapWallPaper );
+            SYSPARAMS_Save(SPI_SETDESKWALLPAPER_REGKEY, SPI_SETDESKWALLPAPER_VALNAME, pvParam, fWinIni);
+            return TRUE;
+        }
+
+        hdc = GetDC( 0 );
+        hbitmap = SYSPARAMS_LoadBitmap( hdc, pvParam );
+        ReleaseDC( 0, hdc );
+        if (hbitmapWallPaper)
+            DeleteObject( hbitmapWallPaper );
+        hbitmapWallPaper = hbitmap;
+        fTileWallPaper = GetProfileIntW( desktop, TileWallPaper, 0 );
+        if (hbitmap)
+        {
+            BITMAP bmp;
+            GetObjectW( hbitmap, sizeof(bmp), &bmp );
+            bitmapSize.cx = (bmp.bmWidth != 0) ? bmp.bmWidth : 1;
+            bitmapSize.cy = (bmp.bmHeight != 0) ? bmp.bmHeight : 1;
+        }
         SYSPARAMS_Save(SPI_SETDESKWALLPAPER_REGKEY, SPI_SETDESKWALLPAPER_VALNAME, pvParam, fWinIni);
+        return ( 0 != hbitmap || def );
+    }
 	break;
 	
     case SPI_SETDESKPATTERN:			/*     21 */
@@ -1327,9 +1536,9 @@ #define WINE_SPI_WARN(x) \
             GetProfileStringW( Desktop, Pattern,
                                defPattern,
                                buf, sizeof(buf)/sizeof(WCHAR) );
-            ret = DESKTOP_SetPattern( buf );
+            ret = SYSPARAMS_SetPattern( buf );
         } else
-            ret = DESKTOP_SetPattern( (LPWSTR)pvParam );
+            ret = SYSPARAMS_SetPattern( (LPWSTR)pvParam );
 	break;
 
     case SPI_GETKEYBOARDDELAY:
@@ -2387,6 +2596,8 @@ BOOL WINAPI SystemParametersInfoA( UINT 
     switch (uiAction)
     {
     case SPI_SETDESKWALLPAPER:			/*     20 */
+        if ((LPCSTR)SETWALLPAPER_DEFAULT == pvParam)
+            pvParam = NULL;
     case SPI_SETDESKPATTERN:			/*     21 */
     {
 	WCHAR buffer[256];
-- 
1.4.0




More information about the wine-patches mailing list