You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
487 lines
12 KiB
487 lines
12 KiB
/*
|
|
** d e m a n d . c p p
|
|
**
|
|
** Purpose: implement the loader functions for defer/demand -loaded libraries
|
|
**
|
|
** Creators: jimsch, brimo, t-erikne
|
|
** Created: 5/15/97
|
|
**
|
|
** Copyright (C) Microsoft Corp. 1997
|
|
*/
|
|
|
|
#include "_apipch.h"
|
|
|
|
// W4 stuff
|
|
#pragma warning(disable: 4201) // nameless struct/union
|
|
#pragma warning(disable: 4514) // unreferenced inline function removed
|
|
|
|
#include <wincrypt.h>
|
|
#define IMPLEMENT_LOADER_FUNCTIONS
|
|
#include "demand.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Macros
|
|
|
|
#define CRIT_GET_PROC_ADDR(h, fn, temp) \
|
|
temp = (TYP_##fn) GetProcAddress(h, #fn); \
|
|
if (temp) \
|
|
VAR_##fn = temp; \
|
|
else \
|
|
{ \
|
|
AssertSz(VAR_##fn TEXT(" failed to load")); \
|
|
goto error; \
|
|
}
|
|
|
|
#define RESET(fn) \
|
|
VAR_##fn = LOADER_##fn;
|
|
|
|
#define GET_PROC_ADDR(h, fn) \
|
|
VAR_##fn = (TYP_##fn) GetProcAddress(h, #fn); \
|
|
Assert(VAR_##fn != NULL); \
|
|
if(NULL == VAR_##fn ) { \
|
|
VAR_##fn = LOADER_##fn; \
|
|
}
|
|
|
|
#define GET_PROC_ADDR3(h, fn, varname) \
|
|
VAR_##varname = (TYP_##varname) GetProcAddress(h, #fn); \
|
|
Assert(VAR_##varname != NULL);
|
|
|
|
#define GET_PROC_ADDR_FLAG(h, fn, pflag) \
|
|
VAR_##fn = (TYP_##fn) GetProcAddress(h, #fn); \
|
|
*pflag = (VAR_##fn != NULL);
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Variables
|
|
|
|
static HMODULE s_hCrypt = 0;
|
|
static HMODULE s_hAdvApi = 0;
|
|
static HMODULE s_hPstoreC = 0;
|
|
static HMODULE s_hCryptDlg = 0;
|
|
static HMODULE s_hWinTrust = 0;
|
|
static HMODULE s_hVersion = 0;
|
|
static HMODULE s_hImm32 = 0;
|
|
static HMODULE s_hWininet = 0;
|
|
static HMODULE s_hUrlmon = 0;
|
|
static HMODULE s_hShlwapi = NULL;
|
|
|
|
#ifdef USE_CRITSEC
|
|
static CRITICAL_SECTION cs = {0};
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
|
static BOOL s_fInit = FALSE;
|
|
#endif
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Management functions
|
|
|
|
void InitDemandLoadedLibs()
|
|
{
|
|
#ifdef USE_CRITSEC
|
|
InitializeCriticalSection(&cs);
|
|
#endif
|
|
#ifdef DEBUG
|
|
s_fInit = TRUE;
|
|
#endif
|
|
}
|
|
|
|
void FreeDemandLoadedLibs()
|
|
{
|
|
#ifdef USE_CRITSEC
|
|
EnterCriticalSection(&cs);
|
|
#endif
|
|
if (s_hCrypt)
|
|
FreeLibrary(s_hCrypt);
|
|
if (s_hAdvApi)
|
|
FreeLibrary(s_hAdvApi);
|
|
if (s_hPstoreC)
|
|
FreeLibrary(s_hPstoreC);
|
|
if (s_hCryptDlg)
|
|
FreeLibrary(s_hCryptDlg);
|
|
if (s_hWinTrust)
|
|
FreeLibrary(s_hWinTrust);
|
|
if (s_hVersion)
|
|
FreeLibrary(s_hVersion);
|
|
if (s_hImm32)
|
|
FreeLibrary(s_hImm32);
|
|
if (s_hWininet)
|
|
FreeLibrary(s_hWininet);
|
|
if (s_hUrlmon)
|
|
FreeLibrary(s_hUrlmon);
|
|
if (s_hShlwapi)
|
|
FreeLibrary(s_hShlwapi);
|
|
|
|
#ifdef DEBUG
|
|
s_fInit = FALSE;
|
|
#endif
|
|
#ifdef USE_CRITSEC
|
|
LeaveCriticalSection(&cs);
|
|
DeleteCriticalSection(&cs);
|
|
#endif
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Loader functions
|
|
|
|
/* sample loader with critical proc addrs
|
|
** but not thread-safe
|
|
BOOL DemandLoadFoo()
|
|
{
|
|
FARPROC fp;
|
|
|
|
if (0 == g_hFoo)
|
|
{
|
|
g_hFoo = LoadLibrary("FOO.DLL");
|
|
|
|
if (0 == g_hFoo)
|
|
return FALSE;
|
|
|
|
CRIT_GET_PROC_ADDR(NeededFunction1, fp);
|
|
CRIT_GET_PROC_ADDR(NeededFunction2, fp);
|
|
GET_PROC_ADDR(OptionalFunction);
|
|
}
|
|
return TRUE;
|
|
|
|
error:
|
|
FreeLibrary(g_hFoo);
|
|
g_hFoo = NULL;
|
|
RESET(NeededFunction1)
|
|
RESET(NeededFunction2)
|
|
RESET(OptionalFunction)
|
|
return FALSE;
|
|
}
|
|
*/
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL DemandLoadCrypt32()
|
|
{
|
|
BOOL fRet = TRUE;
|
|
|
|
Assert(s_fInit);
|
|
#ifdef USE_CRITSEC
|
|
EnterCriticalSection(&cs);
|
|
#endif
|
|
|
|
if (0 == s_hCrypt)
|
|
{
|
|
s_hCrypt = LoadLibrary(TEXT("CRYPT32.DLL"));
|
|
AssertSz((NULL != s_hCrypt), TEXT("LoadLibrary failed on CRYPT32.DLL"));
|
|
|
|
if (0 == s_hCrypt)
|
|
fRet = FALSE;
|
|
else
|
|
{
|
|
GET_PROC_ADDR(s_hCrypt, CertFreeCertificateContext)
|
|
GET_PROC_ADDR(s_hCrypt, CertDuplicateCertificateContext)
|
|
GET_PROC_ADDR(s_hCrypt, CertFindCertificateInStore)
|
|
GET_PROC_ADDR(s_hCrypt, CertVerifyTimeValidity)
|
|
GET_PROC_ADDR(s_hCrypt, CertOpenSystemStoreA)
|
|
GET_PROC_ADDR(s_hCrypt, CertCloseStore)
|
|
GET_PROC_ADDR(s_hCrypt, CertGetCertificateContextProperty)
|
|
GET_PROC_ADDR(s_hCrypt, CertOpenStore)
|
|
GET_PROC_ADDR(s_hCrypt, CertCompareCertificate)
|
|
GET_PROC_ADDR(s_hCrypt, CryptMsgClose)
|
|
GET_PROC_ADDR(s_hCrypt, CryptDecodeObjectEx)
|
|
GET_PROC_ADDR(s_hCrypt, CryptMsgGetParam)
|
|
GET_PROC_ADDR(s_hCrypt, CryptMsgUpdate)
|
|
GET_PROC_ADDR(s_hCrypt, CryptMsgOpenToDecode)
|
|
GET_PROC_ADDR(s_hCrypt, CertAddCertificateContextToStore)
|
|
}
|
|
}
|
|
|
|
#ifdef USE_CRITSEC
|
|
LeaveCriticalSection(&cs);
|
|
#endif
|
|
return fRet;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL DemandLoadAdvApi32()
|
|
{
|
|
BOOL fRet = TRUE;
|
|
|
|
Assert(s_fInit);
|
|
#ifdef USE_CRITSEC
|
|
EnterCriticalSection(&cs);
|
|
#endif
|
|
|
|
if (0 == s_hAdvApi)
|
|
{
|
|
s_hAdvApi = LoadLibrary(TEXT("ADVAPI32.DLL"));
|
|
AssertSz((NULL != s_hAdvApi), TEXT("LoadLibrary failed on ADVAPI32.DLL"));
|
|
|
|
if (0 == s_hAdvApi)
|
|
fRet = FALSE;
|
|
else
|
|
{
|
|
GET_PROC_ADDR(s_hAdvApi, CryptAcquireContextA)
|
|
GET_PROC_ADDR(s_hAdvApi, CryptAcquireContextW)
|
|
GET_PROC_ADDR(s_hAdvApi, CryptReleaseContext)
|
|
}
|
|
}
|
|
|
|
#ifdef USE_CRITSEC
|
|
LeaveCriticalSection(&cs);
|
|
#endif
|
|
return fRet;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL DemandLoadPStoreC()
|
|
{
|
|
BOOL fRet = TRUE;
|
|
|
|
Assert(s_fInit);
|
|
#ifdef USE_CRITSEC
|
|
EnterCriticalSection(&cs);
|
|
#endif
|
|
|
|
if (0 == s_hPstoreC)
|
|
{
|
|
s_hPstoreC = LoadLibrary(TEXT("PSTOREC.DLL"));
|
|
AssertSz((NULL != s_hPstoreC), TEXT("LoadLibrary failed on PSTOREC.DLL"));
|
|
|
|
if (0 == s_hPstoreC)
|
|
fRet = FALSE;
|
|
else
|
|
{
|
|
GET_PROC_ADDR(s_hPstoreC, PStoreCreateInstance)
|
|
GET_PROC_ADDR(s_hPstoreC, PStoreEnumProviders)
|
|
}
|
|
}
|
|
|
|
#ifdef USE_CRITSEC
|
|
LeaveCriticalSection(&cs);
|
|
#endif
|
|
return fRet;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static BOOL s_fCertViewPropertiesCryptUIA = FALSE;
|
|
|
|
BOOL DemandLoadCryptDlg()
|
|
{
|
|
BOOL fRet = TRUE;
|
|
|
|
Assert(s_fInit);
|
|
#ifdef USE_CRITSEC
|
|
EnterCriticalSection(&cs);
|
|
#endif
|
|
|
|
if (0 == s_hCryptDlg)
|
|
{
|
|
s_hCryptDlg = LoadLibrary(TEXT("CRYPTDLG.DLL"));
|
|
AssertSz((NULL != s_hCryptDlg), TEXT("LoadLibrary failed on CRYPTDLG.DLL"));
|
|
|
|
if (0 == s_hCryptDlg)
|
|
fRet = FALSE;
|
|
else
|
|
{
|
|
GET_PROC_ADDR(s_hCryptDlg, GetFriendlyNameOfCertA)
|
|
GET_PROC_ADDR(s_hCryptDlg, CertViewPropertiesA)
|
|
}
|
|
}
|
|
|
|
#ifdef USE_CRITSEC
|
|
LeaveCriticalSection(&cs);
|
|
#endif
|
|
return fRet;
|
|
}
|
|
|
|
BOOL CryptUIAvailable(void) {
|
|
DemandLoadCryptDlg();
|
|
return(s_fCertViewPropertiesCryptUIA);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL DemandLoadWinTrust()
|
|
{
|
|
BOOL fRet = TRUE;
|
|
|
|
Assert(s_fInit);
|
|
#ifdef USE_CRITSEC
|
|
EnterCriticalSection(&cs);
|
|
#endif
|
|
|
|
if (0 == s_hWinTrust)
|
|
{
|
|
s_hWinTrust = LoadLibrary(TEXT("WINTRUST.DLL"));
|
|
AssertSz((NULL != s_hWinTrust), TEXT("LoadLibrary failed on WINTRUST.DLL"));
|
|
|
|
if (0 == s_hWinTrust)
|
|
fRet = FALSE;
|
|
else
|
|
{
|
|
GET_PROC_ADDR(s_hWinTrust, WinVerifyTrust)
|
|
}
|
|
}
|
|
|
|
#ifdef USE_CRITSEC
|
|
LeaveCriticalSection(&cs);
|
|
#endif
|
|
return fRet;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL DemandLoadVersion()
|
|
{
|
|
BOOL fRet = TRUE;
|
|
|
|
Assert(s_fInit);
|
|
#ifdef USE_CRITSEC
|
|
EnterCriticalSection(&cs);
|
|
#endif
|
|
|
|
if (0 == s_hVersion)
|
|
{
|
|
s_hVersion = LoadLibrary(TEXT("VERSION.DLL"));
|
|
AssertSz((NULL != s_hVersion), TEXT("LoadLibrary failed on VERSION.DLL"));
|
|
|
|
if (0 == s_hVersion)
|
|
fRet = FALSE;
|
|
else
|
|
{
|
|
GET_PROC_ADDR(s_hVersion, GetFileVersionInfoSizeW)
|
|
GET_PROC_ADDR(s_hVersion, GetFileVersionInfoW)
|
|
GET_PROC_ADDR(s_hVersion, VerQueryValueW)
|
|
GET_PROC_ADDR(s_hVersion, GetFileVersionInfoSizeA)
|
|
GET_PROC_ADDR(s_hVersion, GetFileVersionInfoA)
|
|
GET_PROC_ADDR(s_hVersion, VerQueryValueA)
|
|
}
|
|
}
|
|
|
|
#ifdef USE_CRITSEC
|
|
LeaveCriticalSection(&cs);
|
|
#endif
|
|
return fRet;
|
|
}
|
|
|
|
BOOL DemandLoadImm32()
|
|
{
|
|
BOOL fRet = TRUE;
|
|
|
|
Assert(s_fInit);
|
|
#ifdef USE_CRITSEC
|
|
EnterCriticalSection(&cs);
|
|
#endif
|
|
|
|
if (0 == s_hImm32)
|
|
{
|
|
s_hImm32 = LoadLibrary(TEXT("IMM32.DLL"));
|
|
AssertSz((NULL != s_hImm32), TEXT("LoadLibrary failed on IMM32.DLL"));
|
|
|
|
if (0 == s_hImm32)
|
|
fRet = FALSE;
|
|
else
|
|
{
|
|
GET_PROC_ADDR(s_hImm32, ImmAssociateContext)
|
|
GET_PROC_ADDR(s_hImm32, ImmGetContext)
|
|
GET_PROC_ADDR(s_hImm32, ImmGetCompositionStringW)
|
|
GET_PROC_ADDR(s_hImm32, ImmReleaseContext)
|
|
}
|
|
}
|
|
|
|
#ifdef USE_CRITSEC
|
|
LeaveCriticalSection(&cs);
|
|
#endif
|
|
return fRet;
|
|
}
|
|
|
|
BOOL DemandLoadWininet()
|
|
{
|
|
BOOL fRet = TRUE;
|
|
|
|
Assert(s_fInit);
|
|
#ifdef USE_CRITSEC
|
|
EnterCriticalSection(&cs);
|
|
#endif
|
|
|
|
if (0 == s_hWininet)
|
|
{
|
|
s_hWininet = LoadLibrary(TEXT("wininet.dll"));
|
|
AssertSz((NULL != s_hWininet), TEXT("LoadLibrary failed on Wininet.DLL"));
|
|
|
|
if (0 == s_hWininet)
|
|
fRet = FALSE;
|
|
else
|
|
{
|
|
GET_PROC_ADDR(s_hWininet, InternetCanonicalizeUrlW)
|
|
GET_PROC_ADDR(s_hWininet, InternetGetConnectedState)
|
|
}
|
|
}
|
|
|
|
#ifdef USE_CRITSEC
|
|
LeaveCriticalSection(&cs);
|
|
#endif
|
|
return fRet;
|
|
}
|
|
|
|
|
|
BOOL DemandLoadURLMON(void)
|
|
{
|
|
BOOL fRet = TRUE;
|
|
|
|
Assert(s_fInit);
|
|
#ifdef USE_CRITSEC
|
|
EnterCriticalSection(&cs);
|
|
#endif
|
|
|
|
if (0 == s_hUrlmon)
|
|
{
|
|
s_hUrlmon = LoadLibrary(TEXT("URLMON.DLL"));
|
|
AssertSz((NULL != s_hUrlmon), TEXT("LoadLibrary failed on Urlmon.DLL"));
|
|
|
|
if (0 == s_hUrlmon)
|
|
fRet = FALSE;
|
|
else
|
|
{
|
|
GET_PROC_ADDR(s_hUrlmon, ObtainUserAgentString);
|
|
}
|
|
}
|
|
|
|
#ifdef USE_CRITSEC
|
|
LeaveCriticalSection(&cs);
|
|
#endif
|
|
return fRet;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// DemandLoadShlwapi()
|
|
//
|
|
// Only load version 5.0 or greater
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
static const TCHAR c_szShlwapiDll[] = TEXT("shlwapi.dll");
|
|
|
|
HINSTANCE DemandLoadShlwapi()
|
|
{
|
|
Assert(s_fInit);
|
|
#ifdef USE_CRITSEC
|
|
EnterCriticalSection(&cs);
|
|
#endif
|
|
|
|
if (!s_hShlwapi)
|
|
s_hShlwapi = LoadLibrary(c_szShlwapiDll);
|
|
|
|
#ifdef USE_CRITSEC
|
|
LeaveCriticalSection(&cs);
|
|
#endif
|
|
|
|
return s_hShlwapi;
|
|
}
|