248 lines
9.6 KiB
C++
248 lines
9.6 KiB
C++
/*****************************************************************************\
|
|
FILE: dllload.cpp
|
|
|
|
DESCRIPTION:
|
|
Delay load functions that we want to use when they are available.
|
|
|
|
BryanSt (Bryan Starbuck) - Created
|
|
Copyright (c) 1998-2000 Microsoft Corporation
|
|
\*****************************************************************************/
|
|
|
|
#include "priv.h"
|
|
#include <pstore.h>
|
|
#include <wininet.h>
|
|
|
|
#pragma warning(disable:4229) // No warnings when modifiers used on data
|
|
|
|
// Delay loading mechanism. This allows you to write code as if you are
|
|
// calling implicitly linked APIs, and yet have these APIs really be
|
|
// explicitly linked. You can reduce the initial number of DLLs that
|
|
// are loaded (load on demand) using this technique.
|
|
//
|
|
// Use the following macros to indicate which APIs/DLLs are delay-linked
|
|
// and -loaded.
|
|
//
|
|
// DELAY_LOAD
|
|
// DELAY_LOAD_HRESULT
|
|
// DELAY_LOAD_SAFEARRAY
|
|
// DELAY_LOAD_UINT
|
|
// DELAY_LOAD_INT
|
|
// DELAY_LOAD_VOID
|
|
//
|
|
// Use these macros for APIs that are exported by ordinal only.
|
|
//
|
|
// DELAY_LOAD_ORD
|
|
// DELAY_LOAD_ORD_VOID
|
|
//
|
|
// Use these macros for APIs that only exist on the integrated-shell
|
|
// installations (i.e., a new shell32 is on the system).
|
|
//
|
|
// DELAY_LOAD_SHELL
|
|
// DELAY_LOAD_SHELL_HRESULT
|
|
// DELAY_LOAD_SHELL_VOID
|
|
//
|
|
//
|
|
|
|
|
|
/**********************************************************************/
|
|
|
|
void _GetProcFromDLL(HINSTANCE* phinst, LPCSTR pszDLL, FARPROC* ppfn, LPCSTR pszProc)
|
|
{
|
|
#ifdef DEBUG
|
|
CHAR szProcD[MAX_PATH];
|
|
if (HIWORD(pszProc)) {
|
|
lstrcpynA(szProcD, pszProc, ARRAYSIZE(szProcD));
|
|
} else {
|
|
wnsprintfA(szProcD, ARRAYSIZE(szProcD), "(ordinal %d)", LOWORD(pszProc));
|
|
}
|
|
#endif // DEBUG
|
|
// If it's already loaded, return.
|
|
if (*ppfn) {
|
|
return;
|
|
}
|
|
|
|
if (*phinst == NULL) {
|
|
#ifdef DEBUG
|
|
TraceMsg(TF_FTP_DLLLOADING, "DLLLOAD: Loading %hs for the first time for %hs", pszDLL, szProcD);
|
|
|
|
/*
|
|
if (g_dwBreakFlags & TF_FTP_DLLLOAD_BREAK)
|
|
{
|
|
DebugBreak();
|
|
}
|
|
*/
|
|
#endif // DEBUG
|
|
*phinst = LoadLibraryA(pszDLL);
|
|
if (*phinst == NULL) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
TraceMsg(TF_FTP_DLLLOADING, "DLLLOAD: GetProc'ing %hs from %hs for the first time", pszDLL, szProcD);
|
|
#endif // DEBUG
|
|
*ppfn = GetProcAddress(*phinst, pszProc);
|
|
}
|
|
|
|
/*----------------------------------------------------------
|
|
Purpose: Performs a loadlibrary on the DLL only if the machine
|
|
has the integrated shell installation.
|
|
|
|
*/
|
|
void _SHGetProcFromDLL(HINSTANCE* phinst, LPCSTR pszDLL, FARPROC* ppfn, LPCSTR pszProc)
|
|
{
|
|
_GetProcFromDLL(phinst, pszDLL, ppfn, pszProc);
|
|
}
|
|
|
|
#define DELAY_LOAD_MAP(_hinst, _dll, _ret, _fnpriv, _fn, _args, _nargs, _err) \
|
|
_ret __stdcall _fnpriv _args \
|
|
{ \
|
|
static _ret (* __stdcall _pfn##_fn) _args = NULL; \
|
|
_GetProcFromDLL(&_hinst, #_dll, (FARPROC*)&_pfn##_fn, #_fn); \
|
|
if (_pfn##_fn) \
|
|
return _pfn##_fn _nargs; \
|
|
return (_ret)_err; \
|
|
}
|
|
|
|
#define DELAY_MAP_HRESULT(_hinst, _dll, _fnpriv, _fn, _args, _nargs) DELAY_LOAD_MAP(_hinst, _dll, HRESULT, _fnpriv, _fn, _args, _nargs, E_FAIL)
|
|
#define DELAY_MAP_DWORD(_hinst, _dll, _fnpriv, _fn, _args, _nargs) DELAY_LOAD_MAP(_hinst, _dll, DWORD, _fnpriv, _fn, _args, _nargs, 0)
|
|
#define DELAY_MAP_BOOL(_hinst, _dll, _fnpriv, _fn, _args, _nargs) DELAY_LOAD_MAP(_hinst, _dll, BOOL, _fnpriv, _fn, _args, _nargs, 0)
|
|
|
|
|
|
#define DELAY_LOAD_ERR(_hinst, _dll, _ret, _fn, _args, _nargs, _err) DELAY_LOAD_MAP(_hinst, _dll, _ret, _fn, _fn, _args, _nargs, _err)
|
|
|
|
#define DELAY_LOAD(_hinst, _dll, _ret, _fn, _args, _nargs) DELAY_LOAD_ERR(_hinst, _dll, _ret, _fn, _args, _nargs, 0)
|
|
#define DELAY_LOAD_HRESULT(_hinst, _dll, _fn, _args, _nargs) DELAY_LOAD_ERR(_hinst, _dll, HRESULT, _fn, _args, _nargs, E_FAIL)
|
|
#define DELAY_LOAD_SAFEARRAY(_hinst, _dll, _fn, _args, _nargs) DELAY_LOAD_ERR(_hinst, _dll, SAFEARRAY *, _fn, _args, _nargs, NULL)
|
|
#define DELAY_LOAD_DWORD(_hinst, _dll, _fn, _args, _nargs) DELAY_LOAD_ERR(_hinst, _dll, DWORD, _fn, _args, _nargs, 0)
|
|
#define DELAY_LOAD_BOOL(_hinst, _dll, _fn, _args, _nargs) DELAY_LOAD_ERR(_hinst, _dll, BOOL, _fn, _args, _nargs, 0)
|
|
#define DELAY_LOAD_UINT(_hinst, _dll, _fn, _args, _nargs) DELAY_LOAD_ERR(_hinst, _dll, UINT, _fn, _args, _nargs, 0)
|
|
#define DELAY_LOAD_INT(_hinst, _dll, _fn, _args, _nargs) DELAY_LOAD_ERR(_hinst, _dll, INT, _fn, _args, _nargs, 0)
|
|
|
|
#define DELAY_LOAD_VOID(_hinst, _dll, _fn, _args, _nargs) \
|
|
void __stdcall _fn _args \
|
|
{ \
|
|
static void (* __stdcall _pfn##_fn) _args = NULL; \
|
|
_GetProcFromDLL(&_hinst, #_dll, (FARPROC*)&_pfn##_fn, #_fn); \
|
|
if (_pfn##_fn) \
|
|
_pfn##_fn _nargs; \
|
|
return; \
|
|
}
|
|
|
|
//
|
|
// For private entrypoints exported by ordinal.
|
|
//
|
|
|
|
#define DELAY_LOAD_ORD_ERR(_hinst, _dll, _ret, _fn, _ord, _args, _nargs, _err) \
|
|
_ret __stdcall _fn _args \
|
|
{ \
|
|
static _ret (* __stdcall _pfn##_fn) _args = NULL; \
|
|
_GetProcFromDLL(&_hinst, #_dll, (FARPROC*)&_pfn##_fn, (LPCSTR)_ord); \
|
|
if (_pfn##_fn) \
|
|
return _pfn##_fn _nargs; \
|
|
return (_ret)_err; \
|
|
}
|
|
|
|
#define DELAY_LOAD_ORD(_hinst, _dll, _ret, _fn, _ord, _args, _nargs) DELAY_LOAD_ORD_ERR(_hinst, _dll, _ret, _fn, _ord, _args, _nargs, 0)
|
|
#define DELAY_LOAD_ORD_HRESULT(_hinst, _dll, _fn, _ord, _args, _nargs) DELAY_LOAD_ORD(_hinst, _dll, HRESULT, _fn, _ord, _args, _nargs)
|
|
|
|
|
|
#define DELAY_LOAD_ORD_VOID(_hinst, _dll, _fn, _ord, _args, _nargs) \
|
|
void __stdcall _fn _args \
|
|
{ \
|
|
static void (* __stdcall _pfn##_fn) _args = NULL; \
|
|
_GetProcFromDLL(&_hinst, #_dll, (FARPROC*)&_pfn##_fn, (LPCSTR)_ord); \
|
|
if (_pfn##_fn) \
|
|
_pfn##_fn _nargs; \
|
|
return; \
|
|
}
|
|
|
|
|
|
//
|
|
// Private exports by ordinal for integrated-shell installs
|
|
//
|
|
|
|
|
|
#define DELAY_LOAD_SHELL_ERR(_hinst, _dll, _ret, _fn, _ord, _args, _nargs, _err) \
|
|
_ret __stdcall _fn _args \
|
|
{ \
|
|
static _ret (* __stdcall _pfn##_fn) _args = NULL; \
|
|
_SHGetProcFromDLL(&_hinst, #_dll, (FARPROC*)&_pfn##_fn, (LPCSTR)_ord); \
|
|
if (_pfn##_fn) \
|
|
return _pfn##_fn _nargs; \
|
|
return (_ret)_err; \
|
|
}
|
|
|
|
#define DELAY_LOAD_SHELL(_hinst, _dll, _ret, _fn, _ord, _args, _nargs) DELAY_LOAD_SHELL_ERR(_hinst, _dll, _ret, _fn, _ord, _args, _nargs, 0)
|
|
#define DELAY_LOAD_SHELL_HRESULT(_hinst, _dll, _fn, _ord, _args, _nargs) DELAY_LOAD_SHELL_ERR(_hinst, _dll, HRESULT, _fn, _ord, _args, _nargs, E_FAIL)
|
|
|
|
|
|
#define DELAY_LOAD_SHELL_VOID(_hinst, _dll, _fn, _ord, _args, _nargs) \
|
|
void __stdcall _fn _args \
|
|
{ \
|
|
static void (* __stdcall _pfn##_fn) _args = NULL; \
|
|
_SHGetProcFromDLL(&_hinst, #_dll, (FARPROC*)&_pfn##_fn, (LPCSTR)_ord); \
|
|
if (_pfn##_fn) \
|
|
_pfn##_fn _nargs; \
|
|
return; \
|
|
}
|
|
|
|
|
|
|
|
/**********************************************************************/
|
|
/**********************************************************************/
|
|
|
|
|
|
// --------- MLANG.DLL ---------------
|
|
|
|
HINSTANCE g_hinstMLANG = NULL;
|
|
|
|
DELAY_LOAD_HRESULT(g_hinstMLANG, MLANG.DLL, ConvertINetMultiByteToUnicode,
|
|
(LPDWORD lpdwMode, DWORD dwEncoding, LPCSTR lpSrcStr, LPINT lpnMultiCharCount, LPWSTR lpDstStr, LPINT lpnWideCharCount),
|
|
(lpdwMode, dwEncoding, lpSrcStr, lpnMultiCharCount, lpDstStr, lpnWideCharCount));
|
|
|
|
DELAY_LOAD_HRESULT(g_hinstMLANG, MLANG.DLL, ConvertINetUnicodeToMultiByte,
|
|
(LPDWORD lpdwMode, DWORD dwEncoding, LPCWSTR lpSrcStr, LPINT lpnWideCharCount, LPSTR lpDstStr, LPINT lpnMultiCharCount),
|
|
(lpdwMode, dwEncoding, lpSrcStr, lpnWideCharCount, lpDstStr, lpnMultiCharCount));
|
|
|
|
DELAY_LOAD_HRESULT(g_hinstMLANG, MLANG.DLL, LcidToRfc1766W,
|
|
(LCID Locale, LPWSTR pszRfc1766, int nChar),
|
|
(Locale, pszRfc1766, nChar));
|
|
|
|
|
|
// --------- MSHTML.DLL ---------------
|
|
HINSTANCE g_hinstMSHTML = NULL;
|
|
|
|
DELAY_LOAD_HRESULT(g_hinstMSHTML, MSHTML.DLL, ShowHTMLDialog,
|
|
(HWND hwnd, IMoniker * pmk, VARIANT * pvarArgIn, LPWSTR pchOptions, VARIANT * pvarArgOut),
|
|
(hwnd, pmk, pvarArgIn, pchOptions, pvarArgOut));
|
|
|
|
|
|
// --------- CRYPT32.DLL ---------------
|
|
HINSTANCE g_hinstCRYPT32 = NULL;
|
|
|
|
DELAY_MAP_BOOL(g_hinstCRYPT32, CRYPT32.DLL, _CryptProtectData, CryptProtectData,
|
|
(DATA_BLOB *pDataIn, LPCWSTR pszDataDescr, DATA_BLOB * pOptionalEntropy, PVOID pvReserved, CRYPTPROTECT_PROMPTSTRUCT *pPromptStruct, DWORD dwFlags, DATA_BLOB *pDataOut),
|
|
(pDataIn, pszDataDescr, pOptionalEntropy, pvReserved, pPromptStruct, dwFlags, pDataOut));
|
|
|
|
DELAY_MAP_BOOL(g_hinstCRYPT32, CRYPT32.DLL, _CryptUnprotectData, CryptUnprotectData,
|
|
(DATA_BLOB *pDataIn, LPWSTR *ppszDataDescr, DATA_BLOB * pOptionalEntropy, PVOID pvReserved, CRYPTPROTECT_PROMPTSTRUCT *pPromptStruct, DWORD dwFlags, DATA_BLOB *pDataOut),
|
|
(pDataIn, ppszDataDescr, pOptionalEntropy, pvReserved, pPromptStruct, dwFlags, pDataOut));
|
|
|
|
|
|
// --------- SHELL32.DLL ---------------
|
|
HINSTANCE g_hinstSHELL32 = NULL;
|
|
|
|
DELAY_LOAD_ORD_HRESULT(g_hinstSHELL32, SHELL32.DLL, _SHCreateShellFolderView, SHCreateShellFolderViewORD,
|
|
(const SFV_CREATE* pcsfv, LPSHELLVIEW FAR* ppsv),
|
|
(pcsfv, ppsv));
|
|
|
|
DELAY_MAP_HRESULT(g_hinstSHELL32, SHELL32.DLL, _SHPathPrepareForWriteW, SHPathPrepareForWriteW,
|
|
(HWND hwnd, IUnknown *punkEnableModless, LPCWSTR pwzPath, DWORD dwFlags),
|
|
(hwnd, punkEnableModless, pwzPath, dwFlags));
|
|
|
|
|
|
#pragma warning(default:4229)
|
|
|
|
|