windows-nt/Source/XPSP1/NT/shell/browseui/apithk.c
2020-09-26 16:20:57 +08:00

462 lines
12 KiB
C

#ifdef UNICODE
#error start menu won't run on win95 if this apithk.c is compiled unicode
#endif
//
// APITHK.C
//
// This file has API thunks that allow shdocvw 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 "priv.h" // Don't use precompiled header here
#include "uxtheme.h"
HINSTANCE GetComctl32Hinst()
{
static HINSTANCE s_hinst = NULL;
if (!s_hinst)
s_hinst = GetModuleHandle(TEXT("comctl32.dll"));
return s_hinst;
}
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(GetComctl32Hinst(), IDC_HAND_INTERNAL);
}
/*----------------------------------------------------------
Purpose: Use the Microsoft ActiveAccessiblity routines to
notify Accessibility programs of events
*/
typedef void (* PFNNOTIFYWINEVENT)(DWORD event, HWND hwnd, LONG idObject, LONG idChild);
#define DONOTHING_WINEVENT (PFNNOTIFYWINEVENT)1
void NT5_NotifyWinEvent(
IN DWORD event,
IN HWND hwnd,
IN LONG idObject,
IN LONG idChild)
{
static PFNNOTIFYWINEVENT pfn = NULL;
if (NULL == pfn)
{
HMODULE hmod = GetModuleHandle(TEXT("USER32"));
if (hmod)
pfn = (PFNNOTIFYWINEVENT)GetProcAddress(hmod, "NotifyWinEvent");
if (!pfn)
pfn = DONOTHING_WINEVENT;
}
if (pfn != DONOTHING_WINEVENT)
pfn(event, hwnd, idObject, idChild);
}
// Use the Microsoft ActiveAccessiblity routines to return an IAccessible object
typedef LRESULT (* PFNLRESULTFROMOBJECT)(REFIID riid, WPARAM wParam, IUnknown* punk);
LRESULT ACCESSIBLE_LresultFromObject(
IN REFIID riid,
IN WPARAM wParam,
OUT IUnknown* punk)
{
static PFNLRESULTFROMOBJECT pfn = NULL;
static BOOL fLoadAttempted = FALSE;
LRESULT lRet = (LRESULT)E_FAIL;
if (NULL == pfn && !fLoadAttempted)
{
// LoadLibrary here because OLEAcc is not loaded in the process
HMODULE hmod = LoadLibrary(TEXT("OLEACC"));
if (hmod)
pfn = (PFNLRESULTFROMOBJECT)GetProcAddress(hmod, "LresultFromObject");
else
fLoadAttempted = TRUE;
}
if (pfn)
lRet = pfn(riid, wParam, punk);
return lRet;
}
// wrapper for NT5/Millennium AllowSetForegroundWindow
typedef BOOL (* PFNALLOWSFW)(DWORD dwProcessId);
BOOL NT5_AllowSetForegroundWindow(IN DWORD dwProcessId )
{
static PFNALLOWSFW pfn = (PFNALLOWSFW)-1;
if (((PFNALLOWSFW)-1) == pfn)
{
HMODULE hmod = GetModuleHandle(TEXT("USER32"));
pfn = hmod ? (PFNALLOWSFW)GetProcAddress(hmod, "AllowSetForegroundWindow") : NULL;
}
return pfn ? pfn(dwProcessId) : FALSE;
}
typedef BOOL (* PFNANIMATEWINDOW)(HWND hwnd, DWORD dwTime, DWORD dwFlags);
// Thunk for NT 5's AnimateWindow.
BOOL NT5_AnimateWindow(IN HWND hwnd, IN DWORD dwTime, IN DWORD dwFlags)
{
BOOL bRet = FALSE;
static PFNANIMATEWINDOW pfn = NULL;
ASSERT(g_bRunOnMemphis || g_bRunOnNT5);
if (NULL == pfn)
{
HMODULE hmod = GetModuleHandle(TEXT("USER32"));
if (hmod)
pfn = (PFNANIMATEWINDOW)GetProcAddress(hmod, "AnimateWindow");
}
if (pfn)
bRet = pfn(hwnd, dwTime, dwFlags);
return bRet;
}
// Position Menubands using NT5's AnimateWindow if available.
void SlideAnimate(HWND hwnd, RECT* prc, UINT uFlags, UINT uSide)
{
DWORD dwAnimateFlags = AW_CENTER;
switch(uSide)
{
case MENUBAR_LEFT: dwAnimateFlags = AW_HOR_NEGATIVE;
break;
case MENUBAR_RIGHT: dwAnimateFlags = AW_HOR_POSITIVE;
break;
case MENUBAR_TOP: dwAnimateFlags = AW_VER_NEGATIVE;
break;
case MENUBAR_BOTTOM: dwAnimateFlags = AW_VER_POSITIVE;
break;
}
NT5_AnimateWindow(hwnd, 120, dwAnimateFlags | AW_SLIDE);
}
void AnimateSetMenuPos(HWND hwnd, RECT* prc, UINT uFlags, UINT uSide, BOOL fNoAnimate)
{
if ((g_bRunOnMemphis || g_bRunOnNT5) && !fNoAnimate)
{
BOOL fAnimate = FALSE;
SystemParametersInfo(SPI_GETMENUANIMATION, 0, &fAnimate, 0);
if (fAnimate)
{
SetWindowPos(hwnd, HWND_TOPMOST, prc->left, prc->top,
RECTWIDTH(*prc), RECTHEIGHT(*prc), uFlags);
fAnimate = FALSE;
#ifdef WINNT
SystemParametersInfo(SPI_GETMENUFADE, 0, &fAnimate, 0);
#endif // WINNT
if (fAnimate)
{
NT5_AnimateWindow(hwnd, 175, AW_BLEND);
}
else
{
SlideAnimate(hwnd, prc, uFlags, uSide);
}
}
else
goto UseSetWindowPos;
}
else
{
UseSetWindowPos:
// Enable the show window so that it gets displayed.
uFlags |= SWP_SHOWWINDOW;
SetWindowPos(hwnd, HWND_TOPMOST, prc->left, prc->top, RECTWIDTH(*prc), RECTHEIGHT(*prc),
uFlags);
}
}
/*----------------------------------------------------------
Purpose: Use the Microsoft ActiveAccessiblity routines to
return an IAccessible object
*/
typedef LRESULT (* PFNCREATESTDACCESSIBLEOBJECT)(HWND hwnd, LONG idObject, REFIID riid, void** ppvObj);
LRESULT ACCESSIBLE_CreateStdAccessibleObject(
IN HWND hwnd,
IN LONG idObject,
IN REFIID riid,
OUT void** ppvObj)
{
static PFNCREATESTDACCESSIBLEOBJECT pfn = NULL;
static BOOL fLoadAttempted = FALSE;
LRESULT lRet = (LRESULT)E_FAIL;
if (NULL == pfn && !fLoadAttempted)
{
// LoadLibrary here because OLEAcc is not loaded in the process
HMODULE hmod = LoadLibrary(TEXT("OLEACC"));
if (hmod)
pfn = (PFNCREATESTDACCESSIBLEOBJECT)GetProcAddress(hmod, "CreateStdAccessibleObject");
else
fLoadAttempted = TRUE;
}
if (pfn)
lRet = pfn(hwnd, idObject, riid, ppvObj);
return lRet;
}
typedef BOOL (* PFNLOCKSETFOREGROUNDWINDOW)(UINT);
BOOL MyLockSetForegroundWindow(BOOL fLock)
{
static PFNLOCKSETFOREGROUNDWINDOW pfn = (PFNLOCKSETFOREGROUNDWINDOW)-1;
BOOL fRet = FALSE;
if ((PFNLOCKSETFOREGROUNDWINDOW)-1 == pfn)
{
HMODULE hmod = GetModuleHandle(TEXT("USER32"));
if (hmod)
pfn = (PFNLOCKSETFOREGROUNDWINDOW)GetProcAddress(hmod, "LockSetForegroundWindow");
else
pfn = NULL;
}
if (pfn)
fRet = pfn(fLock ? LSFW_LOCK : LSFW_UNLOCK);
return fRet;
}
typedef UINT (* PFNSHEXTRACTICONSW)(LPCWSTR wszFileName, int nIconIndex, int cxIcon, int cyIcon, HICON *phicon, UINT *piconid, UINT nIcons, UINT flags);
STDAPI_(UINT) MyExtractIconsW(LPCWSTR wszFileName, int nIconIndex, int cxIcon, int cyIcon, HICON *phicon, UINT *piconid, UINT nIcons, UINT flags)
{
UINT uiRet = 0;
static PFNSHEXTRACTICONSW pfn = NULL;
if (GetUIVersion() >= 5)
{
if (NULL == pfn)
{
HMODULE hmod = GetModuleHandle(TEXT("SHELL32"));
if (hmod)
pfn = (PFNSHEXTRACTICONSW)GetProcAddress(hmod, "SHExtractIconsW");
}
if (pfn)
uiRet = pfn(wszFileName, nIconIndex, cxIcon, cyIcon, phicon, piconid, nIcons, flags);
}
return uiRet;
}
typedef BOOL (* PFNUPDATELAYEREDWINDOW)
(HWND hwnd,
HDC hdcDst,
POINT *pptDst,
SIZE *psize,
HDC hdcSrc,
POINT *pptSrc,
COLORREF crKey,
BLENDFUNCTION *pblend,
DWORD dwFlags);
BOOL BlendLayeredWindow(HWND hwnd, HDC hdcDest, POINT* ppt, SIZE* psize, HDC hdc, POINT* pptSrc, BYTE bBlendConst)
{
BOOL bRet = FALSE;
static PFNUPDATELAYEREDWINDOW pfn = NULL;
if (NULL == pfn)
{
HMODULE hmod = GetModuleHandle(TEXT("USER32"));
if (hmod)
pfn = (PFNUPDATELAYEREDWINDOW)GetProcAddress(hmod, "UpdateLayeredWindow");
}
if (pfn)
{
BLENDFUNCTION blend;
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.AlphaFormat = 0;
blend.SourceConstantAlpha = bBlendConst;
bRet = pfn(hwnd, hdcDest, ppt, psize, hdc, pptSrc, 0, &blend, ULW_ALPHA);
}
return bRet;
}
BOOL NT5_SetLayeredWindowAttributes(
HWND hwnd,
COLORREF crKey,
BYTE bAlpha,
DWORD dwFlags)
{
static BOOL (*pfn)(HWND, COLORREF, BYTE, DWORD) = NULL;
if (pfn == NULL)
{
HMODULE hMod = LoadLibrary(TEXT("user32.dll"));
if (hMod)
{
pfn = (BOOL (*)(HWND, COLORREF, BYTE, DWORD))GetProcAddress(hMod, "SetLayeredWindowAttributes");
}
}
if (pfn)
return pfn(hwnd, crKey, bAlpha, dwFlags);
return 0;
}
typedef HRESULT (* PFNSHPATHPREPAREFORWRITE)(HWND hwnd, IUnknown* punkModless, LPCWSTR pwzPath, DWORD dwFlags);
STDAPI NT5_SHPathPrepareForWrite(HWND hwnd, IUnknown* punkModless, LPCWSTR pwzPath, DWORD dwFlags)
{
HRESULT hRet = E_FAIL;
static PFNSHPATHPREPAREFORWRITE pfn = NULL;
if (GetUIVersion() >= 5)
{
if (NULL == pfn)
{
HMODULE hmod = GetModuleHandle(TEXT("shell32.dll"));
if (hmod)
{
pfn = (PFNSHPATHPREPAREFORWRITE)GetProcAddress(hmod, "SHPathPrepareForWriteW");
}
}
if (pfn)
{
hRet = pfn(hwnd, punkModless, pwzPath, dwFlags);
}
}
return hRet;
}
void Comctl32_SetWindowTheme(HWND hwnd, LPWSTR psz)
{
SendMessage(hwnd, CCM_SETWINDOWTHEME, 0, (LPARAM)psz);
}
void Comctl32_GetBandMargins(HWND hwnd, MARGINS* pmar)
{
SendMessage(hwnd, RB_GETBANDMARGINS, 0, (LPARAM)pmar);
}
void Comctl32_FixAutoBreak(LPNMHDR pnm)
{
LPNMREBARAUTOBREAK pnmab = (LPNMREBARAUTOBREAK) pnm;
pnmab->fAutoBreak = !(pnmab->uMsg == RBAB_AUTOSIZE);
}
void Comctl32_SetDPIScale(HWND hwnd)
{
SendMessage(hwnd, CCM_DPISCALE, TRUE, 0);
}
// enable the marquee mode. note, this only works on comctl32 v6
STDAPI_(void) ProgressSetMarqueeMode(HWND hwndPrgress, BOOL bOn)
{
if (IsOS(OS_WHISTLERORGREATER))
{
SendMessage(hwndPrgress, PBM_SETMARQUEE, bOn, 0);
SHSetWindowBits(hwndPrgress, GWL_STYLE, PBS_MARQUEE, bOn ? PBS_MARQUEE : 0);
}
}
// terminal server session notification:
static HMODULE s_hmodWTSApi = NULL;
typedef BOOL (* PFNWTS_REGISTER_SESSION_NOTIFICATION)(HWND hwnd, DWORD dwFlags);
static PFNWTS_REGISTER_SESSION_NOTIFICATION s_pfnWTSRegisterSession = NULL;
typedef BOOL (* PFNWTS_UNREGISTER_SESSION_NOTIFICATION)(HWND hwnd);
static PFNWTS_UNREGISTER_SESSION_NOTIFICATION s_pfnWTSUnRegisterSession = NULL;
BOOL DL_WTSRegisterSessionNotification(HWND hwnd, DWORD dwFlags)
{
if (s_pfnWTSRegisterSession == NULL)
{
if (s_hmodWTSApi == NULL)
{
s_hmodWTSApi = LoadLibrary(TEXT("wtsapi32"));
}
if (s_hmodWTSApi)
{
s_pfnWTSRegisterSession = (PFNWTS_REGISTER_SESSION_NOTIFICATION)GetProcAddress(s_hmodWTSApi, "WTSRegisterSessionNotification");
}
}
if (s_pfnWTSRegisterSession != NULL)
{
return s_pfnWTSRegisterSession(hwnd, dwFlags);
}
return FALSE;
}
BOOL DL_WTSUnRegisterSessionNotification(HWND hwnd)
{
if (s_pfnWTSUnRegisterSession == NULL)
{
if (s_hmodWTSApi == NULL)
{
s_hmodWTSApi = LoadLibrary(TEXT("wtsapi32"));
}
if (s_hmodWTSApi)
{
s_pfnWTSUnRegisterSession = (PFNWTS_UNREGISTER_SESSION_NOTIFICATION)GetProcAddress(s_hmodWTSApi, "WTSUnRegisterSessionNotification");
}
}
if (s_pfnWTSUnRegisterSession != NULL)
{
BOOL fRet = s_pfnWTSUnRegisterSession(hwnd);
FreeLibrary(s_hmodWTSApi);
s_hmodWTSApi = NULL;
s_pfnWTSRegisterSession = NULL;
s_pfnWTSUnRegisterSession = NULL;
return fRet;
}
return FALSE;
}