Windows2003-3790/inetcore/outlookexpress/msoeacct/mimedem.cpp
2020-09-30 16:53:55 +02:00

335 lines
11 KiB
C++

/*
** m i m e d e m . c p p
**
** Purpose: implement the loader functions for defer/demand -loaded libraries
**
** Creators: yst
** Created: 2/10/99
**
** Copyright (C) Microsoft Corp. 1999
*/
#include "pch.hxx"
#include "imnact.h"
#include <acctimp.h>
#include "resource.h"
// W4 stuff
#pragma warning(disable: 4201) // nameless struct/union
#pragma warning(disable: 4514) // unreferenced inline function removed
#define IMPLEMENT_LOADER_FUNCTIONS
#include "mimedem.h"
// --------------------------------------------------------------------------------
// CRIT_GET_PROC_ADDR
// --------------------------------------------------------------------------------
#define CRIT_GET_PROC_ADDR(h, fn, temp) \
temp = (TYP_##fn) GetProcAddress(h, #fn); \
if (temp) \
VAR_##fn = temp; \
else \
{ \
AssertSz(0, VAR_##fn" failed to load"); \
goto error; \
}
// --------------------------------------------------------------------------------
// RESET
// --------------------------------------------------------------------------------
#define RESET(fn) VAR_##fn = LOADER_##fn;
// --------------------------------------------------------------------------------
// GET_PROC_ADDR
// --------------------------------------------------------------------------------
#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; \
}
// --------------------------------------------------------------------------------
// GET_PROC_ADDR_ORDINAL
// --------------------------------------------------------------------------------
#define GET_PROC_ADDR_ORDINAL(h, fn, ord) \
VAR_##fn = (TYP_##fn) GetProcAddress(h, MAKEINTRESOURCE(ord)); \
Assert(VAR_##fn != NULL); \
if(NULL == VAR_##fn ) { \
VAR_##fn = LOADER_##fn; \
}
// --------------------------------------------------------------------------------
// GET_PROC_ADDR3
// --------------------------------------------------------------------------------
#define GET_PROC_ADDR3(h, fn, varname) \
VAR_##varname = (TYP_##varname) GetProcAddress(h, #fn); \
Assert(VAR_##varname != NULL);
////////////////////////////////////////////////////////////////////////////
//
// Variables
////////////////////////////////////////////////////////////////////////////
static HMODULE s_hMimeOle = 0;
static CRITICAL_SECTION g_csDefMimeLoad = {0};
// --------------------------------------------------------------------------------
// InitDemandLoadedLibs
// --------------------------------------------------------------------------------
void InitDemandMimeole(void)
{
InitializeCriticalSection(&g_csDefMimeLoad);
}
// --------------------------------------------------------------------------------
// FreeDemandLoadedLibs
// --------------------------------------------------------------------------------
void FreeDemandMimeOle(void)
{
EnterCriticalSection(&g_csDefMimeLoad);
SafeFreeLibrary(s_hMimeOle);
LeaveCriticalSection(&g_csDefMimeLoad);
DeleteCriticalSection(&g_csDefMimeLoad);
}
// --------------------------------------------------------------------------------
// DemandLoadCrypt32
// --------------------------------------------------------------------------------
BOOL DemandLoadMimeOle(void)
{
BOOL fRet = TRUE;
EnterCriticalSection(&g_csDefMimeLoad);
if (0 == s_hMimeOle)
{
s_hMimeOle = LoadLibrary("INETCOMM.DLL");
AssertSz((NULL != s_hMimeOle), TEXT("LoadLibrary failed on INETCOMM.DLL"));
if (0 == s_hMimeOle)
fRet = FALSE;
else
{
GET_PROC_ADDR(s_hMimeOle, MimeOleSMimeCapsToDlg);
GET_PROC_ADDR(s_hMimeOle, MimeOleSMimeCapsFromDlg);
GET_PROC_ADDR(s_hMimeOle, MimeOleSMimeCapsFull);
GET_PROC_ADDR(s_hMimeOle, MimeOleSMimeCapInit);
}
}
LeaveCriticalSection(&g_csDefMimeLoad);
return fRet;
}
HRESULT HrGetHighestSymcaps(LPBYTE * ppbSymcap, ULONG *pcbSymcap);
const BYTE c_RC2_40_ALGORITHM_ID[] =
{0x30, 0x0F, 0x30, 0x0D, 0x06, 0x08, 0x2A, 0x86,
0x48, 0x86, 0xF7, 0x0D, 0x03, 0x02, 0x02, 0x01,
0x28};
const ULONG cbRC2_40_ALGORITHM_ID = 0x11; // Must be 11 hex to match size!
BOOL AdvSec_FillEncAlgCombo(HWND hwnd, IImnAccount *pAcct, PCCERT_CONTEXT * prgCerts)
{
HRESULT hr;
THUMBBLOB tb = {0,0};
// Get the default caps blob from the registry
// hr = poi->pOpt->GetProperty(MAKEPROPSTRING(OPT_MAIL_DEFENCRYPTSYMCAPS), &var, 0);
if (SUCCEEDED(hr = pAcct->GetProp(AP_SMTP_ENCRYPT_ALGTH, NULL, &tb.cbSize)))
{
if (!MemAlloc((void**)&tb.pBlobData, tb.cbSize))
tb.pBlobData = NULL;
else
hr = pAcct->GetProp(AP_SMTP_ENCRYPT_ALGTH, tb.pBlobData, &tb.cbSize);
}
if (FAILED(hr) || ! tb.cbSize || ! tb.pBlobData)
{
HrGetHighestSymcaps(&tb.pBlobData, &tb.cbSize);
}
if (tb.pBlobData && tb.cbSize)
{
// Init the caps->dlg engine
if (FAILED(hr = MimeOleSMimeCapsToDlg(
tb.pBlobData,
tb.cbSize,
(prgCerts ? 1 : 0),
prgCerts,
hwnd,
IDC_ALGCOMBO, // combo box for encryption algorithms
0, // combo box for signing algorithms (we combine encrypt and signing)
0))) // id of checkbox for pkcs7-opaque. We handle this elsewhere.
{
DOUTL(1024, "MimeOleSMimeCapsToDlg -> %x\n", hr);
}
SafeMemFree(tb.pBlobData);
}
return(SUCCEEDED(hr));
}
// Largest symcap is currently 0x4E with 3DES, RC2/128, RC2/64, DES, RC2/40 and SHA-1.
// You may want to bump up the size when FORTEZZA algorithms are supported.
#define CCH_BEST_SYMCAP 0x50
HRESULT HrGetHighestSymcaps(LPBYTE * ppbSymcap, ULONG *pcbSymcap)
{
HRESULT hr=S_OK;
LPVOID pvSymCapsCookie = NULL;
LPBYTE pbEncode = NULL;
ULONG cbEncode = 0;
DWORD dwBits;
// The MimeOleSMimeCapsFull call is quite expensive. The results are always
// the same during a session. (They can only change with software upgrade.)
// Cache the results here for better performance.
static BYTE szSaveBestSymcap[CCH_BEST_SYMCAP];
static ULONG cbSaveBestSymcap = 0;
if (cbSaveBestSymcap == 0)
{
// Init with no symcap gives max allowed by providers
hr = MimeOleSMimeCapInit(NULL, NULL, &pvSymCapsCookie);
if (FAILED(hr))
goto exit;
if (pvSymCapsCookie)
{
// Finish up with SymCaps
MimeOleSMimeCapsFull(pvSymCapsCookie, TRUE, FALSE, pbEncode, &cbEncode);
if (cbEncode)
{
if (! MemAlloc((LPVOID *)&pbEncode, cbEncode))
cbEncode = 0;
else
{
hr = MimeOleSMimeCapsFull(pvSymCapsCookie, TRUE, FALSE, pbEncode, &cbEncode);
if (SUCCEEDED(hr))
{
// Save this symcap in the static array for next time
// Only if we have room!
if (cbEncode <= CCH_BEST_SYMCAP)
{
memcpy(szSaveBestSymcap, pbEncode, cbEncode);
cbSaveBestSymcap = cbEncode;
}
}
}
}
SafeMemFree(pvSymCapsCookie);
}
}
else
{
// We have saved the best in the static array. Avoid the time intensive
// MimeOle query.
cbEncode = cbSaveBestSymcap;
if (! MemAlloc((LPVOID *)&pbEncode, cbEncode))
cbEncode = 0;
else
memcpy(pbEncode, szSaveBestSymcap, cbEncode);
}
exit:
if (! pbEncode)
{
// Hey, there should ALWAYS be at least RC2 (40 bit). What happened?
AssertSz(cbEncode, "MimeOleSMimeCapGetEncAlg gave us no encoding algorithm");
// Try to fix it up as best you can. Stick in the RC2 value.
cbEncode = cbRC2_40_ALGORITHM_ID;
if (MemAlloc((LPVOID *)&pbEncode, cbEncode))
{
memcpy(pbEncode, (LPBYTE)c_RC2_40_ALGORITHM_ID, cbEncode);
hr = S_OK;
}
}
if (cbEncode && pbEncode)
{
*pcbSymcap = cbEncode;
*ppbSymcap = pbEncode;
}
return(hr);
}
BOOL AdvSec_GetEncryptAlgCombo(HWND hwnd, IImnAccount *pAcct)
{
HRESULT hr;
LPBYTE pbSymCaps = NULL;
ULONG cbSymCaps = 0;
// How big a buffer do I need?
hr = MimeOleSMimeCapsFromDlg(hwnd,
IDC_ALGCOMBO, // idEncryptAlgs
0, // idSignAlgs,
0, // idBlob,
NULL,
&cbSymCaps);
// Never mind the hr, it's screwy. Do we have a size?
if (cbSymCaps)
{
if (MemAlloc((void **)&pbSymCaps, cbSymCaps))
{
if (hr = MimeOleSMimeCapsFromDlg(hwnd,
IDC_ALGCOMBO, // idEncryptAlgs
0, // idSignAlgs,
0, // idBlob,
pbSymCaps, &cbSymCaps))
{
DOUTL(1024, "MimeOleSMimeCapsFromDlg -> %x", hr);
}
else
{
LPBYTE pbBestSymcaps = NULL;
ULONG cbBestSymcaps = 0;
// Compare symcaps to highest available.
if (SUCCEEDED(HrGetHighestSymcaps(&pbBestSymcaps, &cbBestSymcaps)) &&
(cbBestSymcaps == cbSymCaps && (0 == memcmp(pbBestSymcaps, pbSymCaps, cbBestSymcaps)))) {
// Best available symcaps. Set it to default value of NULL (which should delete the prop.)
SafeMemFree(pbSymCaps);
cbSymCaps = 0;
pbSymCaps = NULL;
}
SafeMemFree(pbBestSymcaps);
pAcct->SetProp(AP_SMTP_ENCRYPT_ALGTH, pbSymCaps, cbSymCaps);
}
}
else
{
DOUTL(1024, "MemAlloc of SymCaps blob failed");
hr = E_OUTOFMEMORY;
}
}
else
{
DOUTL(1024, "BAD NEWS: First MimeOleSMimeCapsFromDlg didn't return size", hr);
Assert(hr); // Weird, maybe there isn't a symcaps?
hr = E_FAIL;
}
SafeMemFree(pbSymCaps);
return(SUCCEEDED(hr));
}