Windows2000/private/shell/comctl32/apithk.c
2020-09-30 17:12:32 +02:00

277 lines
7.1 KiB
C

// APITHK.C
// This file has API thunks that allow comctl32 to load and run on
// multiple versions of NT or Win95. Since this component needs
// to load on the base-level NT 4.0 and Win95, any calls to system
// APIs introduced in later OS versions must be done via GetProcAddress.
// Also, any code that may need to access data structures that are
// post-4.0 specific can be added here.
// NOTE: this file does *not* use the standard precompiled header,
// so it can set _WIN32_WINNT to a later version.
#include "ctlspriv.h" // Don't use precompiled header here
typedef BOOL (* PFNANIMATEWINDOW)(HWND hwnd, DWORD dwTime, DWORD dwFlags);
/*
Purpose: Thunk for NT 5's AnimateWindow.
Returns:
Cond: --
*/
BOOL
NT5_AnimateWindow(
IN HWND hwnd,
IN DWORD dwTime,
IN DWORD dwFlags)
{
BOOL bRet = FALSE;
static PFNANIMATEWINDOW pfn = NULL;
if (NULL == pfn)
{
HMODULE hmod = GetModuleHandle(TEXT("USER32"));
if (hmod)
pfn = (PFNANIMATEWINDOW)GetProcAddress(hmod, "AnimateWindow");
}
if (pfn)
bRet = pfn(hwnd, dwTime, dwFlags);
return bRet;
}
/*
Purpose: Shows the tooltip. On NT4/Win95, this is a standard
show window. On NT5/Memphis, this slides the tooltip
bubble from an invisible point.
Returns: --
Cond: --
*/
#define CMS_TOOLTIP 135
void SlideAnimate(HWND hwnd, LPCRECT prc)
{
DWORD dwPos, dwFlags;
dwPos = GetMessagePos();
if (GET_Y_LPARAM(dwPos) > prc->top + (prc->bottom - prc->top) / 2)
{
dwFlags = AW_VER_NEGATIVE;
}
else
{
dwFlags = AW_VER_POSITIVE;
}
AnimateWindow(hwnd, CMS_TOOLTIP, dwFlags | AW_SLIDE);
}
STDAPI_(void) CoolTooltipBubble(IN HWND hwnd, IN LPCRECT prc, BOOL fAllowFade, BOOL fAllowAnimate)
{
ASSERT(prc);
if (g_bRunOnNT5 || g_bRunOnMemphis)
{
#ifdef WINNT
BOOL fAnimate = TRUE;
SystemParametersInfo(SPI_GETTOOLTIPANIMATION, 0, &fAnimate, 0);
#else
// Memphis doesn't support the tooltip SPI's, so we piggyback
// off of SPI_GETSCREENREADER instead. Note that we want to
// animate if SPI_GETSCREENREADER is >off<, so we need to do some
// flippery. Fortunately, the compiler will optimize all this out.
BOOL fScreenRead = FALSE;
BOOL fAnimate;
SystemParametersInfo(SPI_GETSCREENREADER, 0, &fScreenRead, 0);
fAnimate = !fScreenRead;
#endif
if (fAnimate)
{
fAnimate = FALSE;
#ifdef WINNT
SystemParametersInfo(SPI_GETTOOLTIPFADE, 0, &fAnimate, 0);
#endif // WINNT
if (fAnimate && fAllowFade)
{
AnimateWindow(hwnd, CMS_TOOLTIP, AW_BLEND);
}
else if (fAllowAnimate)
{
SlideAnimate(hwnd, prc);
}
else
goto UseSetWindowPos;
}
else
goto UseSetWindowPos;
}
else
{
UseSetWindowPos:
SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
SWP_NOACTIVATE|SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
}
}
/*
Purpose: Get the COLOR_HOTLIGHT system color index from NT5 or Memphis.
Get COLOR_HIGHLIGHT from NT4 or Win95, where COLOR_HOTLIGHT is not defined.
Returns: --
Cond: --
*/
int GetCOLOR_HOTLIGHT()
{
return (g_bRunOnNT5 || g_bRunOnMemphis) ? COLOR_HOTLIGHT : COLOR_HIGHLIGHT;
}
STDAPI_(HCURSOR) LoadHandCursor(DWORD dwRes)
{
if (g_bRunOnNT5 || g_bRunOnMemphis)
{
HCURSOR hcur = LoadCursor(NULL, IDC_HAND); // from USER, system supplied
if (hcur)
return hcur;
}
return LoadCursor(HINST_THISDLL, MAKEINTRESOURCE(IDC_HAND_INTERNAL));
}
typedef BOOL (*PFNQUEUEUSERWORKITEM)(LPTHREAD_START_ROUTINE Function,
PVOID Context, BOOL PreferIo);
STDAPI_(BOOL) NT5_QueueUserWorkItem(LPTHREAD_START_ROUTINE Function,
PVOID Context, BOOL PreferIo)
{
BOOL bRet = FALSE;
static PFNQUEUEUSERWORKITEM pfn = (PFNQUEUEUSERWORKITEM)-1;
if ((PFNQUEUEUSERWORKITEM)-1 == pfn)
{
HMODULE hmod = GetModuleHandle(TEXT("KERNEL32"));
if (hmod)
pfn = (PFNQUEUEUSERWORKITEM)GetProcAddress(hmod, "QueueUserWorkItem");
else
pfn = NULL;
}
if (pfn)
bRet = pfn( Function, Context, PreferIo);
return bRet;
}
// Here's how CAL_ITWODIGITYEARMAX works.
// If a two-digit year is input from the user, we put it into the range
// (N-99) ... N. for example, if the maximum value is 2029, then all
// two-digit numbers will be coerced into the range 1930 through 2029.
// Win95 and NT4 don't have GetCalendarInfo, but they do have
// EnumCalendarInfo, so you'd think we could avoid the GetProcAddress
// by enumerating the one calendar we care about.
// Unfortunately, Win98 has a bug where EnumCalendarInfo can't enumerate
// the maximum two-digit year value! What a lamer!
// So we're stuck with GetProcAddress.
// But wait, Win98 exports GetCalendarInfoW but doesn't implement it!
// Double lame!
// So we have to use the Ansi version exclusively. Fortunately, we
// are only interested in numbers (so far) so there is no loss of amenity.
// First, here's the dummy function that emulates GetCalendarInfoA
// on Win95 and NT4.
STDAPI_(int)
Emulate_GetCalendarInfoA(LCID lcid, CALID calid, CALTYPE cal,
LPSTR pszBuf, int cchBuf, LPDWORD pdwOut)
{
// In the absence of the API, we go straight for the information
// in the registry.
BOOL fSuccess = FALSE;
HKEY hkey;
ASSERT(cal == CAL_RETURN_NUMBER + CAL_ITWODIGITYEARMAX);
ASSERT(pszBuf == NULL);
ASSERT(cchBuf == 0);
if (RegOpenKeyExA(HKEY_CURRENT_USER, "Control Panel\\International\\Calendars\\TwoDigitYearMax", 0, KEY_READ, &hkey) == ERROR_SUCCESS)
{
char szKey[16];
char szBuf[64];
DWORD dwSize;
wsprintfA(szKey, "%d", calid);
dwSize = sizeof(szBuf);
if (RegQueryValueExA(hkey, szKey, 0, NULL, (LPBYTE)szBuf, &dwSize) == ERROR_SUCCESS)
{
*pdwOut = StrToIntA(szBuf);
fSuccess = TRUE;
}
RegCloseKey(hkey);
}
return fSuccess;
}
typedef int (CALLBACK *GETCALENDARINFOA)(LCID, CALID, CALTYPE, LPSTR, int, LPDWORD);
GETCALENDARINFOA _GetCalendarInfoA;
STDAPI_(int)
NT5_GetCalendarInfoA(LCID lcid, CALID calid, CALTYPE cal,
LPSTR pszBuf, int cchBuf, LPDWORD pdwOut)
{
// This is the only function our emulator supports
ASSERT(cal == CAL_RETURN_NUMBER + CAL_ITWODIGITYEARMAX);
ASSERT(pszBuf == NULL);
ASSERT(cchBuf == 0);
if (_GetCalendarInfoA == NULL)
{
HMODULE hmod = GetModuleHandle(TEXT("KERNEL32"));
// Must keep in a local to avoid thread races.
GETCALENDARINFOA pfn = NULL;
if (hmod)
pfn = (GETCALENDARINFOA)
GetProcAddress(hmod, "GetCalendarInfoA");
// If function is not available, then use our fallback
if (pfn == NULL)
pfn = Emulate_GetCalendarInfoA;
ASSERT(pfn != NULL);
_GetCalendarInfoA = pfn;
}
return _GetCalendarInfoA(lcid, calid, cal, pszBuf, cchBuf, pdwOut);
}