/* * 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 #include #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