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.

1111 lines
24 KiB

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