Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1353 lines
37 KiB

/****************************** Module Header ******************************\
* Module Name: dtbitmap.c
*
* Copyright (c) 1985-1995, 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
#define SetBestStretchMode(hdc, bpp, fHT) \
GreSetStretchBltMode(hdc, \
(fHT ? HALFTONE : \
((bpp) == 1 ? BLACKONWHITE : COLORONCOLOR)))
#ifdef DEBUG
/*
* The version strings are stored in a contiguous-buffer. Each string
* is of equal-size (MAXVERSIONSTRING).
*/
#define MAXTXTBUFFER 80
#define MAXVERSIONBUFFER 400 // Max size of buffer (contains all 3 strings).
#define MAXVERSIONSTRING 100 // Size of each string buffer.
#define OFFSET_VERSTRING 0 // Offset into verbuffer of version-string.
#define OFFSET_BLDSTRING 100 // Offset into verbuffer of build-string.
#define OFFSET_CSDSTRING 200 // Offset into verbuffer of CSD string.
#define OFFSET_PTHSTRING 300 // Offset into verbuffer of path string.
UNICODE_STRING UserVersionString;
UNICODE_STRING UserBuildString;
UNICODE_STRING UserCSDString;
UNICODE_STRING UserPathString;
WCHAR wszT[MAXTXTBUFFER];
/***************************************************************************\
* GetVersionInfo
*
* Outputs a string on the desktop indicating debug-version.
*
* History:
\***************************************************************************/
RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable[] = {
{NULL,
RTL_QUERY_REGISTRY_DIRECT,
L"CurrentVersion",
&UserVersionString,REG_SZ,
L"4.00",
0
},
{NULL,
RTL_QUERY_REGISTRY_DIRECT,
L"CurrentBuildNumber",
&UserBuildString,
REG_NONE,
NULL,
0
},
{NULL,
RTL_QUERY_REGISTRY_DIRECT,
L"CSDVersion",
&UserCSDString,
REG_NONE,
NULL,
0
},
{NULL,
RTL_QUERY_REGISTRY_DIRECT,
L"PathName",
&UserPathString,
REG_NONE,
NULL,
0
},
{NULL,
0,
NULL,
NULL,
REG_NONE,
NULL,
0
}
};
VOID GetVersionInfo(VOID)
{
WCHAR NameBuffer[MAXVERSIONBUFFER];
NTSTATUS Status;
UserVersionString.Buffer = &NameBuffer[OFFSET_VERSTRING];
UserVersionString.Length = 0;
UserVersionString.MaximumLength = MAXVERSIONSTRING * sizeof(WCHAR);
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);
UserPathString.Buffer = &NameBuffer[OFFSET_PTHSTRING];
UserPathString.Length = 0;
UserPathString.MaximumLength = MAXVERSIONSTRING * sizeof(WCHAR);
Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
L"",
BaseServerRegistryConfigurationTable,
NULL,
NULL);
UserAssert(NT_SUCCESS(Status));
/*
* Write out Debugging Version message.
*/
wsprintfW(wszT,
UserCSDString.Length == 0 ?
L"Microsoft (R) Windows NT (TM) %ws (Build %ws%0.0ws) %ws" :
L"Microsoft (R) Windows NT (TM) %ws (Build %ws: %ws) %ws",
UserVersionString.Buffer,
UserBuildString.Buffer,
UserCSDString.Buffer,
UserPathString.Buffer);
}
#endif // DEBUG
/***************************************************************************\
* 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)
{
HANDLE hkRegistry;
OBJECT_ATTRIBUTES ObjectAttributes;
WCHAR achProductType[512];
DWORD cbStringSize;
UNICODE_STRING UnicodeString;
NTSTATUS Status;
LPWSTR lpszBitmap;
/*
* Get the product name. There is a bitmap by this name in the windows
* directory.
*/
RtlInitUnicodeString(&UnicodeString,
L"\\Registry\\Machine\\System\\CurrentControlSet\\"
L"Control\\ProductOptions");
InitializeObjectAttributes(&ObjectAttributes,
&UnicodeString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenKey(&hkRegistry, KEY_READ, &ObjectAttributes);
if (NT_SUCCESS(Status)) {
/*
* With this handle, query the ProductType string (for now, either
* lanmannt or winnt).
*/
RtlInitUnicodeString(&UnicodeString, L"ProductType");
Status = ZwQueryValueKey(hkRegistry,
&UnicodeString,
KeyValueFullInformation,
achProductType,
sizeof(achProductType),
&cbStringSize);
if (NT_SUCCESS(Status) &&
(((PKEY_VALUE_FULL_INFORMATION)achProductType)->DataLength != 0)) {
/*
* Now try to read this bitmap file (there is a lanmannt.bmp or
* a winnt.bmp in the windows directory).
*/
lpszBitmap = (LPWSTR)((PUCHAR)achProductType +
((PKEY_VALUE_FULL_INFORMATION)achProductType)->DataOffset);
/*
* 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.
*
* In the case for NT-Server, we do not use the lpszBitmap
* string, since it's refered to as "ServerNT" in the registry.
*/
if (_wcsicmp(lpszBitmap, L"winnt") == 0) {
wcsncpycch(lpszWallpaper, lpszBitmap, 8);
} else {
wcsncpycch(lpszWallpaper, L"lanmannt", 8);
}
lpszWallpaper[8] = (WCHAR)0;
if ((oemInfo.BitsPixel * oemInfo.Planes) > 4) {
int iStart = wcslen(lpszWallpaper);
iStart = min(iStart, 5);
lpszWallpaper[iStart] = (WCHAR)0;
wcscat(lpszWallpaper, L"256");
}
ZwClose(hkRegistry);
return;
}
}
/*
* Failed to get the name from the registry, so just return a known name.
*/
wcscpy(lpszWallpaper, L"lanmannt");
}
/***************************************************************************\
* 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(
IN 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, sizeof(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;
ServerLoadString(hModuleWin, STR_DTBITMAP, wszKey, sizeof(wszKey));
FastOpenProfileUserMapping();
/*
* 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.
*/
if (!FastGetProfileStringW(PMAP_DESKTOP,
wszKey,
wszNone,
lpszBitmap,
(GDWPN_BITSIZE * sizeof(WCHAR)))) {
wcscpy(lpszBitmap, wszNone);
}
FastCloseProfileUserMapping();
} else {
UINT uLen;
uLen = max((wcslen(lpszFile) + sizeof(WCHAR)),
(GDWPN_BITSIZE * sizeof(WCHAR)));
/*
* 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, sizeof(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);
}
return;
}
/***************************************************************************\
* 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 > oemInfo.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 = 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(
PWND pwnd,
HDC hdc,
HBITMAP hbm,
int xO,
int yO)
{
RECT rc;
BITMAP bm;
int x;
int y;
HBITMAP hbmT = NULL;
if (pwnd != NULL) {
_GetClientRect(pwnd, &rc);
} else {
GreGetClipBox(hdc, &rc, FALSE);
}
/*
* Make sure we can read the bitmap-info, so that the loop
* counts make sense.
*/
if (GreExtGetObjectW(hbm, sizeof(BITMAP), (PBITMAP)&bm)) {
while (xO + bm.bmWidth < rc.left)
xO += bm.bmWidth;
while (yO + bm.bmHeight < rc.top)
yO += bm.bmHeight;
while (xO > rc.left)
xO -= bm.bmWidth;
while (yO > rc.top)
yO -= bm.bmHeight;
/*
* Tile the bitmap to the surface.
*/
if (hbmT = GreSelectBitmap(ghdcMem, hbm)) {
for (y = yO; y < rc.bottom; y += bm.bmHeight) {
for (x = xO; x < rc.right; x += bm.bmWidth) {
GreBitBlt(hdc,
x,
y,
bm.bmWidth,
bm.bmHeight,
ghdcMem,
0,
0,
SRCCOPY,
0);
}
}
GreSelectBitmap(ghdcMem, hbmT);
}
}
return (hbmT != NULL);
}
/***************************************************************************\
* CenterWallpaper
*
*
* History:
* 29-Jul-1991 MikeKe From win31
\***************************************************************************/
BOOL CenterWallpaper(
PWND pwnd,
HDC hdc,
HBITMAP hbm,
int x0,
int y0)
{
RECT rc;
BITMAP bm;
HBITMAP hbmT;
int iClip;
BOOL f = TRUE;
GreExtGetObjectW(hbm, sizeof(BITMAP), (PBITMAP)&bm);
rc.left = x0;
rc.top = y0;
rc.right = x0 + bm.bmWidth;
rc.bottom = y0 + bm.bmHeight;
/*
* Save the DC.
*/
GreSaveDC(hdc);
/*
* Fake up a clipping rect to only use the centered bitmap. If
* we're returned a NULLREGION, we'll just return TRUE.
*/
iClip = GreIntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
if (iClip == ERROR) {
f = FALSE;
} else if (iClip != NULLREGION) {
/*
* 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, hbm)) {
GreBitBlt(hdc,
x0,
y0,
bm.bmWidth,
bm.bmHeight,
ghdcMem,
0,
0,
SRCCOPY,
0);
GreSelectBitmap(ghdcMem, hbmT);
} else {
f = FALSE;
}
}
/*
* Restore the original DC.
*/
GreRestoreDC(hdc, -1);
/*
* Fill the bacground (excluding the bitmap) with the desktop
* brush. Save the DC with the cliprect.
*/
GreSaveDC(hdc);
GreExcludeClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
if (pwnd != NULL) {
_GetClientRect(pwnd, &rc);
} else {
GreGetClipBox(hdc, &rc, FALSE);
}
FillRect(hdc, &rc, SYSHBR(DESKTOP));
GreRestoreDC(hdc, -1);
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 pwndDesk,
HDC hdc,
BOOL fPaint)
{
BOOL f;
HPALETTE hpalT;
int i;
UserAssert(ghbmWallpaper != NULL);
/*
* Select in the palette if one exists. As a wallpaper, we should only
* be able to do background-realizations.
*/
if (ghpalWallpaper) {
hpalT = _SelectPalette(hdc, ghpalWallpaper, FALSE);
i = xxxRealizePalette(hdc);
}
/*
* If we are doing drawing, then we will do the draw. Otherwise, this
* is pretty much a palette-realization.
*/
if (fPaint) {
POINT pt;
GreGetDCOrg(hdc, &pt);
GreSetViewportOrg(hdc, -pt.x, -pt.y, &pt);
if (gwWPStyle & DTF_TILE)
f = TileWallpaper(pwndDesk,
hdc,
ghbmWallpaper,
gptDesktop.x,
gptDesktop.y);
else
f = CenterWallpaper(pwndDesk,
hdc,
ghbmWallpaper,
gptDesktop.x,
gptDesktop.y);
/*
* Reset the viewport org.
*/
GreSetViewportOrg(hdc, 0, 0, &pt);
}
if (ghpalWallpaper && hpalT) {
_SelectPalette(hdc, hpalT, FALSE);
xxxRealizePalette(hdc);
/*
* On palette changes, makes sure that palettized wallpaper is
* redrawn in the desktop. If the shell window is around,
* invalidate that sucker. Otherwise, invalidate our normal desktop.
*/
if (i > 0) {
PWND pwndShell;
TL tldeskwnd;
PDESKTOP pdesk = PtiCurrent()->rpdesk;
pwndShell = (pdesk ? pdesk->pDeskInfo->spwndShell : NULL);
if (pwndShell) {
ThreadLockAlways(pwndShell, &tldeskwnd);
xxxRedrawWindow(pwndShell,
&grcWallpaper,
NULL,
RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
ThreadUnlock(&tldeskwnd);
} else {
ThreadLock(pwndDesk, &tldeskwnd);
xxxRedrawWindow(pwndDesk,
&grcWallpaper,
NULL,
RDW_INVALIDATE | RDW_ERASE | RDW_NOCHILDREN);
ThreadUnlock(&tldeskwnd);
}
}
}
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;
/*
* Get the dimensions of the scren 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);
nx = (SYSMET(CXSCREEN) / TILE_XMINSIZE) / bm.bmWidth;
ny = (SYSMET(CYSCREEN) / 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.
*/
hbmD = GreSelectBitmap(ghdcMem, hbm);
hbmNew = GreCreateCompatibleBitmap(ghdcMem,
nx * bm.bmWidth,
ny * bm.bmHeight);
GreSelectBitmap(ghdcMem, hbmD);
if (hbmNew == NULL)
return hbm;
if (hbmD = GreSelectBitmap(ghdcMem2, hbmNew)) {
/*
* Expand the bitmap to the new surface.
*/
xxxDrawWallpaper(NULL, ghdcMem2, TRUE);
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;
BITMAP bm;
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 (gpsi->fPaletteDisplay || (oemInfo.BitCount >= 8))
LR_flags |= LR_CREATEREALDIB;
/*
* If we're stretching, then we will ask the loaddib code to do
* it.
*/
if (gwWPStyle & DTF_STRETCH) {
dxDesired = SYSMET(CXSCREEN);
dyDesired = SYSMET(CYSCREEN);
} else {
dxDesired = 0;
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 (gpsi->fPaletteDisplay)
ghpalWallpaper = CreatePaletteFromBitmap(ghbmWallpaper);
/*
* If the DIB is a higher bitdepth than the display, convert it to
* a DDB, otherwise keep it as DIB. This way it takes the least
* amount of memory and provides a identity-translation blt.
*
*/
GreExtGetObjectW(ghbmWallpaper, sizeof(bm), &bm);
if (oemInfo.BitCount <= (bm.bmPlanes * bm.bmBitsPixel)) {
ghbmWallpaper = ConvertToDDB(gpDispInfo->hdcScreen,
ghbmWallpaper,
ghpalWallpaper);
}
/*
* Expand bitmap if we are going to tile it. Mark the bitmap
* as public, so any process can party with it. This must
* preceed the expand, since it performs a xxxDrawWallpaper
* call that can leave the section.
*/
GreSetBitmapOwner(ghbmWallpaper, OBJECT_OWNER_PUBLIC);
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(
LPWSTR lpszFile)
{
BITMAP bm;
UINT WallpaperStyle2;
PWND pwndShell;
TL tldeskwnd;
HBITMAP hbmOld = ghbmWallpaper;
PDESKTOP pdesk = PtiCurrent()->rpdesk;
BOOL fRet = FALSE;
static LPWSTR gpszWall = NULL;
PROFINTINFO apsi[] = {
{PMAP_DESKTOP, (LPWSTR)STR_TILEWALL , 0, &gwWPStyle},
{PMAP_DESKTOP, (LPWSTR)STR_DTSTYLE , 0, &WallpaperStyle2 },
{PMAP_DESKTOP, (LPWSTR)STR_DTORIGINX, 0, &gptDesktop.x },
{PMAP_DESKTOP, (LPWSTR)STR_DTORIGINY, 0, &gptDesktop.y },
{0, NULL, 0, NULL }
};
if ((lpszFile == SETWALLPAPER_METRICS) && !(gwWPStyle & DTF_STRETCH)) {
gptDesktop.x = 0;
gptDesktop.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.
* 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.
*/
FreeAllSpbs(NULL);
/*
* Get the shell-window. This could be NULL on system
* initialization. We will use this to do palette realization.
*/
pwndShell = (pdesk ? pdesk->pDeskInfo->spwnd : NULL);
/*
* 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.
*/
if ((gpszWall = GetDeskWallpaperName(lpszFile)) == NULL) {
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.
*/
UT_FastGetProfileIntsW(apsi);
if (gwWPStyle & DTF_TILE)
WallpaperStyle2 &= ~(DTF_FIT | DTF_STRETCH);
else
gwWPStyle &= ~DTF_TILE;
gwWPStyle |= WallpaperStyle2;
/*
* 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) {
/*
* 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 (pwndShell) {
HWND hwnd = HW(pwndShell);
ThreadLockAlways(pwndShell, &tldeskwnd);
xxxSendNotifyMessage(pwndShell, WM_PALETTECHANGED, (DWORD)hwnd, 0);
ThreadUnlock(&tldeskwnd);
}
}
Metric_Change:
/*
* Set the wallpaper-rect.
*/
grcWallpaper = gpDispInfo->rcScreen;
/*
* Are we centering the bitmap? Save the starting offset
* for a centered bitmap.
*/
if (!(gwWPStyle & (DTF_TILE | DTF_STRETCH))) {
GreExtGetObjectW(ghbmWallpaper, sizeof(bm), (PBITMAP)&bm);
if (!gptDesktop.x)
gptDesktop.x = (gpDispInfo->rcScreen.right - bm.bmWidth) / 2;
if (!gptDesktop.y)
gptDesktop.y = (gpDispInfo->rcScreen.bottom - bm.bmHeight) / 2;
grcWallpaper.left = gptDesktop.x;
grcWallpaper.top = gptDesktop.y;
grcWallpaper.right = gptDesktop.x + bm.bmWidth;
grcWallpaper.bottom = gptDesktop.y + bm.bmHeight;
}
fRet = TRUE;
SDW_Exit:
/*
* Notify the shell-window that the wallpaper changed.
*/
if ((pwndShell != NULL) &&
((hbmOld && !ghbmWallpaper) || (!hbmOld && ghbmWallpaper))) {
ThreadLockAlways(pwndShell, &tldeskwnd);
xxxSendNotifyMessage(pwndShell,
WM_SHELLNOTIFY,
SHELLNOTIFY_WALLPAPERCHANGED,
(LPARAM)ghbmWallpaper);
ThreadUnlock(&tldeskwnd);
}
return fRet;
}
/***************************************************************************\
* InternalPaintDesktop
*
*
* History:
* 29-Jul-1991 MikeKe From win31
\***************************************************************************/
BOOL InternalPaintDesktop(
PDESKWND pdeskwnd,
HDC hdc,
BOOL fPaint)
{
BOOL f;
/*
* Paint the desktop with a color or the wallpaper.
*/
if (ghbmWallpaper) {
f = xxxDrawWallpaper((PWND)pdeskwnd, hdc, fPaint);
} else {
FillRect(hdc, &gpDispInfo->rcScreen, SYSHBR(DESKTOP));
f = TRUE;
}
#ifdef DEBUG
{
SIZE size;
int imode;
static BOOL fInit = TRUE;
/*
* Grab the stuff from the registry
*/
if (fInit) {
GetVersionInfo();
fInit = FALSE;
}
GreGetTextExtentW(hdc, wszT, wcslen(wszT), &size, GGTE_WIN3_EXTENT);
imode = GreSetBkMode(hdc, TRANSPARENT);
GreExtTextOutW(hdc,
(gpDispInfo->rcPrimaryScreen.right - size.cx) / 2,
0,
0,
(LPRECT)NULL,
wszT,
wcslen(wszT),
(LPINT)NULL);
GreSetBkMode(hdc, imode);
}
#endif // !DEBUG
return f;
}