|
|
/****************************** Module Header ******************************\
* Module Name: dtbitmap.c * * Copyright (c) 1985 - 1999, Microsoft Corporation * * Desktop Wallpaper Routines. * * History: * 29-Jul-1991 MikeKe From win31 \***************************************************************************/
#include "precomp.h"
#pragma hdrstop
/*
* Local Constants. */ #define MAXPAL 256
#define MAXSTATIC 20
#define TILE_XMINSIZE 2
#define TILE_YMINSIZE 4
/*
* The version strings are stored in a contiguous-buffer. Each string * is of size MAXVERSIONSTRING. */
// Size of each string buffer.
#define MAXVERSIONSTRING 128
// Offset into verbuffer of build-string.
#define OFFSET_BLDSTRING 0
// Offset into verbuffer of CSD string.
#define OFFSET_CSDSTRING OFFSET_BLDSTRING + MAXVERSIONSTRING
// Max size of buffer (contains all 3 strings).
#define MAXVERSIONBUFFER OFFSET_CSDSTRING + MAXVERSIONSTRING
WCHAR wszSafeMode[MAX_PATH + 3 * MAXVERSIONSTRING]; WCHAR SafeModeStr[64]; int SafeModeStrLen; WCHAR wszProductName[MAXVERSIONSTRING]; WCHAR wszProductBuild[2 * MAXVERSIONSTRING];
__inline PWND _GetShellWindow( PDESKTOP pdesk) { if (pdesk == NULL) { return NULL; } else { return pdesk->pDeskInfo->spwndShell; } }
/***************************************************************************\
* GetVersionInfo * * Outputs a string on the desktop indicating debug-version. * * History: \***************************************************************************/ VOID GetVersionInfo( BOOL Verbose) { WCHAR NameBuffer[MAXVERSIONBUFFER]; WCHAR Title1[MAXVERSIONSTRING]; WCHAR Title2[MAXVERSIONSTRING]; WCHAR wszPID[MAXVERSIONSTRING]; WCHAR wszProduct[MAXVERSIONSTRING]; WCHAR wszPBuild[MAXVERSIONSTRING]; WCHAR wszEvaluation[MAXVERSIONSTRING]; UNICODE_STRING UserBuildString; UNICODE_STRING UserCSDString; NTSTATUS Status; UINT uProductStrId;
/*
* Temporary code name handling. Used internally and turned off by "" * for release. The matching string in strid.mc doesn't have a space * separator between code name and the rest of the title, so this * space must be included at end of this code name string. */ WCHAR wszCodeName[] = L"";
RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable[] = {
{NULL, RTL_QUERY_REGISTRY_DIRECT, #ifdef PRERELEASE
L"BuildLab", #else
L"CurrentBuildNumber", #endif // PRERELEASE
&UserBuildString, REG_NONE, NULL, 0},
{NULL, RTL_QUERY_REGISTRY_DIRECT, L"CSDVersion", &UserCSDString, REG_NONE, NULL, 0},
{NULL, 0, NULL, NULL, REG_NONE, NULL, 0} };
UserBuildString.Buffer = &NameBuffer[OFFSET_BLDSTRING]; UserBuildString.Length = 0; UserBuildString.MaximumLength = MAXVERSIONSTRING * sizeof(WCHAR);
UserCSDString.Buffer = &NameBuffer[OFFSET_CSDSTRING]; UserCSDString.Length = 0; UserCSDString.MaximumLength = MAXVERSIONSTRING * sizeof(WCHAR);
Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT, L"", BaseServerRegistryConfigurationTable, NULL, NULL);
if (!NT_SUCCESS(Status)) { RIPMSG1(RIP_WARNING, "GetVersionInfo failed with status %x", Status); return; }
ServerLoadString(hModuleWin, STR_DTBS_PRODUCTID, wszPID, ARRAY_SIZE(wszPID)); ServerLoadString(hModuleWin, STR_DTBS_PRODUCTBUILD, wszPBuild, ARRAY_SIZE(wszPBuild));
/*
* Write out Debugging Version message. */
/*
* Bug 280256 - joejo * Create new desktop build information strings */ if (USER_SHARED_DATA->SuiteMask & (1 << EmbeddedNT)) { uProductStrId = STR_DTBS_PRODUCTEMB; } else if (USER_SHARED_DATA->NtProductType == NtProductWinNt) { #ifdef _WIN64
uProductStrId = STR_DTBS_PRODUCTWKS64; #else
if (USER_SHARED_DATA->SuiteMask & (1 << Personal)) { uProductStrId = STR_DTBS_PRODUCTPER; } else { uProductStrId = STR_DTBS_PRODUCTPRO; } #endif
} else { #ifdef _WIN64
if (USER_SHARED_DATA->SuiteMask & (1 << DataCenter)) { uProductStrId = STR_DTBS_PRODUCTDTC64; } else if (USER_SHARED_DATA->SuiteMask & (1 << Enterprise)) { uProductStrId = STR_DTBS_PRODUCTADV64; } else { uProductStrId = STR_DTBS_PRODUCTSRV64; } #else
if (USER_SHARED_DATA->SuiteMask & (1 << DataCenter)) { uProductStrId = STR_DTBS_PRODUCTDTC; } else if (USER_SHARED_DATA->SuiteMask & (1 << Enterprise)) { uProductStrId = STR_DTBS_PRODUCTADV; } else if (USER_SHARED_DATA->SuiteMask & (1 << Blade)) { uProductStrId = STR_DTBS_PRODUCTBLA; } else if(USER_SHARED_DATA->SuiteMask & (1 << SmallBusinessRestricted)) { uProductStrId = STR_DTBS_PRODUCTSBS; } else { uProductStrId = STR_DTBS_PRODUCTSRV; } #endif /* _WIN64 */
}
ServerLoadString(hModuleWin, uProductStrId, wszProduct, ARRAY_SIZE(wszProduct));
swprintf( wszProductName, wszPID, wszCodeName, wszProduct);
if (gfUnsignedDrivers) { /* This takes precedence */ ServerLoadString(hModuleWin, STR_TESTINGONLY, wszEvaluation, ARRAY_SIZE(wszEvaluation)); } else if (USER_SHARED_DATA->SystemExpirationDate.QuadPart) { ServerLoadString(hModuleWin, STR_DTBS_EVALUATION, wszEvaluation, ARRAY_SIZE(wszEvaluation)); } else { wszEvaluation[0] = '\0'; }
swprintf( wszProductBuild, wszPBuild, wszEvaluation, UserBuildString.Buffer );
if (Verbose) { ServerLoadString(hModuleWin, STR_SAFEMODE_TITLE1, Title1, ARRAY_SIZE(Title1)); ServerLoadString(hModuleWin, STR_SAFEMODE_TITLE2, Title2, ARRAY_SIZE(Title2));
swprintf( wszSafeMode, UserCSDString.Length == 0 ? Title1 : Title2, wszCodeName, UserBuildString.Buffer, UserCSDString.Buffer, USER_SHARED_DATA->NtSystemRoot ); } else { ServerLoadString(hModuleWin, STR_SAFEMODE_TITLE3, Title1, ARRAY_SIZE(Title1)); ServerLoadString(hModuleWin, STR_SAFEMODE_TITLE4, Title2, ARRAY_SIZE(Title2));
swprintf( wszSafeMode, UserCSDString.Length == 0 ? Title1 : Title2, wszCodeName, UserBuildString.Buffer, UserCSDString.Buffer); } }
/***************************************************************************\
* GetDefaultWallpaperName * * Get initial bitmap name * * History: * 21-Feb-1995 JimA Created. * 06-Mar-1996 ChrisWil Moved to kernel to facilite ChangeDisplaySettings. \***************************************************************************/ VOID GetDefaultWallpaperName( LPWSTR lpszWallpaper) { /*
* Set the initial global wallpaper bitmap name for (Default) * The global name is an at most 8 character name with no * extension. It is "winnt" for workstation or "lanmannt" * for server or server upgrade. It is followed by 256 it * is for 256 color devices. */ if (USER_SHARED_DATA->NtProductType == NtProductWinNt) { wcsncpycch(lpszWallpaper, L"winnt", 8); } else { wcsncpycch(lpszWallpaper, L"lanmannt", 8); }
lpszWallpaper[8] = (WCHAR)0;
if (gpsi->BitsPixel * gpsi->Planes > 4) { int iStart = wcslen(lpszWallpaper); iStart = min(iStart, 5);
lpszWallpaper[iStart] = (WCHAR)0; wcscat(lpszWallpaper, L"256"); } }
/***************************************************************************\
* GetDeskWallpaperName * * History: * 19-Dec-1994 JimA Created. * 29-Sep-1995 ChrisWil ReWrote to return filename. \***************************************************************************/ #define GDWPN_KEYSIZE 40
#define GDWPN_BITSIZE 256
LPWSTR GetDeskWallpaperName(PUNICODE_STRING pProfileUserName, LPWSTR lpszFile ) { WCHAR wszKey[GDWPN_KEYSIZE]; WCHAR wszNone[GDWPN_KEYSIZE]; LPWSTR lpszBitmap = NULL;
/*
* Load the none-string. This will be used for comparisons later. */ ServerLoadString(hModuleWin, STR_NONE, wszNone, ARRAY_SIZE(wszNone));
if ((lpszFile == NULL) || (lpszFile == SETWALLPAPER_DEFAULT) || (lpszFile == SETWALLPAPER_METRICS)) {
/*
* Allocate a buffer for the wallpaper. We will assume * a default-size in this case. */ lpszBitmap = UserAllocPool(GDWPN_BITSIZE * sizeof(WCHAR), TAG_SYSTEM); if (lpszBitmap == NULL) return NULL;
/*
* Get the "Wallpaper" string from WIN.INI's [Desktop] section. The * section name is not localized, so hard code it. If the string * returned is Empty, then set it up for a none-wallpaper. * * Unlike the rest of per user settings that got updated in * xxxUpdatePerUserSystemParameters, wallpaper is being updated via a * direct call to SystemParametersInfo from UpdatePerUserSystemParameters. * Force remote settings check in this case. */ if (!FastGetProfileStringFromIDW(pProfileUserName, PMAP_DESKTOP, STR_DTBITMAP, wszNone, lpszBitmap, GDWPN_BITSIZE, POLICY_REMOTE )) { wcscpy(lpszBitmap, wszNone); }
} else {
UINT uLen;
uLen = wcslen(lpszFile) + 1; uLen = max(uLen, GDWPN_BITSIZE);
/*
* Allocate enough space to store the name passed in. Returning * NULL will allow the wallpaper to redraw. As well, if we're * out of memory, then no need to load a wallpaper anyway. */ lpszBitmap = UserAllocPool(uLen * sizeof(WCHAR), TAG_SYSTEM); if (lpszBitmap == NULL) return NULL;
wcscpy(lpszBitmap, lpszFile); }
/*
* No bitmap if NULL passed in or if (NONE) in win.ini entry. We * return NULL to force the redraw of the wallpaper in the kernel. */ if ((*lpszBitmap == (WCHAR)0) || (_wcsicmp(lpszBitmap, wszNone) == 0)) { UserFreePool(lpszBitmap); return NULL; }
/*
* If bitmap name set to (DEFAULT) then set it to the system bitmap. */ ServerLoadString(hModuleWin, STR_DEFAULT, wszKey, ARRAY_SIZE(wszKey));
if (_wcsicmp(lpszBitmap, wszKey) == 0) { GetDefaultWallpaperName(lpszBitmap); }
return lpszBitmap; }
/***************************************************************************\
* TestVGAColors * * Tests whether the log-palette is just a standard 20 palette. * * History: * 29-Sep-1995 ChrisWil Created. \***************************************************************************/
BOOL TestVGAColors( LPLOGPALETTE ppal) { int i; int n; int size; COLORREF clr;
static CONST DWORD StupidColors[] = { 0x00000000, // 0 Sys Black
0x00000080, // 1 Sys Dk Red
0x00008000, // 2 Sys Dk Green
0x00008080, // 3 Sys Dk Yellow
0x00800000, // 4 Sys Dk Blue
0x00800080, // 5 Sys Dk Violet
0x00808000, // 6 Sys Dk Cyan
0x00c0c0c0, // 7 Sys Lt Grey
0x00808080, // 248 Sys Lt Gray
0x000000ff, // 249 Sys Red
0x0000ff00, // 250 Sys Green
0x0000ffff, // 251 Sys Yellow
0x00ff0000, // 252 Sys Blue
0x00ff00ff, // 253 Sys Violet
0x00ffff00, // 254 Sys Cyan
0x00ffffff, // 255 Sys White
0x000000BF, // 1 Sys Dk Red again
0x0000BF00, // 2 Sys Dk Green again
0x0000BFBF, // 3 Sys Dk Yellow again
0x00BF0000, // 4 Sys Dk Blue again
0x00BF00BF, // 5 Sys Dk Violet again
0x00BFBF00, // 6 Sys Dk Cyan again
0x000000C0, // 1 Sys Dk Red again
0x0000C000, // 2 Sys Dk Green again
0x0000C0C0, // 3 Sys Dk Yellow again
0x00C00000, // 4 Sys Dk Blue again
0x00C000C0, // 5 Sys Dk Violet again
0x00C0C000, // 6 Sys Dk Cyan again
};
size = (sizeof(StupidColors) / sizeof(StupidColors[0]));
for (i = 0; i < (int)ppal->palNumEntries; i++) {
clr = ((LPDWORD)ppal->palPalEntry)[i];
for (n = 0; n < size; n++) {
if (StupidColors[n] == clr) break; }
if (n == size) return FALSE; }
return TRUE; }
/***************************************************************************\
* DoHTColorAdjustment * * The default HT-Gamma adjustment was 2.0 on 3.5 (internal to gdi). For * 3.51 this value was decreased to 1.0 to accomdate printing. For our * desktop-wallpaper we are going to darken it slightly to that the image * doesn't appear to light. For the Shell-Release we will provid a UI to * allow users to change this for themselves. * * * History: * 11-May-1995 ChrisWil Created. \***************************************************************************/
#define FIXED_GAMMA (WORD)13000
VOID DoHTColorAdjust( HDC hdc) { COLORADJUSTMENT ca;
if (GreGetColorAdjustment(hdc, &ca)) {
ca.caRedGamma = ca.caGreenGamma = ca.caBlueGamma = FIXED_GAMMA;
GreSetColorAdjustment(hdc, &ca); } }
/***************************************************************************\
* ConvertToDDB * * Converts a DIBSection to a DDB. We do this to speed up drawings so that * bitmap-colors don't have to go through a palette-translation match. This * will also stretch/expand the image if the syle is set. * * If the new image requires a halftone-palette, the we will create one and * set it as the new wallpaper-palette. * * History: * 26-Oct-1995 ChrisWil Ported. * 30-Oct-1995 ChrisWil Added halftoning. Rewote the stretch/expand stuff. \***************************************************************************/
HBITMAP ConvertToDDB( HDC hdc, HBITMAP hbmOld, HPALETTE hpal) { BITMAP bm; HBITMAP hbmNew;
/*
* This object must be a REALDIB type bitmap. */ GreExtGetObjectW(hbmOld, sizeof(bm), &bm);
/*
* Create the new wallpaper-surface. */ if (hbmNew = GreCreateCompatibleBitmap(hdc, bm.bmWidth, bm.bmHeight)) {
HPALETTE hpalDst; HPALETTE hpalSrc; HBITMAP hbmDst; HBITMAP hbmSrc; UINT bpp; BOOL fHalftone = FALSE;
/*
* Select in the surfaces. */ hbmDst = GreSelectBitmap(ghdcMem2, hbmNew); hbmSrc = GreSelectBitmap(ghdcMem, hbmOld);
/*
* Determine image bits/pixel. */ bpp = (bm.bmPlanes * bm.bmBitsPixel);
/*
* Use the palette if given. If the image is of a greater * resolution than the device, then we're going to go through * a halftone-palette to get better colors. */ if (hpal) {
hpalDst = _SelectPalette(ghdcMem2, hpal, FALSE); hpalSrc = _SelectPalette(ghdcMem, hpal, FALSE);
xxxRealizePalette(ghdcMem2);
/*
* Set the halftoning for the destination. This is done * for images of greater resolution than the device. */ if (bpp > gpsi->BitCount) { fHalftone = TRUE; DoHTColorAdjust(ghdcMem2); } }
/*
* Set the stretchbltmode. This is more necessary when doing * halftoning. Since otherwise, the colors won't translate * correctly. */ SetBestStretchMode(ghdcMem2, bpp, fHalftone);
/*
* Set the new surface bits. Use StretchBlt() so the SBMode * will be used in color-translation. */ GreStretchBlt(ghdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, ghdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY, 0);
/*
* Restore palettes. */ if (hpal) { _SelectPalette(ghdcMem2, hpalDst, FALSE); _SelectPalette(ghdcMem, hpalSrc, FALSE); }
/*
* Restore the surfaces. */ GreSelectBitmap(ghdcMem2, hbmDst); GreSelectBitmap(ghdcMem, hbmSrc); GreDeleteObject(hbmOld);
GreSetBitmapOwner(hbmNew, OBJECT_OWNER_PUBLIC);
} else { hbmNew = hbmOld; }
return hbmNew; }
/***************************************************************************\
* CreatePaletteFromBitmap * * Take in a REAL dib handle and create a palette from it. This will not * work for bitmaps created by any other means than CreateDIBSection or * CreateDIBitmap(CBM_CREATEDIB). This is due to the fact that these are * the only two formats who have palettes stored with their object. * * History: * 29-Sep-1995 ChrisWil Created. \***************************************************************************/
HPALETTE CreatePaletteFromBitmap( HBITMAP hbm) { HPALETTE hpal; LPLOGPALETTE ppal; HBITMAP hbmT; DWORD size; int i;
/*
* Make room for temp logical palette of max size. */ size = sizeof(LOGPALETTE) + (MAXPAL * sizeof(PALETTEENTRY));
ppal = (LPLOGPALETTE)UserAllocPool(size, TAG_SYSTEM); if (!ppal) return NULL;
/*
* Retrieve the palette from the DIB(Section). The method of calling * GreGetDIBColorTable() can only be done on sections or REAL-Dibs. */ hbmT = GreSelectBitmap(ghdcMem, hbm); ppal->palVersion = 0x300; ppal->palNumEntries = (WORD)GreGetDIBColorTable(ghdcMem, 0, MAXPAL, (LPRGBQUAD)ppal->palPalEntry); GreSelectBitmap(ghdcMem, hbmT);
/*
* Create a halftone-palette if their are no entries. Otherwise, * swap the RGB values to be palentry-compatible and create us a * palette. */ if (ppal->palNumEntries == 0) { hpal = GreCreateHalftonePalette(gpDispInfo->hdcScreen); } else {
BYTE tmpR;
/*
* Swap red/blue because a RGBQUAD and PALETTEENTRY dont get along. */ for (i=0; i < (int)ppal->palNumEntries; i++) { tmpR = ppal->palPalEntry[i].peRed; ppal->palPalEntry[i].peRed = ppal->palPalEntry[i].peBlue; ppal->palPalEntry[i].peBlue = tmpR; ppal->palPalEntry[i].peFlags = 0; }
/*
* If the Bitmap only has VGA colors in it we dont want to * use a palette. It just causes unessesary palette flashes. */ hpal = TestVGAColors(ppal) ? NULL : GreCreatePalette(ppal); }
UserFreePool(ppal);
/*
* Make this palette public. */ if (hpal) GreSetPaletteOwner(hpal, OBJECT_OWNER_PUBLIC);
return hpal; }
/***************************************************************************\
* TileWallpaper * * History: * 29-Jul-1991 MikeKe From win31 \***************************************************************************/
BOOL TileWallpaper(HDC hdc, LPCRECT lprc, BOOL fOffset) { int xO; int yO; int x; int y; BITMAP bm; HBITMAP hbmT = NULL; POINT ptOffset;
if (fOffset) { ptOffset.x = gsrcWallpaper.x; ptOffset.y = gsrcWallpaper.y; } else { ptOffset.x = 0; ptOffset.y = 0; }
/*
* We need to get the dimensions of the bitmap here rather than rely on * the dimensions in srcWallpaper because this function may * be called as part of ExpandBitmap, before srcWallpaper is * set. */ if (GreExtGetObjectW(ghbmWallpaper, sizeof(BITMAP), (PBITMAP)&bm)) { xO = lprc->left - (lprc->left % bm.bmWidth) + (ptOffset.x % bm.bmWidth); if (xO > lprc->left) { xO -= bm.bmWidth; }
yO = lprc->top - (lprc->top % bm.bmHeight) + (ptOffset.y % bm.bmHeight); if (yO > lprc->top) { yO -= bm.bmHeight; }
/*
* Tile the bitmap to the surface. */ if (hbmT = GreSelectBitmap(ghdcMem, ghbmWallpaper)) { for (y = yO; y < lprc->bottom; y += bm.bmHeight) { for (x = xO; x < lprc->right; x += bm.bmWidth) { GreBitBlt(hdc, x, y, bm.bmWidth, bm.bmHeight, ghdcMem, 0, 0, SRCCOPY, 0); } }
GreSelectBitmap(ghdcMem, hbmT); } }
return (hbmT != NULL); }
/***************************************************************************\
* GetWallpaperCenterRect * * Returns the rect of centered wallpaper on a particular monitor. * * History: * 26-Sep-1996 adams Created. \***************************************************************************/
BOOL GetWallpaperCenterRect(LPRECT lprc, LPPOINT lppt, LPCRECT lprcMonitor) { RECT rc;
if (gsrcWallpaper.x != 0 || gsrcWallpaper.y != 0) { rc.left = lprcMonitor->left + gsrcWallpaper.x; rc.top = lprcMonitor->top + gsrcWallpaper.y; } else { rc.left = (lprcMonitor->left + lprcMonitor->right - gsrcWallpaper.cx) / 2; rc.top = (lprcMonitor->top + lprcMonitor->bottom - gsrcWallpaper.cy) / 2; }
rc.right = rc.left + gsrcWallpaper.cx; rc.bottom = rc.top + gsrcWallpaper.cy;
lppt->x = max(0, lprcMonitor->left - rc.left); lppt->y = max(0, lprcMonitor->top - rc.top);
return IntersectRect(lprc, &rc, lprcMonitor); }
/***************************************************************************\
* CenterOrStretchWallpaper * * * History: * 29-Jul-1991 MikeKe From win31 \***************************************************************************/
BOOL CenterOrStretchWallpaper(HDC hdc, LPCRECT lprcMonitor) { BOOL fStretchToEachMonitor = FALSE; RECT rc; HBITMAP hbmT; BOOL f = FALSE; HRGN hrgn; POINT pt; BITMAP bm; int oldStretchMode;
/*
* This used to call TileWallpaper, but this really slowed up the system * for small dimension bitmaps. We really only need to blt it once for * centered bitmaps. */ if (hbmT = GreSelectBitmap(ghdcMem, ghbmWallpaper)) { if (fStretchToEachMonitor && (gwWPStyle & DTF_STRETCH)) { if (GreExtGetObjectW(ghbmWallpaper, sizeof(BITMAP), (PBITMAP)&bm)) { oldStretchMode = GreSetStretchBltMode(hdc, COLORONCOLOR); f = GreStretchBlt(hdc, lprcMonitor->left, lprcMonitor->top, lprcMonitor->right - lprcMonitor->left, lprcMonitor->bottom - lprcMonitor->top, ghdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY, 0); GreSetStretchBltMode(hdc, oldStretchMode); } } else { if (GetWallpaperCenterRect(&rc, &pt, lprcMonitor)) { f = GreBitBlt(hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, ghdcMem, pt.x, pt.y, SRCCOPY, 0);
/*
* Fill the bacground (excluding the bitmap) with the desktop * brush. Save the DC with the cliprect. */ if (f && NULL != (hrgn = CreateEmptyRgn())) { if (GreGetRandomRgn(hdc, hrgn, 1) != -1) { GreExcludeClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); FillRect(hdc, lprcMonitor, SYSHBR(DESKTOP)); GreExtSelectClipRgn(hdc, hrgn, RGN_COPY); }
GreDeleteObject(hrgn); } } }
GreSelectBitmap(ghdcMem, hbmT); }
/*
* As a last-ditch effort, if something failed, just clear the desktop. */ if (!f) { FillRect(hdc, lprcMonitor, SYSHBR(DESKTOP)); }
return f; }
/***************************************************************************\
* xxxDrawWallpaper * * Performs the drawing of the wallpaper. This can be either tiled or * centered. This routine provides the common things like palette-handling. * If the (fPaint) is false, then we only to palette realization and no * drawing. * * History: * 01-Oct-1995 ChrisWil Ported. \***************************************************************************/
BOOL xxxDrawWallpaper( PWND pwnd, HDC hdc, PMONITOR pMonitorPaint, LPCRECT lprc) { BOOL f; HPALETTE hpalT; int i;
CheckLock(pwnd); CheckLock(pMonitorPaint); UserAssert(ghbmWallpaper != NULL); UserAssert(lprc);
/*
* Select in the palette if one exists. As a wallpaper, we should only * be able to do background-realizations. */ if (ghpalWallpaper && pMonitorPaint->dwMONFlags & MONF_PALETTEDISPLAY) { hpalT = _SelectPalette(hdc, ghpalWallpaper, FALSE); i = xxxRealizePalette(hdc); } else { hpalT = NULL; }
if (gwWPStyle & DTF_TILE) { f = TileWallpaper(hdc, lprc, pwnd != NULL); } else { f = CenterOrStretchWallpaper(hdc, &pMonitorPaint->rcMonitor); }
if (hpalT) { _SelectPalette(hdc, hpalT, FALSE); }
return f; }
/***************************************************************************\
* xxxExpandBitmap * * Expand this bitmap to fit the screen. This is used for tiled images * only. * * History: * 29-Sep-1995 ChrisWil Ported from Chicago. \***************************************************************************/
HBITMAP xxxExpandBitmap( HBITMAP hbm) { int nx; int ny; BITMAP bm; HBITMAP hbmNew; HBITMAP hbmD; LPRECT lprc; RECT rc; PMONITOR pMonitor; TL tlpMonitor;
/*
* Get the dimensions of the screen and bitmap we'll be dealing with. * We'll adjust the xScreen/yScreen to reflect the new surface size. * The default adjustment is to stretch the image to fit the screen. */ GreExtGetObjectW(hbm, sizeof(bm), (PBITMAP)&bm);
pMonitor = GetPrimaryMonitor(); lprc = &pMonitor->rcMonitor; nx = (lprc->right / TILE_XMINSIZE) / bm.bmWidth; ny = (lprc->bottom / TILE_YMINSIZE) / bm.bmHeight;
if (nx == 0) nx++;
if (ny == 0) ny++;
if ((nx + ny) <= 2) return hbm;
/*
* Create the surface for the new-bitmap. */ rc.left = rc.top = 0; rc.right = nx * bm.bmWidth; rc.bottom = ny * bm.bmHeight; hbmD = GreSelectBitmap(ghdcMem, hbm); hbmNew = GreCreateCompatibleBitmap(ghdcMem, rc.right, rc.bottom); GreSelectBitmap(ghdcMem, hbmD);
if (hbmNew == NULL) return hbm;
if (hbmD = GreSelectBitmap(ghdcMem2, hbmNew)) { /*
* Expand the bitmap to the new surface. */ ThreadLockAlways(pMonitor, &tlpMonitor); xxxDrawWallpaper(NULL, ghdcMem2, pMonitor, &rc); ThreadUnlock(&tlpMonitor); GreSelectBitmap(ghdcMem2, hbmD); }
GreDeleteObject(hbm);
GreSetBitmapOwner(hbmNew, OBJECT_OWNER_PUBLIC);
return hbmNew; }
/***************************************************************************\
* xxxLoadDesktopWallpaper * * Load the dib (section) from the client-side. We make this callback to * utilize code in USER32 for loading/creating a dib or section. Since, * the wallpaper-code can be called from any-process, we can't use DIBSECTIONS * for a wallpaper. Luckily we can use Real-DIBs for this. That way we * can extract out a palette from the bitmap. We couldn't do this if the * bitmap was created "compatible". * * History: * 29-Sep-1995 ChrisWil Created. \***************************************************************************/
BOOL xxxLoadDesktopWallpaper( LPWSTR lpszFile) { UINT LR_flags; int dxDesired; int dyDesired; UNICODE_STRING strName;
/*
* If the bitmap is somewhat large (big bpp), then we'll deal * with it as a real-dib. We'll also do this for 8bpp since it * can utilize a palette. Chicago uses DIBSECTIONS since it can * count on the one-process handling the drawing. Since, NT can * have different processes doing the drawing, we can't use sections. */ LR_flags = LR_LOADFROMFILE;
if (gpDispInfo->fAnyPalette || gpsi->BitCount >= 8) { LR_flags |= LR_CREATEREALDIB; }
/*
* If we are going to be stretching the bitmap, go ahead and pre-stretch * the bitmap to the size of the primary monitor. This makes blitting * to the primary monitor quicker (because it doesn't have to stretch), * while other monitors will be a little slower. */ if (gwWPStyle & DTF_STRETCH) { PMONITOR pMonitor = GetPrimaryMonitor(); dxDesired = pMonitor->rcMonitor.right - pMonitor->rcMonitor.left; dyDesired = pMonitor->rcMonitor.bottom - pMonitor->rcMonitor.top; } else { dxDesired = dyDesired = 0; }
/*
* Make a callback to the client to perform the loading. * Saves us some code. */ RtlInitUnicodeString(&strName, lpszFile);
ghbmWallpaper = xxxClientLoadImage( &strName, 0, IMAGE_BITMAP, dxDesired, dyDesired, LR_flags, TRUE);
if (ghbmWallpaper == NULL) return FALSE;
/*
* If it's a palette-display, then we will derive the global * wallpaper palette from the bitmap. */ if (gpDispInfo->fAnyPalette) { ghpalWallpaper = CreatePaletteFromBitmap(ghbmWallpaper); }
/*
* Always try to convert the bitmap to a DDB. On single monitor * systems this will improve performance. On multiple-monitor * systems, GDI will refuse to create the DDB and just leave it * as a DIB at the color format of the primary monitor. */ ghbmWallpaper = ConvertToDDB(gpDispInfo->hdcScreen, ghbmWallpaper, ghpalWallpaper);
/*
* Mark the bitmap as public, so any process can party with it. */ GreSetBitmapOwner(ghbmWallpaper, OBJECT_OWNER_PUBLIC);
/*
* Expand bitmap if we are going to tile it. This creates a larger * bitmap that contains an even multiple of the source bitmap. This * larger bitmap can then be tiled more quickly than the smaller bitmap. */ if (gwWPStyle & DTF_TILE) { ghbmWallpaper = xxxExpandBitmap(ghbmWallpaper); }
return TRUE; }
/***************************************************************************\
* xxxSetDeskWallpaper * * Sets the desktop-wallpaper. This deletes the old handles in the process. * * History: * 29-Jul-1991 MikeKe From win31. * 01-Oct-1995 ChrisWil Rewrote for LoadImage(). \***************************************************************************/
BOOL xxxSetDeskWallpaper(PUNICODE_STRING pProfileUserName, LPWSTR lpszFile) { BITMAP bm; UINT WallpaperStyle2; PWND pwndShell; TL tl; PTHREADINFO ptiCurrent = PtiCurrent(); PDESKTOP pdesk; BOOL fRet = FALSE; HBITMAP hbmOld;
PROFINTINFO apsi[] = { {PMAP_DESKTOP, (LPWSTR)STR_TILEWALL , 0, &gwWPStyle }, {PMAP_DESKTOP, (LPWSTR)STR_DTSTYLE , 0, &WallpaperStyle2 }, {PMAP_DESKTOP, (LPWSTR)STR_DTORIGINX, 0, &gsrcWallpaper.x }, {PMAP_DESKTOP, (LPWSTR)STR_DTORIGINY, 0, &gsrcWallpaper.y }, {0, NULL, 0, NULL } };
pdesk = ptiCurrent->rpdesk; hbmOld = ghbmWallpaper;
if ((lpszFile == SETWALLPAPER_METRICS) && !(gwWPStyle & DTF_STRETCH)) {
gsrcWallpaper.x = 0; gsrcWallpaper.y = 0;
if (ghbmWallpaper) goto CreateNewWallpaper;
goto Metric_Change; }
CreateNewWallpaper:
/*
* Delete the old wallpaper and palette if the exist. */ if (ghpalWallpaper) { GreDeleteObject(ghpalWallpaper); ghpalWallpaper = NULL; }
if (ghbmWallpaper) { GreDeleteObject(ghbmWallpaper); ghbmWallpaper = NULL; }
/*
* Kill any SPBs no matter what. This works if we're switching from/to * palettized wallpaper. Fixes a lot of problems because palette doesn't * change, shell paints funny on desktop, etc. */ BEGINATOMICCHECK(); FreeAllSpbs(); ENDATOMICCHECK();
/*
* If this is a metric-change (and stretched), then we need to * reload it. However, since we are called from the winlogon process * during a desktop-switch, we would be mapped to the wrong Luid * when we attempt to grab the name from GetDeskWallpaperName. This * would use the Luid from the DEFAULT user rather than the current * logged on user. In order to avoid this, we cache the wallpaer * name so that on METRIC-CHANGES we use the current-user's wallpaper. * * NOTE: we assume that prior to any METRIC change, we have already * setup the ghbmWallpaper and lpszCached. This is usually done * either on logon or during user desktop-changes through conrol-Panel. */ if (lpszFile == SETWALLPAPER_METRICS) {
UserAssert(gpszWall != NULL);
goto LoadWallpaper; }
/*
* Free the cached handle. */ if (gpszWall) { UserFreePool(gpszWall); gpszWall = NULL; }
/*
* Load the wallpaper-name. If this returns FALSE, then * the user specified (None). We will return true to force * the repainting of the desktop. */ gpszWall = GetDeskWallpaperName(pProfileUserName,lpszFile); if (!gpszWall) { fRet = TRUE; goto SDW_Exit; }
/*
* Retrieve the default settings from the registry. * * If tile is indicated, then normalize style to not include * FIT/STRETCH which are center-only styles. Likewise, if * we are centered, then normalize out the TILE bit. */ FastGetProfileIntsW(pProfileUserName, apsi, 0);
gwWPStyle &= DTF_TILE; if (!(gwWPStyle & DTF_TILE)) { gwWPStyle = WallpaperStyle2 & DTF_STRETCH; }
/*
* Load the wallpaper. This makes a callback to the client to * perform the bitmap-creation. */
LoadWallpaper:
if (xxxLoadDesktopWallpaper(gpszWall) == FALSE) { gwWPStyle = 0; goto SDW_Exit; }
/*
* If we have a palette, then we need to do the correct realization and * notification. */ if (ghpalWallpaper != NULL) { PWND pwndSend;
/*
* Get the shell window. This could be NULL on system * initialization. We will use this to do palette realization. */ pwndShell = _GetShellWindow(pdesk); if (pwndShell) { pwndSend = pwndShell; } else { pwndSend = (pdesk ? pdesk->pDeskInfo->spwnd : NULL); }
/*
* Update the desktop with the new bitmap. This cleans * out the system-palette so colors can be realized. */ GreRealizeDefaultPalette(gpDispInfo->hdcScreen, TRUE);
/*
* Don't broadcast if system initialization is occuring. Otherwise * this gives the shell first crack at realizing its colors * correctly. */ if (pwndSend) { HWND hwnd = HW(pwndSend);
ThreadLockAlways(pwndSend, &tl); xxxSendNotifyMessage(pwndSend, WM_PALETTECHANGED, (WPARAM)hwnd, 0); ThreadUnlock(&tl); } }
Metric_Change: if (fRet = GreExtGetObjectW(ghbmWallpaper, sizeof(bm), (PBITMAP)&bm)) { gsrcWallpaper.cx = bm.bmWidth; gsrcWallpaper.cy = bm.bmHeight; }
SDW_Exit:
/*
* Notify the shell-window that the wallpaper changed. We need to refresh * our local pwndShell here because we might have called-back above. */ pwndShell = _GetShellWindow(pdesk); if ((pwndShell != NULL) && ((hbmOld && !ghbmWallpaper) || (!hbmOld && ghbmWallpaper))) {
ThreadLockAlways(pwndShell, &tl); xxxSendNotifyMessage(pwndShell, WM_SHELLNOTIFY, SHELLNOTIFY_WALLPAPERCHANGED, (LPARAM)ghbmWallpaper); ThreadUnlock(&tl); }
return fRet; }
/***************************************************************************\
* DesktopBuildPaint * * Draw the build information onto the desktop * * History: * 2/4/99 joejo - Bug 280256 \***************************************************************************/ void DesktopBuildPaint( HDC hdc, PMONITOR pMonitor) { int imode; COLORREF oldColor; RECT rcText = {0,0,0,0}; RECT rcBuildInfo = {0,0,0,0}; HFONT oldFont = GreGetHFONT(hdc); SIZE sizeText; SIZE sizeProductName; SIZE sizeProductBuild; SIZE sizeSystemRoot; BOOL fDrawSolidBackground = FALSE; int cBorder = 5; int cMargin = fDrawSolidBackground ? 5 : 0;
/*
* Set up DC */ imode = GreSetBkMode(hdc, TRANSPARENT);
if (fDrawSolidBackground) { /*
* Since we are going to draw our own background, we can always set * the pen color to black. */ oldColor = GreSetTextColor( hdc, RGB(0,0,0) ); } else { /*
* Since we are not going to draw our own background, we have to work * with whatever is already there. This is an ugly hack to try and * cover the case where our white text won't show up on a white * background. Of course, this doesn't catch the bitmap case. Or * the almost white case. */ if (GreGetBrushColor(SYSHBR(BACKGROUND)) != 0x00ffffff) { oldColor = GreSetTextColor( hdc, RGB(255,255,255) ); } else { oldColor = GreSetTextColor( hdc, RGB(0,0,0) ); } }
/*
* Get the width in pixels of the longest string we are going to print out. */ if (gpsi && gpsi->hCaptionFont) { GreSelectFont(hdc, gpsi->hCaptionFont); }
GreGetTextExtentW( hdc, wszProductName, wcslen(wszProductName), &sizeProductName, GGTE_WIN3_EXTENT);
if (ghMenuFont != NULL ) { GreSelectFont(hdc, ghMenuFont); }
GreGetTextExtentW( hdc, wszProductBuild, wcslen(wszProductBuild), &sizeProductBuild, GGTE_WIN3_EXTENT);
if (gDrawVersionAlways) { GreGetTextExtentW( hdc, USER_SHARED_DATA->NtSystemRoot, wcslen(USER_SHARED_DATA->NtSystemRoot), &sizeSystemRoot, GGTE_WIN3_EXTENT); } else { sizeSystemRoot.cx = 0; sizeSystemRoot.cy = 0; }
sizeText.cx = sizeProductName.cx >= sizeProductBuild.cx ? sizeProductName.cx : sizeProductBuild.cx; sizeText.cy = sizeProductName.cy + sizeProductBuild.cy; if (gDrawVersionAlways) { sizeText.cx = (sizeText.cx >= sizeSystemRoot.cx) ? sizeText.cx : sizeSystemRoot.cx; sizeText.cy += sizeSystemRoot.cy; }
/*
* Calculate the position for all of the build info on the desktop. * We will draw either 2 or 3 lines of text. */ rcBuildInfo.left = pMonitor->rcWork.right - cBorder - cMargin - sizeText.cx - cMargin; rcBuildInfo.top = pMonitor->rcWork.bottom - cBorder - cMargin - sizeText.cy - cMargin; rcBuildInfo.right = pMonitor->rcWork.right - cBorder; rcBuildInfo.bottom = pMonitor->rcWork.bottom - cBorder;
/*
* Draw the background if we want it. * */ if (fDrawSolidBackground) { NtGdiRoundRect(hdc, rcBuildInfo.left, rcBuildInfo.top, rcBuildInfo.right, rcBuildInfo.bottom, 10, 10); }
/*
* Print Windows 2000 name */ if (gpsi && gpsi->hCaptionFont) { GreSelectFont(hdc, gpsi->hCaptionFont); }
rcText.left = rcBuildInfo.left + cMargin; rcText.top = rcBuildInfo.top + cMargin; rcText.right = rcText.left + sizeText.cx; rcText.bottom = rcText.top + sizeProductName.cy;
GreSetTextAlign(hdc, TA_RIGHT | TA_BOTTOM);
GreExtTextOutW( hdc, rcText.right, rcText.bottom, 0, &rcText, wszProductName, wcslen(wszProductName), (LPINT)NULL );
/*
* Print Build Number */ if (ghMenuFont != NULL ) { GreSelectFont(hdc, ghMenuFont); }
rcText.top = rcText.bottom + 1; rcText.bottom = rcText.top + sizeProductBuild.cy;
GreExtTextOutW( hdc, rcText.right, rcText.bottom, 0, &rcText, wszProductBuild, wcslen(wszProductBuild), (LPINT)NULL );
/*
* If we are in CHK mode, draw the System Dir Path */ if (gDrawVersionAlways) { rcText.top = rcText.bottom + 1; rcText.bottom = rcText.top + sizeSystemRoot.cy;
GreExtTextOutW( hdc, rcText.right, rcText.bottom, 0, &rcText, USER_SHARED_DATA->NtSystemRoot, wcslen(USER_SHARED_DATA->NtSystemRoot), (LPINT)NULL ); }
if (oldFont) { GreSelectFont(hdc, oldFont); }
GreSetBkMode(hdc, imode); GreSetTextColor(hdc, oldColor); }
/***************************************************************************\
* xxxDesktopPaintCallback * * Draw the wallpaper or fill with the background brush. In debug, * also draw the build number on the top of each monitor. * * History: * 20-Sep-1996 adams Created. \***************************************************************************/ BOOL xxxDesktopPaintCallback( PMONITOR pMonitor, HDC hdc, LPRECT lprcMonitorClip, LPARAM dwData) { BOOL f; PWND pwnd;
CheckLock(pMonitor);
pwnd = (PWND)dwData;
if (SYSMET(CLEANBOOT)) { FillRect(hdc, lprcMonitorClip, ghbrBlack ); f = TRUE; } else { /*
* if this is the disconnected desktop, skip the bitmap paint */ if (gbDesktopLocked) { f = FALSE; } else {
/*
* Paint the desktop with a color or the wallpaper. */ if (ghbmWallpaper) { f = xxxDrawWallpaper( pwnd, hdc, pMonitor, lprcMonitorClip); } else { FillRect(hdc, lprcMonitorClip, SYSHBR(DESKTOP)); f = TRUE; } } }
if (SYSMET(CLEANBOOT) || gDrawVersionAlways || gdwCanPaintDesktop) { static BOOL fInit = TRUE; SIZE size; int imode; COLORREF oldColor; HFONT oldFont = NULL;
/*
* Grab the stuff from the registry */ if (fInit) { if (SYSMET(CLEANBOOT)) { ServerLoadString( hModuleWin, STR_SAFEMODE, SafeModeStr, ARRAY_SIZE(SafeModeStr) ); SafeModeStrLen = wcslen(SafeModeStr); } GetVersionInfo(SYSMET(CLEANBOOT) == 0); fInit = FALSE; }
if (SYSMET(CLEANBOOT)) { if (gpsi != NULL && gpsi->hCaptionFont != NULL) { oldFont = GreSelectFont(hdc, gpsi->hCaptionFont); }
GreGetTextExtentW(hdc, wszSafeMode, wcslen(wszSafeMode), &size, GGTE_WIN3_EXTENT); imode = GreSetBkMode(hdc, TRANSPARENT);
oldColor = GreSetTextColor( hdc, RGB(255,255,255) );
GreExtTextOutW( hdc, (pMonitor->rcWork.left + pMonitor->rcWork.right - size.cx) / 2, pMonitor->rcWork.top, 0, (LPRECT)NULL, wszSafeMode, wcslen(wszSafeMode), (LPINT)NULL );
GreGetTextExtentW(hdc, SafeModeStr, SafeModeStrLen, &size, GGTE_WIN3_EXTENT);
GreExtTextOutW( hdc, pMonitor->rcWork.left, pMonitor->rcWork.top, 0, (LPRECT)NULL, SafeModeStr, SafeModeStrLen, (LPINT)NULL );
GreExtTextOutW( hdc, pMonitor->rcWork.right - size.cx, pMonitor->rcWork.top, 0, (LPRECT)NULL, SafeModeStr, SafeModeStrLen, (LPINT)NULL );
GreExtTextOutW( hdc, pMonitor->rcWork.right - size.cx, pMonitor->rcWork.bottom - gpsi->tmSysFont.tmHeight, 0, (LPRECT)NULL, SafeModeStr, SafeModeStrLen, (LPINT)NULL );
GreExtTextOutW( hdc, pMonitor->rcWork.left, pMonitor->rcWork.bottom - gpsi->tmSysFont.tmHeight, 0, (LPRECT)NULL, SafeModeStr, SafeModeStrLen, (LPINT)NULL );
GreSetBkMode(hdc, imode); GreSetTextColor(hdc, oldColor);
if (oldFont) { GreSelectFont(hdc, oldFont); } } else { if (!gbRemoteSession || !gdwTSExcludeDesktopVersion) { DesktopBuildPaint(hdc, pMonitor); } } }
return f; }
/***************************************************************************\
* xxxInvalidateDesktopOnPaletteChange * * Invalidates the shell window and uncovered areas of the desktop * when the palette changes. * * History: * 28-Apr-1997 adams Created. \***************************************************************************/ VOID xxxInvalidateDesktopOnPaletteChange( PWND pwnd) { PDESKTOP pdesk; PWND pwndShell; TL tlpwndShell; RECT rc; BOOL fRedrawDesktop;
CheckLock(pwnd);
/*
* Invalidate the shell window. */ pdesk = PtiCurrent()->rpdesk; pwndShell = _GetShellWindow(pdesk); if (!pwndShell) { fRedrawDesktop = TRUE; rc = gpsi->rcScreen; } else { ThreadLockAlways(pwndShell, &tlpwndShell); xxxRedrawWindow( pwndShell, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
/*
* The shell window may not cover all of the desktop. * Invalidate the part of the desktop wallpaper it * doesn't sit over. */ fRedrawDesktop = SubtractRect(&rc, &pwnd->rcWindow, &pwndShell->rcWindow); ThreadUnlock(&tlpwndShell); }
/*
* Invalidate the desktop window. */ if (fRedrawDesktop) { xxxRedrawWindow( pwnd, &rc, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN); } }
/***************************************************************************\
* xxxInternalPaintDesktop * * If fPaint is TRUE, enumerate the monitors to paint the desktop. * Otherwise, it selects the bitmap palette into the DC to select * its colors into the hardware palette. * * History: * 29-Jul-1991 MikeKe From win31 \***************************************************************************/ BOOL xxxInternalPaintDesktop( PWND pwnd, HDC hdc, BOOL fPaint) { BOOL fRet = FALSE;
CheckLock(pwnd);
if (fPaint) { RECT rcOrg, rcT; POINT pt;
/*
* For compatiblity purposes the DC origin of desktop windows * is set to the primary monitor, i.e. (0,0). Since we may get * either desktop or non-desktop DCs here, temporarily reset * the hdc origin to (0,0). */ GreGetDCOrgEx(hdc, &pt, &rcOrg); CopyRect(&rcT, &rcOrg); OffsetRect(&rcT, -rcT.left, -rcT.top); GreSetDCOrg(hdc, rcT.left, rcT.top, (PRECTL)&rcT);
fRet = xxxEnumDisplayMonitors( hdc, NULL, (MONITORENUMPROC) xxxDesktopPaintCallback, (LPARAM)pwnd, TRUE);
/*
* Reset the DC origin back. */ GreSetDCOrg(hdc, rcOrg.left, rcOrg.top, (PRECTL)&rcOrg);
} else if (ghpalWallpaper && GetPrimaryMonitor()->dwMONFlags & MONF_PALETTEDISPLAY) { /*
* Select in the palette if one exists. */ HPALETTE hpalT; int i;
hpalT = _SelectPalette(hdc, ghpalWallpaper, FALSE); i = xxxRealizePalette(hdc); _SelectPalette(hdc, hpalT, FALSE);
if (i > 0) { xxxInvalidateDesktopOnPaletteChange(pwnd); } fRet = TRUE; }
return fRet; }
|