apithk.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 8k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //
  2. //  APITHK.C
  3. //
  4. //  This file has API thunks that allow comctl32 to load and run on
  5. //  multiple versions of NT or Win95.  Since this component needs
  6. //  to load on the base-level NT 4.0 and Win95, any calls to system
  7. //  APIs introduced in later OS versions must be done via GetProcAddress.
  8. // 
  9. //  Also, any code that may need to access data structures that are
  10. //  post-4.0 specific can be added here.
  11. //
  12. //  NOTE:  this file does *not* use the standard precompiled header,
  13. //         so it can set _WIN32_WINNT to a later version.
  14. //
  15. #include "ctlspriv.h"       // Don't use precompiled header here
  16. typedef BOOL (* PFNANIMATEWINDOW)(HWND hwnd, DWORD dwTime, DWORD dwFlags);
  17. /*----------------------------------------------------------
  18. Purpose: Thunk for NT 5's AnimateWindow.
  19. Returns: 
  20. Cond:    --
  21. */
  22. BOOL
  23. NT5_AnimateWindow(
  24.     IN HWND hwnd,
  25.     IN DWORD dwTime,
  26.     IN DWORD dwFlags)
  27. {
  28.     BOOL bRet = FALSE;
  29.     static PFNANIMATEWINDOW pfn = NULL;
  30.     if (NULL == pfn)
  31.     {
  32.         HMODULE hmod = GetModuleHandle(TEXT("USER32"));
  33.         
  34.         if (hmod)
  35.             pfn = (PFNANIMATEWINDOW)GetProcAddress(hmod, "AnimateWindow");
  36.     }
  37.     if (pfn)
  38.         bRet = pfn(hwnd, dwTime, dwFlags);
  39.     return bRet;    
  40. }
  41. /*----------------------------------------------------------
  42. Purpose: Shows the tooltip.  On NT4/Win95, this is a standard
  43.          show window.  On NT5/Memphis, this slides the tooltip
  44.          bubble from an invisible point.
  45. Returns: --
  46. Cond:    --
  47. */
  48. #define CMS_TOOLTIP 135
  49. void SlideAnimate(HWND hwnd, LPCRECT prc)
  50. {
  51.     DWORD dwPos, dwFlags;
  52.     dwPos = GetMessagePos();
  53.     if (GET_Y_LPARAM(dwPos) > prc->top + (prc->bottom - prc->top) / 2)
  54.     {
  55.         dwFlags = AW_VER_NEGATIVE;
  56.     } 
  57.     else
  58.     {
  59.         dwFlags = AW_VER_POSITIVE;
  60.     }
  61.     AnimateWindow(hwnd, CMS_TOOLTIP, dwFlags | AW_SLIDE);
  62. }
  63. STDAPI_(void) CoolTooltipBubble(IN HWND hwnd, IN LPCRECT prc, BOOL fAllowFade, BOOL fAllowAnimate)
  64. {
  65.     ASSERT(prc);
  66.     if (g_bRunOnNT5 || g_bRunOnMemphis)
  67.     {
  68. #ifdef WINNT
  69.         BOOL fAnimate = TRUE;
  70.         SystemParametersInfo(SPI_GETTOOLTIPANIMATION, 0, &fAnimate, 0);
  71. #else
  72.         // Memphis doesn't support the tooltip SPI's, so we piggyback
  73.         // off of SPI_GETSCREENREADER instead.  Note that we want to
  74.         // animate if SPI_GETSCREENREADER is >off<, so we need to do some
  75.         // flippery.  Fortunately, the compiler will optimize all this out.
  76.         BOOL fScreenRead = FALSE;
  77.         BOOL fAnimate;
  78.         SystemParametersInfo(SPI_GETSCREENREADER, 0, &fScreenRead, 0);
  79.         fAnimate = !fScreenRead;
  80. #endif
  81.         if (fAnimate)
  82.         {
  83.             fAnimate = FALSE;
  84. #ifdef WINNT
  85.             SystemParametersInfo(SPI_GETTOOLTIPFADE, 0, &fAnimate, 0);
  86. #endif // WINNT
  87.             if (fAnimate && fAllowFade)
  88.             {
  89.                 AnimateWindow(hwnd, CMS_TOOLTIP, AW_BLEND);
  90.             }
  91.             else if (fAllowAnimate)
  92.             {
  93.                 SlideAnimate(hwnd, prc);
  94.             }
  95.             else
  96.                 goto UseSetWindowPos;
  97.         }
  98.         else
  99.             goto UseSetWindowPos;
  100.     }
  101.     else
  102.     {
  103. UseSetWindowPos:
  104.         SetWindowPos(hwnd, NULL, 0, 0, 0, 0, 
  105.                      SWP_NOACTIVATE|SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
  106.     }
  107. }
  108. /*----------------------------------------------------------
  109. Purpose: Get the COLOR_HOTLIGHT system color index from NT5 or Memphis.
  110.          Get COLOR_HIGHLIGHT from NT4 or Win95, where COLOR_HOTLIGHT is not defined.
  111. Returns: --
  112. Cond:    --
  113. */
  114. int GetCOLOR_HOTLIGHT()
  115. {
  116.     return (g_bRunOnNT5 || g_bRunOnMemphis) ? COLOR_HOTLIGHT : COLOR_HIGHLIGHT;
  117. }
  118. STDAPI_(HCURSOR) LoadHandCursor(DWORD dwRes)
  119. {
  120.     if (g_bRunOnNT5 || g_bRunOnMemphis)
  121.     {
  122.         HCURSOR hcur = LoadCursor(NULL, IDC_HAND);  // from USER, system supplied
  123.         if (hcur)
  124.             return hcur;
  125.     }
  126.     return LoadCursor(HINST_THISDLL, MAKEINTRESOURCE(IDC_HAND_INTERNAL));
  127. }
  128. typedef BOOL (*PFNQUEUEUSERWORKITEM)(LPTHREAD_START_ROUTINE Function,
  129.     PVOID Context, BOOL PreferIo);
  130. STDAPI_(BOOL) NT5_QueueUserWorkItem(LPTHREAD_START_ROUTINE Function,
  131.     PVOID Context, BOOL PreferIo)
  132. {
  133.     BOOL bRet = FALSE;
  134.     static PFNQUEUEUSERWORKITEM pfn = (PFNQUEUEUSERWORKITEM)-1;
  135.     if ((PFNQUEUEUSERWORKITEM)-1 == pfn)
  136.     {
  137.         HMODULE hmod = GetModuleHandle(TEXT("KERNEL32"));
  138.         
  139.         if (hmod)
  140.             pfn = (PFNQUEUEUSERWORKITEM)GetProcAddress(hmod, "QueueUserWorkItem");
  141.         else
  142.             pfn = NULL;
  143.     }
  144.     if (pfn)
  145.         bRet = pfn( Function, Context, PreferIo);
  146.     return bRet;    
  147. }
  148. //
  149. //  Here's how CAL_ITWODIGITYEARMAX works.
  150. //
  151. //  If a two-digit year is input from the user, we put it into the range
  152. //  (N-99) ... N.  for example, if the maximum value is 2029, then all
  153. //  two-digit numbers will be coerced into the range 1930 through 2029.
  154. //
  155. //  Win95 and NT4 don't have GetCalendarInfo, but they do have
  156. //  EnumCalendarInfo, so you'd think we could avoid the GetProcAddress
  157. //  by enumerating the one calendar we care about.
  158. //
  159. //  Unfortunately, Win98 has a bug where EnumCalendarInfo can't enumerate
  160. //  the maximum two-digit year value!  What a lamer!
  161. //
  162. //  So we're stuck with GetProcAddress.
  163. //
  164. //  But wait, Win98 exports GetCalendarInfoW but doesn't implement it!
  165. //  Double lame!
  166. //
  167. //  So we have to use the Ansi version exclusively.  Fortunately, we
  168. //  are only interested in numbers (so far) so there is no loss of amenity.
  169. //
  170. //  First, here's the dummy function that emulates GetCalendarInfoA
  171. //  on Win95 and NT4.
  172. //
  173. STDAPI_(int)
  174. Emulate_GetCalendarInfoA(LCID lcid, CALID calid, CALTYPE cal,
  175.                          LPSTR pszBuf, int cchBuf, LPDWORD pdwOut)
  176. {
  177.     //
  178.     //  In the absence of the API, we go straight for the information
  179.     //  in the registry.
  180.     //
  181.     BOOL fSuccess = FALSE;
  182.     HKEY hkey;
  183.     ASSERT(cal == CAL_RETURN_NUMBER + CAL_ITWODIGITYEARMAX);
  184.     ASSERT(pszBuf == NULL);
  185.     ASSERT(cchBuf == 0);
  186.     if (RegOpenKeyExA(HKEY_CURRENT_USER,
  187.                       "Control Panel\International\Calendars\TwoDigitYearMax",
  188.                       0, KEY_READ, &hkey) == ERROR_SUCCESS)
  189.     {
  190.         char szKey[16];
  191.         char szBuf[64];
  192.         DWORD dwSize;
  193.         wsprintfA(szKey, "%d", calid);
  194.         dwSize = sizeof(szBuf);
  195.         if (RegQueryValueExA(hkey, szKey, 0, NULL, (LPBYTE)szBuf, &dwSize) == ERROR_SUCCESS)
  196.         {
  197.             *pdwOut = StrToIntA(szBuf);
  198.             fSuccess = TRUE;
  199.         }
  200.         RegCloseKey(hkey);
  201.     }
  202.     return fSuccess;
  203. }
  204. typedef int (CALLBACK *GETCALENDARINFOA)(LCID, CALID, CALTYPE, LPSTR, int, LPDWORD);
  205. GETCALENDARINFOA _GetCalendarInfoA;
  206. STDAPI_(int)
  207. NT5_GetCalendarInfoA(LCID lcid, CALID calid, CALTYPE cal,
  208.                      LPSTR pszBuf, int cchBuf, LPDWORD pdwOut)
  209. {
  210.     // This is the only function our emulator supports
  211.     ASSERT(cal == CAL_RETURN_NUMBER + CAL_ITWODIGITYEARMAX);
  212.     ASSERT(pszBuf == NULL);
  213.     ASSERT(cchBuf == 0);
  214.     if (_GetCalendarInfoA == NULL)
  215.     {
  216.         HMODULE hmod = GetModuleHandle(TEXT("KERNEL32"));
  217.         //
  218.         //  Must keep in a local to avoid thread races.
  219.         //
  220.         GETCALENDARINFOA pfn = NULL;
  221.         if (hmod)
  222.             pfn = (GETCALENDARINFOA)
  223.                     GetProcAddress(hmod, "GetCalendarInfoA");
  224.         //
  225.         //  If function is not available, then use our fallback
  226.         //
  227.         if (pfn == NULL)
  228.             pfn = Emulate_GetCalendarInfoA;
  229.         ASSERT(pfn != NULL);
  230.         _GetCalendarInfoA = pfn;
  231.     }
  232.     return _GetCalendarInfoA(lcid, calid, cal, pszBuf, cchBuf, pdwOut);
  233. }