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.

133 lines
3.7 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. HeroSDVD.cpp
  5. Abstract:
  6. Background: clicking the nonclient close button when a movie clip is playing causes the app
  7. to hang and then AV when themes are active. The DisableThemes shim has no effect.
  8. This is related to the app's repeated calls to SetClassLong(hwnd, GCL_HICON) in order to produce
  9. the effect of an animated window icon. This generates frequent requests to redraw the window's icon,
  10. which in turn generates the NCUAHDRAWCAPTION. This is a huge perf hit to the app in any case,
  11. but particularly if the SetClassLong call makes an extra round trip to user mode and back as a
  12. result of the SendMessage.
  13. When the user hits the Close button, the app's WM_SYSCOMMAND handler resets an event that is waited
  14. on by the icon-transitioning thread, and then puts himself (the UI thread) to sleep.
  15. Then he calls SetClassLong(..., GCL_ICON) one last time from the icon-switching thread,
  16. which hangs the app because the message-pumping thread is sleeping. This does not repro when win32k
  17. doesn't send the NCUAHDRAWCAPTION message; i.e., when user API hooks are not active.
  18. The DisableTheme does not work because this shim operates in user mode on a per-process basis.
  19. This shim has no effect on win32k, which does special processing on a session-wide basis when themes are enabled.
  20. To address this, we shim this app to nop on SetClassLong(..., GCL_HICON), which means the app at
  21. best loses animation of the icon and at worst display a bogus icon when themes are active,
  22. Notes:
  23. This is an app specific shim.
  24. History:
  25. 05/11/2001 scotthan Created
  26. --*/
  27. #include "precomp.h"
  28. IMPLEMENT_SHIM_BEGIN(HeroSDVD)
  29. #include "ShimHookMacro.h"
  30. APIHOOK_ENUM_BEGIN
  31. APIHOOK_ENUM_ENTRY(SetClassLongA)
  32. APIHOOK_ENUM_END
  33. typedef BOOL (STDAPICALLTYPE * PFNTHEMEACTIVE)(void);
  34. PFNTHEMEACTIVE g_pfnThemeActive;
  35. HINSTANCE g_hinstUxtheme;
  36. HINSTANCE LoadUxTheme()
  37. {
  38. if( NULL == g_hinstUxtheme )
  39. {
  40. HINSTANCE hinst = LoadLibrary(TEXT("UxTheme.dll"));
  41. if( NULL != hinst )
  42. {
  43. if( InterlockedCompareExchangePointer( (PVOID*)&g_hinstUxtheme, hinst, NULL ) )
  44. {
  45. FreeLibrary(hinst); // already loaded.
  46. }
  47. }
  48. }
  49. return g_hinstUxtheme;
  50. }
  51. DWORD
  52. APIHOOK(SetClassLongA)(
  53. IN HWND hwnd,
  54. IN int nIndex,
  55. IN LONG dwNewLong
  56. )
  57. {
  58. if( GCL_HICON == nIndex )
  59. {
  60. if( NULL == g_pfnThemeActive )
  61. {
  62. HINSTANCE hinst = LoadUxTheme();
  63. if( hinst )
  64. {
  65. g_pfnThemeActive = (PFNTHEMEACTIVE)GetProcAddress( hinst, "IsThemeActive" );
  66. }
  67. }
  68. if( g_pfnThemeActive && g_pfnThemeActive() )
  69. {
  70. // no-op the request to change icon, and return the current one.
  71. return GetClassLongA(hwnd, nIndex);
  72. }
  73. }
  74. return ORIGINAL_API(SetClassLongA)(hwnd, nIndex, dwNewLong);
  75. }
  76. /*++
  77. Register hooked functions
  78. --*/
  79. BOOL
  80. NOTIFY_FUNCTION(
  81. DWORD fdwReason)
  82. {
  83. if( DLL_PROCESS_ATTACH == fdwReason )
  84. {
  85. g_hinstUxtheme = NULL;
  86. g_pfnThemeActive = NULL;
  87. }
  88. else if( DLL_PROCESS_DETACH == fdwReason )
  89. {
  90. if( g_hinstUxtheme )
  91. {
  92. FreeLibrary(g_hinstUxtheme);
  93. g_hinstUxtheme = NULL;
  94. }
  95. g_pfnThemeActive = NULL;
  96. }
  97. return TRUE;
  98. }
  99. HOOK_BEGIN
  100. CALL_NOTIFY_FUNCTION
  101. APIHOOK_ENTRY(USER32.DLL, SetClassLongA )
  102. HOOK_END
  103. IMPLEMENT_SHIM_END