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.

165 lines
4.2 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. ExtractAssociatedIcon.cpp
  5. Abstract:
  6. 32bpp icons do not render into old style metafiles. When an application uses OleGetIconOfFile,
  7. The icons are not rendered. We shim shell32's ExtractAssociatedIcon to return 24bpp icons,
  8. so we don't try to use functions that aren't available in old metafiles.
  9. Notes:
  10. This shim is a general purpose shim.
  11. History:
  12. 07/19/2001 lamadio created
  13. --*/
  14. #include "precomp.h"
  15. IMPLEMENT_SHIM_BEGIN(ExtractAssociatedIcon)
  16. #include "ShimHookMacro.h"
  17. APIHOOK_ENUM_BEGIN
  18. APIHOOK_ENUM_ENTRY(ExtractAssociatedIconW)
  19. APIHOOK_ENUM_ENTRY(ExtractAssociatedIconA)
  20. APIHOOK_ENUM_ENTRY(DrawIcon)
  21. APIHOOK_ENUM_ENTRY(DrawIconEx)
  22. APIHOOK_ENUM_END
  23. HBITMAP CreateDIB(HDC h, WORD depth, int cx, int cy, RGBQUAD** pprgb)
  24. {
  25. BITMAPINFO bi = {0};
  26. bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
  27. bi.bmiHeader.biWidth = cx;
  28. bi.bmiHeader.biHeight = cy;
  29. bi.bmiHeader.biPlanes = 1;
  30. bi.bmiHeader.biBitCount = depth;
  31. bi.bmiHeader.biCompression = BI_RGB;
  32. return CreateDIBSection(h, &bi, DIB_RGB_COLORS, (void**)pprgb, NULL, 0);
  33. }
  34. // Strip a 32bbp icon of it's alpha channel
  35. HICON StripIcon(HICON hicon, BOOL fDestroyOriginal)
  36. {
  37. // Get the original bitmaps. Don't forget to delete them
  38. ICONINFO ii;
  39. if (GetIconInfo(hicon, &ii))
  40. {
  41. // Make sure we have a good height and width.
  42. BITMAP bm;
  43. GetObject(ii.hbmColor, sizeof(bm), &bm);
  44. HDC hdcNew = CreateCompatibleDC(NULL);
  45. HDC hdcSrc = CreateCompatibleDC(NULL);
  46. if (hdcNew && hdcSrc)
  47. {
  48. // Create a 24bpp icon. This strips the alpha channel
  49. RGBQUAD* prgb;
  50. HBITMAP hbmpNew = CreateDIB(hdcNew, 24, bm.bmWidth, bm.bmHeight, &prgb);
  51. if (hbmpNew)
  52. {
  53. HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcNew, hbmpNew);
  54. HBITMAP hbmpOld2 = (HBITMAP)SelectObject(hdcSrc, ii.hbmColor);
  55. // Copy from 32bpp to 24bpp.
  56. BitBlt(hdcNew, 0, 0, bm.bmWidth, bm.bmHeight, hdcSrc, 0, 0, SRCCOPY);
  57. SelectObject(hdcSrc, hbmpOld2);
  58. SelectObject(hdcNew, hbmpOld);
  59. // Delete the original bitmap
  60. DeleteObject(ii.hbmColor);
  61. // and return the new one
  62. ii.hbmColor = hbmpNew;
  63. }
  64. }
  65. if (hdcNew)
  66. DeleteDC(hdcNew);
  67. if (hdcSrc)
  68. DeleteDC(hdcSrc);
  69. // Now, create the new icon from the 16bpp image and the mask.
  70. HICON hiconStripped = CreateIconIndirect(&ii);
  71. if (hiconStripped)
  72. {
  73. if (fDestroyOriginal)
  74. DestroyIcon(hicon);
  75. hicon = hiconStripped;
  76. }
  77. // Don't forget to clean up.
  78. DeleteObject(ii.hbmColor);
  79. DeleteObject(ii.hbmMask);
  80. }
  81. return hicon;
  82. }
  83. HICON APIHOOK(ExtractAssociatedIconA)(HINSTANCE hInst, LPSTR lpIconPath, LPWORD lpiIcon)
  84. {
  85. HICON hicon = ORIGINAL_API(ExtractAssociatedIconA)(hInst, lpIconPath, lpiIcon);
  86. return StripIcon(hicon, TRUE);
  87. }
  88. HICON APIHOOK(ExtractAssociatedIconW)(HINSTANCE hInst, LPWSTR lpIconPath, LPWORD lpiIcon)
  89. {
  90. HICON hicon = ORIGINAL_API(ExtractAssociatedIconW)(hInst, lpIconPath, lpiIcon);
  91. return StripIcon(hicon, TRUE);
  92. }
  93. BOOL APIHOOK(DrawIcon)(HDC hDC, int X, int Y, HICON hIcon)
  94. {
  95. HICON hIconNew = StripIcon(hIcon, FALSE);
  96. BOOL b = ORIGINAL_API(DrawIcon)(hDC, X, Y, hIconNew);
  97. DestroyIcon(hIconNew);
  98. return b;
  99. }
  100. BOOL APIHOOK(DrawIconEx)(HDC hDC, int X, int Y, HICON hIcon, int cxWidth, int cyHeight, UINT istepIfAniCur,
  101. HBRUSH hbrFlickerFreeDraw, UINT diFlags)
  102. {
  103. HICON hIconNew = StripIcon(hIcon, FALSE);
  104. BOOL b = ORIGINAL_API(DrawIconEx)(hDC, X, Y, hIconNew, cxWidth, cyHeight, istepIfAniCur,
  105. hbrFlickerFreeDraw, diFlags);
  106. DestroyIcon(hIconNew);
  107. return b;
  108. }
  109. /*++
  110. Register hooked functions
  111. --*/
  112. HOOK_BEGIN
  113. APIHOOK_ENTRY(SHELL32.DLL, ExtractAssociatedIconA)
  114. APIHOOK_ENTRY(SHELL32.DLL, ExtractAssociatedIconW)
  115. APIHOOK_ENTRY(USER32.DLL, DrawIcon)
  116. APIHOOK_ENTRY(USER32.DLL, DrawIconEx)
  117. HOOK_END
  118. IMPLEMENT_SHIM_END