462 lines
12 KiB
C
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;
|
|
}
|
|
|