Source code of Windows XP (NT5)
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.

1114 lines
23 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. PaletteRestore.cpp
  5. Abstract:
  6. On win9x, all palette state was maintained through a mode change. On NT,
  7. this can cause numerous problems, most often when task switching between
  8. the application and the desktop.
  9. Unfortunately, GetSystemPaletteEntries does NOT return the peFlags part
  10. of the PALETTEENTRY struct, which means that we have to intercept the
  11. other palette setting functions just to find out what the real palette
  12. is.
  13. The strategy is as follows:
  14. 1. Catch all known ways of setting up the palette
  15. 2. After a mode change, restore the palette
  16. In order to do this, we also have to keep a list of the DCs so we know
  17. which palette was animated/realized and the active window to which it
  18. belongs.
  19. Not yet implemented:
  20. 1. Track whether a palette change came from within DirectDraw, since on
  21. win9x, DirectDraw doesn't use GDI to set the palette, so calls to
  22. GetSystemPaletteEntries will return different results.
  23. Notes:
  24. This is a general purpose shim.
  25. History:
  26. 05/20/2000 linstev Created
  27. --*/
  28. #include "precomp.h"
  29. #include "CharVector.h"
  30. // This module has been given an official blessing to use the str routines.
  31. #include "LegalStr.h"
  32. IMPLEMENT_SHIM_BEGIN(PaletteRestore)
  33. #include "ShimHookMacro.h"
  34. APIHOOK_ENUM_BEGIN
  35. APIHOOK_ENUM_ENTRY(ChangeDisplaySettingsA)
  36. APIHOOK_ENUM_ENTRY(ChangeDisplaySettingsW)
  37. APIHOOK_ENUM_ENTRY(ChangeDisplaySettingsExA)
  38. APIHOOK_ENUM_ENTRY(ChangeDisplaySettingsExW)
  39. APIHOOK_ENUM_ENTRY(SetSystemPaletteUse)
  40. APIHOOK_ENUM_ENTRY(CreatePalette)
  41. APIHOOK_ENUM_ENTRY(SetPaletteEntries)
  42. APIHOOK_ENUM_ENTRY(AnimatePalette)
  43. APIHOOK_ENUM_ENTRY(CreateDCA)
  44. APIHOOK_ENUM_ENTRY(CreateDCW)
  45. APIHOOK_ENUM_ENTRY(CreateCompatibleDC)
  46. APIHOOK_ENUM_ENTRY(DeleteDC)
  47. APIHOOK_ENUM_ENTRY(GetDC)
  48. APIHOOK_ENUM_ENTRY(GetWindowDC)
  49. APIHOOK_ENUM_ENTRY(ReleaseDC)
  50. APIHOOK_ENUM_ENTRY(SelectPalette)
  51. APIHOOK_ENUM_ENTRY(GetSystemPaletteEntries)
  52. APIHOOK_ENUM_ENTRY(RealizePalette)
  53. APIHOOK_ENUM_ENTRY(DeleteObject)
  54. APIHOOK_ENUM_END
  55. //
  56. // Keep track of the last realized palette
  57. //
  58. PALETTEENTRY g_lastPal[256];
  59. //
  60. // Keeps the last value of the call to SetSystemPaletteUse
  61. //
  62. UINT g_uLastUse = SYSPAL_NOSTATIC256;
  63. //
  64. // Default system palette: needed because NT only keeps 20 colors
  65. //
  66. DWORD g_palDefault[256] =
  67. {
  68. 0x00000000, 0x00000080, 0x00008000, 0x00008080,
  69. 0x00800000, 0x00800080, 0x00808000, 0x00C0C0C0,
  70. 0x00C0DCC0, 0x00F0CAA6, 0x04081824, 0x04142830,
  71. 0x0418303C, 0x04304D61, 0x0451514D, 0x044D7161,
  72. 0x04826D61, 0x040C1414, 0x04597582, 0x04759E08,
  73. 0x04303438, 0x04AA6938, 0x04203428, 0x04496161,
  74. 0x0449869E, 0x047D9A6D, 0x040869CB, 0x048E8682,
  75. 0x0475615D, 0x040061EB, 0x04000871, 0x042C3830,
  76. 0x040471EF, 0x048E92AA, 0x04306DF7, 0x0404C3C3,
  77. 0x0492AAB2, 0x04101814, 0x04040C08, 0x040C7110,
  78. 0x04CFA282, 0x040008AA, 0x0428412C, 0x04498EB2,
  79. 0x04204D61, 0x04555955, 0x0404D3D3, 0x041C3C4D,
  80. 0x0420A6F7, 0x0410A210, 0x0418241C, 0x045DAEF3,
  81. 0x04719EAA, 0x04B2E720, 0x04102871, 0x0486C3D3,
  82. 0x04288A2C, 0x040C51BA, 0x0459716D, 0x04494D4D,
  83. 0x04AAB6C3, 0x04005100, 0x0420CBF7, 0x044D8A51,
  84. 0x04BEC7B2, 0x04043CBA, 0x04101C18, 0x040851DF,
  85. 0x04A6E7A6, 0x049ECF24, 0x04797592, 0x04AE7559,
  86. 0x049E8269, 0x04CFE3DF, 0x040C2030, 0x0428692C,
  87. 0x049EA2A2, 0x04F7C782, 0x0434617D, 0x04B6BEBE,
  88. 0x04969E86, 0x04DBFBD3, 0x04655149, 0x0465EF65,
  89. 0x04AED3D3, 0x04E7924D, 0x04B2BEB2, 0x04D7DBDB,
  90. 0x04797571, 0x04344D59, 0x0486B2CF, 0x04512C14,
  91. 0x04A6FBFB, 0x04385965, 0x04828E92, 0x041C4161,
  92. 0x04595961, 0x04002000, 0x043C6D7D, 0x045DB2D7,
  93. 0x0438EF3C, 0x0451CB55, 0x041C2424, 0x0461C3F3,
  94. 0x0408A2A2, 0x0438413C, 0x04204951, 0x04108A14,
  95. 0x04103010, 0x047DE7F7, 0x04143449, 0x04B2652C,
  96. 0x04F7EBAA, 0x043C7192, 0x0404FBFB, 0x04696151,
  97. 0x04EFC796, 0x040441D7, 0x04000404, 0x04388AF7,
  98. 0x048AD3F3, 0x04006500, 0x040004E3, 0x04DBFFFF,
  99. 0x04F7AE69, 0x04CF864D, 0x0455A2D3, 0x04EBEFE3,
  100. 0x04EB8A41, 0x04CF9261, 0x04C3F710, 0x048E8E82,
  101. 0x04FBFFFF, 0x04104110, 0x04040851, 0x0482FBFB,
  102. 0x043CC734, 0x04088A8A, 0x04384545, 0x04514134,
  103. 0x043C7996, 0x041C6161, 0x04EBB282, 0x04004100,
  104. 0x04715951, 0x04A2AAA6, 0x04B2B6B2, 0x04C3FBFB,
  105. 0x04000834, 0x0428413C, 0x04C7C7CF, 0x04CFD3D3,
  106. 0x04824520, 0x0408CB0C, 0x041C1C1C, 0x04A6B29A,
  107. 0x0471A6BE, 0x04CF9E6D, 0x046D7161, 0x04008A04,
  108. 0x045171BE, 0x04C7D3C3, 0x04969E96, 0x04798696,
  109. 0x042C1C10, 0x04385149, 0x04BE7538, 0x0408141C,
  110. 0x04C3C7C7, 0x04202C28, 0x04D3E3CF, 0x0471826D,
  111. 0x04653C1C, 0x0404EF08, 0x04345575, 0x046D92A6,
  112. 0x04797979, 0x0486F38A, 0x04925528, 0x04E3E7E7,
  113. 0x04456151, 0x041C499A, 0x04656961, 0x048E9EA2,
  114. 0x047986D3, 0x04204151, 0x048AC7E3, 0x04007100,
  115. 0x04519EBE, 0x0410510C, 0x04A6AAAA, 0x042C3030,
  116. 0x04D37934, 0x04183030, 0x0449828E, 0x04CBFBC3,
  117. 0x046D7171, 0x040428A6, 0x044D4545, 0x04040C14,
  118. 0x04087575, 0x0471CB79, 0x044D6D0C, 0x04FBFBD3,
  119. 0x04AAB2AE, 0x04929292, 0x04F39E55, 0x04005D00,
  120. 0x04E3D7B2, 0x04F7FBC3, 0x043C5951, 0x0404B2B2,
  121. 0x0434658E, 0x040486EF, 0x04F7FBE3, 0x04616161,
  122. 0x04DFE3DF, 0x041C100C, 0x0408100C, 0x0408180C,
  123. 0x04598600, 0x0424FBFB, 0x04346171, 0x04042CC7,
  124. 0x04AEC79A, 0x0445AE4D, 0x0428A62C, 0x04EFA265,
  125. 0x047D8282, 0x04F7D79A, 0x0465D3F7, 0x04E3E7BA,
  126. 0x04003000, 0x04245571, 0x04DF823C, 0x048AAEC3,
  127. 0x04A2C3D3, 0x04A6FBA2, 0x04F3FFF3, 0x04AAD7E7,
  128. 0x04EFEFC3, 0x0455F7FB, 0x04EFF3F3, 0x04BED3B2,
  129. 0x0404EBEB, 0x04A6E3F7, 0x00F0FBFF, 0x00A4A0A0,
  130. 0x00808080, 0x000000FF, 0x0000FF00, 0x0000FFFF,
  131. 0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x00FFFFFF
  132. };
  133. //
  134. // Critical section used when accessing our lists
  135. //
  136. CRITICAL_SECTION g_csLists;
  137. //
  138. // A single item in the list of palettes
  139. //
  140. struct PALITEM
  141. {
  142. HPALETTE hPal;
  143. PALETTEENTRY palPalEntry[256];
  144. };
  145. //
  146. // Vector class that stores all the known palettes
  147. //
  148. class CPalVector : public VectorT<PALITEM>
  149. {
  150. public:
  151. // Find an hPal
  152. PALITEM *Find(HPALETTE hPal)
  153. {
  154. for (int i=0; i<Size(); ++i)
  155. {
  156. PALITEM &pitem = Get(i);
  157. if (pitem.hPal == hPal)
  158. {
  159. return &pitem;
  160. }
  161. }
  162. DPFN( eDbgLevelWarning, "Find: Could not find HPALETTE %08lx", hPal);
  163. return NULL;
  164. }
  165. // Remove an hPal
  166. BOOL Remove(HPALETTE hPal)
  167. {
  168. if (hPal)
  169. {
  170. EnterCriticalSection(&g_csLists);
  171. for (int i=0; i<Size(); ++i)
  172. {
  173. PALITEM &pitem = Get(i);
  174. if (pitem.hPal == hPal)
  175. {
  176. pitem = Get(Size() - 1);
  177. nVectorList -= 1;
  178. LeaveCriticalSection(&g_csLists);
  179. return TRUE;
  180. }
  181. }
  182. LeaveCriticalSection(&g_csLists);
  183. }
  184. return FALSE;
  185. }
  186. };
  187. CPalVector *g_palList;
  188. //
  189. // A single item in the list of DCs
  190. //
  191. struct DCITEM
  192. {
  193. HDC hDc;
  194. HWND hWnd;
  195. HPALETTE hPal;
  196. };
  197. //
  198. // Vector class that stores all the known DCs acquired by GetDC
  199. //
  200. class CDcVector : public VectorT<DCITEM>
  201. {
  202. public:
  203. // Find an hWnd/hDC
  204. DCITEM *Find(HWND hWnd, HDC hDc)
  205. {
  206. for (int i=0; i<Size(); ++i)
  207. {
  208. DCITEM &ditem = Get(i);
  209. if ((ditem.hDc == hDc) &&
  210. (ditem.hWnd == hWnd))
  211. {
  212. return &ditem;
  213. }
  214. }
  215. DPFN( eDbgLevelWarning, "Find: Could not find HDC %08lx", hDc);
  216. return NULL;
  217. }
  218. // Add an hWnd/hDC
  219. void Add(HWND hWnd, HDC hDc)
  220. {
  221. EnterCriticalSection(&g_csLists);
  222. DCITEM ditem;
  223. ditem.hPal = 0;
  224. ditem.hWnd = hWnd;
  225. ditem.hDc = hDc;
  226. Append(ditem);
  227. LeaveCriticalSection(&g_csLists);
  228. }
  229. // Remove an hWnd/hDC
  230. BOOL Remove(HWND hWnd, HDC hDc)
  231. {
  232. if (hDc)
  233. {
  234. EnterCriticalSection(&g_csLists);
  235. for (int i=0; i<Size(); ++i)
  236. {
  237. DCITEM &ditem = Get(i);
  238. if ((ditem.hDc == hDc) && (ditem.hWnd == hWnd))
  239. {
  240. ditem = Get(Size() - 1);
  241. nVectorList -= 1;
  242. LeaveCriticalSection(&g_csLists);
  243. return TRUE;
  244. }
  245. }
  246. LeaveCriticalSection(&g_csLists);
  247. }
  248. DPFN( eDbgLevelWarning, "Remove: Could not find hWnd=%08lx, hDC=%08lx", hWnd, hDc);
  249. return FALSE;
  250. }
  251. };
  252. CDcVector *g_dcList;
  253. /*++
  254. Restore the last palette that was realized if we're in a palettized mode.
  255. --*/
  256. VOID
  257. FixPalette()
  258. {
  259. LPLOGPALETTE plogpal;
  260. HWND hwnd;
  261. HDC hdc;
  262. HPALETTE hpal, hpalold;
  263. int icaps;
  264. hwnd = GetActiveWindow();
  265. hdc = ORIGINAL_API(GetDC)(hwnd);
  266. icaps = GetDeviceCaps(hdc, RASTERCAPS);
  267. // Check for palettized mode
  268. if (icaps & RC_PALETTE)
  269. {
  270. DPFN( eDbgLevelInfo, "Restoring palette");
  271. // We've set into a palettized mode, so fix the palette use
  272. ORIGINAL_API(SetSystemPaletteUse)(hdc, g_uLastUse);
  273. // Create a palette we can realize
  274. plogpal = (LPLOGPALETTE) malloc(sizeof(LOGPALETTE) + sizeof(g_lastPal));
  275. plogpal->palVersion = 0x0300;
  276. plogpal->palNumEntries = 256;
  277. MoveMemory(&plogpal->palPalEntry[0], &g_lastPal[0], sizeof(g_lastPal));
  278. // Realize the palette
  279. hpal = ORIGINAL_API(CreatePalette)(plogpal);
  280. hpalold = ORIGINAL_API(SelectPalette)(hdc, hpal, FALSE);
  281. ORIGINAL_API(RealizePalette)(hdc);
  282. ORIGINAL_API(SelectPalette)(hdc, hpalold, FALSE);
  283. ORIGINAL_API(DeleteObject)(hpal);
  284. }
  285. else
  286. {
  287. // Release the DC we used
  288. ORIGINAL_API(ReleaseDC)(hwnd, hdc);
  289. }
  290. }
  291. /*++
  292. Restore palette after change
  293. --*/
  294. LONG
  295. APIHOOK(ChangeDisplaySettingsA)(
  296. LPDEVMODEA lpDevMode,
  297. DWORD dwFlags
  298. )
  299. {
  300. LONG lRet = ORIGINAL_API(ChangeDisplaySettingsA)(
  301. lpDevMode,
  302. dwFlags);
  303. if (lpDevMode)
  304. {
  305. DPFN( eDbgLevelInfo,
  306. "%08lx=ChangeDisplaySettings(%d x %d x %d)",
  307. lRet,
  308. lpDevMode->dmPelsWidth,
  309. lpDevMode->dmPelsHeight,
  310. lpDevMode->dmBitsPerPel);
  311. }
  312. else
  313. {
  314. DPFN( eDbgLevelInfo,
  315. "%08lx=ChangeDisplaySettings Restore",lRet);
  316. }
  317. if (lpDevMode) FixPalette();
  318. return lRet;
  319. }
  320. /*++
  321. Restore palette after change
  322. --*/
  323. LONG
  324. APIHOOK(ChangeDisplaySettingsW)(
  325. LPDEVMODEW lpDevMode,
  326. DWORD dwFlags
  327. )
  328. {
  329. LONG lRet = ORIGINAL_API(ChangeDisplaySettingsW)(
  330. lpDevMode,
  331. dwFlags);
  332. if (lpDevMode)
  333. {
  334. DPFN( eDbgLevelInfo,
  335. "%08lx=ChangeDisplaySettings(%d x %d x %d)",
  336. lRet,
  337. lpDevMode->dmPelsWidth,
  338. lpDevMode->dmPelsHeight,
  339. lpDevMode->dmBitsPerPel);
  340. }
  341. else
  342. {
  343. DPFN( eDbgLevelInfo,
  344. "%08lx=ChangeDisplaySettings Restore",lRet);
  345. }
  346. if (lpDevMode) FixPalette();
  347. return lRet;
  348. }
  349. /*++
  350. Restore palette after change
  351. --*/
  352. LONG
  353. APIHOOK(ChangeDisplaySettingsExA)(
  354. LPCSTR lpszDeviceName,
  355. LPDEVMODEA lpDevMode,
  356. HWND hwnd,
  357. DWORD dwFlags,
  358. LPVOID lParam
  359. )
  360. {
  361. LONG lRet = ORIGINAL_API(ChangeDisplaySettingsExA)(
  362. lpszDeviceName,
  363. lpDevMode,
  364. hwnd,
  365. dwFlags,
  366. lParam);
  367. if (lpDevMode)
  368. {
  369. DPFN( eDbgLevelInfo,
  370. "%08lx=ChangeDisplaySettings(%d x %d x %d)",
  371. lRet,
  372. lpDevMode->dmPelsWidth,
  373. lpDevMode->dmPelsHeight,
  374. lpDevMode->dmBitsPerPel);
  375. }
  376. else
  377. {
  378. DPFN( eDbgLevelInfo,
  379. "%08lx=ChangeDisplaySettings Restore",lRet);
  380. }
  381. if (lpDevMode) FixPalette();
  382. return lRet;
  383. }
  384. /*++
  385. Restore palette after change
  386. --*/
  387. LONG
  388. APIHOOK(ChangeDisplaySettingsExW)(
  389. LPCWSTR lpszDeviceName,
  390. LPDEVMODEW lpDevMode,
  391. HWND hwnd,
  392. DWORD dwFlags,
  393. LPVOID lParam
  394. )
  395. {
  396. LONG lRet = ORIGINAL_API(ChangeDisplaySettingsExW)(
  397. lpszDeviceName,
  398. lpDevMode,
  399. hwnd,
  400. dwFlags,
  401. lParam);
  402. if (lpDevMode)
  403. {
  404. DPFN( eDbgLevelInfo,
  405. "%08lx=ChangeDisplaySettings(%d x %d x %d)",
  406. lRet,
  407. lpDevMode->dmPelsWidth,
  408. lpDevMode->dmPelsHeight,
  409. lpDevMode->dmBitsPerPel);
  410. }
  411. else
  412. {
  413. DPFN( eDbgLevelInfo,
  414. "%08lx=ChangeDisplaySettings Restore",lRet);
  415. }
  416. if (lpDevMode) FixPalette();
  417. return lRet;
  418. }
  419. /*++
  420. Track the system palette use
  421. --*/
  422. UINT
  423. APIHOOK(SetSystemPaletteUse)(
  424. HDC hdc,
  425. UINT uUsage
  426. )
  427. {
  428. g_uLastUse = uUsage;
  429. DPFN( eDbgLevelInfo, "SetSystemPaletteUse=%08lx", uUsage);
  430. return ORIGINAL_API(SetSystemPaletteUse)(hdc, uUsage);
  431. }
  432. /*++
  433. Track created palette
  434. --*/
  435. HPALETTE
  436. APIHOOK(CreatePalette)(
  437. CONST LOGPALETTE *lplgpl
  438. )
  439. {
  440. HPALETTE hRet;
  441. hRet = ORIGINAL_API(CreatePalette)(lplgpl);
  442. if (hRet)
  443. {
  444. PALITEM pitem;
  445. pitem.hPal = hRet;
  446. MoveMemory(
  447. &pitem.palPalEntry[0],
  448. &lplgpl->palPalEntry[0],
  449. lplgpl->palNumEntries * sizeof(PALETTEENTRY));
  450. EnterCriticalSection(&g_csLists);
  451. g_palList->Append(pitem);
  452. LeaveCriticalSection(&g_csLists);
  453. }
  454. DPFN( eDbgLevelInfo, "%08lx=CreatePalette", hRet);
  455. return hRet;
  456. }
  457. /*++
  458. Update our private palette with the new entries.
  459. --*/
  460. UINT
  461. APIHOOK(SetPaletteEntries)(
  462. HPALETTE hpal,
  463. UINT iStart,
  464. UINT cEntries,
  465. CONST PALETTEENTRY *lppe
  466. )
  467. {
  468. UINT uRet;
  469. uRet = ORIGINAL_API(SetPaletteEntries)(
  470. hpal,
  471. iStart,
  472. cEntries,
  473. lppe);
  474. if (uRet)
  475. {
  476. EnterCriticalSection(&g_csLists);
  477. PALITEM *pitem = g_palList->Find(hpal);
  478. if (pitem)
  479. {
  480. MoveMemory(
  481. &pitem->palPalEntry[iStart],
  482. lppe,
  483. cEntries * sizeof(PALETTEENTRY));
  484. }
  485. LeaveCriticalSection(&g_csLists);
  486. }
  487. DPFN( eDbgLevelInfo,
  488. "%08lx=SetPaletteEntries(%08lx,%d,%d)",
  489. uRet,
  490. hpal,
  491. iStart,
  492. cEntries);
  493. return uRet;
  494. }
  495. /*++
  496. Update our private palette with the new entries.
  497. --*/
  498. BOOL
  499. APIHOOK(AnimatePalette)(
  500. HPALETTE hpal,
  501. UINT iStartIndex,
  502. UINT cEntries,
  503. CONST PALETTEENTRY *ppe
  504. )
  505. {
  506. BOOL bRet;
  507. UINT ui;
  508. int i;
  509. bRet = ORIGINAL_API(AnimatePalette)(
  510. hpal,
  511. iStartIndex,
  512. cEntries,
  513. ppe);
  514. if (bRet)
  515. {
  516. EnterCriticalSection(&g_csLists);
  517. PALITEM *pitem = g_palList->Find(hpal);
  518. if (pitem)
  519. {
  520. //
  521. // Animate palette only replaces entries with the PC_RESERVED flag
  522. //
  523. PALETTEENTRY *pe = &pitem->palPalEntry[iStartIndex];
  524. for (ui=0; ui<cEntries; ui++)
  525. {
  526. if (pe->peFlags & PC_RESERVED)
  527. {
  528. pe->peRed = ppe->peRed;
  529. pe->peGreen = ppe->peGreen;
  530. pe->peBlue = ppe->peBlue;
  531. }
  532. pe++;
  533. ppe++;
  534. }
  535. //
  536. // Check if this palette will be realized.
  537. // Note: check all DCs since the palette it may have been
  538. // selected into more than 1.
  539. //
  540. for (i=0; i<g_dcList->Size(); i++)
  541. {
  542. DCITEM &ditem = g_dcList->Get(i);
  543. if ((hpal == ditem.hPal) &&
  544. (GetActiveWindow() == ditem.hWnd))
  545. {
  546. MoveMemory(
  547. &g_lastPal[0],
  548. &pitem->palPalEntry[0],
  549. sizeof(g_lastPal));
  550. break;
  551. }
  552. }
  553. }
  554. LeaveCriticalSection(&g_csLists);
  555. }
  556. DPFN( eDbgLevelInfo,
  557. "%08lx=AnimatePalette(%08lx,%d,%d)",
  558. bRet,
  559. hpal,
  560. iStartIndex,
  561. cEntries);
  562. return bRet;
  563. }
  564. /*++
  565. Keep a list of DCs and their associated windows so we can look them up when
  566. we need to find out which DC has which palette.
  567. --*/
  568. HDC
  569. APIHOOK(CreateCompatibleDC)(
  570. HDC hdc
  571. )
  572. {
  573. HDC hRet;
  574. hRet = ORIGINAL_API(CreateCompatibleDC)(hdc);
  575. if (hRet)
  576. {
  577. g_dcList->Add(0, hRet);
  578. }
  579. DPFN( eDbgLevelInfo,
  580. "%08lx=CreateCompatibleDC(%08lx)",
  581. hRet,
  582. hdc);
  583. return hRet;
  584. }
  585. /*++
  586. Keep a list of DCs and their associated windows so we can look them up when
  587. we need to find out which DC has which palette. We only care about CreateDC
  588. if it's passed 'display'
  589. --*/
  590. HDC
  591. APIHOOK(CreateDCA)(
  592. LPCSTR lpszDriver,
  593. LPCSTR lpszDevice,
  594. LPCSTR lpszOutput,
  595. CONST DEVMODEA *lpInitData
  596. )
  597. {
  598. HDC hRet;
  599. hRet = ORIGINAL_API(CreateDCA)(
  600. lpszDriver,
  601. lpszDevice,
  602. lpszOutput,
  603. lpInitData);
  604. if (hRet && (!lpszDriver || (_stricmp(lpszDriver, "DISPLAY") == 0)))
  605. {
  606. g_dcList->Add(0, hRet);
  607. }
  608. DPFN( eDbgLevelInfo,
  609. "%08lx=CreateDCA(%s,%s)",
  610. hRet,
  611. lpszDriver,
  612. lpszDevice);
  613. return hRet;
  614. }
  615. /*++
  616. Keep a list of DCs and their associated windows so we can look them up when
  617. we need to find out which DC has which palette. We only care about CreateDC
  618. if it's passed 'display'
  619. --*/
  620. HDC
  621. APIHOOK(CreateDCW)(
  622. LPCWSTR lpszDriver,
  623. LPCWSTR lpszDevice,
  624. LPCWSTR lpszOutput,
  625. CONST DEVMODEW *lpInitData
  626. )
  627. {
  628. HDC hRet;
  629. hRet = ORIGINAL_API(CreateDCW)(
  630. lpszDriver,
  631. lpszDevice,
  632. lpszOutput,
  633. lpInitData);
  634. if (hRet && (!lpszDriver || (_wcsicmp(lpszDriver, L"DISPLAY") == 0)))
  635. {
  636. g_dcList->Add(0, hRet);
  637. }
  638. DPFN( eDbgLevelInfo,
  639. "%08lx=CreateDCW(%S,%S)",
  640. hRet,
  641. lpszDriver,
  642. lpszDevice);
  643. return hRet;
  644. }
  645. /*++
  646. Remove a DC created with CreateDC
  647. --*/
  648. BOOL
  649. APIHOOK(DeleteDC)(
  650. HDC hdc
  651. )
  652. {
  653. int bRet;
  654. bRet = ORIGINAL_API(DeleteDC)(hdc);
  655. if (bRet)
  656. {
  657. g_dcList->Remove(0, hdc);
  658. }
  659. DPFN( eDbgLevelInfo, "%08lx=DeleteDC(%08lx)", bRet, hdc);
  660. return bRet;
  661. }
  662. /*++
  663. Keep a list of DCs and their associated windows so we can look them up when
  664. we need to find out which DC has which palette.
  665. --*/
  666. HDC
  667. APIHOOK(GetDC)(
  668. HWND hWnd
  669. )
  670. {
  671. HDC hRet;
  672. hRet = ORIGINAL_API(GetDC)(hWnd);
  673. if (hRet)
  674. {
  675. g_dcList->Add(hWnd, hRet);
  676. }
  677. DPFN( eDbgLevelInfo, "%08lx=GetDC(%08lx)", hRet, hWnd);
  678. return hRet;
  679. }
  680. /*++
  681. Keep a list of DCs and their associated windows so we can look them up when
  682. we need to find out which DC has which palette.
  683. --*/
  684. HDC
  685. APIHOOK(GetWindowDC)(
  686. HWND hWnd
  687. )
  688. {
  689. HDC hRet;
  690. hRet = ORIGINAL_API(GetWindowDC)(hWnd);
  691. if (hRet)
  692. {
  693. g_dcList->Add(hWnd, hRet);
  694. }
  695. DPFN( eDbgLevelInfo, "%08lx=GetWindowDC(%08lx)", hRet, hWnd);
  696. return hRet;
  697. }
  698. /*++
  699. Release the DC and remove it from our list
  700. --*/
  701. int
  702. APIHOOK(ReleaseDC)(
  703. HWND hWnd,
  704. HDC hDC
  705. )
  706. {
  707. int iRet;
  708. iRet = ORIGINAL_API(ReleaseDC)(hWnd, hDC);
  709. if (iRet)
  710. {
  711. g_dcList->Remove(hWnd, hDC);
  712. }
  713. DPFN( eDbgLevelInfo, "%08lx=ReleaseDC(%08lx, %08lx)", iRet, hWnd, hDC);
  714. return iRet;
  715. }
  716. /*++
  717. Keep track of which DC the palette lives in.
  718. --*/
  719. HPALETTE
  720. APIHOOK(SelectPalette)(
  721. HDC hdc,
  722. HPALETTE hpal,
  723. BOOL bForceBackground
  724. )
  725. {
  726. HPALETTE hRet;
  727. hRet = ORIGINAL_API(SelectPalette)(
  728. hdc,
  729. hpal,
  730. bForceBackground);
  731. EnterCriticalSection(&g_csLists);
  732. //
  733. // Select this palette into all copies of this DC
  734. //
  735. for (int i=0; i<g_dcList->Size(); i++)
  736. {
  737. DCITEM & ditem = g_dcList->Get(i);
  738. if (hdc == ditem.hDc)
  739. {
  740. ditem.hPal = hpal;
  741. }
  742. }
  743. LeaveCriticalSection(&g_csLists);
  744. DPFN( eDbgLevelInfo, "%08lx=SelectPalette(%08lx, %08lx)", hRet, hdc, hpal);
  745. return hRet;
  746. }
  747. /*++
  748. Stub this for now because of known problems listed at top.
  749. --*/
  750. UINT
  751. APIHOOK(GetSystemPaletteEntries)(
  752. HDC hdc,
  753. UINT iStartIndex,
  754. UINT nEntries,
  755. LPPALETTEENTRY lppe
  756. )
  757. {
  758. UINT uRet;
  759. uRet = ORIGINAL_API(GetSystemPaletteEntries)(
  760. hdc,
  761. iStartIndex,
  762. nEntries,
  763. lppe);
  764. DPFN( eDbgLevelInfo, "%08lx=GetSystemPaletteEntries(%08lx, %08lx, %08lx)", uRet, hdc, iStartIndex, nEntries);
  765. return uRet;
  766. }
  767. /*++
  768. Fill in the last known palette if anything was realized
  769. --*/
  770. UINT
  771. APIHOOK(RealizePalette)(
  772. HDC hdc
  773. )
  774. {
  775. UINT uRet;
  776. uRet = ORIGINAL_API(RealizePalette)(hdc);
  777. if (uRet)
  778. {
  779. EnterCriticalSection(&g_csLists);
  780. //
  781. // Check for all windows of all DCs
  782. //
  783. HWND hwnd = GetActiveWindow();
  784. for (int i=0; i<g_dcList->Size(); i++)
  785. {
  786. DCITEM &ditem = g_dcList->Get(i);
  787. if (hwnd == ditem.hWnd)
  788. {
  789. PALITEM *pitem = g_palList->Find(ditem.hPal);
  790. if (pitem)
  791. {
  792. MoveMemory(
  793. &g_lastPal[0],
  794. &pitem->palPalEntry[0],
  795. sizeof(g_lastPal));
  796. break;
  797. }
  798. }
  799. }
  800. LeaveCriticalSection(&g_csLists);
  801. }
  802. DPFN( eDbgLevelInfo, "%08lx=RealizePalette(%08lx)", uRet, hdc);
  803. return uRet;
  804. }
  805. /*++
  806. Delete palette objects from the list.
  807. --*/
  808. UINT
  809. APIHOOK(DeleteObject)(
  810. HGDIOBJ hObject
  811. )
  812. {
  813. BOOL bRet;
  814. bRet = ORIGINAL_API(DeleteObject)(hObject);
  815. if (bRet)
  816. {
  817. g_palList->Remove((HPALETTE)hObject);
  818. }
  819. return bRet;
  820. }
  821. /*++
  822. Register hooked functions
  823. --*/
  824. BOOL
  825. NOTIFY_FUNCTION(
  826. DWORD fdwReason
  827. )
  828. {
  829. if (fdwReason == DLL_PROCESS_ATTACH)
  830. {
  831. g_palList = new CPalVector;
  832. g_dcList = new CDcVector;
  833. InitializeCriticalSection(&g_csLists);
  834. MoveMemory(&g_lastPal, &g_palDefault, sizeof(g_lastPal));
  835. }
  836. else if (fdwReason == DLL_PROCESS_DETACH)
  837. {
  838. // Can't free since we might still be called
  839. // delete g_palList;
  840. // delete g_dcList;
  841. // DeleteCriticalSection(&g_csLists);
  842. }
  843. return TRUE;
  844. }
  845. HOOK_BEGIN
  846. CALL_NOTIFY_FUNCTION
  847. APIHOOK_ENTRY(USER32.DLL, ChangeDisplaySettingsA);
  848. APIHOOK_ENTRY(USER32.DLL, ChangeDisplaySettingsW);
  849. APIHOOK_ENTRY(USER32.DLL, ChangeDisplaySettingsExA);
  850. APIHOOK_ENTRY(USER32.DLL, ChangeDisplaySettingsExW);
  851. APIHOOK_ENTRY(USER32.DLL, GetDC);
  852. APIHOOK_ENTRY(USER32.DLL, GetWindowDC);
  853. APIHOOK_ENTRY(USER32.DLL, ReleaseDC);
  854. APIHOOK_ENTRY(GDI32.DLL, CreateCompatibleDC);
  855. APIHOOK_ENTRY(GDI32.DLL, CreateDCA);
  856. APIHOOK_ENTRY(GDI32.DLL, CreateDCW);
  857. APIHOOK_ENTRY(GDI32.DLL, DeleteDC);
  858. APIHOOK_ENTRY(GDI32.DLL, SetSystemPaletteUse);
  859. APIHOOK_ENTRY(GDI32.DLL, CreatePalette);
  860. APIHOOK_ENTRY(GDI32.DLL, SetPaletteEntries);
  861. APIHOOK_ENTRY(GDI32.DLL, AnimatePalette);
  862. APIHOOK_ENTRY(GDI32.DLL, SelectPalette);
  863. APIHOOK_ENTRY(GDI32.DLL, GetSystemPaletteEntries);
  864. APIHOOK_ENTRY(GDI32.DLL, RealizePalette);
  865. APIHOOK_ENTRY(GDI32.DLL, DeleteObject);
  866. HOOK_END
  867. IMPLEMENT_SHIM_END