From c6a9402e60f7f8943fa79cba6ebce3b7b8da4a4d Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Tue, 17 Aug 2004 21:47:36 +0000 Subject: [PATCH] added very basic support for desktop wallpapers svn path=/trunk/; revision=10578 --- reactos/bootdata/hivedef.inf | 1 + reactos/lib/user32/Makefile | 4 +- reactos/lib/user32/misc/desktop.c | 190 +++++++++++++++++++++- reactos/ntoskrnl/include/internal/ex.h | 13 ++ reactos/subsys/system/userinit/userinit.c | 35 +++- reactos/subsys/win32k/ntuser/desktop.c | 43 ++++- reactos/subsys/win32k/ntuser/misc.c | 84 +++++++++- 7 files changed, 362 insertions(+), 8 deletions(-) diff --git a/reactos/bootdata/hivedef.inf b/reactos/bootdata/hivedef.inf index e75c736219b..e81a3cbbeb7 100644 --- a/reactos/bootdata/hivedef.inf +++ b/reactos/bootdata/hivedef.inf @@ -7,6 +7,7 @@ HKCU,"Control Panel",,0x00000012 HKCU,"Control Panel\Appearance",,0x00000012 HKCU,"Control Panel\Desktop","CursorBlinkRate",0x00000002,"530" HKCU,"Control Panel\Desktop","DragFullWindows",0x00000002,"0" +HKCU,"Control Panel\Desktop","Wallpaper",0x00000000,"" HKCU,"Control Panel\International",,0x00000012 HKCU,"Control Panel\International","Locale",0x00000000,"0409" diff --git a/reactos/lib/user32/Makefile b/reactos/lib/user32/Makefile index 19da778ab9f..50bf6f25a87 100644 --- a/reactos/lib/user32/Makefile +++ b/reactos/lib/user32/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.39 2004/08/15 21:36:25 chorns Exp $ +# $Id: Makefile,v 1.40 2004/08/17 21:47:36 weiden Exp $ PATH_TO_TOP = ../.. @@ -10,7 +10,7 @@ TARGET_PCH = include/user32.h TARGET_BASE = $(TARGET_BASE_LIB_USER32) -TARGET_SDKLIBS = libwine.a ntdll.a kernel32.a gdi32.a rosrtl.a +TARGET_SDKLIBS = libwine.a ntdll.a gdi32.a rosrtl.a kernel32.a advapi32.a TARGET_CFLAGS = \ -I./include \ diff --git a/reactos/lib/user32/misc/desktop.c b/reactos/lib/user32/misc/desktop.c index cb9abb42b61..a03f9fdc524 100644 --- a/reactos/lib/user32/misc/desktop.c +++ b/reactos/lib/user32/misc/desktop.c @@ -1,4 +1,4 @@ -/* $Id: desktop.c,v 1.32 2004/08/15 21:36:27 chorns Exp $ +/* $Id: desktop.c,v 1.33 2004/08/17 21:47:36 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS user32.dll @@ -45,9 +45,21 @@ SystemParametersInfoA(UINT uiAction, { switch (uiAction) { + case SPI_SETDOUBLECLKWIDTH: + case SPI_SETDOUBLECLKHEIGHT: + case SPI_SETDOUBLECLICKTIME: + case SPI_SETGRADIENTCAPTIONS: + case SPI_SETFONTSMOOTHING: + case SPI_SETFOCUSBORDERHEIGHT: + case SPI_SETFOCUSBORDERWIDTH: + case SPI_SETWORKAREA: case SPI_GETWORKAREA: + case SPI_GETFONTSMOOTHING: + case SPI_GETGRADIENTCAPTIONS: + case SPI_GETFOCUSBORDERHEIGHT: + case SPI_GETFOCUSBORDERWIDTH: { - return SystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni); + return NtUserSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni); } case SPI_GETNONCLIENTMETRICS: { @@ -83,6 +95,91 @@ SystemParametersInfoA(UINT uiAction, RosRtlLogFontW2A(pvParam, &lfw); return TRUE; } + case SPI_GETDESKWALLPAPER: + { + HKEY hKey; + BOOL Ret = FALSE; + +#if 0 + /* Get the desktop bitmap handle, this does NOT return the file name! */ + if(!NtUserSystemParametersInfo(SPI_GETDESKWALLPAPER, 0, &hbmWallpaper, 0)) + { + /* Return an empty string, no wallpapaper is set */ + *(CHAR*)pvParam = '\0'; + return TRUE; + } +#endif + + /* FIXME - Read the registry key for now, but what happens if the wallpaper was + changed without SPIF_UPDATEINIFILE?! */ + if(RegOpenKeyExW(HKEY_CURRENT_USER, + L"Control Panel\\Desktop", + 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) + { + DWORD Type, Size; + Size = uiParam; + if(RegQueryValueExA(hKey, + "Wallpaper", + NULL, + &Type, + (LPBYTE)pvParam, + &Size) == ERROR_SUCCESS + && Type == REG_SZ) + { + Ret = TRUE; + } + RegCloseKey(hKey); + } + return Ret; + } + case SPI_SETDESKWALLPAPER: + { + HBITMAP hNewWallpaper; + BOOL Ret; + LPSTR lpWallpaper = (LPSTR)pvParam; + + if(lpWallpaper != NULL && *lpWallpaper != '\0') + { + hNewWallpaper = LoadImageA(0, lpWallpaper, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); + if(hNewWallpaper == NULL) + { + return FALSE; + } + } + else + { + hNewWallpaper = NULL; + lpWallpaper = NULL; + } + + /* Set the wallpaper bitmap */ + if(!NtUserSystemParametersInfo(SPI_SETDESKWALLPAPER, 0, &hNewWallpaper, fWinIni & SPIF_SENDCHANGE)) + { + if(hNewWallpaper != NULL) + DeleteObject(hNewWallpaper); + return FALSE; + } + /* Do not use the bitmap handle anymore, it doesn't belong to our process anymore! */ + + Ret = TRUE; + if(fWinIni & SPIF_UPDATEINIFILE) + { + /* Save the path to the file in the registry */ + HKEY hKey; + if(RegOpenKeyExW(HKEY_CURRENT_USER, + L"Control Panel\\Desktop", + 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) + { + Ret = RegSetValueExA(hKey, "Wallpaper", 0, REG_SZ, (lpWallpaper != NULL ? lpWallpaper : ""), + (lpWallpaper != NULL ? (lstrlenA(lpWallpaper) + 1) * sizeof(CHAR) : sizeof(CHAR)) == ERROR_SUCCESS); + RegCloseKey(hKey); + } + } + + RedrawWindow(GetDesktopWindow(), NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + return Ret; + } } return FALSE; @@ -98,6 +195,95 @@ SystemParametersInfoW(UINT uiAction, PVOID pvParam, UINT fWinIni) { + switch(uiAction) + { + case SPI_GETDESKWALLPAPER: + { + HKEY hKey; + BOOL Ret = FALSE; + +#if 0 + /* Get the desktop bitmap handle, this does NOT return the file name! */ + if(!NtUserSystemParametersInfo(SPI_GETDESKWALLPAPER, 0, &hbmWallpaper, 0)) + { + /* Return an empty string, no wallpapaper is set */ + *(WCHAR*)pvParam = L'\0'; + return TRUE; + } +#endif + + /* FIXME - Read the registry key for now, but what happens if the wallpaper was + changed without SPIF_UPDATEINIFILE?! */ + if(RegOpenKeyExW(HKEY_CURRENT_USER, + L"Control Panel\\Desktop", + 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) + { + DWORD Type, Size; + Size = uiParam * sizeof(WCHAR); + if(RegQueryValueExW(hKey, + L"Wallpaper", + NULL, + &Type, + (LPBYTE)pvParam, + &Size) == ERROR_SUCCESS + && Type == REG_SZ) + { + Ret = TRUE; + } + RegCloseKey(hKey); + } + return Ret; + } + case SPI_SETDESKWALLPAPER: + { + HBITMAP hNewWallpaper; + BOOL Ret; + LPWSTR lpWallpaper = (LPWSTR)pvParam; + + if(lpWallpaper != NULL && *lpWallpaper != L'\0') + { + hNewWallpaper = LoadImageW(0, lpWallpaper, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); + + if(hNewWallpaper == NULL) + { + return FALSE; + } + } + else + { + hNewWallpaper = NULL; + lpWallpaper = NULL; + } + + /* Set the wallpaper bitmap */ + if(!NtUserSystemParametersInfo(SPI_SETDESKWALLPAPER, 0, &hNewWallpaper, fWinIni & SPIF_SENDCHANGE)) + { + if(hNewWallpaper != NULL) + DeleteObject(hNewWallpaper); + return FALSE; + } + /* Do not use the bitmap handle anymore, it doesn't belong to our process anymore! */ + Ret = TRUE; + if(fWinIni & SPIF_UPDATEINIFILE) + { + /* Save the path to the file in the registry */ + HKEY hKey; + + if(RegOpenKeyExW(HKEY_CURRENT_USER, + L"Control Panel\\Desktop", + 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) + { + Ret = RegSetValueExW(hKey, L"Wallpaper", 0, REG_SZ, (lpWallpaper != NULL ? (LPBYTE)lpWallpaper : (LPBYTE)L""), + (lpWallpaper != NULL ? (lstrlenW(lpWallpaper) + 1) * sizeof(WCHAR) : sizeof(WCHAR)) == ERROR_SUCCESS); + RegCloseKey(hKey); + } + } + + RedrawWindow(GetDesktopWindow(), NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + return Ret; + } + } return NtUserSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni); } diff --git a/reactos/ntoskrnl/include/internal/ex.h b/reactos/ntoskrnl/include/internal/ex.h index b8b65eb20c5..63e17650000 100644 --- a/reactos/ntoskrnl/include/internal/ex.h +++ b/reactos/ntoskrnl/include/internal/ex.h @@ -8,6 +8,13 @@ #define NTOS_MODE_KERNEL #include +typedef enum +{ + wmCenter = 0, + wmTile, + wmStretch +} WALLPAPER_MODE; + typedef struct _WINSTATION_OBJECT { CSHORT Type; @@ -22,6 +29,12 @@ typedef struct _WINSTATION_OBJECT UINT CaretBlinkRate; HANDLE ShellWindow; HANDLE ShellListView; + + /* Wallpaper */ + HANDLE hbmWallpaper; + ULONG cxWallpaper, cyWallpaper; + WALLPAPER_MODE WallpaperMode; + ULONG Flags; struct _DESKTOP_OBJECT* ActiveDesktop; /* FIXME: Clipboard */ diff --git a/reactos/subsys/system/userinit/userinit.c b/reactos/subsys/system/userinit/userinit.c index 5a39d9cca89..fa60fd1a75b 100644 --- a/reactos/subsys/system/userinit/userinit.c +++ b/reactos/subsys/system/userinit/userinit.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: userinit.c,v 1.3 2003/12/27 11:09:58 weiden Exp $ +/* $Id: userinit.c,v 1.4 2004/08/17 21:47:36 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Userinit Logon Application @@ -104,12 +104,45 @@ void StartShell(void) MessageBox(0, L"Userinit failed to start the shell!\n", NULL, 0); } +static +void SetUserSettings(void) +{ + HKEY hKey; + DWORD Type, Size; + WCHAR szWallpaper[MAX_PATH + 1]; + + if(RegOpenKeyEx(HKEY_CURRENT_USER, + L"Control Panel\\Desktop", + 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) + { + Size = sizeof(szWallpaper); + if(RegQueryValueEx(hKey, + L"Wallpaper", + NULL, + &Type, + (LPBYTE)szWallpaper, + &Size) == ERROR_SUCCESS + && Type == REG_SZ) + { + /* Change the wallpaper */ + SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, szWallpaper, SPIF_SENDCHANGE); + } + else + { + /* Set the default wallpaper */ + SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, NULL, SPIF_SENDCHANGE); + } + RegCloseKey(hKey); + } +} + int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { + SetUserSettings(); StartShell(); return 0; } diff --git a/reactos/subsys/win32k/ntuser/desktop.c b/reactos/subsys/win32k/ntuser/desktop.c index fa4019b7ce7..ba9ea751f63 100644 --- a/reactos/subsys/win32k/ntuser/desktop.c +++ b/reactos/subsys/win32k/ntuser/desktop.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: desktop.c,v 1.18 2004/08/08 17:57:34 weiden Exp $ + * $Id: desktop.c,v 1.19 2004/08/17 21:47:36 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -688,6 +688,7 @@ NtUserPaintDesktop(HDC hDC) RECT Rect; HBRUSH DesktopBrush, PreviousBrush; HWND hWndDesktop; + PWINSTATION_OBJECT WinSta = PsGetWin32Thread()->Desktop->WindowStation; IntGdiGetClipBox(hDC, &Rect); @@ -698,6 +699,46 @@ NtUserPaintDesktop(HDC hDC) * Paint desktop background */ + if(WinSta->hbmWallpaper != NULL) + { + PWINDOW_OBJECT DeskWin; + DbgPrint("Paint 1\n"); + if((DeskWin = IntGetWindowObject(hWndDesktop))) + { + SIZE sz; + int x, y; + HDC hWallpaperDC; + + sz.cx = DeskWin->WindowRect.right - DeskWin->WindowRect.left; + sz.cy = DeskWin->WindowRect.bottom - DeskWin->WindowRect.top; + IntReleaseWindowObject(DeskWin); + DbgPrint("Paint 2\n"); + x = (sz.cx / 2) - (WinSta->cxWallpaper / 2); + y = (sz.cy / 2) - (WinSta->cyWallpaper / 2); + + hWallpaperDC = NtGdiCreateCompatableDC(hDC); + if(hWallpaperDC != NULL) + { + HBITMAP hOldBitmap; + DbgPrint("Paint 3->%d, %d, %d, %d\n", x, y, sz.cx, sz.cy); + if(x > 0 || y > 0) + { + /* FIXME - clip out the bitmap */ + PreviousBrush = NtGdiSelectObject(hDC, DesktopBrush); + NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY); + NtGdiSelectObject(hDC, PreviousBrush); + } + + hOldBitmap = NtGdiSelectObject(hWallpaperDC, WinSta->hbmWallpaper); + NtGdiBitBlt(hDC, x, y, WinSta->cxWallpaper, WinSta->cyWallpaper, hWallpaperDC, 0, 0, SRCCOPY); + NtGdiSelectObject(hWallpaperDC, hOldBitmap); + + NtGdiDeleteDC(hWallpaperDC); + if(x <= 0 && y <= 0) return TRUE; + } + } + } + PreviousBrush = NtGdiSelectObject(hDC, DesktopBrush); NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY); NtGdiSelectObject(hDC, PreviousBrush); diff --git a/reactos/subsys/win32k/ntuser/misc.c b/reactos/subsys/win32k/ntuser/misc.c index 67841b6e12a..c0f927569db 100644 --- a/reactos/subsys/win32k/ntuser/misc.c +++ b/reactos/subsys/win32k/ntuser/misc.c @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.83 2004/07/12 20:09:35 gvg Exp $ +/* $Id: misc.c,v 1.84 2004/08/17 21:47:36 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -677,6 +677,8 @@ IntSystemParametersInfo( case SPI_SETDOUBLECLKWIDTH: case SPI_SETDOUBLECLKHEIGHT: case SPI_SETDOUBLECLICKTIME: + case SPI_SETDESKWALLPAPER: + case SPI_GETDESKWALLPAPER: { PSYSTEM_CURSORINFO CurInfo; @@ -690,21 +692,68 @@ IntSystemParametersInfo( return (DWORD)FALSE; } - CurInfo = IntGetSysCursorInfo(WinStaObject); switch(uiAction) { case SPI_SETDOUBLECLKWIDTH: + CurInfo = IntGetSysCursorInfo(WinStaObject); /* FIXME limit the maximum value? */ CurInfo->DblClickWidth = uiParam; break; case SPI_SETDOUBLECLKHEIGHT: + CurInfo = IntGetSysCursorInfo(WinStaObject); /* FIXME limit the maximum value? */ CurInfo->DblClickHeight = uiParam; break; case SPI_SETDOUBLECLICKTIME: + CurInfo = IntGetSysCursorInfo(WinStaObject); /* FIXME limit the maximum time to 1000 ms? */ CurInfo->DblClickSpeed = uiParam; break; + case SPI_SETDESKWALLPAPER: + { + /* This function expects different parameters than the user mode version! + + We let the user mode code load the bitmap, it passed the handle to + the bitmap. We'll change it's ownership to system and replace it with + the current wallpaper bitmap */ + HBITMAP hOldBitmap, hNewBitmap; + ASSERT(pvParam); + + hNewBitmap = *(HBITMAP*)pvParam; + if(hNewBitmap != NULL) + { + BITMAPOBJ *bmp; + /* try to get the size of the wallpaper */ + if(!(bmp = BITMAPOBJ_LockBitmap(hNewBitmap))) + { + ObDereferenceObject(WinStaObject); + return FALSE; + } + WinStaObject->cxWallpaper = bmp->SurfObj.sizlBitmap.cx; + WinStaObject->cyWallpaper = bmp->SurfObj.sizlBitmap.cy; + + BITMAPOBJ_UnlockBitmap(hNewBitmap); + + /* change the bitmap's ownership */ + GDIOBJ_SetOwnership(hNewBitmap, NULL); + } + hOldBitmap = (HBITMAP)InterlockedExchange((LONG*)&WinStaObject->hbmWallpaper, (LONG)hNewBitmap); + if(hOldBitmap != NULL) + { + /* delete the old wallpaper */ + NtGdiDeleteObject(hOldBitmap); + } + break; + } + case SPI_GETDESKWALLPAPER: + /* This function expects different parameters than the user mode version! + + We basically return the current wallpaper handle - if any. The user + mode version should load the string from the registry and return it + without calling this function */ + ASSERT(pvParam); + *(HBITMAP*)pvParam = (HBITMAP)WinStaObject->hbmWallpaper; + break; } /* FIXME save the value to the registry */ @@ -895,6 +944,37 @@ NtUserSystemParametersInfo( } return TRUE; } + case SPI_SETDESKWALLPAPER: + { + /* !!! As opposed to the user mode version this version accepts a handle + to the bitmap! */ + HBITMAP hbmWallpaper; + + Status = MmCopyFromCaller(&hbmWallpaper, pvParam, sizeof(HBITMAP)); + if(!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return FALSE; + } + return IntSystemParametersInfo(SPI_SETDESKWALLPAPER, 0, &hbmWallpaper, fWinIni); + } + case SPI_GETDESKWALLPAPER: + { + /* !!! As opposed to the user mode version this version returns a handle + to the bitmap! */ + HBITMAP hbmWallpaper; + BOOL Ret; + + Ret = IntSystemParametersInfo(SPI_GETDESKWALLPAPER, 0, &hbmWallpaper, fWinIni); + + Status = MmCopyToCaller(pvParam, &hbmWallpaper, sizeof(HBITMAP)); + if(!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return FALSE; + } + return Ret; + } case SPI_GETICONTITLELOGFONT: { LOGFONTW IconFont;