202 lines
6.2 KiB
C++
202 lines
6.2 KiB
C++
|
// Wrappers for APIs that have moved elsewhere
|
||
|
|
||
|
#include "priv.h"
|
||
|
#include "shlwapip.h"
|
||
|
|
||
|
//------------------------------------------------------------------------
|
||
|
//
|
||
|
// APIs from SHDOCVW that are now forwarded to SHLWAPI
|
||
|
//
|
||
|
//
|
||
|
// Note that we cannot use DLL forwarders because there is a bug
|
||
|
// in Win95 where the loader screws up forwarders for bound DLLs.
|
||
|
|
||
|
STDAPI_(DWORD) StopWatchModeFORWARD(VOID)
|
||
|
{
|
||
|
return StopWatchMode();
|
||
|
}
|
||
|
|
||
|
STDAPI_(DWORD) StopWatchFlushFORWARD(VOID)
|
||
|
{
|
||
|
return StopWatchFlush();
|
||
|
}
|
||
|
|
||
|
STDAPI SHRunIndirectRegClientCommandForward(HWND hwnd, LPCWSTR pszClient)
|
||
|
{
|
||
|
return SHRunIndirectRegClientCommand(hwnd, pszClient);
|
||
|
}
|
||
|
|
||
|
#ifdef ux10
|
||
|
/*IEUNIX : In the hp-ux linker, there is no option of specifying an internal name and an external name. */
|
||
|
#define StopWatch StopWatch
|
||
|
#define StopWatchFORWARD StopWatch
|
||
|
#endif
|
||
|
|
||
|
STDAPI_(DWORD) StopWatchFORWARD(DWORD dwId, LPCSTR pszDesc, DWORD dwType, DWORD dwFlags, DWORD dwCount)
|
||
|
{
|
||
|
return StopWatchA(dwId, (LPCSTR)pszDesc, dwType, dwFlags, dwCount);
|
||
|
}
|
||
|
|
||
|
//------------------------------------------------------------------------
|
||
|
//
|
||
|
// APIs from SHDOCVW that are now forwarded to SHELL32/SHDOC41
|
||
|
|
||
|
//
|
||
|
// This variable name is a misnomer. It's really
|
||
|
//
|
||
|
// g_hinstShell32OrShdoc401DependingOnWhatWeDetected;
|
||
|
//
|
||
|
// I can live with the misnomer; saves typing. Think of it as
|
||
|
// "the INSTANCE of SHDOC401 or whatever DLL is masquerading as
|
||
|
// SHDOC401".
|
||
|
//
|
||
|
//
|
||
|
|
||
|
extern "C" { HINSTANCE g_hinstSHDOC401 = NULL; }
|
||
|
|
||
|
//
|
||
|
// GetShdoc401
|
||
|
//
|
||
|
// Detect whether we should be using Shell32 or Shdoc401 to handle
|
||
|
// active desktop stuff. The rule is
|
||
|
//
|
||
|
// If PF_FORCESHDOC401 is set, then use shdoc401. (DEBUG only)
|
||
|
// If shell32 version >= 5, then use shell32.
|
||
|
// Else use shdoc401.
|
||
|
//
|
||
|
// Warning: THIS FUNCTION CANNOT BE CALLED DURING PROCESS_ATTACH
|
||
|
// because it calls LoadLibrary.
|
||
|
|
||
|
HINSTANCE GetShdoc401()
|
||
|
{
|
||
|
DWORD dwMajorVersion;
|
||
|
HINSTANCE hinst;
|
||
|
HINSTANCE hinstSh32 = GetModuleHandle(TEXT("SHELL32.DLL"));
|
||
|
ASSERT(hinstSh32);
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
if (g_dwPrototype & PF_FORCESHDOC401) {
|
||
|
hinstSh32 = NULL; // force SHDOC401 to be loaded
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (hinstSh32) {
|
||
|
DLLVERSIONINFO dllinfo;
|
||
|
DLLGETVERSIONPROC pfnGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstSh32, "DllGetVersion");
|
||
|
|
||
|
dllinfo.cbSize = sizeof(DLLVERSIONINFO);
|
||
|
if (pfnGetVersion && SUCCEEDED(pfnGetVersion(&dllinfo))) {
|
||
|
dwMajorVersion = dllinfo.dwMajorVersion;
|
||
|
} else {
|
||
|
dwMajorVersion = 0;
|
||
|
}
|
||
|
} else {
|
||
|
dwMajorVersion = 0;
|
||
|
}
|
||
|
|
||
|
if (dwMajorVersion >= 5) {
|
||
|
hinst = hinstSh32;
|
||
|
} else {
|
||
|
hinst = LoadLibrary(TEXT("SHDOC401.DLL"));
|
||
|
|
||
|
if (NULL == hinst)
|
||
|
{
|
||
|
// If this fails we're screwed
|
||
|
TraceMsg(TF_ERROR, "Failed to load SHDOC401.DLL.");
|
||
|
}
|
||
|
}
|
||
|
g_hinstSHDOC401 = hinst;
|
||
|
|
||
|
return hinst;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// GetShdoc401ProcAddress
|
||
|
//
|
||
|
// Get a procedure from SHDOC401 or whoever is masquerading as same.
|
||
|
//
|
||
|
// Warning: THIS FUNCTION CANNOT BE CALLED DURING PROCESS_ATTACH
|
||
|
// because it calls LoadLibrary.
|
||
|
|
||
|
FARPROC GetShdoc401ProcAddress(FARPROC *ppfn, UINT ord)
|
||
|
{
|
||
|
if (*ppfn) {
|
||
|
return *ppfn;
|
||
|
} else {
|
||
|
HINSTANCE hinst = g_hinstSHDOC401;
|
||
|
|
||
|
//
|
||
|
// No race condition here. If two threads both call GetShdoc401,
|
||
|
// all that happens is that we load SHDOC401 into memory and then
|
||
|
// bump his refcount up to 2 instead of leaving it at 1. Big deal.
|
||
|
//
|
||
|
if (hinst == NULL) {
|
||
|
hinst = GetShdoc401();
|
||
|
}
|
||
|
|
||
|
if (hinst) {
|
||
|
return *ppfn = GetProcAddress(hinst, (LPCSTR)LongToHandle(ord));
|
||
|
} else {
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Delay-load-like macros.
|
||
|
//
|
||
|
|
||
|
#define DELAY_LOAD_SHDOC401(_type, _err, _fn, _ord, _arg, _nargs) \
|
||
|
STDAPI_(_type) _fn _arg \
|
||
|
{ \
|
||
|
static FARPROC s_pfn##_fn = NULL; \
|
||
|
FARPROC pfn = GetShdoc401ProcAddress(&s_pfn##_fn, _ord); \
|
||
|
if (pfn) { \
|
||
|
typedef _type (__stdcall *PFN##_fn) _arg; \
|
||
|
return ((PFN##_fn)pfn) _nargs; \
|
||
|
} else { \
|
||
|
return _err; \
|
||
|
} \
|
||
|
} \
|
||
|
|
||
|
#define DELAY_LOAD_SHDOC401_VOID(_fn, _ord, _arg, _nargs) \
|
||
|
STDAPI_(void) _fn _arg \
|
||
|
{ \
|
||
|
static FARPROC s_pfn##_fn = NULL; \
|
||
|
FARPROC pfn = GetShdoc401ProcAddress(&s_pfn##_fn, _ord); \
|
||
|
if (pfn) { \
|
||
|
typedef void (__stdcall *PFN##_fn) _arg; \
|
||
|
((PFN##_fn)pfn) _nargs; \
|
||
|
} \
|
||
|
} \
|
||
|
|
||
|
// IE4 Shell Integrated Explorer called ShellDDEInit in shdocvw to
|
||
|
// set up DDE. Forward this call to SHELL32/SHDOC401 appropriately.
|
||
|
|
||
|
DELAY_LOAD_SHDOC401_VOID(ShellDDEInit, 188,
|
||
|
(BOOL fInit),
|
||
|
(fInit));
|
||
|
|
||
|
DELAY_LOAD_SHDOC401(HANDLE, NULL,
|
||
|
SHCreateDesktop, 200,
|
||
|
(IDeskTray* pdtray),
|
||
|
(pdtray));
|
||
|
|
||
|
DELAY_LOAD_SHDOC401(BOOL, FALSE,
|
||
|
SHDesktopMessageLoop, 201,
|
||
|
(HANDLE hDesktop),
|
||
|
(hDesktop));
|
||
|
|
||
|
// This may not have been used in IE4
|
||
|
DELAY_LOAD_SHDOC401(BOOL, FALSE,
|
||
|
DDEHandleViewFolderNotify, 202,
|
||
|
(IShellBrowser* psb, HWND hwnd, LPNMVIEWFOLDER lpnm),
|
||
|
(psb, hwnd, lpnm));
|
||
|
|
||
|
DELAY_LOAD_SHDOC401(LPNMVIEWFOLDER, NULL,
|
||
|
DDECreatePostNotify, 82,
|
||
|
(LPNMVIEWFOLDER pnm),
|
||
|
(pnm));
|
||
|
|
||
|
|