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

  1. /*
  2. * DynaRes
  3. *
  4. * replacment for ChangeDisplaySettings EnumDisplaySettings to allow
  5. * changing the bitdepth on the fly
  6. *
  7. * ToddLa
  8. *
  9. */
  10. #ifdef IS_16
  11. #define DIRECT_DRAW
  12. #endif
  13. #ifdef DIRECT_DRAW
  14. #include "ddraw16.h"
  15. #else
  16. #include <windows.h>
  17. #include <print.h>
  18. #include "gdihelp.h"
  19. #include "dibeng.inc"
  20. #endif
  21. #define BABYSIT // if this is defined, work around bugs in the display driver
  22. #define O95_HACK // enable the Office95 (any app bar) hack to prevent icons from being squished
  23. #define SPI_HACK // enable the SPI_SETWORKAREA hack, when a app bar is up.
  24. /*----------------------------------------------------------------------------*\
  25. \*----------------------------------------------------------------------------*/
  26. #undef Assert
  27. #undef DPF
  28. #ifdef DEBUG
  29. static void CDECL DPF(char *sz, ...)
  30. {
  31. char ach[128];
  32. lstrcpy(ach, "QuickRes: ");
  33. wvsprintf(ach+10, sz, (LPVOID)(&sz+1));
  34. #ifdef DIRECT_DRAW
  35. dprintf(2, ach);
  36. #else
  37. lstrcat(ach, "\r\n");
  38. OutputDebugString(ach);
  39. #endif
  40. }
  41. static void NEAR PASCAL __Assert(char *exp, char *file, int line)
  42. {
  43. DPF("Assert(%s) failed at %s line %d.", (LPSTR)exp, (LPSTR)file, line);
  44. DebugBreak();
  45. }
  46. #define Assert(exp) ( (exp) ? (void)0 : __Assert(#exp,__FILE__,__LINE__) )
  47. #else
  48. #define Assert(f)
  49. #define DPF ; / ## /
  50. #endif
  51. /*----------------------------------------------------------------------------*\
  52. \*----------------------------------------------------------------------------*/
  53. extern void FAR PASCAL SetMagicColors(HDC, DWORD, WORD);
  54. extern UINT FAR PASCAL AllocCStoDSAlias(UINT);
  55. extern void FAR PASCAL Death(HDC);
  56. extern void FAR PASCAL Resurrection(HDC,LONG,LONG,LONG);
  57. static char szClassName[] = "DynaResFullscreenWindow";
  58. static char szDIBENG[] = "DIBENG";
  59. static char szDISPLAY[] = "DISPLAY";
  60. static char szUSER[] = "USER";
  61. extern LONG FAR PASCAL DIBENG_Control(LPVOID,UINT,LPVOID,LPVOID);
  62. extern HINSTANCE hInstApp;
  63. #ifdef DIRECT_DRAW
  64. extern bInOurSetMode;
  65. #else
  66. BOOL bInOurSetMode;
  67. #endif
  68. BOOL fNewDibEng;
  69. BOOL fDirectDrawDriver;
  70. BOOL InitDynaRes(void);
  71. void PreStartMenuHack(DEVMODE FAR *);
  72. void StartMenuHack(DEVMODE FAR *);
  73. BOOL ForceSoftwareCursor(BOOL);
  74. BOOL IsMatrox(void);
  75. void PatchDisplay(int oem, BOOL patch);
  76. void PatchControl(BOOL patch);
  77. LONG FAR PASCAL _loadds Control(LPVOID lpDevice,UINT function,LPVOID lp_in_data,LPVOID lp_out_data);
  78. #undef ChangeDisplaySettings
  79. LONG WINAPI RealChangeDisplaySettings(LPDEVMODE pdm, DWORD flags)
  80. {
  81. return ChangeDisplaySettings(pdm, flags & ~CDS_EXCLUSIVE);
  82. }
  83. #ifdef DIRECT_DRAW
  84. LONG DDAPI DD16_ChangeDisplaySettings(LPDEVMODE pdm, DWORD flags)
  85. #else
  86. LONG WINAPI DynaChangeDisplaySettings(LPDEVMODE pdm, DWORD flags)
  87. #endif
  88. {
  89. LONG err;
  90. HDC hdc;
  91. int rc,bpp,w,h;
  92. int new_rc,new_bpp;
  93. HWND hwnd=NULL;
  94. bInOurSetMode = TRUE;
  95. flags &= ~CDS_EXCLUSIVE;
  96. if (!InitDynaRes())
  97. {
  98. err = ChangeDisplaySettings(pdm, flags);
  99. bInOurSetMode = FALSE;
  100. return err;
  101. }
  102. if (flags & CDS_TEST)
  103. {
  104. err = ChangeDisplaySettings(pdm, flags | CDS_EXCLUSIVE);
  105. bInOurSetMode = FALSE;
  106. return err;
  107. }
  108. if (flags & CDS_FULLSCREEN)
  109. PreStartMenuHack(pdm);
  110. //
  111. // try changing the mode normaly first
  112. // if it works, we are done.
  113. //
  114. #ifdef BABYSIT
  115. bInOurSetMode = (BOOL)2;
  116. PatchControl(TRUE);
  117. err = ChangeDisplaySettings(pdm, flags);
  118. PatchControl(FALSE);
  119. bInOurSetMode = TRUE;
  120. #else
  121. err = ChangeDisplaySettings(pdm, flags);
  122. #endif
  123. if (err == DISP_CHANGE_SUCCESSFUL)
  124. {
  125. if (flags & CDS_FULLSCREEN)
  126. StartMenuHack(pdm);
  127. bInOurSetMode = FALSE;
  128. return err;
  129. }
  130. //
  131. // if the mode is not valid dont even try.
  132. //
  133. err = ChangeDisplaySettings(pdm, CDS_EXCLUSIVE | CDS_TEST);
  134. if (err != DISP_CHANGE_SUCCESSFUL)
  135. {
  136. bInOurSetMode = FALSE;
  137. return err;
  138. }
  139. //
  140. // get the current settings
  141. //
  142. hdc = GetDC(NULL);
  143. rc = GetDeviceCaps(hdc, RASTERCAPS);
  144. bpp = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
  145. w = GetDeviceCaps(hdc, HORZRES);
  146. h = GetDeviceCaps(hdc, VERTRES);
  147. ReleaseDC(NULL, hdc);
  148. //
  149. // dont try to do a invalid change
  150. //
  151. if (pdm && (pdm->dmFields & DM_BITSPERPEL))
  152. {
  153. if ((int)pdm->dmBitsPerPel == bpp)
  154. {
  155. bInOurSetMode = FALSE;
  156. return DISP_CHANGE_FAILED;
  157. }
  158. if (bpp <= 4 && (int)pdm->dmBitsPerPel != bpp)
  159. {
  160. bInOurSetMode = FALSE;
  161. return DISP_CHANGE_RESTART;
  162. }
  163. if (bpp > 4 && (int)pdm->dmBitsPerPel <= 4)
  164. {
  165. bInOurSetMode = FALSE;
  166. return DISP_CHANGE_RESTART;
  167. }
  168. }
  169. #ifndef NOCREATEWINDOW
  170. //
  171. // bring up a "cover" window to hide all the activity of the mode
  172. // change from the user. and brings up a wait cursor
  173. //
  174. // NOTE this does a little more than just hide the mode change
  175. // from the user, it also makes sure to set a MONO hourglass cursor
  176. // some display drivers dont like a software cursor being active
  177. // durring a mode set, so we give them a mono one.
  178. //
  179. if (TRUE || !(flags & CDS_FULLSCREEN))
  180. {
  181. #define OCR_WAIT_DEFAULT 102
  182. WNDCLASS cls;
  183. cls.lpszClassName = szClassName;
  184. cls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  185. cls.hInstance = hInstApp;
  186. cls.hIcon = NULL;
  187. cls.hCursor = (HCURSOR)LoadImage(NULL,MAKEINTRESOURCE(OCR_WAIT_DEFAULT),IMAGE_CURSOR,0,0,0);
  188. cls.lpszMenuName = NULL;
  189. cls.style = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
  190. cls.lpfnWndProc = DefWindowProc;
  191. cls.cbWndExtra = 0;
  192. cls.cbClsExtra = 0;
  193. RegisterClass(&cls);
  194. hwnd = CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW,
  195. szClassName, szClassName,
  196. WS_POPUP|WS_VISIBLE, 0, 0, 10000, 10000,
  197. NULL, NULL, hInstApp, NULL);
  198. if (hwnd == NULL)
  199. {
  200. bInOurSetMode = FALSE;
  201. return DISP_CHANGE_FAILED;
  202. }
  203. SetForegroundWindow(hwnd); // we want cursor focus
  204. SetCursor(cls.hCursor); // set wait cursor.
  205. }
  206. #endif
  207. //
  208. // no one gets to draw until we are done.
  209. //
  210. LockWindowUpdate(GetDesktopWindow());
  211. DPF("Begin mode change from %dx%dx%d....", w,h,bpp);
  212. //
  213. // first thing we have to do is convert all DDBs and Pattern brushs
  214. // to DIBSections so they will still work after the mode has changed.
  215. //
  216. ConvertObjects();
  217. //
  218. // convert all icons so they can be drawn correctly.
  219. //
  220. if (!fNewDibEng && !(flags & CDS_FULLSCREEN))
  221. {
  222. //ConvertIcons();
  223. }
  224. #ifdef BABYSIT
  225. //
  226. // the matrox driver is broken
  227. // it has a global variable for bPaletized mode, and it only
  228. // reads it if the mode is 8bpp.
  229. //
  230. if (!fDirectDrawDriver && bpp == 8 && IsMatrox())
  231. {
  232. static char szSystemIni[] = "system.ini";
  233. static char szPalettized[] = "palettized";
  234. static char szZero[] = "0";
  235. static DEVMODE dm;
  236. dm.dmSize = sizeof(DEVMODE);
  237. dm.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
  238. dm.dmBitsPerPel = 8;
  239. dm.dmPelsWidth = 640;
  240. dm.dmPelsHeight = 480;
  241. DPF("**BABYSIT** Fixing the broken Matrox driver....");
  242. WritePrivateProfileString(szDISPLAY,szPalettized,szZero,szSystemIni);
  243. err = ChangeDisplaySettings(&dm, CDS_RESET | CDS_FULLSCREEN);
  244. WritePrivateProfileString(szDISPLAY,szPalettized,NULL,szSystemIni);
  245. }
  246. #endif
  247. //
  248. // some drivers are total broken and we need to
  249. // route some of its entry points to the DIBENG
  250. //
  251. // WARNING this can break some remote control programs!
  252. //
  253. #ifdef BABYSIT
  254. if (!fDirectDrawDriver)
  255. {
  256. DPF("**BABYSIT** turning off OEMOutput....");
  257. PatchDisplay(8, TRUE); // route OEMOutput to the DIBENG
  258. DPF("**BABYSIT** turning off OEMDibBlt....");
  259. PatchDisplay(19, TRUE); // route OEMDibBlt to the DIBENG
  260. }
  261. #endif
  262. //
  263. // change the display settings.
  264. //
  265. PatchControl(TRUE);
  266. DPF("Calling ChangeDisplaySettings....");
  267. //
  268. // NOTE USER will Yield unless CDS_FULLSCREEN is specifed
  269. //
  270. err = ChangeDisplaySettings(pdm, flags | CDS_EXCLUSIVE);
  271. DPF("....ChangeDisplaySettings returns %d", err);
  272. // get the new settings
  273. //
  274. hdc = GetDC(NULL);
  275. new_rc = GetDeviceCaps(hdc, RASTERCAPS);
  276. new_bpp = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
  277. ReleaseDC(NULL, hdc);
  278. //
  279. // make sure the driver has not messed up its rastercaps!
  280. // for example the QVision driver does not get this right.
  281. //
  282. if ((new_rc & RC_PALETTE) && new_bpp != 8)
  283. {
  284. DPF("**BABYSIT** drivers RC_PALETTE bit is messed up.");
  285. err = DISP_CHANGE_RESTART; // err = DISP_CHANGE_FAILED;
  286. }
  287. //
  288. // if the driver failed the mode set things could be real messed up
  289. // reset the current mode, to try to recover.
  290. //
  291. #ifdef BABYSIT
  292. if (err != DISP_CHANGE_SUCCESSFUL)
  293. {
  294. static DEVMODE dm;
  295. dm.dmSize = sizeof(DEVMODE);
  296. dm.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS;
  297. dm.dmBitsPerPel = bpp;
  298. dm.dmPelsWidth = w;
  299. dm.dmPelsHeight = h;
  300. dm.dmDisplayFlags = 0;
  301. DPF("**BABYSIT** mode set failed, going back to old mode.");
  302. ChangeDisplaySettings(&dm, CDS_RESET | CDS_EXCLUSIVE | CDS_FULLSCREEN);
  303. }
  304. #endif
  305. PatchControl(FALSE);
  306. //
  307. // call Death/Resurection this will kick drivers in the head
  308. // about the mode change
  309. //
  310. if (!fDirectDrawDriver && err == 0 &&
  311. (pdm == NULL || (flags & CDS_UPDATEREGISTRY)))
  312. {
  313. hdc = GetDC(NULL);
  314. DPF("Calling Death/Resurection....");
  315. SetCursor(NULL);
  316. Death(hdc);
  317. Resurrection(hdc,NULL,NULL,NULL);
  318. ReleaseDC(NULL, hdc);
  319. }
  320. //
  321. // force a SW cursor, most drivers are broken and dont disable
  322. // the HW cursor when changing modes.
  323. //
  324. #ifdef BABYSIT
  325. if (!fDirectDrawDriver)
  326. {
  327. if (pdm == NULL && (flags & CDS_FULLSCREEN))
  328. {
  329. DPF("**BABYSIT** restoring HW cursor (return from fullscreen mode)");
  330. ForceSoftwareCursor(FALSE);
  331. }
  332. else if (err == 0 && (new_bpp > 8 || GetSystemMetrics(SM_CXSCREEN) < 640))
  333. {
  334. DPF("**BABYSIT** Forcing a software cursor");
  335. ForceSoftwareCursor(TRUE);
  336. }
  337. else
  338. {
  339. DPF("**BABYSIT** restoring HW cursor");
  340. ForceSoftwareCursor(FALSE);
  341. }
  342. }
  343. #endif
  344. #if 0 /// moved to Control patch
  345. //
  346. // we should now convert any DIBSections that used to be DDBs back to DDBs
  347. // our code to find the right palette for a DDB is not too hot
  348. // so a lot of DDBs will have wrong colors.
  349. //
  350. #if 1
  351. ConvertBitmapsBack(FALSE);
  352. #else
  353. ConvertBitmapsBack(!(flags & CDS_FULLSCREEN));
  354. #endif
  355. #endif
  356. //
  357. // let other apps draw.
  358. //
  359. LockWindowUpdate(NULL);
  360. //
  361. // remove our "cover" window
  362. //
  363. if (hwnd)
  364. {
  365. DestroyWindow(hwnd);
  366. UnregisterClass(szClassName, hInstApp);
  367. }
  368. //
  369. // should we reload the wallpaper, because it got converted to
  370. // a DDB by ConvertBitmapsBack
  371. //
  372. if (!(flags & CDS_FULLSCREEN))
  373. {
  374. DPF("Reloading wallpaper...");
  375. SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, NULL, 0);
  376. }
  377. //
  378. // have all the apps deal with a color change
  379. //
  380. if (!(flags & CDS_FULLSCREEN))
  381. {
  382. //
  383. //
  384. //
  385. // if we just post the WM_SYSCOLORCHANGE message to all apps
  386. // a hidden office window will go back and forth Invalidating
  387. // other office apps and re-sending the WM_SYSCOLORCHANGE message
  388. // you either stack overflow, hang or XL just flashes for a few
  389. // minutes.
  390. //
  391. // the "fix" is to not post the WM_SYSCOLORCHANGE message to
  392. // this hidden window, we also have to make sure not to call
  393. // SystemParametersInfo(SPI_SETDESKPATTERN) later in the code.
  394. //
  395. HWND hwnd;
  396. HWND hwndX;
  397. if (hwndX = FindWindow("File Open Message Window", "File Open Message Window"))
  398. {
  399. for (hwnd = GetWindow(GetDesktopWindow(), GW_CHILD);
  400. hwnd;
  401. hwnd = GetWindow(hwnd, GW_HWNDNEXT))
  402. {
  403. if (hwnd != hwndX)
  404. PostMessage(hwnd, WM_SYSCOLORCHANGE, 0, 0);
  405. }
  406. // dont reload desktop pattern.
  407. flags |= CDS_FULLSCREEN;
  408. }
  409. else
  410. {
  411. PostMessage(HWND_BROADCAST, WM_SYSCOLORCHANGE, 0, 0);
  412. }
  413. }
  414. //
  415. // reload the desktop pattern
  416. //
  417. if (!(flags & CDS_FULLSCREEN) || pdm == NULL)
  418. {
  419. DPF("Reloading wallpaper pattern...");
  420. SystemParametersInfo(SPI_SETDESKPATTERN, (UINT)-1, NULL, 0);
  421. }
  422. //
  423. // we dont want the StartMenu to rebuild when we change modes
  424. //
  425. if (err == DISP_CHANGE_SUCCESSFUL)
  426. {
  427. if (flags & CDS_FULLSCREEN)
  428. StartMenuHack(pdm);
  429. }
  430. bInOurSetMode = FALSE;
  431. DPF("Done...");
  432. return err;
  433. }
  434. #ifndef DCICOMMAND
  435. #define DCICOMMAND 3075 // escape value
  436. #endif
  437. BOOL InitDynaRes()
  438. {
  439. int v;
  440. HDC hdc;
  441. HBRUSH hbr1, hbr2;
  442. BOOL f=TRUE;
  443. OSVERSIONINFO ver = {sizeof(OSVERSIONINFO)};
  444. GetVersionEx(&ver);
  445. // must be Windows95 build 950 or higher
  446. if (LOWORD(GetVersion()) != 0x5F03)
  447. {
  448. DPF("Init: Windows version not 3.95.");
  449. f = FALSE;
  450. }
  451. if (ver.dwMajorVersion != 4 ||
  452. ver.dwMinorVersion != 0 ||
  453. LOWORD(ver.dwBuildNumber) < 950)
  454. {
  455. DPF("Init: Windows version less than 4.0.950");
  456. f = FALSE;
  457. }
  458. //
  459. // we assume create/delete/create will get the same handle
  460. //
  461. hbr1 = CreateSolidBrush(RGB(1,1,1));
  462. DeleteObject(hbr1);
  463. hbr2 = CreateSolidBrush(RGB(2,2,2));
  464. DeleteObject(hbr2);
  465. if (hbr1 != hbr2)
  466. {
  467. DPF("Init: cant use Destroy/Create brush trick");
  468. f = FALSE;
  469. }
  470. if (GetModuleHandle(szDIBENG) == 0)
  471. {
  472. DPF("Init: DIBENG not loaded");
  473. f = FALSE;
  474. }
  475. hdc = GetDC(NULL);
  476. // check the DIBENG version
  477. v = 0x5250;
  478. v = Escape(hdc, QUERYESCSUPPORT, sizeof(int), (LPVOID)&v, NULL);
  479. if (v == 0)
  480. {
  481. DPF("Init: we dont have a new DIBENG");
  482. fNewDibEng = FALSE;
  483. }
  484. else
  485. {
  486. DPF("Init: DIBENG version: %04X", v);
  487. fNewDibEng = TRUE;
  488. }
  489. //
  490. // see if the display supports DirectDraw
  491. //
  492. v = DCICOMMAND;
  493. v = Escape(hdc, QUERYESCSUPPORT, sizeof(int), (LPVOID)&v, NULL);
  494. if (v == 0 || v == 0x5250)
  495. {
  496. DPF("Init: display driver does not support DirectDraw");
  497. fDirectDrawDriver = FALSE;
  498. }
  499. else
  500. {
  501. if (LOBYTE(v) == 0xFF)
  502. v++;
  503. DPF("Init: display driver supports DirectDraw: %04X", v);
  504. fDirectDrawDriver = TRUE;
  505. }
  506. //
  507. // must be a windows 4.0 mini driver.
  508. //
  509. if (GetDeviceCaps(hdc, DRIVERVERSION) < 0x0400)
  510. {
  511. DPF("Init: not a 4.0 display driver");
  512. f = FALSE;
  513. }
  514. if (!(GetDeviceCaps(hdc, CAPS1) & C1_DIBENGINE))
  515. {
  516. DPF("Init: not a DIBENG display driver");
  517. f = FALSE;
  518. }
  519. if (!(GetDeviceCaps(hdc, CAPS1) & C1_REINIT_ABLE))
  520. {
  521. DPF("Init: does not support C1_REINIT_ABLE");
  522. f = FALSE;
  523. }
  524. ReleaseDC(NULL, hdc);
  525. return f;
  526. }
  527. //
  528. // we hook the OEMControl entry point in the display driver while a
  529. // mode change is happening. GDI will issue a QUERYDIBSUPPORT escape
  530. // right after the mode change happens so this is the first thing
  531. // called after the mode changed worked. USER also issues a
  532. // MOUSETRAILS escape.
  533. //
  534. // we need this hook for two reasons...
  535. //
  536. // 1. some display drivers are broken and dont set deFlags right
  537. // we fix up the deFlags, we fix up the flags for them.
  538. //
  539. // 2. we rerealize all the gdi objects in this routine when
  540. // USER calls us, this way all the pen/brushs/text colors
  541. // are correct when user goes and rebuilds its bitmaps...
  542. //
  543. LONG FAR PASCAL _loadds Control(LPVOID lpDevice,UINT function,LPVOID lp_in_data,LPVOID lp_out_data)
  544. {
  545. DIBENGINE FAR *pde = (DIBENGINE FAR *)lpDevice;
  546. LONG ret;
  547. Assert(bInOurSetMode);
  548. #ifdef BABYSIT
  549. if (pde->deType == 0x5250)
  550. {
  551. if ((pde->deFlags & FIVE6FIVE) && pde->deBitsPixel != 16)
  552. {
  553. DPF("**BABYSIT** fixing FIVE6FIVE bit");
  554. pde->deFlags &= ~FIVE6FIVE;
  555. }
  556. if ((pde->deFlags & PALETTIZED) && pde->deBitsPixel != 8)
  557. {
  558. DPF("**BABYSIT** fixing PALETTIZED bit");
  559. pde->deFlags &= ~PALETTIZED;
  560. }
  561. if ((pde->deFlags & PALETTE_XLAT) && pde->deBitsPixel != 8)
  562. {
  563. DPF("**BABYSIT** fixing PALETTE_XLAT bit");
  564. pde->deFlags &= ~PALETTE_XLAT;
  565. }
  566. }
  567. #endif
  568. //
  569. // this is USER calling from LW_OEMDependentInit()
  570. // force all GDI objects to be rerealized
  571. //
  572. if (function == MOUSETRAILS && bInOurSetMode != (BOOL)2)
  573. {
  574. //
  575. // fix up the magic colors before we rerealize the brushes
  576. // the "right" way to do this is to reset the UI colors
  577. // by calling SetSysColors() but we dont want to send
  578. // a sync WM_SYSCOLORCHANGE from here.
  579. //
  580. HDC hdc = GetDC(NULL);
  581. if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
  582. {
  583. SetSystemPaletteUse(hdc, SYSPAL_STATIC);
  584. SetMagicColors(hdc, GetSysColor(COLOR_3DSHADOW) , 8);
  585. SetMagicColors(hdc, GetSysColor(COLOR_3DFACE) , 9);
  586. SetMagicColors(hdc, GetSysColor(COLOR_3DHILIGHT), 246);
  587. }
  588. ReleaseDC(NULL, hdc);
  589. //
  590. // re-realize all GDI objects for the new mode.
  591. //
  592. ReRealizeObjects();
  593. //
  594. // we should now convert any DIBSections that used to be DDBs back to DDBs
  595. // our code to find the right palette for a DDB is not too hot
  596. // so a lot of DDBs will have wrong colors.
  597. //
  598. ConvertBitmapsBack(FALSE);
  599. }
  600. PatchControl(FALSE);
  601. ret = DIBENG_Control(lpDevice,function,lp_in_data,lp_out_data);
  602. PatchControl(TRUE);
  603. return ret;
  604. }
  605. //
  606. // patch
  607. //
  608. void Patch(LPCSTR szMod, LPCSTR szProc, FARPROC PatchFunc, LPDWORD PatchSave, BOOL fPatch)
  609. {
  610. LPDWORD pdw;
  611. FARPROC x;
  612. //
  613. // ATM 2.5 has GetProcAddress patched to return some sort of
  614. // thunk, that ends up totaly confusing us and we dont end up
  615. // patching the DIBENG, we patch ATM's thunk.
  616. //
  617. // so when we want to patch DIBENG!OEMControl we use the value we
  618. // *linked* to, not the value GetProcAddress returns.
  619. //
  620. if (lstrcmpi(szMod, szDIBENG) == 0 && szProc == MAKEINTATOM(3))
  621. x = (FARPROC)DIBENG_Control;
  622. else
  623. x = GetProcAddress(GetModuleHandle(szMod), szProc);
  624. if (x == NULL || PatchFunc == NULL)
  625. return;
  626. GlobalReAlloc((HGLOBAL)SELECTOROF(x), 0, GMEM_MODIFY|GMEM_MOVEABLE);
  627. pdw = (LPDWORD)MAKELP(AllocCStoDSAlias(SELECTOROF(x)), OFFSETOF(x));
  628. if (fPatch)
  629. {
  630. DPF("Patching %s!%d %04X:%04X", szMod, OFFSETOF(szProc), SELECTOROF(x), OFFSETOF(x));
  631. if (PatchSave[0] == 0)
  632. {
  633. PatchSave[0] = pdw[0];
  634. PatchSave[1] = pdw[1];
  635. }
  636. *((LPBYTE)pdw)++ = 0xEA; // JMP
  637. *pdw = (DWORD)PatchFunc;
  638. }
  639. else
  640. {
  641. DPF("UnPatching %s!%d %04X:%04X", szMod, OFFSETOF(szProc), SELECTOROF(x), OFFSETOF(x));
  642. if (PatchSave[0] != 0)
  643. {
  644. pdw[0] = PatchSave[0];
  645. pdw[1] = PatchSave[1];
  646. PatchSave[0] = 0;
  647. PatchSave[1] = 0;
  648. }
  649. }
  650. FreeSelector(SELECTOROF(pdw));
  651. }
  652. //
  653. // hook the DIBENGs OEMControl() entry point, to jump to our own code
  654. //
  655. void PatchControl(BOOL patch)
  656. {
  657. static DWORD SaveBytes[2];
  658. Patch(szDIBENG, MAKEINTATOM(3), (FARPROC)Control, SaveBytes, patch);
  659. }
  660. //
  661. // patch a entry in the display driver to jump directly to the DIBENG
  662. //
  663. void PatchDisplay(int oem, BOOL patch)
  664. {
  665. FARPROC p;
  666. #define MAX_DDI 35
  667. static DWORD PatchBytes[MAX_DDI*2];
  668. if (oem >= MAX_DDI)
  669. return;
  670. p = GetProcAddress(GetModuleHandle(szDIBENG), MAKEINTATOM(oem));
  671. Patch(szDISPLAY, MAKEINTATOM(oem), p, &PatchBytes[oem*2], patch);
  672. }
  673. /*----------------------------------------------------------------------------*\
  674. \*----------------------------------------------------------------------------*/
  675. #ifdef O95_HACK
  676. static BOOL fOffice95Hack;
  677. static char szDisplaySettings[] = "Display\\Settings";
  678. static char szResolution[] = "Resolution";
  679. static char szDD[] = "%d,%d";
  680. //
  681. // put back the right resolution into the registy key HKCC\Display\Settings
  682. //
  683. void Office95Hack()
  684. {
  685. if (fOffice95Hack)
  686. {
  687. HKEY hkey;
  688. char ach[20];
  689. int len;
  690. DPF("Office95 hack: restoring registry");
  691. if (RegOpenKey(HKEY_CURRENT_CONFIG, szDisplaySettings, &hkey) == 0)
  692. {
  693. len = wsprintf(ach, szDD, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
  694. RegSetValueEx(hkey, szResolution, NULL, REG_SZ, ach, len);
  695. RegCloseKey(hkey);
  696. }
  697. fOffice95Hack = FALSE;
  698. }
  699. }
  700. #endif
  701. #ifdef SPI_HACK
  702. BOOL FAR PASCAL _loadds SPI(UINT spi, UINT wParam, LPVOID lParam, UINT flags);
  703. //
  704. // patch USERs SystemParametersInfo function
  705. //
  706. void PatchSPI(BOOL patch)
  707. {
  708. static DWORD SaveBytes[2];
  709. Patch(szUSER, MAKEINTATOM(483), (FARPROC)SPI, SaveBytes, patch);
  710. }
  711. BOOL FAR PASCAL _loadds SPI(UINT spi, UINT wParam, LPVOID lParam, UINT flags)
  712. {
  713. BOOL f;
  714. if (spi == SPI_SETWORKAREA)
  715. {
  716. if (lParam)
  717. 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);
  718. else
  719. DPF("Ignoring a SPI_SETWORKAREA lParam=NULL call");
  720. return 0;
  721. }
  722. PatchSPI(FALSE);
  723. f = SystemParametersInfo(spi, wParam, lParam, flags);
  724. PatchSPI(TRUE);
  725. return f;
  726. }
  727. #endif
  728. /*----------------------------------------------------------------------------*\
  729. \*----------------------------------------------------------------------------*/
  730. //
  731. // make the start menu not update in the background.
  732. //
  733. #define IDT_FAVOURITE 4
  734. #define WNDCLASS_TRAYNOTIFY "Shell_TrayWnd"
  735. LRESULT CALLBACK _loadds TrayWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  736. {
  737. #ifdef SPI_HACK
  738. PatchSPI(FALSE);
  739. #endif
  740. #ifdef O95_HACK
  741. Office95Hack();
  742. #endif
  743. DPF("StartMenu hack: killing timer to refresh start menu");
  744. KillTimer(hwnd, IDT_FAVOURITE);
  745. return 0;
  746. }
  747. #ifdef SPI_HACK
  748. RECT rcScreen;
  749. RECT rcWork;
  750. #endif
  751. void PreStartMenuHack(DEVMODE FAR *pdm)
  752. {
  753. #ifdef SPI_HACK
  754. SetRect(&rcScreen, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
  755. SystemParametersInfo(SPI_GETWORKAREA, 0, (LPVOID)&rcWork, 0);
  756. #endif
  757. #ifdef O95_HACK
  758. // make sure registry is put back
  759. Office95Hack();
  760. #endif
  761. }
  762. void StartMenuHack(DEVMODE FAR *pdm)
  763. {
  764. HWND hwndTray;
  765. BOOL fAppBar=FALSE;
  766. hwndTray = FindWindow(WNDCLASS_TRAYNOTIFY, NULL);
  767. if (hwndTray == NULL)
  768. {
  769. DPF("Cant find tray window");
  770. return;
  771. }
  772. // hack to get into the shells context, so we can clean up these hacks
  773. PostMessage(hwndTray, WM_TIMER, 0, (LONG)TrayWndProc);
  774. #ifdef SPI_HACK
  775. {
  776. RECT rc;
  777. RECT rcTray;
  778. //
  779. // see if there are any other app bars around.
  780. //
  781. GetWindowRect(hwndTray, &rcTray);
  782. SubtractRect(&rc, &rcScreen, &rcTray);
  783. DPF("rcScreen [%d,%d,%d,%d]", rcScreen.left, rcScreen.top, rcScreen.right-rcScreen.left,rcScreen.bottom-rcScreen.top);
  784. DPF("rcTray [%d,%d,%d,%d]", rcTray.left, rcTray.top, rcTray.right-rcTray.left,rcTray.bottom-rcTray.top);
  785. DPF("rc [%d,%d,%d,%d]", rc.left, rc.top, rc.right-rc.left,rc.bottom-rc.top);
  786. DPF("rcWork [%d,%d,%d,%d]", rcWork.left, rcWork.top, rcWork.right-rcWork.left,rcWork.bottom-rcWork.top);
  787. if (!EqualRect(&rcScreen, &rcWork) && !EqualRect(&rc, &rcWork))
  788. {
  789. DPF("StartMenuHack: !!!!!there is a APP bar!!!!!!");
  790. fAppBar = TRUE;
  791. //
  792. // Patch the USER!SystemParameterInto function, so when the
  793. // shell does a SPI_SETWORKAREA call it will ignored
  794. // this prevents windows from being "sqished" to fit inside
  795. // the work area.
  796. //
  797. PatchSPI(TRUE);
  798. }
  799. }
  800. #endif
  801. #ifdef O95_HACK
  802. //
  803. // the shell does the following...
  804. //
  805. // read the HKEY_CURRENT_CONFIG\Display\Settings "Resloluton" key
  806. // if this is LESS THAN the current display size, dont repark
  807. // all the icons on the desktop because this is just a temporary
  808. // mode set.
  809. //
  810. // this sound right, except the bug happens when we are returning
  811. // to the "normal" mode, the shell will repark the icons because
  812. // it checks for LESS THEN, not LESS THAN OR EQUAL, normaly this
  813. // is fine because the re-park does nothing. when a app bar
  814. // like Office95 is running it has not moved before the shell
  815. // re-re-parks icons.
  816. //
  817. // what this hack does it set the size stored in the registry
  818. // to be real large so the shell does not park icons.
  819. // later we will but the right values back. we only need to
  820. // do this if we are returning to the "normal" mode (ie pdm==NULL)
  821. //
  822. if (fAppBar && pdm == NULL)
  823. {
  824. HKEY hkey;
  825. char ach[20];
  826. int len;
  827. fOffice95Hack = TRUE;
  828. if (RegOpenKey(HKEY_CURRENT_CONFIG, szDisplaySettings, &hkey) == 0)
  829. {
  830. len = wsprintf(ach, szDD, 30000, 30000);
  831. RegSetValueEx(hkey, szResolution, NULL, REG_SZ, ach, len);
  832. RegCloseKey(hkey);
  833. }
  834. }
  835. else
  836. {
  837. fOffice95Hack = FALSE;
  838. }
  839. #endif
  840. }
  841. #ifdef BABYSIT
  842. //
  843. // force (or trick) the display driver into using a software cursor.
  844. //
  845. BOOL ForceSoftwareCursor(BOOL f)
  846. {
  847. int n=0;
  848. //
  849. // get the mouse trails setting from USER
  850. //
  851. SystemParametersInfo(SPI_GETMOUSETRAILS, 0, (LPVOID)&n, 0);
  852. if (f)
  853. {
  854. //
  855. // enable mouse trails, this will cause the display driver to
  856. // turn off its hardware cursor
  857. //
  858. SystemParametersInfo(SPI_SETMOUSETRAILS, 2, NULL, 0);
  859. //
  860. // now tell the DIBENG to turn off mouse trails, the display driver
  861. // will think they are still on...
  862. //
  863. PatchDisplay(3, TRUE); // route to DIBENG
  864. SystemParametersInfo(SPI_SETMOUSETRAILS, n, NULL, 0);
  865. PatchDisplay(3, FALSE); // back to DISPLAY
  866. }
  867. else
  868. {
  869. SystemParametersInfo(SPI_SETMOUSETRAILS, n, NULL, 0);
  870. }
  871. return TRUE;
  872. }
  873. /*----------------------------------------------------------------------------*\
  874. \*----------------------------------------------------------------------------*/
  875. BOOL IsMatrox()
  876. {
  877. char ach[80];
  878. int len;
  879. GetModuleFileName(GetModuleHandle(szDISPLAY), ach, sizeof(ach));
  880. len = lstrlen(ach);
  881. return len >= 7 && lstrcmpi(ach+len-7, "mga.drv") == 0;
  882. }
  883. #endif