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.

131 lines
3.7 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. EmulateClipboardDIBFormat.cpp
  5. Abstract:
  6. On Win9x when you copy a high color bitmap onto the clipboard, it always
  7. gets converted to a 24-bit DIB when you ask the clipboard for CF_DIB
  8. format. On NT the conversion doesn't happen. So some apps are only
  9. designed to handle 8-bit and 24-bit DIBs (example, Internet Commsuite).
  10. So we convert the high-color (16-bit and 32-bit) DIBs to 24-bit DIBs
  11. - we don't need to handle 24-bit ones as they should already be handled
  12. by the app itself (or it won't work on 9x).
  13. Notes:
  14. This is a general purpose shim.
  15. History:
  16. 01/24/2001 maonis Created
  17. --*/
  18. #include "precomp.h"
  19. //#include <userenv.h>
  20. IMPLEMENT_SHIM_BEGIN(EmulateClipboardDIBFormat)
  21. #include "ShimHookMacro.h"
  22. typedef HANDLE (*_pfn_GetClipboardData)(UINT);
  23. typedef BOOL (*_pfn_CloseClipboard)(VOID);
  24. APIHOOK_ENUM_BEGIN
  25. APIHOOK_ENUM_ENTRY(GetClipboardData)
  26. APIHOOK_ENUM_ENTRY(CloseClipboard)
  27. APIHOOK_ENUM_END
  28. BITMAPINFOHEADER* g_pv = NULL;
  29. DWORD CalcBitmapSize(BITMAPINFOHEADER* pbih)
  30. {
  31. return pbih->biWidth * pbih->biHeight * pbih->biBitCount / 8;
  32. }
  33. HANDLE
  34. APIHOOK(GetClipboardData)(
  35. UINT uFormat // clipboard format
  36. )
  37. {
  38. if (uFormat == CF_DIB)
  39. {
  40. BITMAPINFO* pbmiOriginal = (BITMAPINFO*)ORIGINAL_API(GetClipboardData)(uFormat);
  41. if ((pbmiOriginal->bmiHeader.biBitCount > 8) && (pbmiOriginal->bmiHeader.biBitCount != 24))
  42. {
  43. HDC hdc = CreateCompatibleDC(NULL);
  44. if (hdc)
  45. {
  46. VOID* pvOriginal;
  47. HBITMAP hbmpOriginal = CreateDIBSection(hdc, pbmiOriginal, DIB_RGB_COLORS, &pvOriginal, NULL, 0);
  48. if (hbmpOriginal)
  49. {
  50. DWORD* pdwOriginal = (DWORD *)(pbmiOriginal + 1) +
  51. ((pbmiOriginal->bmiHeader.biCompression == BI_BITFIELDS) ? 2 : -1);
  52. // Fill in the data.
  53. memcpy(pvOriginal, pdwOriginal, CalcBitmapSize(&(pbmiOriginal->bmiHeader)));
  54. BITMAPINFOHEADER bmi;
  55. memcpy(&bmi, pbmiOriginal, sizeof(BITMAPINFOHEADER));
  56. bmi.biBitCount = 24;
  57. bmi.biSizeImage = 0;
  58. bmi.biCompression = BI_RGB;
  59. if (GetDIBits(hdc, hbmpOriginal, 0, bmi.biHeight, NULL, (BITMAPINFO*)&bmi, DIB_RGB_COLORS))
  60. {
  61. // We need to allocate a contiguous block of memory to hold both the
  62. // bitmap header and the data.
  63. g_pv = (BITMAPINFOHEADER*) new BYTE [sizeof(BITMAPINFOHEADER) + bmi.biSizeImage];
  64. if (g_pv)
  65. {
  66. memcpy(g_pv, &bmi, sizeof(BITMAPINFOHEADER));
  67. if (GetDIBits(hdc, hbmpOriginal, 0, bmi.biHeight, g_pv + 1, (BITMAPINFO*)&bmi, DIB_RGB_COLORS))
  68. {
  69. return (HANDLE)g_pv;
  70. }
  71. }
  72. }
  73. DeleteObject(hbmpOriginal);
  74. }
  75. DeleteDC(hdc);
  76. }
  77. }
  78. }
  79. return ORIGINAL_API(GetClipboardData)(uFormat);
  80. }
  81. BOOL
  82. APIHOOK(CloseClipboard)(
  83. VOID
  84. )
  85. {
  86. if (g_pv)
  87. {
  88. delete g_pv;
  89. g_pv = NULL;
  90. }
  91. return ORIGINAL_API(CloseClipboard)();
  92. }
  93. HOOK_BEGIN
  94. APIHOOK_ENTRY(USER32.DLL, GetClipboardData)
  95. APIHOOK_ENTRY(USER32.DLL, CloseClipboard)
  96. HOOK_END
  97. IMPLEMENT_SHIM_END