Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1027 lines
28 KiB

/*
* DynaRes
*
* replacment for ChangeDisplaySettings EnumDisplaySettings to allow
* changing the bitdepth on the fly
*
* ToddLa
*
*/
#ifdef IS_16
#define DIRECT_DRAW
#endif
#ifdef DIRECT_DRAW
#include "ddraw16.h"
#else
#include <windows.h>
#include <print.h>
#include "gdihelp.h"
#include "dibeng.inc"
#endif
#define BABYSIT // if this is defined, work around bugs in the display driver
#define O95_HACK // enable the Office95 (any app bar) hack to prevent icons from being squished
#define SPI_HACK // enable the SPI_SETWORKAREA hack, when a app bar is up.
/*----------------------------------------------------------------------------*\
\*----------------------------------------------------------------------------*/
#undef Assert
#undef DPF
#ifdef DEBUG
static void CDECL DPF(char *sz, ...)
{
char ach[128];
lstrcpy(ach, "QuickRes: ");
wvsprintf(ach+10, sz, (LPVOID)(&sz+1));
#ifdef DIRECT_DRAW
dprintf(2, ach);
#else
lstrcat(ach, "\r\n");
OutputDebugString(ach);
#endif
}
static void NEAR PASCAL __Assert(char *exp, char *file, int line)
{
DPF("Assert(%s) failed at %s line %d.", (LPSTR)exp, (LPSTR)file, line);
DebugBreak();
}
#define Assert(exp) ( (exp) ? (void)0 : __Assert(#exp,__FILE__,__LINE__) )
#else
#define Assert(f)
#define DPF ; / ## /
#endif
/*----------------------------------------------------------------------------*\
\*----------------------------------------------------------------------------*/
extern void FAR PASCAL SetMagicColors(HDC, DWORD, WORD);
extern UINT FAR PASCAL AllocCStoDSAlias(UINT);
extern void FAR PASCAL Death(HDC);
extern void FAR PASCAL Resurrection(HDC,LONG,LONG,LONG);
static char szClassName[] = "DynaResFullscreenWindow";
static char szDIBENG[] = "DIBENG";
static char szDISPLAY[] = "DISPLAY";
static char szUSER[] = "USER";
extern LONG FAR PASCAL DIBENG_Control(LPVOID,UINT,LPVOID,LPVOID);
extern HINSTANCE hInstApp;
#ifdef DIRECT_DRAW
extern bInOurSetMode;
#else
BOOL bInOurSetMode;
#endif
BOOL fNewDibEng;
BOOL fDirectDrawDriver;
BOOL InitDynaRes(void);
void PreStartMenuHack(DEVMODE FAR *);
void StartMenuHack(DEVMODE FAR *);
BOOL ForceSoftwareCursor(BOOL);
BOOL IsMatrox(void);
void PatchDisplay(int oem, BOOL patch);
void PatchControl(BOOL patch);
LONG FAR PASCAL _loadds Control(LPVOID lpDevice,UINT function,LPVOID lp_in_data,LPVOID lp_out_data);
#undef ChangeDisplaySettings
LONG WINAPI RealChangeDisplaySettings(LPDEVMODE pdm, DWORD flags)
{
return ChangeDisplaySettings(pdm, flags & ~CDS_EXCLUSIVE);
}
#ifdef DIRECT_DRAW
LONG DDAPI DD16_ChangeDisplaySettings(LPDEVMODE pdm, DWORD flags)
#else
LONG WINAPI DynaChangeDisplaySettings(LPDEVMODE pdm, DWORD flags)
#endif
{
LONG err;
HDC hdc;
int rc,bpp,w,h;
int new_rc,new_bpp;
HWND hwnd=NULL;
bInOurSetMode = TRUE;
flags &= ~CDS_EXCLUSIVE;
if (!InitDynaRes())
{
err = ChangeDisplaySettings(pdm, flags);
bInOurSetMode = FALSE;
return err;
}
if (flags & CDS_TEST)
{
err = ChangeDisplaySettings(pdm, flags | CDS_EXCLUSIVE);
bInOurSetMode = FALSE;
return err;
}
if (flags & CDS_FULLSCREEN)
PreStartMenuHack(pdm);
//
// try changing the mode normaly first
// if it works, we are done.
//
#ifdef BABYSIT
bInOurSetMode = (BOOL)2;
PatchControl(TRUE);
err = ChangeDisplaySettings(pdm, flags);
PatchControl(FALSE);
bInOurSetMode = TRUE;
#else
err = ChangeDisplaySettings(pdm, flags);
#endif
if (err == DISP_CHANGE_SUCCESSFUL)
{
if (flags & CDS_FULLSCREEN)
StartMenuHack(pdm);
bInOurSetMode = FALSE;
return err;
}
//
// if the mode is not valid dont even try.
//
err = ChangeDisplaySettings(pdm, CDS_EXCLUSIVE | CDS_TEST);
if (err != DISP_CHANGE_SUCCESSFUL)
{
bInOurSetMode = FALSE;
return err;
}
//
// get the current settings
//
hdc = GetDC(NULL);
rc = GetDeviceCaps(hdc, RASTERCAPS);
bpp = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
w = GetDeviceCaps(hdc, HORZRES);
h = GetDeviceCaps(hdc, VERTRES);
ReleaseDC(NULL, hdc);
//
// dont try to do a invalid change
//
if (pdm && (pdm->dmFields & DM_BITSPERPEL))
{
if ((int)pdm->dmBitsPerPel == bpp)
{
bInOurSetMode = FALSE;
return DISP_CHANGE_FAILED;
}
if (bpp <= 4 && (int)pdm->dmBitsPerPel != bpp)
{
bInOurSetMode = FALSE;
return DISP_CHANGE_RESTART;
}
if (bpp > 4 && (int)pdm->dmBitsPerPel <= 4)
{
bInOurSetMode = FALSE;
return DISP_CHANGE_RESTART;
}
}
#ifndef NOCREATEWINDOW
//
// bring up a "cover" window to hide all the activity of the mode
// change from the user. and brings up a wait cursor
//
// NOTE this does a little more than just hide the mode change
// from the user, it also makes sure to set a MONO hourglass cursor
// some display drivers dont like a software cursor being active
// durring a mode set, so we give them a mono one.
//
if (TRUE || !(flags & CDS_FULLSCREEN))
{
#define OCR_WAIT_DEFAULT 102
WNDCLASS cls;
cls.lpszClassName = szClassName;
cls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
cls.hInstance = hInstApp;
cls.hIcon = NULL;
cls.hCursor = (HCURSOR)LoadImage(NULL,MAKEINTRESOURCE(OCR_WAIT_DEFAULT),IMAGE_CURSOR,0,0,0);
cls.lpszMenuName = NULL;
cls.style = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
cls.lpfnWndProc = DefWindowProc;
cls.cbWndExtra = 0;
cls.cbClsExtra = 0;
RegisterClass(&cls);
hwnd = CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW,
szClassName, szClassName,
WS_POPUP|WS_VISIBLE, 0, 0, 10000, 10000,
NULL, NULL, hInstApp, NULL);
if (hwnd == NULL)
{
bInOurSetMode = FALSE;
return DISP_CHANGE_FAILED;
}
SetForegroundWindow(hwnd); // we want cursor focus
SetCursor(cls.hCursor); // set wait cursor.
}
#endif
//
// no one gets to draw until we are done.
//
LockWindowUpdate(GetDesktopWindow());
DPF("Begin mode change from %dx%dx%d....", w,h,bpp);
//
// first thing we have to do is convert all DDBs and Pattern brushs
// to DIBSections so they will still work after the mode has changed.
//
ConvertObjects();
//
// convert all icons so they can be drawn correctly.
//
if (!fNewDibEng && !(flags & CDS_FULLSCREEN))
{
//ConvertIcons();
}
#ifdef BABYSIT
//
// the matrox driver is broken
// it has a global variable for bPaletized mode, and it only
// reads it if the mode is 8bpp.
//
if (!fDirectDrawDriver && bpp == 8 && IsMatrox())
{
static char szSystemIni[] = "system.ini";
static char szPalettized[] = "palettized";
static char szZero[] = "0";
static DEVMODE dm;
dm.dmSize = sizeof(DEVMODE);
dm.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
dm.dmBitsPerPel = 8;
dm.dmPelsWidth = 640;
dm.dmPelsHeight = 480;
DPF("**BABYSIT** Fixing the broken Matrox driver....");
WritePrivateProfileString(szDISPLAY,szPalettized,szZero,szSystemIni);
err = ChangeDisplaySettings(&dm, CDS_RESET | CDS_FULLSCREEN);
WritePrivateProfileString(szDISPLAY,szPalettized,NULL,szSystemIni);
}
#endif
//
// some drivers are total broken and we need to
// route some of its entry points to the DIBENG
//
// WARNING this can break some remote control programs!
//
#ifdef BABYSIT
if (!fDirectDrawDriver)
{
DPF("**BABYSIT** turning off OEMOutput....");
PatchDisplay(8, TRUE); // route OEMOutput to the DIBENG
DPF("**BABYSIT** turning off OEMDibBlt....");
PatchDisplay(19, TRUE); // route OEMDibBlt to the DIBENG
}
#endif
//
// change the display settings.
//
PatchControl(TRUE);
DPF("Calling ChangeDisplaySettings....");
//
// NOTE USER will Yield unless CDS_FULLSCREEN is specifed
//
err = ChangeDisplaySettings(pdm, flags | CDS_EXCLUSIVE);
DPF("....ChangeDisplaySettings returns %d", err);
// get the new settings
//
hdc = GetDC(NULL);
new_rc = GetDeviceCaps(hdc, RASTERCAPS);
new_bpp = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
ReleaseDC(NULL, hdc);
//
// make sure the driver has not messed up its rastercaps!
// for example the QVision driver does not get this right.
//
if ((new_rc & RC_PALETTE) && new_bpp != 8)
{
DPF("**BABYSIT** drivers RC_PALETTE bit is messed up.");
err = DISP_CHANGE_RESTART; // err = DISP_CHANGE_FAILED;
}
//
// if the driver failed the mode set things could be real messed up
// reset the current mode, to try to recover.
//
#ifdef BABYSIT
if (err != DISP_CHANGE_SUCCESSFUL)
{
static DEVMODE dm;
dm.dmSize = sizeof(DEVMODE);
dm.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS;
dm.dmBitsPerPel = bpp;
dm.dmPelsWidth = w;
dm.dmPelsHeight = h;
dm.dmDisplayFlags = 0;
DPF("**BABYSIT** mode set failed, going back to old mode.");
ChangeDisplaySettings(&dm, CDS_RESET | CDS_EXCLUSIVE | CDS_FULLSCREEN);
}
#endif
PatchControl(FALSE);
//
// call Death/Resurection this will kick drivers in the head
// about the mode change
//
if (!fDirectDrawDriver && err == 0 &&
(pdm == NULL || (flags & CDS_UPDATEREGISTRY)))
{
hdc = GetDC(NULL);
DPF("Calling Death/Resurection....");
SetCursor(NULL);
Death(hdc);
Resurrection(hdc,NULL,NULL,NULL);
ReleaseDC(NULL, hdc);
}
//
// force a SW cursor, most drivers are broken and dont disable
// the HW cursor when changing modes.
//
#ifdef BABYSIT
if (!fDirectDrawDriver)
{
if (pdm == NULL && (flags & CDS_FULLSCREEN))
{
DPF("**BABYSIT** restoring HW cursor (return from fullscreen mode)");
ForceSoftwareCursor(FALSE);
}
else if (err == 0 && (new_bpp > 8 || GetSystemMetrics(SM_CXSCREEN) < 640))
{
DPF("**BABYSIT** Forcing a software cursor");
ForceSoftwareCursor(TRUE);
}
else
{
DPF("**BABYSIT** restoring HW cursor");
ForceSoftwareCursor(FALSE);
}
}
#endif
#if 0 /// moved to Control patch
//
// we should now convert any DIBSections that used to be DDBs back to DDBs
// our code to find the right palette for a DDB is not too hot
// so a lot of DDBs will have wrong colors.
//
#if 1
ConvertBitmapsBack(FALSE);
#else
ConvertBitmapsBack(!(flags & CDS_FULLSCREEN));
#endif
#endif
//
// let other apps draw.
//
LockWindowUpdate(NULL);
//
// remove our "cover" window
//
if (hwnd)
{
DestroyWindow(hwnd);
UnregisterClass(szClassName, hInstApp);
}
//
// should we reload the wallpaper, because it got converted to
// a DDB by ConvertBitmapsBack
//
if (!(flags & CDS_FULLSCREEN))
{
DPF("Reloading wallpaper...");
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, NULL, 0);
}
//
// have all the apps deal with a color change
//
if (!(flags & CDS_FULLSCREEN))
{
//
//
//
// if we just post the WM_SYSCOLORCHANGE message to all apps
// a hidden office window will go back and forth Invalidating
// other office apps and re-sending the WM_SYSCOLORCHANGE message
// you either stack overflow, hang or XL just flashes for a few
// minutes.
//
// the "fix" is to not post the WM_SYSCOLORCHANGE message to
// this hidden window, we also have to make sure not to call
// SystemParametersInfo(SPI_SETDESKPATTERN) later in the code.
//
HWND hwnd;
HWND hwndX;
if (hwndX = FindWindow("File Open Message Window", "File Open Message Window"))
{
for (hwnd = GetWindow(GetDesktopWindow(), GW_CHILD);
hwnd;
hwnd = GetWindow(hwnd, GW_HWNDNEXT))
{
if (hwnd != hwndX)
PostMessage(hwnd, WM_SYSCOLORCHANGE, 0, 0);
}
// dont reload desktop pattern.
flags |= CDS_FULLSCREEN;
}
else
{
PostMessage(HWND_BROADCAST, WM_SYSCOLORCHANGE, 0, 0);
}
}
//
// reload the desktop pattern
//
if (!(flags & CDS_FULLSCREEN) || pdm == NULL)
{
DPF("Reloading wallpaper pattern...");
SystemParametersInfo(SPI_SETDESKPATTERN, (UINT)-1, NULL, 0);
}
//
// we dont want the StartMenu to rebuild when we change modes
//
if (err == DISP_CHANGE_SUCCESSFUL)
{
if (flags & CDS_FULLSCREEN)
StartMenuHack(pdm);
}
bInOurSetMode = FALSE;
DPF("Done...");
return err;
}
#ifndef DCICOMMAND
#define DCICOMMAND 3075 // escape value
#endif
BOOL InitDynaRes()
{
int v;
HDC hdc;
HBRUSH hbr1, hbr2;
BOOL f=TRUE;
OSVERSIONINFO ver = {sizeof(OSVERSIONINFO)};
GetVersionEx(&ver);
// must be Windows95 build 950 or higher
if (LOWORD(GetVersion()) != 0x5F03)
{
DPF("Init: Windows version not 3.95.");
f = FALSE;
}
if (ver.dwMajorVersion != 4 ||
ver.dwMinorVersion != 0 ||
LOWORD(ver.dwBuildNumber) < 950)
{
DPF("Init: Windows version less than 4.0.950");
f = FALSE;
}
//
// we assume create/delete/create will get the same handle
//
hbr1 = CreateSolidBrush(RGB(1,1,1));
DeleteObject(hbr1);
hbr2 = CreateSolidBrush(RGB(2,2,2));
DeleteObject(hbr2);
if (hbr1 != hbr2)
{
DPF("Init: cant use Destroy/Create brush trick");
f = FALSE;
}
if (GetModuleHandle(szDIBENG) == 0)
{
DPF("Init: DIBENG not loaded");
f = FALSE;
}
hdc = GetDC(NULL);
// check the DIBENG version
v = 0x5250;
v = Escape(hdc, QUERYESCSUPPORT, sizeof(int), (LPVOID)&v, NULL);
if (v == 0)
{
DPF("Init: we dont have a new DIBENG");
fNewDibEng = FALSE;
}
else
{
DPF("Init: DIBENG version: %04X", v);
fNewDibEng = TRUE;
}
//
// see if the display supports DirectDraw
//
v = DCICOMMAND;
v = Escape(hdc, QUERYESCSUPPORT, sizeof(int), (LPVOID)&v, NULL);
if (v == 0 || v == 0x5250)
{
DPF("Init: display driver does not support DirectDraw");
fDirectDrawDriver = FALSE;
}
else
{
if (LOBYTE(v) == 0xFF)
v++;
DPF("Init: display driver supports DirectDraw: %04X", v);
fDirectDrawDriver = TRUE;
}
//
// must be a windows 4.0 mini driver.
//
if (GetDeviceCaps(hdc, DRIVERVERSION) < 0x0400)
{
DPF("Init: not a 4.0 display driver");
f = FALSE;
}
if (!(GetDeviceCaps(hdc, CAPS1) & C1_DIBENGINE))
{
DPF("Init: not a DIBENG display driver");
f = FALSE;
}
if (!(GetDeviceCaps(hdc, CAPS1) & C1_REINIT_ABLE))
{
DPF("Init: does not support C1_REINIT_ABLE");
f = FALSE;
}
ReleaseDC(NULL, hdc);
return f;
}
//
// we hook the OEMControl entry point in the display driver while a
// mode change is happening. GDI will issue a QUERYDIBSUPPORT escape
// right after the mode change happens so this is the first thing
// called after the mode changed worked. USER also issues a
// MOUSETRAILS escape.
//
// we need this hook for two reasons...
//
// 1. some display drivers are broken and dont set deFlags right
// we fix up the deFlags, we fix up the flags for them.
//
// 2. we rerealize all the gdi objects in this routine when
// USER calls us, this way all the pen/brushs/text colors
// are correct when user goes and rebuilds its bitmaps...
//
LONG FAR PASCAL _loadds Control(LPVOID lpDevice,UINT function,LPVOID lp_in_data,LPVOID lp_out_data)
{
DIBENGINE FAR *pde = (DIBENGINE FAR *)lpDevice;
LONG ret;
Assert(bInOurSetMode);
#ifdef BABYSIT
if (pde->deType == 0x5250)
{
if ((pde->deFlags & FIVE6FIVE) && pde->deBitsPixel != 16)
{
DPF("**BABYSIT** fixing FIVE6FIVE bit");
pde->deFlags &= ~FIVE6FIVE;
}
if ((pde->deFlags & PALETTIZED) && pde->deBitsPixel != 8)
{
DPF("**BABYSIT** fixing PALETTIZED bit");
pde->deFlags &= ~PALETTIZED;
}
if ((pde->deFlags & PALETTE_XLAT) && pde->deBitsPixel != 8)
{
DPF("**BABYSIT** fixing PALETTE_XLAT bit");
pde->deFlags &= ~PALETTE_XLAT;
}
}
#endif
//
// this is USER calling from LW_OEMDependentInit()
// force all GDI objects to be rerealized
//
if (function == MOUSETRAILS && bInOurSetMode != (BOOL)2)
{
//
// fix up the magic colors before we rerealize the brushes
// the "right" way to do this is to reset the UI colors
// by calling SetSysColors() but we dont want to send
// a sync WM_SYSCOLORCHANGE from here.
//
HDC hdc = GetDC(NULL);
if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
{
SetSystemPaletteUse(hdc, SYSPAL_STATIC);
SetMagicColors(hdc, GetSysColor(COLOR_3DSHADOW) , 8);
SetMagicColors(hdc, GetSysColor(COLOR_3DFACE) , 9);
SetMagicColors(hdc, GetSysColor(COLOR_3DHILIGHT), 246);
}
ReleaseDC(NULL, hdc);
//
// re-realize all GDI objects for the new mode.
//
ReRealizeObjects();
//
// we should now convert any DIBSections that used to be DDBs back to DDBs
// our code to find the right palette for a DDB is not too hot
// so a lot of DDBs will have wrong colors.
//
ConvertBitmapsBack(FALSE);
}
PatchControl(FALSE);
ret = DIBENG_Control(lpDevice,function,lp_in_data,lp_out_data);
PatchControl(TRUE);
return ret;
}
//
// patch
//
void Patch(LPCSTR szMod, LPCSTR szProc, FARPROC PatchFunc, LPDWORD PatchSave, BOOL fPatch)
{
LPDWORD pdw;
FARPROC x;
//
// ATM 2.5 has GetProcAddress patched to return some sort of
// thunk, that ends up totaly confusing us and we dont end up
// patching the DIBENG, we patch ATM's thunk.
//
// so when we want to patch DIBENG!OEMControl we use the value we
// *linked* to, not the value GetProcAddress returns.
//
if (lstrcmpi(szMod, szDIBENG) == 0 && szProc == MAKEINTATOM(3))
x = (FARPROC)DIBENG_Control;
else
x = GetProcAddress(GetModuleHandle(szMod), szProc);
if (x == NULL || PatchFunc == NULL)
return;
GlobalReAlloc((HGLOBAL)SELECTOROF(x), 0, GMEM_MODIFY|GMEM_MOVEABLE);
pdw = (LPDWORD)MAKELP(AllocCStoDSAlias(SELECTOROF(x)), OFFSETOF(x));
if (fPatch)
{
DPF("Patching %s!%d %04X:%04X", szMod, OFFSETOF(szProc), SELECTOROF(x), OFFSETOF(x));
if (PatchSave[0] == 0)
{
PatchSave[0] = pdw[0];
PatchSave[1] = pdw[1];
}
*((LPBYTE)pdw)++ = 0xEA; // JMP
*pdw = (DWORD)PatchFunc;
}
else
{
DPF("UnPatching %s!%d %04X:%04X", szMod, OFFSETOF(szProc), SELECTOROF(x), OFFSETOF(x));
if (PatchSave[0] != 0)
{
pdw[0] = PatchSave[0];
pdw[1] = PatchSave[1];
PatchSave[0] = 0;
PatchSave[1] = 0;
}
}
FreeSelector(SELECTOROF(pdw));
}
//
// hook the DIBENGs OEMControl() entry point, to jump to our own code
//
void PatchControl(BOOL patch)
{
static DWORD SaveBytes[2];
Patch(szDIBENG, MAKEINTATOM(3), (FARPROC)Control, SaveBytes, patch);
}
//
// patch a entry in the display driver to jump directly to the DIBENG
//
void PatchDisplay(int oem, BOOL patch)
{
FARPROC p;
#define MAX_DDI 35
static DWORD PatchBytes[MAX_DDI*2];
if (oem >= MAX_DDI)
return;
p = GetProcAddress(GetModuleHandle(szDIBENG), MAKEINTATOM(oem));
Patch(szDISPLAY, MAKEINTATOM(oem), p, &PatchBytes[oem*2], patch);
}
/*----------------------------------------------------------------------------*\
\*----------------------------------------------------------------------------*/
#ifdef O95_HACK
static BOOL fOffice95Hack;
static char szDisplaySettings[] = "Display\\Settings";
static char szResolution[] = "Resolution";
static char szDD[] = "%d,%d";
//
// put back the right resolution into the registy key HKCC\Display\Settings
//
void Office95Hack()
{
if (fOffice95Hack)
{
HKEY hkey;
char ach[20];
int len;
DPF("Office95 hack: restoring registry");
if (RegOpenKey(HKEY_CURRENT_CONFIG, szDisplaySettings, &hkey) == 0)
{
len = wsprintf(ach, szDD, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
RegSetValueEx(hkey, szResolution, NULL, REG_SZ, ach, len);
RegCloseKey(hkey);
}
fOffice95Hack = FALSE;
}
}
#endif
#ifdef SPI_HACK
BOOL FAR PASCAL _loadds SPI(UINT spi, UINT wParam, LPVOID lParam, UINT flags);
//
// patch USERs SystemParametersInfo function
//
void PatchSPI(BOOL patch)
{
static DWORD SaveBytes[2];
Patch(szUSER, MAKEINTATOM(483), (FARPROC)SPI, SaveBytes, patch);
}
BOOL FAR PASCAL _loadds SPI(UINT spi, UINT wParam, LPVOID lParam, UINT flags)
{
BOOL f;
if (spi == SPI_SETWORKAREA)
{
if (lParam)
DPF("Ignoring a SPI_SETWORKAREA [%d,%d,%d,%d] call", ((LPRECT)lParam)->left, ((LPRECT)lParam)->top, ((LPRECT)lParam)->right - ((LPRECT)lParam)->left, ((LPRECT)lParam)->bottom - ((LPRECT)lParam)->top);
else
DPF("Ignoring a SPI_SETWORKAREA lParam=NULL call");
return 0;
}
PatchSPI(FALSE);
f = SystemParametersInfo(spi, wParam, lParam, flags);
PatchSPI(TRUE);
return f;
}
#endif
/*----------------------------------------------------------------------------*\
\*----------------------------------------------------------------------------*/
//
// make the start menu not update in the background.
//
#define IDT_FAVOURITE 4
#define WNDCLASS_TRAYNOTIFY "Shell_TrayWnd"
LRESULT CALLBACK _loadds TrayWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
#ifdef SPI_HACK
PatchSPI(FALSE);
#endif
#ifdef O95_HACK
Office95Hack();
#endif
DPF("StartMenu hack: killing timer to refresh start menu");
KillTimer(hwnd, IDT_FAVOURITE);
return 0;
}
#ifdef SPI_HACK
RECT rcScreen;
RECT rcWork;
#endif
void PreStartMenuHack(DEVMODE FAR *pdm)
{
#ifdef SPI_HACK
SetRect(&rcScreen, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
SystemParametersInfo(SPI_GETWORKAREA, 0, (LPVOID)&rcWork, 0);
#endif
#ifdef O95_HACK
// make sure registry is put back
Office95Hack();
#endif
}
void StartMenuHack(DEVMODE FAR *pdm)
{
HWND hwndTray;
BOOL fAppBar=FALSE;
hwndTray = FindWindow(WNDCLASS_TRAYNOTIFY, NULL);
if (hwndTray == NULL)
{
DPF("Cant find tray window");
return;
}
// hack to get into the shells context, so we can clean up these hacks
PostMessage(hwndTray, WM_TIMER, 0, (LONG)TrayWndProc);
#ifdef SPI_HACK
{
RECT rc;
RECT rcTray;
//
// see if there are any other app bars around.
//
GetWindowRect(hwndTray, &rcTray);
SubtractRect(&rc, &rcScreen, &rcTray);
DPF("rcScreen [%d,%d,%d,%d]", rcScreen.left, rcScreen.top, rcScreen.right-rcScreen.left,rcScreen.bottom-rcScreen.top);
DPF("rcTray [%d,%d,%d,%d]", rcTray.left, rcTray.top, rcTray.right-rcTray.left,rcTray.bottom-rcTray.top);
DPF("rc [%d,%d,%d,%d]", rc.left, rc.top, rc.right-rc.left,rc.bottom-rc.top);
DPF("rcWork [%d,%d,%d,%d]", rcWork.left, rcWork.top, rcWork.right-rcWork.left,rcWork.bottom-rcWork.top);
if (!EqualRect(&rcScreen, &rcWork) && !EqualRect(&rc, &rcWork))
{
DPF("StartMenuHack: !!!!!there is a APP bar!!!!!!");
fAppBar = TRUE;
//
// Patch the USER!SystemParameterInto function, so when the
// shell does a SPI_SETWORKAREA call it will ignored
// this prevents windows from being "sqished" to fit inside
// the work area.
//
PatchSPI(TRUE);
}
}
#endif
#ifdef O95_HACK
//
// the shell does the following...
//
// read the HKEY_CURRENT_CONFIG\Display\Settings "Resloluton" key
// if this is LESS THAN the current display size, dont repark
// all the icons on the desktop because this is just a temporary
// mode set.
//
// this sound right, except the bug happens when we are returning
// to the "normal" mode, the shell will repark the icons because
// it checks for LESS THEN, not LESS THAN OR EQUAL, normaly this
// is fine because the re-park does nothing. when a app bar
// like Office95 is running it has not moved before the shell
// re-re-parks icons.
//
// what this hack does it set the size stored in the registry
// to be real large so the shell does not park icons.
// later we will but the right values back. we only need to
// do this if we are returning to the "normal" mode (ie pdm==NULL)
//
if (fAppBar && pdm == NULL)
{
HKEY hkey;
char ach[20];
int len;
fOffice95Hack = TRUE;
if (RegOpenKey(HKEY_CURRENT_CONFIG, szDisplaySettings, &hkey) == 0)
{
len = wsprintf(ach, szDD, 30000, 30000);
RegSetValueEx(hkey, szResolution, NULL, REG_SZ, ach, len);
RegCloseKey(hkey);
}
}
else
{
fOffice95Hack = FALSE;
}
#endif
}
#ifdef BABYSIT
//
// force (or trick) the display driver into using a software cursor.
//
BOOL ForceSoftwareCursor(BOOL f)
{
int n=0;
//
// get the mouse trails setting from USER
//
SystemParametersInfo(SPI_GETMOUSETRAILS, 0, (LPVOID)&n, 0);
if (f)
{
//
// enable mouse trails, this will cause the display driver to
// turn off its hardware cursor
//
SystemParametersInfo(SPI_SETMOUSETRAILS, 2, NULL, 0);
//
// now tell the DIBENG to turn off mouse trails, the display driver
// will think they are still on...
//
PatchDisplay(3, TRUE); // route to DIBENG
SystemParametersInfo(SPI_SETMOUSETRAILS, n, NULL, 0);
PatchDisplay(3, FALSE); // back to DISPLAY
}
else
{
SystemParametersInfo(SPI_SETMOUSETRAILS, n, NULL, 0);
}
return TRUE;
}
/*----------------------------------------------------------------------------*\
\*----------------------------------------------------------------------------*/
BOOL IsMatrox()
{
char ach[80];
int len;
GetModuleFileName(GetModuleHandle(szDISPLAY), ach, sizeof(ach));
len = lstrlen(ach);
return len >= 7 && lstrcmpi(ach+len-7, "mga.drv") == 0;
}
#endif