Leaked source code of windows server 2003
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.
 
 
 
 
 
 

4147 lines
121 KiB

// ===========================================================================
// I P A B . C P P
// ===========================================================================
#include "pch.hxx"
#include "ipab.h"
#include "error.h"
#include "xpcomm.h"
#include <strconst.h>
#include "ourguid.h"
#include <wabguid.h> // IID_IDistList etc.
#include <certs.h>
#include <shlwapi.h>
#include <shlwapip.h>
#include <mimeole.h>
#include <secutil.h>
#include "demand.h"
#include "conman.h"
#include "multiusr.h"
#include "instance.h"
// ===========================================================================
// G L O B A L S - The globals are set int HrInitWab
// ===========================================================================
static BOOL g_fWabInit = FALSE;
static BOOL g_fWabLoaded = FALSE;
static HINSTANCE g_hWab32Dll = NULL;
static LPWABOPEN g_lpfnWabOpen = NULL;
static LPWABOBJECT g_lpWabObject = NULL;
static LPADRBOOK g_lpAdrBook = NULL;
static CRITICAL_SECTION g_rWabCritSect = {0};
static CWab *g_pWab = NULL;
static TCHAR c_szOEThis[] = "OE_ThisPtr";
// ===========================================================================
// P R O T O T Y P E S
// ===========================================================================
HRESULT HrLoadWab (VOID);
BOOL FUnloadWab (VOID);
VOID ReleaseWabObjects (LPWABOBJECT lpWabObject, LPADRBOOK lpAdrBook);
void SerialAdrInfoString(LPWSTR *ppwszDest, ULONG cchDest, LPWSTR pwszSrc, ULONG *pcbOff,
LPBYTE *ppbData);
HRESULT HrAddrInfoListToHGlobal (LPADRINFOLIST lpAdrInfoList,
HGLOBAL *phGlobal);
HRESULT HrHGlobalToAddrInfoList (HGLOBAL hGlobal, LPADRINFOLIST *lplpAdrInfoList); // caller frees with MemFree
ULONG CbAdrInfoSize (LPADRINFO lpAdrInfo);
HRESULT HrSetAdrEntry (LPWABOBJECT lpWab, LPADRENTRY lpAdrEntry,
LPADRINFO lpAdrInfo, DWORD mask);
LPTSTR SzWabStringDup (LPWABOBJECT lpWab, LPCSTR lpcsz, LPVOID lpParentObject);
LPWSTR SzWabStringDupW(LPWABOBJECT lpWab, LPCWSTR lpcwsz, LPVOID lpParentObject);
LPBYTE LpbWabBinaryDup (LPWABOBJECT lpWab, LPBYTE lpbSrc, ULONG cb, LPVOID lpParentObject);
void STDMETHODCALLTYPE DismissWabWindow(ULONG_PTR ulUIParam, LPVOID lpvContext);
#ifdef DEBUG
void DEBUGDumpAdrList(LPADRLIST pal);
#endif
// ===========================================================================
// HrInitWab
// ===========================================================================
HRESULT HrInitWab (BOOL fInit)
{
// Locals
HRESULT hr = S_OK;
// Initialize the WAB
if (fInit)
{
// Have we already been initialized ?
if (g_fWabInit)
goto exit;
// Wab has been inited, doesn't imply success
g_fWabInit = TRUE;
// Init Critical Section
InitializeCriticalSection (&g_rWabCritSect);
// Load the WAB
CHECKHR (hr = HrLoadWab ());
}
// Unload Wab
else
{
// Not inited ?
if (!g_fWabInit)
goto exit;
// Unload Wab
if (FUnloadWab () == TRUE)
{
// Kill critical section
DeleteCriticalSection (&g_rWabCritSect);
// Not inited
g_fWabInit = FALSE;
}
}
exit:
// Done
if (fInit && FAILED (hr))
AthMessageBoxW(g_hwndInit, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrLoadingWAB), NULL, MB_OK);
return hr;
}
const static TCHAR lpszWABDLLRegPathKey[] = TEXT("Software\\Microsoft\\WAB\\DLLPath");
const static TCHAR lpszWABEXERegPathKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wab.exe");
const static TCHAR lpszWABEXE[] = TEXT("wab.exe");
// =============================================================================
// HrLoadPathWABEXE - creaetd vikramm 5/14/97 - loads the registered path of the
// latest wab.exe
// szPath - pointer to a buffer
// cbPath - sizeof buffer
// =============================================================================
// ~~~~ @TODO dhaws Might need to convert this
HRESULT HrLoadPathWABEXE(LPTSTR szPath, ULONG cbPath)
{
DWORD dwType;
ULONG cbData = cbPath;
HKEY hKey;
Assert(szPath != NULL);
Assert(cbPath > 0);
*szPath = '\0';
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszWABEXERegPathKey, 0, KEY_READ, &hKey))
{
SHQueryValueEx( hKey, c_szEmpty, NULL, &dwType, (LPBYTE) szPath, &cbData);
RegCloseKey(hKey);
}
if(!lstrlen(szPath))
StrCpyN(szPath, lpszWABEXE,cbPath/sizeof(szPath[0]));
return S_OK;
}
// ===========================================================================
// HrLoadLibraryWabDLL - added vikramm 5/14 - new wab setup needs this
// ===========================================================================
HINSTANCE LoadLibraryWabDLL (VOID)
{
TCHAR szWABDllPath[MAX_PATH];
DWORD dwType;
ULONG cbData = sizeof(szWABDllPath);
HKEY hKey;
*szWABDllPath = '\0';
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszWABDLLRegPathKey, 0, KEY_READ, &hKey))
{
SHQueryValueEx( hKey, c_szEmpty, NULL, &dwType, (LPBYTE) szWABDllPath, &cbData);
RegCloseKey(hKey);
}
if(!lstrlen(szWABDllPath))
StrCpyN(szWABDllPath, WAB_DLL_NAME, ARRAYSIZE(szWABDllPath));
return(LoadLibrary(szWABDllPath));
}
// ===========================================================================
// HrLoadWab
// ===========================================================================
HRESULT HrLoadWab (VOID)
{
// Locals
HRESULT hr = S_OK;
WAB_PARAM wp = {0};
LPWAB pWab;
// We better be init'ed
Assert (g_fWabInit == TRUE);
// Enter Critical Section
EnterCriticalSection (&g_rWabCritSect);
// Load the WAB Dll
g_hWab32Dll = LoadLibraryWabDLL();
// Did it load
if (g_hWab32Dll == NULL)
{
hr = TRAPHR (hrUnableToLoadWab32Dll);
goto exit;
}
// Get WABOpen proc
IF_WIN32(g_lpfnWabOpen = (LPWABOPEN)GetProcAddress (g_hWab32Dll, "WABOpen");)
IF_WIN16(g_lpfnWabOpen = (LPWABOPEN)GetProcAddress (g_hWab32Dll, "_WABOpen");)
// Did we get the proc ?
if (g_lpfnWabOpen == NULL)
{
hr = TRAPHR (hrUnableToLoadWab32Dll);
goto exit;
}
// get the current user id to open the right view in the WAB.
wp.cbSize = sizeof(WAB_PARAM);
wp.guidPSExt = CLSID_AddrObject; // was CLSID_OEBAControl, bug 99652;
wp.ulFlags = (g_dwAthenaMode & MODE_NEWSONLY) ? WAB_ENABLE_PROFILES | MAPI_UNICODE:
WAB_ENABLE_PROFILES | MAPI_UNICODE | WAB_USE_OE_SENDMAIL;
// Open the wab and get the objects
CHECKHR (hr = (*g_lpfnWabOpen)(&g_lpAdrBook, &g_lpWabObject, &wp, 0));
pWab = new CWab;
if (pWab == NULL)
{
hr = TRAPHR (hrMemory);
goto exit;
}
else
{
g_pWab = pWab;
}
// Yee-hah, the wab is loaded
g_fWabLoaded = TRUE;
exit:
// Leave Critical Section
LeaveCriticalSection (&g_rWabCritSect);
// Done
return hr;
}
// ===========================================================================
// UnloadWab
// ===========================================================================
BOOL FUnloadWab (VOID)
{
// Locals
ULONG cWabObjectRefs = 0, cAdrBookRefs = 0, cWabRefs = 0;
BOOL fResult = FALSE;
// We better have been inited
Assert (g_fWabInit == TRUE);
// Enter Critical Section
EnterCriticalSection (&g_rWabCritSect);
// Release global objects
if (g_lpAdrBook && g_lpWabObject && g_pWab)
{
if (g_pWab)
g_pWab->OnClose(); // the close callback will release it.
// Get Ref Counts and cleanup
cWabRefs = g_pWab->Release ();
g_pWab = NULL;
cAdrBookRefs = g_lpAdrBook->Release ();
g_lpAdrBook = NULL;
cWabObjectRefs = g_lpWabObject->Release ();
g_lpWabObject = NULL;
g_fWabLoaded = FALSE;
fResult = TRUE;
// These better be the same
//Assert (cWabObjectRefs == cAdrBookRefs);
// Can we unload now ?
if (cWabObjectRefs == 0 && cAdrBookRefs == 0 && cWabRefs == 0)
{
// Unload the dll
if (g_hWab32Dll)
{
FreeLibrary (g_hWab32Dll);
g_hWab32Dll = NULL;
}
// Reset the proc pointer to NULL
g_lpfnWabOpen = NULL;
}
}
// Leave Critical Section
LeaveCriticalSection (&g_rWabCritSect);
// Done
return fResult;
}
// ===========================================================================
// ReleaseWabObjects
// ===========================================================================
VOID ReleaseWabObjects (LPWABOBJECT lpWabObject, LPADRBOOK lpAdrBook)
{
// Locals
ULONG cWabObjectRefs = 0, cAdrBookRefs = 0;
// We better have been inited
Assert (g_fWabInit == TRUE);
// Check Params
if (lpWabObject == NULL || lpAdrBook == NULL)
{
Assert (FALSE);
return;
}
// Enter Critical Section
EnterCriticalSection (&g_rWabCritSect);
// Release objects
Assert (g_lpAdrBook && g_lpWabObject)
// Release the wab
cAdrBookRefs = lpAdrBook->Release ();
cWabObjectRefs = lpWabObject->Release ();
// Ref counts should hit zero at the same time
#ifdef DEBUG
if (cWabObjectRefs==0)
Assert(cAdrBookRefs==0);
if (cAdrBookRefs==0)
Assert(cWabObjectRefs==0);
#endif
// If both counts are zero, we can unload the dll
if (cWabObjectRefs == 0 && cAdrBookRefs == 0)
{
// Set globals
g_lpWabObject = NULL;
g_lpAdrBook = NULL;
// Unload the WAB
if (g_hWab32Dll)
{
FreeLibrary (g_hWab32Dll);
g_hWab32Dll = NULL;
}
// Reset the proc pointer to NULL
g_lpfnWabOpen = NULL;
// Not loaded, not inited
g_fWabLoaded = FALSE;
// Not inited
g_fWabInit = FALSE;
// Leave Critical Section
LeaveCriticalSection (&g_rWabCritSect);
// Kill critical section
DeleteCriticalSection (&g_rWabCritSect);
}
else
{
// Leave Critical Section
LeaveCriticalSection (&g_rWabCritSect);
}
// Done
return;
}
/***************************************************************************
Name : FWABTranslateAccelerator
Purpose : Give an open WAB window a change to look for accelerators.
Parameters: lpmsg -> lpmsg from the current event
Returns : BOOL - was the event used
***************************************************************************/
BOOL FWABTranslateAccelerator(LPMSG lpmsg)
{
if (g_pWab)
return g_pWab->FTranslateAccelerator(lpmsg);
else
return FALSE;
}
// ===========================================================================
// HrCreateWabObject
// ===========================================================================
HRESULT HrCreateWabObject (LPWAB *lppWab)
{
// Locals
HRESULT hr = S_OK;
// Check Params
Assert (lppWab);
hr=HrInitWab(TRUE);
if (FAILED(hr))
return hr;
// Verify Globals
if (g_fWabLoaded == FALSE || g_fWabInit == FALSE)
{
return TRAPHR (hrWabNotLoaded);
}
// Enter Critical Section
EnterCriticalSection (&g_rWabCritSect);
// Verify globals
Assert (g_lpfnWabOpen && g_hWab32Dll && g_lpAdrBook && g_lpWabObject && g_pWab);
// Inst it
g_pWab->AddRef();
*lppWab = g_pWab;
// Leave Critical Section
LeaveCriticalSection (&g_rWabCritSect);
// Done
return hr;
}
// ===========================================================================
// DismissWabWindow
// ===========================================================================
void STDMETHODCALLTYPE DismissWabWindow(ULONG_PTR ulUIParam, LPVOID lpvContext)
{
CWab *pWab = (CWab *) lpvContext;
Assert(pWab == g_pWab);
if (pWab == g_pWab)
{
g_pWab->BrowseWindowClosed();
}
}
/*
-
- Checks for the existence of a Contact with a specific e-mail address
*
*/
HRESULT HrCheckEMailExistence(LPADRBOOK lpAdrBook, LPWABOBJECT lpWabObject, LPWSTR lpwszLookup)
{
HRESULT hr = NOERROR;
ULONG i = 0, j=0;
LPADRLIST lpAdrList = NULL;
BOOL fFound = FALSE;
Assert(lpAdrBook && lpWabObject);
hr = lpWabObject->AllocateBuffer(sizeof(ADRLIST), (LPVOID *)&lpAdrList);
if(FAILED(hr))
goto Cleanup;
Assert(lpAdrList);
lpAdrList->cEntries = 1;
lpAdrList->aEntries[0].ulReserved1 = 0;
lpAdrList->aEntries[0].cValues = 1;
hr = lpWabObject->AllocateBuffer(sizeof(SPropValue), (LPVOID *)&lpAdrList->aEntries[0].rgPropVals);
if(FAILED(hr))
goto Cleanup;
lpAdrList->aEntries[0].rgPropVals[0].ulPropTag = PR_EMAIL_ADDRESS_W;
lpAdrList->aEntries[0].rgPropVals[0].Value.lpszW = lpwszLookup;
hr = lpAdrBook->ResolveName ( 0,
WAB_RESOLVE_LOCAL_ONLY |
WAB_RESOLVE_ALL_EMAILS |
WAB_RESOLVE_USE_CURRENT_PROFILE |
WAB_RESOLVE_UNICODE,
NULL, lpAdrList);
if(FAILED(hr))
goto Cleanup;
for(j=0; j<lpAdrList->aEntries[0].cValues; j++)
{
if(lpAdrList->aEntries[0].rgPropVals[j].ulPropTag == PR_ENTRYID)
{
fFound = TRUE;
break;
}
}
if(!fFound)
hr = MAPI_E_NOT_FOUND;
Cleanup:
if (lpAdrList)
{
for (ULONG ul = 0; ul < lpAdrList->cEntries; ul++)
lpWabObject->FreeBuffer(lpAdrList->aEntries[ul].rgPropVals);
lpWabObject->FreeBuffer(lpAdrList);
}
return hr;
}
/***************************************************************************
Name : HrWABCreateEntry
Purpose : Create a new entry in the WAB
Parameters: lpAdrBook -> ADDRBOOK object
lpWabObject -> WABOBJECT for allocators
lpszDisplay -> display name to set [optional]
lpszAddress -> email address to set [optional]
ulFlags = flags for CreateEntry
CREATE_CHECK_DUP_STRICT
lppMailUser -> returned MAILUSER object. [optional]
Returns : HRESULT
Comment :
***************************************************************************/
HRESULT HrWABCreateEntry(LPADRBOOK lpAdrBook, LPWABOBJECT lpWabObject,
LPWSTR lpwszDisplay, LPWSTR lpwszAddress, ULONG ulFlags,
LPMAILUSER *lppMailUser, ULONG ulSaveFlags)
{
LPABCONT pabcWAB = NULL;
ULONG cbEidWAB;
LPENTRYID peidWAB = NULL;
LPMAILUSER lpMailUser = NULL;
SPropValue rgpv[3];
SPropTagArray ptaEID = {1, {PR_ENTRYID}};
LPSPropValue ppvDefMailUser=0;
SizedSPropTagArray(1, ptaDefMailUser)=
{ 1, {PR_DEF_CREATE_MAILUSER} };
ULONG cProps,
ulObjectType;
HRESULT hr;
Assert(lpwszDisplay);
Assert(lpAdrBook);
Assert(lpWabObject);
if(lpwszAddress && *lpwszAddress)
{
// Check if the e-mail exists before auto-adding-to-wab
hr = HrCheckEMailExistence(lpAdrBook, lpWabObject, lpwszAddress);
if(hr != MAPI_E_NOT_FOUND)
{
//either it's found or it's an error
//if it's found, then this function should generate a collision error
if(hr == NOERROR)
hr = MAPI_E_COLLISION;
goto error;
}
}
// Create a new contact with these properties
// First, create the basic contact with only a display name
hr = lpAdrBook->GetPAB(&cbEidWAB, &peidWAB);
if (FAILED(hr))
goto error;
hr = lpAdrBook->OpenEntry(cbEidWAB, peidWAB, NULL, 0, &ulObjectType, (LPUNKNOWN *)&pabcWAB);
if (FAILED(hr))
goto error;
Assert(ulObjectType == MAPI_ABCONT);
lpWabObject->FreeBuffer(peidWAB);
hr = pabcWAB->GetProps((LPSPropTagArray)&ptaDefMailUser, 0, &cProps, &ppvDefMailUser);
if (FAILED(hr) || ! ppvDefMailUser || ppvDefMailUser->ulPropTag != PR_DEF_CREATE_MAILUSER)
goto error;
hr = pabcWAB->CreateEntry(ppvDefMailUser->Value.bin.cb, (LPENTRYID)ppvDefMailUser->Value.bin.lpb,
ulFlags, (LPMAPIPROP *)&lpMailUser);
if (FAILED(hr))
goto error;
rgpv[0].ulPropTag = PR_DISPLAY_NAME_W;
rgpv[0].Value.lpszW = lpwszDisplay;
cProps = 1;
if (lpwszAddress)
{
rgpv[1].ulPropTag = PR_ADDRTYPE_W;
rgpv[1].Value.lpszW = L"SMTP";
cProps++;
rgpv[2].ulPropTag = PR_EMAIL_ADDRESS_W;
rgpv[2].Value.lpszW = lpwszAddress;
cProps++;
}
hr = lpMailUser->SetProps(cProps, rgpv, NULL);
if (FAILED(hr))
goto error;
hr = lpMailUser->SaveChanges(ulSaveFlags /*KEEP_OPEN_READONLY*/);
if (FAILED(hr))
goto error;
// Return the new object if it was asked for
if (lppMailUser)
{
*lppMailUser = lpMailUser;
lpMailUser = NULL; // short circuit the release below.
}
error:
ReleaseObj(lpMailUser);
ReleaseObj(pabcWAB);
if (ppvDefMailUser)
lpWabObject->FreeBuffer(ppvDefMailUser);
return(hr);
}
// ===========================================================================
// CWab::CWab
// ===========================================================================
CWab::CWab ()
{
DOUT ("CWab::CWab");
m_cRef = 1;
m_lpWabObject = g_lpWabObject;
m_lpWabObject->AddRef();
m_lpAdrBook = g_lpAdrBook;
m_lpAdrBook->AddRef();
m_hwnd = NULL;
m_pfnWabWndProc = NULL;
ZeroMemory(&m_adrParm, sizeof(m_adrParm));
m_fInternal = FALSE;
ZeroMemory(&m_hlDisabled, sizeof(HWNDLIST));
}
// ===========================================================================
// CWab::CWab
// ===========================================================================
CWab::~CWab ()
{
DOUT ("CWab::~CWab");
ReleaseWabObjects (m_lpWabObject, m_lpAdrBook);
}
// =============================================================================
// CWab::AddRef
// =============================================================================
ULONG CWab::AddRef (VOID)
{
DOUT("CWab::AddRef %lx ==> %d", this, m_cRef+1);
return ++m_cRef;
}
// =============================================================================
// CWab::Release
// =============================================================================
ULONG CWab::Release (VOID)
{
DOUT("CWab::Release %lx ==> %d", this, m_cRef-1);
if (--m_cRef == 0)
{
delete this;
return 0;
}
return m_cRef;
}
// =============================================================================
// CWab::FVerifyState
// =============================================================================
BOOL CWab::FVerifyState (VOID)
{
// We need these things !
if (m_lpWabObject == NULL || m_lpAdrBook == NULL)
{
Assert (FALSE);
return FALSE;
}
// Done
return TRUE;
}
// =============================================================================
// CWab::HrPickNames
// =============================================================================
HRESULT CWab::HrPickNames (HWND hwndParent, ULONG *rgulTypes, int cWells, int iFocus, BOOL fNews, LPADRLIST *lppal)
{
// Locals
int i, ids;
HRESULT hr = S_OK;
WCHAR wsz[CCHMAX_STRINGRES],
wsz2[CCHMAX_STRINGRES];
ADRPARM AdrParms = {0};
LPWSTR *ppwszWells = NULL;
// Check Parameters
Assert (lppal);
Assert(cWells > 0);
// Have we been initialized
if (FVerifyState () == FALSE)
{
hr = TRAPHR (E_FAIL);
return hr;
}
if (!MemAlloc((LPVOID *)&ppwszWells, cWells*sizeof(LPWSTR)))
{
hr = E_OUTOFMEMORY;
goto error;
}
ZeroMemory(ppwszWells, cWells * sizeof(LPWSTR));
AthLoadStringW(idsMsgRecipients, wsz2, ARRAYSIZE(wsz2));
AthLoadStringW(idsPickRecipientsTT, wsz, ARRAYSIZE(wsz));
AdrParms.ulFlags=DIALOG_MODAL|MAPI_UNICODE;
AdrParms.lpszCaption=(LPTSTR)wsz;
AdrParms.cDestFields = cWells;
AdrParms.nDestFieldFocus = iFocus;
AdrParms.lpulDestComps = rgulTypes;
AdrParms.lpszDestWellsTitle = (LPTSTR)wsz2;
for (i = 0; i < cWells; i++)
{
switch (rgulTypes[i])
{
case MAPI_TO:
if (!fNews)
{
ids = idsToWell;
break;
}
// fall thru...
case MAPI_CC:
ids = idsCcWell;
break;
case MAPI_ORIG:
ids = idsFromWell;
break;
case MAPI_REPLYTO:
ids = idsReplyToWell;
break;
case MAPI_BCC:
ids = idsBccWell;
break;
default:
Assert(FALSE);
break;
}
if (!MemAlloc((LPVOID *)&ppwszWells[i], CCHMAX_STRINGRES * sizeof(WCHAR)))
{
hr = E_OUTOFMEMORY;
goto error;
}
AthLoadStringW(ids, ppwszWells[i], CCHMAX_STRINGRES);
}
AdrParms.lppszDestTitles = (LPTSTR *)ppwszWells;
// Show the dialog
hr = m_lpAdrBook->Address ((ULONG_PTR *)&hwndParent, &AdrParms, lppal);
#ifdef DEBUG
DEBUGDumpAdrList(*lppal);
#endif
// Cleanup
if (ppwszWells)
{
for (i=0; i<cWells; i++)
SafeMemFree(ppwszWells[i]);
MemFree(ppwszWells);
}
error:
// Done
return hr;
}
// =============================================================================
// CWab::HrGeneralPickNames
// =============================================================================
HRESULT CWab::HrGeneralPickNames(HWND hwndParent, ADRPARM *pAdrParms, LPADRLIST *lppal)
{
// Locals
HRESULT hr = S_OK;
// Check Parameters
Assert (lppal);
// Have we been initialized
if (FVerifyState () == FALSE)
{
hr = TRAPHR (E_FAIL);
return hr;
}
// Show the dialog
hr = m_lpAdrBook->Address ((ULONG_PTR *)&hwndParent, pAdrParms, lppal);
// Cleanup
if (FAILED (hr))
{
if (*lppal)
{
m_lpWabObject->FreeBuffer (*lppal);
*lppal = NULL;
}
}
// Done
return hr;
}
// =============================================================================
// CWab::HrBrowse
// =============================================================================
HRESULT CWab::HrBrowse (HWND hwndParent, BOOL fModal)
{
ULONG_PTR uiParam = (ULONG_PTR)hwndParent;
LPADRLIST pAdrList = NULL;
HRESULT hr;
TCHAR szWabCaption[CCHMAX_STRINGRES];
// Change to use IAddrBook::Address
Assert(m_lpAdrBook);
AthLoadString(idsAddressBook, szWabCaption, sizeof(szWabCaption));
ZeroMemory(&m_adrParm, sizeof(m_adrParm));
m_adrParm.ulFlags = fModal ? DIALOG_MODAL : DIALOG_SDI;
if (!fModal)
{
//m_adrParm.lpszCaption = szWabCaption;
m_adrParm.lpfnDismiss = &DismissWabWindow;
m_adrParm.lpvDismissContext = (void *)this;
}
hr = m_lpAdrBook->Address(&uiParam, &m_adrParm, &pAdrList);
if (SUCCEEDED(hr) && g_pInstance && !fModal)
{
// subclass the wab window, if there isn't one already up
if (GetProp((HWND)uiParam, c_szOEThis) == 0)
{
m_pfnWabWndProc = (WNDPROC)SetWindowLongPtr((HWND)uiParam, GWLP_WNDPROC, (LONG_PTR)WabSubProc);
SetProp((HWND)uiParam, c_szOEThis, (HANDLE)this);
SetProp((HWND)uiParam, c_szOETopLevel, (HANDLE)TRUE);
CoIncrementInit("WabWindow", MSOEAPI_START_SHOWERRORS, NULL, NULL);
AddRef();
}
}
m_hwnd = (HWND)uiParam;
return NOERROR;
}
// =============================================================================
// CWab::HrAddNewEntry
// =============================================================================
HRESULT CWab::HrAddNewEntryA(LPTSTR lpszDisplay, LPTSTR lpszAddress)
{
LPWSTR pwszDisplay = NULL,
pwszAddress = NULL;
HRESULT hr = S_OK;
Assert(lpszDisplay);
IF_NULLEXIT(pwszDisplay = PszToUnicode(CP_ACP, lpszDisplay));
// If lpszAddress is null, we have an incomplete Entry. This is ok.
pwszAddress = PszToUnicode(CP_ACP, lpszAddress);
if (lpszAddress && !pwszAddress)
IF_NULLEXIT(NULL);
hr = HrAddNewEntry(pwszDisplay, pwszAddress);
exit:
MemFree(pwszDisplay);
MemFree(pwszAddress);
return hr;
}
HRESULT CWab::HrAddNewEntry(LPWSTR lpwszDisplay, LPWSTR lpwszAddress)
{
return(HrWABCreateEntry(m_lpAdrBook,
m_lpWabObject,
lpwszDisplay,
lpwszAddress,
CREATE_CHECK_DUP_STRICT|MAPI_UNICODE,
NULL));
}
VOID CWab::FreeLPSRowSet(LPSRowSet lpsrs)
{
UINT i;
if(NULL == m_lpWabObject)
return;
if(lpsrs)
{
for(i=0;i<lpsrs->cRows;i++)
m_lpWabObject->FreeBuffer(lpsrs->aRow[i].lpProps);
m_lpWabObject->FreeBuffer(lpsrs);
}
}
VOID CWab::FreePadrlist(LPADRLIST lpAdrList)
{
if(NULL == m_lpWabObject)
return;
if(lpAdrList)
{
for (ULONG iEntry = 0; iEntry < lpAdrList->cEntries; ++iEntry)
{
if(lpAdrList->aEntries[iEntry].rgPropVals)
m_lpWabObject->FreeBuffer(lpAdrList->aEntries[iEntry].rgPropVals);
}
m_lpWabObject->FreeBuffer(lpAdrList);
}
}
HRESULT CWab::HrFind(HWND hwnd, LPWSTR lpwszLookup)
{
HRESULT hr = NOERROR;
ULONG i = 0, j=0;
LPSRowSet lpsrs = NULL;
ULONG cbEntryID=0;
LPENTRYID lpEntryID=NULL;
ULONG ulObjType = 0;
LPADRLIST lpAdrList = NULL;
BOOL fFound = FALSE;
Assert(m_lpAdrBook && m_lpWabObject);
if (lpwszLookup == NULL)
return E_INVALIDARG;
hr = m_lpWabObject->AllocateBuffer(sizeof(ADRLIST), (LPVOID *)&lpAdrList);
if(FAILED(hr))
goto Cleanup;
Assert(lpAdrList);
lpAdrList->cEntries = 1;
lpAdrList->aEntries[0].ulReserved1 = 0;
lpAdrList->aEntries[0].cValues = 1;
hr = m_lpWabObject->AllocateBuffer(sizeof(SPropValue), (LPVOID *)&lpAdrList->aEntries[0].rgPropVals);
if(FAILED(hr))
goto Cleanup;
lpAdrList->aEntries[0].rgPropVals[0].ulPropTag = PR_EMAIL_ADDRESS_W;
lpAdrList->aEntries[0].rgPropVals[0].Value.lpszW = lpwszLookup;
hr = m_lpAdrBook->ResolveName ((ULONG_PTR)hwnd, WAB_RESOLVE_NO_NOT_FOUND_UI |
WAB_RESOLVE_ALL_EMAILS |
WAB_RESOLVE_USE_CURRENT_PROFILE |
MAPI_DIALOG |
WAB_RESOLVE_UNICODE,
NULL, lpAdrList);
if(FAILED(hr))
goto Cleanup;
for(j=0; j<lpAdrList->aEntries[0].cValues; j++)
{
if(lpAdrList->aEntries[0].rgPropVals[j].ulPropTag == PR_ENTRYID)
{
cbEntryID = lpAdrList->aEntries[0].rgPropVals[j].Value.bin.cb;
lpEntryID = (LPENTRYID)lpAdrList->aEntries[0].rgPropVals[j].Value.bin.lpb;
fFound = TRUE;
hr = g_lpAdrBook->Details((ULONG_PTR *)&hwnd, NULL, NULL, cbEntryID, lpEntryID, NULL, NULL, NULL, DIALOG_MODAL);
if(FAILED(hr) && hr!=MAPI_E_USER_CANCEL)
goto Cleanup;
hr = NOERROR;
break;
}
}
Cleanup:
FreePadrlist(lpAdrList);
if(!fFound && hr!=MAPI_E_USER_CANCEL)
hr = E_FAIL;
if(hr==MAPI_E_USER_CANCEL)
hr = NOERROR;
return hr;
}
enum
{
ieidPR_DISPLAY_NAME = 0,
ieidPR_ENTRYID,
ieidPR_OBJECT_TYPE,
ieidMax
};
static const SizedSPropTagArray(ieidMax, ptaEid_A)=
{
ieidMax,
{
PR_DISPLAY_NAME_A,
PR_ENTRYID,
PR_OBJECT_TYPE
}
};
static const SizedSPropTagArray(ieidMax, ptaEid_W)=
{
ieidMax,
{
PR_DISPLAY_NAME_W,
PR_ENTRYID,
PR_OBJECT_TYPE
}
};
HRESULT CWab::HrFillComboWithPABNames(HWND hwnd, int* pcRows)
{
ULONG ulObjType = 0;
LPMAPITABLE lpTable = NULL;
LPSRowSet lpRow = NULL;
LPABCONT lpContainer = NULL;
HRESULT hr=NOERROR;
ULONG cbEID=0;
LPENTRYID lpEID = NULL;
int cNumRows = 0;
int nRows=0;
LPSTR psz = NULL;
LPWSTR lpwsz = NULL;
#if defined(FIX_75835)
COMBOBOXEXITEMW cbeiw;
SSortOrderSet ssos;
#endif
if(NULL==hwnd || NULL==pcRows)
return E_INVALIDARG;
IF_FAILEXIT(hr = m_lpAdrBook->GetPAB(&cbEID, &lpEID));
IF_FAILEXIT(hr = m_lpAdrBook->OpenEntry(cbEID, (LPENTRYID)lpEID, NULL, 0, &ulObjType, (LPUNKNOWN *)&lpContainer));
// Request UNICODE strings in table
IF_FAILEXIT(hr = lpContainer->GetContentsTable(WAB_PROFILE_CONTENTS | MAPI_UNICODE, &lpTable));
// We only care about a few columns
IF_FAILEXIT(hr =lpTable->SetColumns((LPSPropTagArray)&ptaEid_W, 0));
#if defined(FIX_75835)
// Sort the list (synchronously) on display name as ComboBoxEx doesn't support CBS_SORT
ssos.cCategories = ssos.cExpanded = 0;
ssos.cSorts = 1;
ssos.aSort[0].ulPropTag = PR_DISPLAY_NAME_W;
ssos.aSort[0].ulOrder = TABLE_SORT_ASCEND;
IF_FAILEXIT(hr = lpTable->SortTable(&ssos, 0));
#endif
// We will add the display names in order, starting with the first
IF_FAILEXIT(hr = lpTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL));
nRows = 0;
do
{
lpRow = NULL;
hr = lpTable->QueryRows(1, 0, &lpRow);
if(FAILED(hr))
goto CleanLoop;
cNumRows = lpRow->cRows;
if(cNumRows)
{
// If we have a mailuser and their display name is valid
if((lpRow->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.l == MAPI_MAILUSER) &&
(PROP_TYPE(lpRow->aRow[0].lpProps[ieidPR_DISPLAY_NAME].ulPropTag) != PT_ERROR))
{
lpwsz = lpRow->aRow[0].lpProps[ieidPR_DISPLAY_NAME].Value.lpszW;
#if defined(FIX_75835)
if(NULL != lpwsz)
{
// display name
cbeiw.pszText = lpwsz;
cbeiw.mask = CBEIF_TEXT;
cbeiw.iItem = -1;
SendMessage(hwnd, CBEM_INSERTITEMW, 0, (LPARAM)&cbeiw);
nRows++;
}
#else
if (psz = PszToANSI(CP_ACP, lpwsz))
{
ComboBox_AddString(hwnd, (LPARAM)psz);
MemFree(psz);
}
#endif
}
}
CleanLoop:
if(lpRow)
FreeLPSRowSet(lpRow);
}while(cNumRows);
*pcRows = nRows;
exit:
ReleaseObj(lpTable);
ReleaseObj(lpContainer);
if(lpEID)
m_lpWabObject->FreeBuffer(lpEID);
return hr;
}
HRESULT CWab::HrFromIDToName(LPTSTR pszName, DWORD cchSize, ULONG cbEID, LPENTRYID lpEID)
{
ULONG ulObjType = 0, ulResult=0;
LPMAPITABLE lpTable = NULL;
LPSRowSet lpRow = NULL;
LPABCONT lpContainer = NULL;
ULONG cbEIDPAB = 0;
LPENTRYID lpEIDPAB = NULL;
HRESULT hr = NOERROR;
int cNumRows = 0;
int nRows = 0;
if((0 == cbEID) || (NULL == lpEID) || (pszName == NULL))
return E_INVALIDARG;
pszName[0] = 0;
hr = m_lpAdrBook->GetPAB(&cbEIDPAB, &lpEIDPAB);
if(FAILED(hr))
goto error;
hr = m_lpAdrBook->OpenEntry(cbEIDPAB, (LPENTRYID)lpEIDPAB, NULL, 0, &ulObjType, (LPUNKNOWN *)&lpContainer);
if(FAILED(hr))
goto error;
hr = lpContainer->GetContentsTable(WAB_PROFILE_CONTENTS, &lpTable);
if(FAILED(hr))
goto error;
hr =lpTable->SetColumns((LPSPropTagArray)&ptaEid_A, 0);
if(FAILED(hr))
goto error;
hr = lpTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL);
if(FAILED(hr))
goto error;
nRows = 0;
do
{
lpRow = NULL;
hr = lpTable->QueryRows(1, 0, &lpRow);
if(FAILED(hr))
goto CleanLoop;
cNumRows = lpRow->cRows;
if(cNumRows)
{
if(lpRow->aRow[0].lpProps[2].Value.l == MAPI_MAILUSER)
{
hr=m_lpAdrBook->CompareEntryIDs(cbEID, (LPENTRYID)lpEID,
lpRow->aRow[0].lpProps[1].Value.bin.cb,
(LPENTRYID)lpRow->aRow[0].lpProps[1].Value.bin.lpb, 0, &ulResult);
if ( (!FAILED(hr)) && ulResult &&
PROP_TYPE(lpRow->aRow[0].lpProps[0].ulPropTag) != PT_ERROR )
{
StrCpyN(pszName, lpRow->aRow[0].lpProps[0].Value.lpszA, cchSize);
goto CleanLoop;
}
}
}
CleanLoop:
if(lpRow)
{
FreeLPSRowSet(lpRow);
lpRow = NULL;
}
if(FAILED(hr))
goto error;
if (pszName[0])
break;
}while(cNumRows);
if (pszName[0] == 0)
hr = E_FAIL;
error:
ReleaseObj(lpTable);
ReleaseObj(lpContainer);
if(lpEIDPAB)
m_lpWabObject->FreeBuffer(lpEIDPAB);
return hr;
}
HRESULT CWab::HrFromNameToIDs(LPCTSTR lpszVCardName, ULONG* pcbEID, LPENTRYID* lppEID)
{
ULONG ulObjType = 0;
LPMAPITABLE lpTable = NULL;
LPSRowSet lpRow = NULL;
LPABCONT lpContainer = NULL;
HRESULT hr = NOERROR;
ULONG cbEID = 0, cbEIDFound = 0;
LPENTRYID lpEID = NULL, lpEIDFound = NULL;
int cNumRows = 0;
int nRows = 0;
LPTSTR lpsz = NULL;
BOOL fFound = FALSE;
if(NULL==pcbEID || NULL==lppEID)
return E_INVALIDARG;
*pcbEID = NULL;
*lppEID = NULL;
hr = m_lpAdrBook->GetPAB(&cbEID, &lpEID);
if(FAILED(hr))
goto error;
hr = m_lpAdrBook->OpenEntry(cbEID, (LPENTRYID)lpEID, NULL, 0, &ulObjType, (LPUNKNOWN *)&lpContainer);
if(FAILED(hr))
goto error;
hr = lpContainer->GetContentsTable(WAB_PROFILE_CONTENTS, &lpTable);
if(FAILED(hr))
goto error;
hr =lpTable->SetColumns((LPSPropTagArray)&ptaEid_A, 0);
if(FAILED(hr))
goto error;
hr = lpTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL);
if(FAILED(hr))
goto error;
nRows = 0;
do
{
lpRow = NULL;
hr = lpTable->QueryRows(1, 0, &lpRow);
if(FAILED(hr))
goto CleanLoop;
cNumRows = lpRow->cRows;
if(cNumRows)
{
if(lpRow->aRow[0].lpProps[2].Value.l == MAPI_MAILUSER)
{
lpsz = lpRow->aRow[0].lpProps[0].Value.lpszA; //display name
if( PROP_TYPE(lpRow->aRow[0].lpProps[0].ulPropTag) != PT_ERROR &&
lpsz &&
0 == lstrcmp(lpsz, lpszVCardName) )
{
cbEIDFound = lpRow->aRow[0].lpProps[1].Value.bin.cb;
lpEIDFound = (LPENTRYID)lpRow->aRow[0].lpProps[1].Value.bin.lpb;
if(0!=cbEIDFound && NULL!=lpEIDFound)
{
*lppEID = (LPENTRYID)LpbWabBinaryDup(m_lpWabObject, (LPBYTE)lpEIDFound, cbEIDFound, NULL);
if(NULL == *lppEID)
{
hr = E_OUTOFMEMORY;
goto CleanLoop;
}
*pcbEID = cbEIDFound;
fFound = TRUE;
}
else
hr = E_FAIL;
goto CleanLoop;
}
}
}
CleanLoop:
if(lpRow)
{
FreeLPSRowSet(lpRow);
lpRow = NULL;
}
if(FAILED(hr))
goto error;
if(fFound)
break;
}while(cNumRows);
if(!fFound)
hr = E_FAIL;
error:
ReleaseObj(lpTable);
ReleaseObj(lpContainer);
if(lpEID)
m_lpWabObject->FreeBuffer(lpEID);
return hr;
}
const static SizedSPropTagArray(4, Cols)=
{
4,
{
PR_DISPLAY_NAME_W,
PR_EMAIL_ADDRESS_W,
PR_NICKNAME_W,
PR_ENTRYID,
}
};
HRESULT CWab::HrGetPABTable(LPMAPITABLE* ppTable)
{
ULONG ulObjType = 0;
LPMAPITABLE lpTable = NULL;
LPABCONT lpContainer = NULL;
ULONG cbEID = 0;
LPENTRYID lpEID = NULL;
HRESULT hr;
if(NULL == ppTable)
return E_INVALIDARG;
*ppTable = NULL;
hr = m_lpAdrBook->GetPAB(&cbEID, &lpEID);
if(FAILED(hr))
goto error;
hr = m_lpAdrBook->OpenEntry(cbEID, (LPENTRYID)lpEID, NULL, 0, &ulObjType, (LPUNKNOWN *)&lpContainer);
if(FAILED(hr))
goto error;
hr = lpContainer->GetContentsTable(WAB_PROFILE_CONTENTS|MAPI_UNICODE, &lpTable);
if(FAILED(hr))
goto error;
hr =lpTable->SetColumns((LPSPropTagArray)&Cols, 0);
if(FAILED(hr))
goto error;
*ppTable = lpTable;
lpTable = NULL;//avoid releasing it.
error:
ReleaseObj(lpTable);
ReleaseObj(lpContainer);
if(lpEID)
m_lpWabObject->FreeBuffer(lpEID);
return hr;
}
HRESULT CWab::SearchPABTable(LPMAPITABLE lpTable, LPWSTR pszValue, LPWSTR pszFound, INT cch)
{
LPSRowSet lpRow = NULL;
SRestriction Res;
SPropValue propSearch;
HRESULT hr=E_FAIL;
int cNumRows = 0;
if(NULL==lpTable || NULL==pszValue || NULL==*pszValue || NULL==pszFound)
return E_INVALIDARG;
ZeroMemory(&Res, sizeof(SRestriction));
ZeroMemory(&propSearch, sizeof(SPropValue));
*pszFound = 0;
for(int i = 0; i < (int)(Cols.cValues - 1); i++)
{
propSearch.ulPropTag = Cols.aulPropTag[i];
propSearch.Value.lpszW = pszValue;
Res.rt = RES_CONTENT;
Res.res.resContent.ulFuzzyLevel = FL_IGNORECASE | FL_PREFIX;
Res.res.resContent.ulPropTag = propSearch.ulPropTag;
Res.res.resContent.lpProp = &propSearch;
hr = lpTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL);
if(FAILED(hr))
return hr;
do
{
hr = lpTable->FindRow(&Res, BOOKMARK_CURRENT, NULL);
if(FAILED(hr))
break;
lpRow = NULL;
cNumRows = 0;
lpTable->QueryRows(1, 0, &lpRow);
if(lpRow)
{
cNumRows = lpRow->cRows;
if(cNumRows)
{
LPWSTR lpsz = lpRow->aRow[0].lpProps[i].Value.lpszW;
if(lstrlenW(lpsz) > 0)
{
if(*pszFound == 0 || StrCmpIW(lpsz, pszFound) < 0)
StrCpyNW(pszFound, lpsz, cch);
}
}
FreeLPSRowSet(lpRow);
}
} while(i!=0 && cNumRows);
if(*pszFound)
break;
}
return hr;
}
HRESULT CWab::HrCreateVCardFile(LPCTSTR lpszVCardName, LPCTSTR lpszFileName)
{
ULONG ulObjType = 0;
HRESULT hr=NOERROR;
ULONG cbEID=0;
LPENTRYID lpEID = NULL;
LPMAILUSER lpMailUser = NULL;
if(NULL==lpszVCardName || NULL==lpszFileName)
return E_INVALIDARG;
hr = HrFromNameToIDs(lpszVCardName, &cbEID, &lpEID);
if(FAILED(hr))
goto error;
hr = m_lpAdrBook->OpenEntry(cbEID, lpEID, NULL, 0, &ulObjType, (LPUNKNOWN *)&lpMailUser);
if(FAILED(hr))
goto error;
hr = m_lpWabObject->VCardCreate(m_lpAdrBook, 0, (LPTSTR)lpszFileName, lpMailUser);
if(FAILED(hr))
goto error;
error:
ReleaseObj(lpMailUser);
if(lpEID)
m_lpWabObject->FreeBuffer(lpEID);
return hr;
}
HRESULT CWab::HrNewEntry(HWND hwnd, LPTSTR pszName, DWORD cchSize)
{
ULONG cbEID=0, cbEIDRet=0;
LPENTRYID lpEID = NULL, lpEIDRet = NULL;
HRESULT hr=NOERROR;
hr = m_lpAdrBook->GetPAB(&cbEID, &lpEID);
if(FAILED(hr))
goto error;
hr = m_lpAdrBook->NewEntry((ULONG_PTR)hwnd, 0, cbEID, lpEID, 0, NULL, &cbEIDRet, &lpEIDRet);
if(FAILED(hr))
goto error;
HrFromIDToName(pszName, cchSize, cbEIDRet, lpEIDRet);
error:
if(lpEID)
m_lpWabObject->FreeBuffer(lpEID);
if(lpEIDRet)
m_lpWabObject->FreeBuffer(lpEIDRet);
return hr;
}
LRESULT CWab::WabSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CWab *pWab;
HWND hwndActive;
LRESULT lResult;
pWab = (CWab *)GetProp(hwnd, c_szOEThis);
if (!pWab)
return 0;
switch (uMsg)
{
case WM_NCDESTROY:
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)pWab->m_pfnWabWndProc);
RemoveProp(hwnd, c_szOEThis);
RemoveProp(hwnd, c_szOETopLevel);
lResult = CallWindowProc(pWab->m_pfnWabWndProc, hwnd, uMsg, wParam, lParam);
pWab->Release();
// bug #59420, can't freelibrary the wab inside the wndproc
PostMessage(g_hwndInit, ITM_WAB_CO_DECREMENT, 0, 0);
return lResult;
case WM_ENABLE:
if (!pWab->m_fInternal)
{
Assert (wParam || (pWab->m_hlDisabled.cHwnd == NULL && pWab->m_hlDisabled.rgHwnd == NULL));
EnableThreadWindows(&pWab->m_hlDisabled, (0 != wParam), ETW_OE_WINDOWS_ONLY, hwnd);
g_hwndActiveModal = wParam ? NULL : hwnd;
}
break;
case WM_OE_ENABLETHREADWINDOW:
pWab->m_fInternal = 1;
EnableWindow(hwnd, (BOOL)wParam);
pWab->m_fInternal = 0;
break;
case WM_OE_ACTIVATETHREADWINDOW:
hwndActive = GetLastActivePopup(hwnd);
if (hwndActive && IsWindowEnabled(hwndActive) && IsWindowVisible(hwndActive))
ActivatePopupWindow(hwndActive);
break;
case WM_ACTIVATEAPP:
if (wParam && g_hwndActiveModal && g_hwndActiveModal != hwnd &&
!IsWindowEnabled(hwnd))
{
// $MODAL
// if we are getting activated, and are disabled then
// bring our 'active' window to the top
Assert (IsWindow(g_hwndActiveModal));
PostMessage(g_hwndActiveModal, WM_OE_ACTIVATETHREADWINDOW, 0, 0);
}
break;
}
return CallWindowProc(pWab->m_pfnWabWndProc, hwnd, uMsg, wParam, lParam);
}
HRESULT CWab::HrEditEntry(HWND hwnd, LPTSTR pszName, DWORD cchSize)
{
ULONG cbEID = 0;
LPENTRYID lpEID = NULL;
HRESULT hr = NOERROR;
if(NULL == pszName)
return E_INVALIDARG;
hr = HrFromNameToIDs(pszName, &cbEID, &lpEID);
if(FAILED(hr))
goto error;
hr=m_lpAdrBook->Details((ULONG_PTR *)&hwnd, NULL, NULL, cbEID, lpEID, NULL, NULL, NULL, DIALOG_MODAL);
if(FAILED(hr))
goto error;
HrFromIDToName(pszName, cchSize, cbEID, lpEID);
error:
if(lpEID)
m_lpWabObject->FreeBuffer(lpEID);
return hr;
}
// =============================================================================
// HrCreateWabalObject
// =============================================================================
HRESULT HrCreateWabalObject (LPWABAL *lppWabal)
{
// Locals
HRESULT hr = S_OK;
// Check Params
Assert (lppWabal);
hr=HrInitWab(TRUE);
if (FAILED(hr))
return hr;
// Verify Globals
if (g_fWabLoaded == FALSE || g_fWabInit == FALSE)
{
return TRAPHR (hrWabNotLoaded);
}
// Enter Critical Section
EnterCriticalSection (&g_rWabCritSect);
// Verify globals
Assert (g_lpfnWabOpen && g_hWab32Dll && g_lpAdrBook && g_lpWabObject);
// Inst it
*lppWabal = new CWabal;
if (*lppWabal == NULL)
{
hr = TRAPHR (hrMemory);
goto exit;
}
exit:
// Leave Critical Section
LeaveCriticalSection (&g_rWabCritSect);
// Done
return hr;
}
// ===========================================================================
// CWabal::CWabal
// ===========================================================================
CWabal::CWabal ()
{
DOUT ("CWabal::CWabal");
m_cRef = 1;
m_cActualEntries = 0;
m_lpAdrList = NULL;
m_lpWabObject = g_lpWabObject;
m_lpWabObject->AddRef();
m_lpAdrBook = g_lpAdrBook;
m_lpAdrBook->AddRef();
m_cMemberEnum=0;
m_cMembers = 0;
m_lprwsMembers = NULL;
m_pMsg = NULL;
}
// ===========================================================================
// CWabal::CWabal
// ===========================================================================
CWabal::~CWabal ()
{
DOUT ("CWabal::~CWabal");
Reset ();
ReleaseWabObjects (m_lpWabObject, m_lpAdrBook);
}
// =============================================================================
// CWabal::AddRef
// =============================================================================
ULONG CWabal::AddRef (VOID)
{
DOUT("CWabal::AddRef %lx ==> %d", this, m_cRef+1);
return ++m_cRef;
}
// =============================================================================
// CWabal::Release
// =============================================================================
ULONG CWabal::Release (VOID)
{
DOUT("CWabal::Release %lx ==> %d", this, m_cRef-1);
if (--m_cRef == 0)
{
delete this;
return 0;
}
return m_cRef;
}
// =============================================================================
// CWabal::FVerifyState
// =============================================================================
BOOL CWabal::FVerifyState (VOID)
{
// We need these things !
if (m_lpWabObject == NULL || m_lpAdrBook == NULL)
{
Assert (FALSE);
return FALSE;
}
// Done
return TRUE;
}
// =============================================================================
// CWabal::HrAddEntry
// =============================================================================
HRESULT CWabal::HrAddEntryA(LPTSTR lpszDisplay, LPTSTR lpszAddress, LONG lRecipType)
{
LPWSTR pwszDisplay = NULL,
pwszAddress = NULL;
HRESULT hr = S_OK;
Assert(lpszDisplay);
IF_NULLEXIT(pwszDisplay = PszToUnicode(CP_ACP, lpszDisplay));
// If lpszAddress is null, we have an incomplete Entry. This is ok.
pwszAddress = PszToUnicode(CP_ACP, lpszAddress);
if (lpszAddress && !pwszAddress)
IF_NULLEXIT(NULL);
hr = HrAddEntry(pwszDisplay, pwszAddress, lRecipType);
exit:
MemFree(pwszDisplay);
MemFree(pwszAddress);
return hr;
}
HRESULT CWabal::HrAddEntry (LPWSTR lpwszDisplay, LPWSTR lpwszAddress, LONG lRecipType)
{
// Locals
HRESULT hr = S_OK;
ADRINFO rAdrInfo;
// Verify State
if (FVerifyState () == FALSE)
return TRAPHR (E_FAIL);
// Zero
ZeroMemory (&rAdrInfo, sizeof (ADRINFO));
// Set adrinfo items
rAdrInfo.lpwszDisplay = lpwszDisplay;
rAdrInfo.lpwszAddress = lpwszAddress;
rAdrInfo.lRecipType = lRecipType;
rAdrInfo.fDistList = FALSE;
if (lRecipType == MAPI_ORIG) {
rAdrInfo.pMsg = m_pMsg; // only on senders
}
// Do we need to grow m_lpAdrList ?
if (m_lpAdrList == NULL || m_cActualEntries == m_lpAdrList->cEntries)
{
// Lets grow my current address list by GROW_SIZE
CHECKHR (hr = HrGrowAdrlist (&m_lpAdrList, GROW_SIZE));
}
// Put new entry into m_cActualEntries
CHECKHR (hr = HrSetAdrEntry (m_lpWabObject, &m_lpAdrList->aEntries[m_cActualEntries], &rAdrInfo, 0));
// Increment actual entries
m_cActualEntries++;
exit:
// Done
return hr;
}
// =============================================================================
// CWabal::HrAddEntry
// =============================================================================
HRESULT CWabal::HrAddEntry (LPADRINFO lpAdrInfo, BOOL fCheckDupes)
{
// Locals
HRESULT hr = S_OK;
// Check Params
Assert (lpAdrInfo);
// Verify State
if (FVerifyState () == FALSE)
return TRAPHR (E_FAIL);
// Do we need to grow m_lpAdrList ?
if (m_lpAdrList == NULL || m_cActualEntries == m_lpAdrList->cEntries)
{
// Lets grow my current address list by GROW_SIZE
CHECKHR (hr = HrGrowAdrlist (&m_lpAdrList, GROW_SIZE));
}
BOOL fSameType,
fSameEmail;
if (fCheckDupes)
{
for(ULONG ul=0; ul<m_cActualEntries; ul++)
{
fSameType=fSameEmail=FALSE;
for(ULONG ulProp=0; ulProp<m_lpAdrList->aEntries[ul].cValues; ulProp++)
{
if (m_lpAdrList->aEntries[ul].rgPropVals[ulProp].ulPropTag==PR_EMAIL_ADDRESS_W &&
StrCmpIW(m_lpAdrList->aEntries[ul].rgPropVals[ulProp].Value.lpszW, lpAdrInfo->lpwszAddress)==0)
fSameEmail=TRUE;
if (m_lpAdrList->aEntries[ul].rgPropVals[ulProp].ulPropTag==PR_RECIPIENT_TYPE &&
(m_lpAdrList->aEntries[ul].rgPropVals[ulProp].Value.l == lpAdrInfo->lRecipType))
fSameType=TRUE;
}
if (fSameEmail && fSameType)
{
DOUTL(4, " -- Already in cache");
return NOERROR;
}
}
DOUTL(4, " -- Adding.");
}
// Put new entry into m_cActualEntries
CHECKHR (hr = HrSetAdrEntry (m_lpWabObject, &m_lpAdrList->aEntries[m_cActualEntries], lpAdrInfo, 0));
// Increment actual entries
m_cActualEntries++;
exit:
// Done
return hr;
}
#define FOUND_ENTRYID 0x01
#define FOUND_DISTLIST 0x02
#define FOUND_EMAIL 0x04
// =============================================================================
// CWabal::ValidateForSending()
// =============================================================================
HRESULT CWabal::IsValidForSending()
{
DWORD dwMask = 0;
ADRENTRY *pAE = NULL;
if (m_cActualEntries == 0)
return hrNoRecipients;
// walk thro' the list and make sure everyone has an entry-id and email name
AssertSz(m_lpAdrList, "How can this be NULL with >0 entries?");
for (ULONG ul=0; ul < m_cActualEntries; ul++)
{
dwMask = 0;
pAE = &m_lpAdrList->aEntries[ul];
for (ULONG ulProp=0; ulProp < pAE->cValues; ulProp++)
{
switch (pAE->rgPropVals[ulProp].ulPropTag)
{
case PR_ENTRYID:
dwMask |= FOUND_ENTRYID;
break;
case PR_OBJECT_TYPE:
if (pAE->rgPropVals[ulProp].Value.l==MAPI_DISTLIST)
dwMask |= FOUND_DISTLIST;
break;
case PR_RECIPIENT_TYPE:
if ((pAE->rgPropVals[ulProp].Value.l==MAPI_ORIG) &&
(m_cActualEntries == 1))
return hrNoRecipients;
break;
case PR_EMAIL_ADDRESS:
case PR_EMAIL_ADDRESS_W:
dwMask |= FOUND_EMAIL;
break;
}
}
// Fail if we don't have and email address, or we don't have a distList and an entryID
if (!((dwMask & FOUND_EMAIL) || ((dwMask & FOUND_ENTRYID) && (dwMask & FOUND_DISTLIST))))
return hrEmptyRecipientAddress;
}
return S_OK;
}
// =============================================================================
// CWabal::HrCopyTo
// =============================================================================
HRESULT CWabal::HrCopyTo (LPWABAL lpWabal)
{
// Locals
HRESULT hr = S_OK;
ADRINFO rAdrInfo;
BOOL fFound;
// Reset the destination
lpWabal->Reset ();
// Iterate through addresses
fFound = FGetFirst (&rAdrInfo);
while (fFound)
{
// Add it into lpWabal
CHECKHR (hr = lpWabal->HrAddEntry (&rAdrInfo));
// Get the next address
fFound = FGetNext (&rAdrInfo);
}
exit:
// Done
return hr;
}
// =============================================================================
// CWabal::Reset
// =============================================================================
VOID CWabal::Reset (VOID)
{
// Are we ready
if (FVerifyState () == FALSE)
return;
// If we have an address list, blow it away
if (m_lpAdrList)
{
// Free propvals
for (ULONG i=0; i<m_lpAdrList->cEntries; i++)
m_lpWabObject->FreeBuffer (m_lpAdrList->aEntries[i].rgPropVals);
// Free Address List
m_lpWabObject->FreeBuffer (m_lpAdrList);
m_lpAdrList = NULL;
}
// Reset actual entries
m_cActualEntries = 0;
}
// =============================================================================
// CWabal::HrGetFirst
// =============================================================================
BOOL CWabal::FGetFirst (LPADRINFO lpAdrInfo)
{
// Verify State
if (FVerifyState () == FALSE)
return FALSE;
// Nothing in my list
if (m_lpAdrList == NULL || m_cActualEntries == 0)
return FALSE;
// Set cookie in addrinfo
lpAdrInfo->dwReserved = 0;
AdrEntryToAdrInfo(&m_lpAdrList->aEntries[lpAdrInfo->dwReserved], lpAdrInfo);
// Set associated message
lpAdrInfo->pMsg = (lpAdrInfo->lRecipType == MAPI_ORIG) ? m_pMsg : NULL;
return TRUE;
}
// =============================================================================
// CWabal::HrGetNext
// =============================================================================
BOOL CWabal::FGetNext (LPADRINFO lpAdrInfo)
{
// Verify State
if (FVerifyState () == FALSE)
return NULL;
// Go to next address
lpAdrInfo->dwReserved++;
// Anymore
if (lpAdrInfo->dwReserved >= m_cActualEntries)
return FALSE;
AdrEntryToAdrInfo(&m_lpAdrList->aEntries[lpAdrInfo->dwReserved], lpAdrInfo);
// Set associated message
lpAdrInfo->pMsg = (lpAdrInfo->lRecipType == MAPI_ORIG) ? m_pMsg : NULL;
// Done
return TRUE;
}
BOOL CWabal::FFindFirst(LPADRINFO lpAdrInfo, LONG lRecipType)
{
if (FGetFirst(lpAdrInfo))
do
if (lpAdrInfo->lRecipType==lRecipType)
return TRUE;
while(FGetNext(lpAdrInfo));
return FALSE;
}
// =============================================================================
// CWabal::LpGetNext
// =============================================================================
HRESULT CWabal::HrResolveNames (HWND hwndParent, BOOL fShowDialog)
{
// Locals
HRESULT hr = S_OK;
HCURSOR hcur=NULL;
HWND hwndFocus = GetFocus();
ULONG ulFlags = WAB_RESOLVE_USE_CURRENT_PROFILE | WAB_RESOLVE_ALL_EMAILS | WAB_RESOLVE_UNICODE;
// Have we been initialized
if (FVerifyState () == FALSE)
return TRAPHR (E_FAIL);
hcur = HourGlass();
if(g_pConMan && g_pConMan->IsGlobalOffline())
ulFlags |= WAB_RESOLVE_LOCAL_ONLY;
// BUG: 23760: ResolveNames pumps messages against an LDAP server
if (fShowDialog)
{
Assert(IsWindow(hwndParent));
EnableWindow(GetTopMostParent(hwndParent), FALSE);
ulFlags |= MAPI_DIALOG;
hr = m_lpAdrBook->ResolveName ((ULONG_PTR)hwndParent, ulFlags, NULL, m_lpAdrList);
EnableWindow(GetTopMostParent(hwndParent), TRUE);
//BUG: user can't put focus back on our dialog wnd for us as we disabled
// the window and the progress dialog got a wm_destroy before we return
// so we cache the focus and set ut back
if (hwndFocus)
SetFocus(hwndFocus);
}
else
hr = m_lpAdrBook->ResolveName ((ULONG_PTR)hwndParent, ulFlags, NULL, m_lpAdrList);
if (hcur)
SetCursor(hcur);
// Done
return hr;
}
// =============================================================================
// SzWabStringDup
// =============================================================================
LPTSTR SzWabStringDup (LPWABOBJECT lpWab, LPCTSTR pcsz, LPVOID lpParentObject)
{
// Locals
LPTSTR pszDup;
ULONG cb;
HRESULT hr;
Assert (lpWab);
if (pcsz == NULL)
return NULL;
INT nLen = lstrlen(pcsz) + 1;
cb = nLen * sizeof(TCHAR);
if (lpParentObject == NULL)
hr = lpWab->AllocateBuffer (cb, (LPVOID *)&pszDup);
else
hr = lpWab->AllocateMore (cb, lpParentObject, (LPVOID *)&pszDup);
if (!FAILED (hr) && pszDup)
CopyMemory (pszDup, pcsz, cb);
return pszDup;
}
LPWSTR SzWabStringDupW(LPWABOBJECT lpWab, LPCWSTR pcwsz, LPVOID lpParentObject)
{
// Locals
LPWSTR pwszDup;
ULONG cb;
HRESULT hr;
Assert (lpWab);
if (pcwsz == NULL)
return NULL;
INT nLen = lstrlenW(pcwsz) + 1;
cb = nLen * sizeof(WCHAR);
if (lpParentObject == NULL)
hr = lpWab->AllocateBuffer (cb, (LPVOID *)&pwszDup);
else
hr = lpWab->AllocateMore (cb, lpParentObject, (LPVOID *)&pwszDup);
if (!FAILED (hr) && pwszDup)
CopyMemory (pwszDup, pcwsz, cb);
return pwszDup;
}
// =============================================================================
// LpbWabBinaryDup
// =============================================================================
LPBYTE LpbWabBinaryDup(LPWABOBJECT lpWab, LPBYTE lpbSrc, ULONG cb, LPVOID lpParentObject)
{
// Locals
HRESULT hr;
LPBYTE pb=0;
Assert (lpWab);
Assert (lpbSrc);
if (lpParentObject == NULL)
hr = lpWab->AllocateBuffer (cb, (LPVOID *)&pb);
else
hr = lpWab->AllocateMore (cb, lpParentObject, (LPVOID *)&pb);
if (pb)
CopyMemory (pb, lpbSrc, cb);
return pb;
}
// =============================================================================
// CWabal::HrAddUnresolved
// =============================================================================
HRESULT CWabal::HrAddUnresolved(LPWSTR lpwszDisplayName, LONG lRecipType)
{
HRESULT hr=NOERROR;
ULONG cb;
LPADRENTRY lpAdrEntry;
ULONG cchDisplayName;
Assert(lpwszDisplayName);
// Do we need to grow m_lpAdrList ?
if (m_lpAdrList == NULL || m_cActualEntries == m_lpAdrList->cEntries)
{
// Lets grow my current address list by GROW_SIZE
CHECKHR (hr = HrGrowAdrlist (&m_lpAdrList, GROW_SIZE));
}
// Put new entry into m_cActualEntries
lpAdrEntry=&m_lpAdrList->aEntries[m_cActualEntries];
lpAdrEntry->cValues=2;
cchDisplayName = lstrlenW(lpwszDisplayName)+1;
cb = (2*sizeof(SPropValue)) + (cchDisplayName) * sizeof(WCHAR);
// Allocate some memory
hr = m_lpWabObject->AllocateBuffer (cb, (LPVOID *)&lpAdrEntry->rgPropVals);
// Alloc failed ?
if (FAILED (hr))
{
hr = TRAPHR (hrMemory);
goto exit;
}
// Set the Properties
lpAdrEntry->rgPropVals[0].ulPropTag = PR_DISPLAY_NAME_W;
lpAdrEntry->rgPropVals[0].Value.lpszW=(LPWSTR)((DWORD_PTR)(lpAdrEntry->rgPropVals) + (DWORD)(2*sizeof(SPropValue)));
StrCpyNW(lpAdrEntry->rgPropVals[0].Value.lpszW, lpwszDisplayName, cchDisplayName);
lpAdrEntry->rgPropVals[1].ulPropTag = PR_RECIPIENT_TYPE;
lpAdrEntry->rgPropVals[1].Value.l= lRecipType;
m_cActualEntries++;
exit:
// Done
return hr;
}
// =============================================================================
// HrSetAdrEntry
// =============================================================================
HRESULT HrSetAdrEntry (LPWABOBJECT lpWab, LPADRENTRY lpAdrEntry,
LPADRINFO lpAdrInfo, DWORD mask)
{
// Locals
HRESULT hr = S_OK;
ULONG cValues;
DWORD dwAlloc;
DWORD cMaskBits;
DWORD mask2;
// Allocate properties
Assert (lpAdrEntry->rgPropVals == NULL);
// BrettM laughed at me that I was passing the bit count into this function.
// So, lets count them
mask2 = mask;
for (cMaskBits=0; mask2; cMaskBits++)
mask2&=mask2-1;
// Allocate some memory
dwAlloc = ((cMaskBits) ? cMaskBits : AE_colLast) * sizeof (SPropValue);
hr = lpWab->AllocateBuffer (dwAlloc, (LPVOID *)&lpAdrEntry->rgPropVals);
// Alloc failed ?
if (FAILED (hr))
{
hr = TRAPHR (hrMemory);
goto exit;
}
// Zero init
ZeroMemory (lpAdrEntry->rgPropVals, dwAlloc);
// Set the Properties
// Init Properties ?
cValues = 0;
if (lpAdrInfo)
{
// If the mask is empty, then we're doing all properties;
// else, if the mask has the bit set, test for emptiness
// and bang in a default; else skip it
if (!mask || mask & AIM_DISPLAY)
{
lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_DISPLAY_NAME_W;
if (FIsStringEmptyW(lpAdrInfo->lpwszDisplay))
{
LPWSTR pwszDisplay;
if (!FIsStringEmptyW(lpAdrInfo->lpwszAddress))
pwszDisplay = SzWabStringDupW(lpWab, lpAdrInfo->lpwszAddress, lpAdrEntry->rgPropVals);
else
{
WCHAR szUnknown[255];
AthLoadStringW(idsUnknown, szUnknown, ARRAYSIZE(szUnknown));
pwszDisplay = SzWabStringDupW(lpWab, szUnknown, lpAdrEntry->rgPropVals);
}
lpAdrEntry->rgPropVals[cValues].Value.lpszW = SzWabStringDupW(lpWab, pwszDisplay, lpAdrEntry->rgPropVals);
}
else
{
lpAdrEntry->rgPropVals[cValues].Value.lpszW = SzWabStringDupW(lpWab, lpAdrInfo->lpwszDisplay, lpAdrEntry->rgPropVals);
}
cValues++;
}
if (!mask || mask & AIM_ADDRESS)
{
if (!FIsStringEmptyW(lpAdrInfo->lpwszAddress))
{
lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_EMAIL_ADDRESS_W;
lpAdrEntry->rgPropVals[cValues].Value.lpszW = SzWabStringDupW(lpWab, lpAdrInfo->lpwszAddress, lpAdrEntry->rgPropVals);
cValues++;
}
}
if (!mask || mask & AIM_ADDRTYPE)
{
lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_ADDRTYPE_W;
if (FIsStringEmptyW(lpAdrInfo->lpwszAddrType))
lpAdrEntry->rgPropVals[cValues].Value.lpszW = SzWabStringDupW(lpWab, (LPWSTR)c_wszSMTP, lpAdrEntry->rgPropVals);
else
lpAdrEntry->rgPropVals[cValues].Value.lpszW = SzWabStringDupW(lpWab, lpAdrInfo->lpwszAddrType, lpAdrEntry->rgPropVals);
cValues++;
}
if (lpAdrInfo->lpwszSurName && (!mask || mask & AIM_SURNAME))
{
lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_SURNAME_W;
lpAdrEntry->rgPropVals[cValues++].Value.lpszW = SzWabStringDupW(lpWab, lpAdrInfo->lpwszSurName, lpAdrEntry->rgPropVals);
}
if (lpAdrInfo->lpwszGivenName && (!mask || mask & AIM_GIVENNAME))
{
lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_GIVEN_NAME_W;
lpAdrEntry->rgPropVals[cValues++].Value.lpszW = SzWabStringDupW(lpWab, lpAdrInfo->lpwszGivenName, lpAdrEntry->rgPropVals);
}
if (!mask || mask & AIM_RECIPTYPE)
{
lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_RECIPIENT_TYPE;
lpAdrEntry->rgPropVals[cValues++].Value.l = lpAdrInfo->lRecipType;
}
if (lpAdrInfo->tbCertificate.pBlobData && (!mask || mask & AIM_CERTIFICATE))
{
ThumbprintToPropValue(&lpAdrEntry->rgPropVals[cValues],
&lpAdrInfo->tbCertificate,
&lpAdrInfo->blSymCaps,
lpAdrInfo->ftSigningTime,
lpAdrInfo->fDefCertificate);
cValues++;
}
if (lpAdrInfo->cbEID && (!mask || mask & AIM_EID))
{
lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_ENTRYID;
lpAdrEntry->rgPropVals[cValues].Value.bin.cb = lpAdrInfo->cbEID;
lpAdrEntry->rgPropVals[cValues].Value.bin.lpb =
LpbWabBinaryDup(lpWab, lpAdrInfo->lpbEID, lpAdrInfo->cbEID, lpAdrEntry->rgPropVals);
if (lpAdrEntry->rgPropVals[cValues].Value.bin.lpb==NULL)
{
hr=E_OUTOFMEMORY;
goto exit;
}
cValues++;
}
if (!mask || mask & AIM_OBJECTTYPE)
{
lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_OBJECT_TYPE;
lpAdrEntry->rgPropVals[cValues++].Value.l=lpAdrInfo->fDistList?MAPI_DISTLIST:MAPI_MAILUSER;
}
if (!mask || mask & AIM_INTERNETENCODING)
{
lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_SEND_INTERNET_ENCODING;
lpAdrEntry->rgPropVals[cValues++].Value.l=lpAdrInfo->fPlainText?BODY_ENCODING_TEXT:BODY_ENCODING_TEXT_AND_HTML;
}
}
#ifdef DEBUG
if (cMaskBits && cValues > cMaskBits)
AssertSz(0, TEXT("Bad... the mask bits don't cover our mem usage"));
#endif
DOUTL(4, "HrSetAdrEntry: lRecip=%d", lpAdrInfo->lRecipType);
// Set number of values
// use cValues since we may have skipped some due to null params and therefore
// cMaskBits >= cValues (t-erikne)
lpAdrEntry->cValues = cValues;
exit:
// Done
return hr;
}
// =============================================================================
// CWabal::HrAllocAdrList
// =============================================================================
HRESULT CWabal::HrGrowAdrlist (LPADRLIST *lppalCurr, ULONG caeToAdd)
{
// Locals
HRESULT hr = S_OK;
ULONG i, j, cbNew, cbCurr = 0;
LPADRLIST lpalNew = NULL;
// Determine number of bytes needed
cbNew = sizeof(ADRLIST) + caeToAdd * sizeof(ADRENTRY);
// Determine number of entries currently in address list
if (*lppalCurr)
{
cbCurr = (UINT)((*lppalCurr)->cEntries * sizeof(ADRENTRY));
}
// Add current cb
cbNew += cbCurr;
// Allocate new buffer
hr = m_lpWabObject->AllocateBuffer (cbNew, (LPVOID *)&lpalNew);
if (FAILED (hr))
{
hr = TRAPHR (hrMemory);
goto exit;
}
// If current address list ?
if (*lppalCurr)
{
// Copy Current Address list into new address list
CopyMemory (lpalNew, *lppalCurr, sizeof (ADRLIST) + cbCurr);
// Free current buffer
m_lpWabObject->FreeBuffer (*lppalCurr);
// Reset pointer
*lppalCurr = NULL;
}
else
lpalNew->cEntries = 0;
// Update entries count
//N seems like we don't need j, just offset the i count by this much?
j = lpalNew->cEntries;
lpalNew->cEntries += caeToAdd;
// Mark new ADRENTRY's as empty and allocate the propvalue array
for (i=0; i<caeToAdd; i++)
{
// Zero init adrentry
ZeroMemory (&lpalNew->aEntries[j+i], sizeof (ADRENTRY));
}
// Assume new pointer
*lppalCurr = lpalNew;
exit:
// Done
return hr;
}
void CWabal::AdrEntryToAdrInfo(LPADRENTRY lpAdrEntry, LPADRINFO lpAdrInfo)
{
ULONG ul,
cValues;
LPSPropValue ppv;
//N look at some kind of {} init
lpAdrInfo->lpwszAddress = NULL;
lpAdrInfo->lpwszAddrType = NULL;
lpAdrInfo->lpwszDisplay = NULL;
lpAdrInfo->lpwszSurName = NULL;
lpAdrInfo->lpwszGivenName = NULL;
lpAdrInfo->lRecipType = -1;
lpAdrInfo->fResolved = FALSE;
lpAdrInfo->fDistList = FALSE;
lpAdrInfo->fPlainText = FALSE;
lpAdrInfo->fDefCertificate = FALSE;
lpAdrInfo->tbCertificate.pBlobData = (BYTE*)0;
lpAdrInfo->tbCertificate.cbSize = 0;
lpAdrInfo->blSymCaps.pBlobData = (BYTE*)0;
lpAdrInfo->blSymCaps.cbSize = 0;
lpAdrInfo->ftSigningTime.dwLowDateTime = lpAdrInfo->ftSigningTime.dwHighDateTime = 0;
lpAdrInfo->cbEID=0;
lpAdrInfo->lpbEID=0;
cValues=lpAdrEntry->cValues;
AssertSz(cValues, "An empty addrentry?");
ppv=lpAdrEntry->rgPropVals;
for(ul=0; ul<cValues; ul++, ppv++)
PropValToAdrInfo(ppv, lpAdrInfo);
DOUTL(4, "AddrEntry2AddrInfo: lRecip=%d", lpAdrInfo->lRecipType);
AssertSz(lpAdrInfo->lpwszAddress==NULL ||
lpAdrInfo->lRecipType != -1, "A resolved entry should have a recip type!");
}
HRESULT CWab::HrDetails(HWND hwndOwner, LPADRINFO *lplpAdrInfo)
{
HRESULT hr;
HWND hwnd=hwndOwner;
LPADRINFO lpAdrInfoNew=0;
ADRINFO adrInfo;
LPMAPIPROP pmp=0;
LPSPropValue ppv=0;
ULONG ul;
HCURSOR hcur=NULL;
SizedSPropTagArray(2, tagNewProps)=
{2, {PR_EMAIL_ADDRESS_W, PR_DISPLAY_NAME_W}};
if (!m_lpAdrBook)
return E_FAIL;
if (!lplpAdrInfo || !*lplpAdrInfo)
return E_INVALIDARG;
hcur = HourGlass();
hr=m_lpAdrBook->Details((ULONG_PTR *)&hwnd, NULL, NULL, (*lplpAdrInfo)->cbEID, (LPENTRYID)(*lplpAdrInfo)->lpbEID, NULL, NULL, NULL, 0);
// re-read the props that may have changed...
CopyMemory(&adrInfo, *lplpAdrInfo, sizeof(ADRINFO));
hr=m_lpAdrBook->OpenEntry((*lplpAdrInfo)->cbEID, (LPENTRYID)(*lplpAdrInfo)->lpbEID,
&IID_IMAPIProp, 0, &ul, (LPUNKNOWN *)&pmp);
if (FAILED(hr))
goto error;
hr=pmp->GetProps((LPSPropTagArray)&tagNewProps, 0, &ul, &ppv);
if (FAILED(hr))
goto error;
adrInfo.lpwszAddress = ppv[0].ulPropTag == PR_EMAIL_ADDRESS_W ? ppv[0].Value.lpszW : NULL;
adrInfo.lpwszDisplay = ppv[1].ulPropTag == PR_DISPLAY_NAME_W ? ppv[1].Value.lpszW : NULL;
hr=HrDupeAddrInfo(&adrInfo, &lpAdrInfoNew);
if (FAILED(hr))
goto error;
// release the old, and replace with the new
MemFree(*lplpAdrInfo);
*lplpAdrInfo=lpAdrInfoNew;
error:
ReleaseObj(pmp);
if (ppv)
m_lpWabObject->FreeBuffer(ppv);
if (hcur)
SetCursor(hcur);
return hr;
}
HRESULT HrDupeAddrInfo(LPADRINFO lpAdrInfo, LPADRINFO *lplpAdrInfo)
{
ULONG cb=0;
LPBYTE pb;
if (!lpAdrInfo || !lplpAdrInfo)
return E_INVALIDARG;
*lplpAdrInfo=NULL;
cb=CbAdrInfoSize(lpAdrInfo);
#ifdef _WIN64
cb = LcbAlignLcb(cb);
#endif
if (!MemAlloc((LPVOID *)lplpAdrInfo, cb))
return E_OUTOFMEMORY;
ZeroMemory(*lplpAdrInfo, cb);
pb=(LPBYTE)*lplpAdrInfo + sizeof(ADRINFO);
#ifdef _WIN64
pb = MyPbAlignPb(pb);
#endif // _WIN64
if (lpAdrInfo->lpwszAddress)
{
StrCpyNW((LPWSTR)pb, lpAdrInfo->lpwszAddress, (cb - (pb - (LPBYTE)*lplpAdrInfo))/sizeof(WCHAR));
(*lplpAdrInfo)->lpwszAddress=(LPWSTR)pb;
pb+=(lstrlenW(lpAdrInfo->lpwszAddress)+1)*sizeof(WCHAR);
#ifdef _WIN64
pb = MyPbAlignPb(pb);
#endif // _WIN64
}
if (lpAdrInfo->lpwszDisplay)
{
StrCpyNW((LPWSTR)pb, lpAdrInfo->lpwszDisplay, (cb - (pb - (LPBYTE)*lplpAdrInfo))/sizeof(WCHAR));
(*lplpAdrInfo)->lpwszDisplay=(LPWSTR)pb;
pb+=(lstrlenW(lpAdrInfo->lpwszDisplay)+1)*sizeof(WCHAR);
#ifdef _WIN64
pb = MyPbAlignPb(pb);
#endif // _WIN64
}
if (lpAdrInfo->lpwszAddrType)
{
StrCpyNW((LPWSTR)pb, lpAdrInfo->lpwszAddrType, (cb - (pb - (LPBYTE)*lplpAdrInfo))/sizeof(WCHAR));
(*lplpAdrInfo)->lpwszAddrType=(LPWSTR)pb;
pb+=(lstrlenW(lpAdrInfo->lpwszAddrType)+1)*sizeof(WCHAR);
#ifdef _WIN64
pb = MyPbAlignPb(pb);
#endif // _WIN64
}
if (lpAdrInfo->lpwszSurName)
{
StrCpyNW((LPWSTR)pb, lpAdrInfo->lpwszSurName, (cb - (pb - (LPBYTE)*lplpAdrInfo))/sizeof(WCHAR));
(*lplpAdrInfo)->lpwszSurName=(LPWSTR)pb;
pb+=(lstrlenW(lpAdrInfo->lpwszSurName)+1)*sizeof(WCHAR);
#ifdef _WIN64
pb = MyPbAlignPb(pb);
#endif // _WIN64
}
if (lpAdrInfo->lpwszGivenName)
{
StrCpyNW((LPWSTR)pb, lpAdrInfo->lpwszGivenName, (cb - (pb - (LPBYTE)*lplpAdrInfo))/sizeof(WCHAR));
(*lplpAdrInfo)->lpwszGivenName=(LPWSTR)pb;
pb+=(lstrlenW(lpAdrInfo->lpwszGivenName)+1)*sizeof(WCHAR);
#ifdef _WIN64
pb = MyPbAlignPb(pb);
#endif // _WIN64
}
// Certificate properties
(*lplpAdrInfo)->tbCertificate.cbSize = lpAdrInfo->tbCertificate.cbSize;
(*lplpAdrInfo)->tbCertificate.pBlobData = lpAdrInfo->tbCertificate.pBlobData;
(*lplpAdrInfo)->blSymCaps.cbSize = lpAdrInfo->blSymCaps.cbSize;
(*lplpAdrInfo)->blSymCaps.pBlobData = lpAdrInfo->blSymCaps.pBlobData;
(*lplpAdrInfo)->ftSigningTime.dwLowDateTime = lpAdrInfo->ftSigningTime.dwLowDateTime;
(*lplpAdrInfo)->ftSigningTime.dwHighDateTime = lpAdrInfo->ftSigningTime.dwHighDateTime;
(*lplpAdrInfo)->fDefCertificate = lpAdrInfo->fDefCertificate;
(*lplpAdrInfo)->lRecipType=lpAdrInfo->lRecipType;
(*lplpAdrInfo)->fResolved=lpAdrInfo->fResolved;
(*lplpAdrInfo)->fDistList=lpAdrInfo->fDistList;
(*lplpAdrInfo)->fPlainText=lpAdrInfo->fPlainText;
(*lplpAdrInfo)->pMsg =lpAdrInfo->pMsg;
if (lpAdrInfo->cbEID)
{
(*lplpAdrInfo)->lpbEID=(LPBYTE)pb;
(*lplpAdrInfo)->cbEID=lpAdrInfo->cbEID;
CopyMemory(pb, lpAdrInfo->lpbEID, lpAdrInfo->cbEID);
}
return NOERROR;
}
ULONG CbAdrInfoSize(LPADRINFO lpAdrInfo)
{
ULONG cb=sizeof(ADRINFO);
#ifdef _WIN64
cb = LcbAlignLcb(cb);
#endif
Assert(lpAdrInfo);
if (lpAdrInfo->lpwszAddress)
{
cb+=(lstrlenW(lpAdrInfo->lpwszAddress)+1)*sizeof(WCHAR);
#ifdef _WIN64
cb = LcbAlignLcb(cb);
#endif
}
if (lpAdrInfo->lpwszDisplay)
{
cb+=(lstrlenW(lpAdrInfo->lpwszDisplay)+1)*sizeof(WCHAR);
#ifdef _WIN64
cb = LcbAlignLcb(cb);
#endif
}
if (lpAdrInfo->lpwszAddrType)
{
cb+=(lstrlenW(lpAdrInfo->lpwszAddrType)+1)*sizeof(WCHAR);
#ifdef _WIN64
cb = LcbAlignLcb(cb);
#endif
}
if (lpAdrInfo->lpwszSurName)
{
cb+=(lstrlenW(lpAdrInfo->lpwszSurName)+1)*sizeof(WCHAR);
#ifdef _WIN64
cb = LcbAlignLcb(cb);
#endif
}
if (lpAdrInfo->lpwszGivenName)
{
cb+=(lstrlenW(lpAdrInfo->lpwszGivenName)+1)*sizeof(WCHAR);
#ifdef _WIN64
cb = LcbAlignLcb(cb);
#endif
}
cb+=lpAdrInfo->cbEID;
return cb;
}
void SerialAdrInfoString(LPWSTR *ppwszDest, ULONG cchDest, LPWSTR pwszSrc, ULONG *pcbOff, LPBYTE *ppbData)
{
ULONG cb;
if (pwszSrc)
{
(*ppwszDest)=(LPWSTR)((ULONG_PTR)(*pcbOff));
StrCpyNW((LPWSTR)(*ppbData), pwszSrc, cchDest);
cb=(lstrlenW(pwszSrc)+1)*sizeof(WCHAR);
(*ppbData)+=cb;
(*pcbOff)+=cb;
}
}
HRESULT HrCreateWabalObjectFromHGlobal(HGLOBAL hGlobal, LPWABAL *lplpWabal)
{
HRESULT hr;
LPWABAL lpWabal=0;
LPADRINFOLIST lpAdrInfoList;
LPADRINFOLIST lpAdrInfoListNew;
LPADRINFO lpAdrInfo;
ULONG cb,
uRow;
if (!lplpWabal)
return E_INVALIDARG;
if (!hGlobal)
return E_INVALIDARG;
hr=HrCreateWabalObject(&lpWabal);
if (FAILED(hr))
return hr;
cb = (ULONG) GlobalSize(hGlobal);
// create a new 'unflattened' addr info list
if (!MemAlloc((LPVOID *)&lpAdrInfoListNew, cb))
return E_OUTOFMEMORY;
ZeroMemory(lpAdrInfoListNew, cb);
lpAdrInfoList=(LPADRINFOLIST)GlobalLock(hGlobal);
if (!lpAdrInfoList)
{
MemFree(lpAdrInfoListNew);
return E_FAIL;
}
// copy the flat data
CopyMemory(lpAdrInfoListNew, lpAdrInfoList, cb);
lpAdrInfoListNew->rgAdrInfo=(LPADRINFO)((DWORD_PTR)lpAdrInfoListNew->rgAdrInfo + (DWORD_PTR)lpAdrInfoListNew);
lpAdrInfo=lpAdrInfoListNew->rgAdrInfo;
// patch the pointers...
for(uRow=0; uRow<lpAdrInfoListNew->cValues; uRow++, lpAdrInfo++)
{
// All the address offsets are in bytes. Make sure we convert to chars.
if (lpAdrInfo->lpwszAddress)
lpAdrInfo->lpwszAddress += (DWORD_PTR)lpAdrInfoListNew/sizeof(WCHAR);
if (lpAdrInfo->lpwszDisplay)
lpAdrInfo->lpwszDisplay += (DWORD_PTR)lpAdrInfoListNew/sizeof(WCHAR);
if (lpAdrInfo->lpwszAddrType)
lpAdrInfo->lpwszAddrType += (DWORD_PTR)lpAdrInfoListNew/sizeof(WCHAR);
if (lpAdrInfo->lpwszSurName)
lpAdrInfo->lpwszSurName += (DWORD_PTR)lpAdrInfoListNew/sizeof(WCHAR);
if (lpAdrInfo->lpwszGivenName)
lpAdrInfo->lpwszGivenName += (DWORD_PTR)lpAdrInfoListNew/sizeof(WCHAR);
if (lpAdrInfo->lpbEID)
lpAdrInfo->lpbEID+=(DWORD_PTR)lpAdrInfoListNew;
}
// now add it all to the wabal
lpAdrInfo=lpAdrInfoListNew->rgAdrInfo;
for(uRow=0; uRow<lpAdrInfoListNew->cValues; uRow++, lpAdrInfo++)
{
if (lpAdrInfo->fResolved)
lpWabal->HrAddEntry(lpAdrInfo);
else
lpWabal->HrAddUnresolved(lpAdrInfo->lpwszDisplay, -1);
}
*lplpWabal=lpWabal;
GlobalUnlock(hGlobal);
MemFree(lpAdrInfoListNew);
return NOERROR;
}
HRESULT CWabal::HrBuildHGlobal(HGLOBAL *phGlobal)
{
HGLOBAL hGlobal=0;
ADRINFO adrInfo;
ULONG cbAlloc,
#ifdef DEBUG
cFound=0,
#endif
cb;
LPADRINFOLIST lpAdrInfoList;
ULONG cbOff;
LPADRINFO lpAdrInfo;
LPBYTE pbData;
if (!phGlobal)
return E_INVALIDARG;
*phGlobal=0;
cbAlloc=sizeof(ADRINFOLIST);
if (FGetFirst(&adrInfo))
{
do
cbAlloc+=CbAdrInfoSize(&adrInfo);
while(FGetNext(&adrInfo));
}
else
return E_FAIL;
hGlobal=GlobalAlloc(GMEM_SHARE|GHND, cbAlloc);
if (!hGlobal)
return E_OUTOFMEMORY;
lpAdrInfoList=(LPADRINFOLIST)GlobalLock(hGlobal);
if (!lpAdrInfoList)
{
GlobalFree(hGlobal);
return E_FAIL;
}
cbOff=sizeof(ADRINFOLIST);
lpAdrInfoList->rgAdrInfo=(LPADRINFO)((ULONG_PTR)cbOff);
lpAdrInfo=(LPADRINFO)((DWORD_PTR)lpAdrInfoList+cbOff);
cbOff+=m_cActualEntries*sizeof(ADRINFO);
lpAdrInfoList->cValues=m_cActualEntries;
pbData=(LPBYTE)((DWORD_PTR)lpAdrInfoList+cbOff);
SideAssert(FGetFirst(&adrInfo)); // there HAS to be entries at this point!
do
{
// copy the flat data
CopyMemory(lpAdrInfo, &adrInfo, sizeof(ADRINFO));
// patch the pointers...
SerialAdrInfoString(&lpAdrInfo->lpwszAddress, (cbAlloc-cbOff)/sizeof(WCHAR), adrInfo.lpwszAddress, &cbOff, &pbData);
SerialAdrInfoString(&lpAdrInfo->lpwszDisplay, (cbAlloc-cbOff)/sizeof(WCHAR), adrInfo.lpwszDisplay, &cbOff, &pbData);
SerialAdrInfoString(&lpAdrInfo->lpwszAddrType, (cbAlloc-cbOff)/sizeof(WCHAR), adrInfo.lpwszAddrType, &cbOff, &pbData);
SerialAdrInfoString(&lpAdrInfo->lpwszSurName, (cbAlloc-cbOff)/sizeof(WCHAR), adrInfo.lpwszSurName, &cbOff, &pbData);
SerialAdrInfoString(&lpAdrInfo->lpwszGivenName, (cbAlloc-cbOff)/sizeof(WCHAR), adrInfo.lpwszGivenName, &cbOff, &pbData);
AssertSz(lpAdrInfo->cbEID==adrInfo.cbEID, "this should have been copied already");
cb=lpAdrInfo->cbEID;
if (cb)
{
lpAdrInfo->lpbEID=(LPBYTE)((ULONG_PTR)cbOff);
CopyMemory(pbData, adrInfo.lpbEID, cb);
cbOff+=cb;
pbData+=cb;
}
lpAdrInfo++;
#ifdef DEBUG
cFound++;
#endif
}
while(FGetNext(&adrInfo));
#ifdef DEBUG
Assert(cFound==m_cActualEntries);
#endif
GlobalUnlock(hGlobal);
*phGlobal=hGlobal;
return NOERROR;
}
HRESULT CWabal::HrRulePickNames(HWND hwndParent, LONG lRecipType, UINT uidsCaption, UINT uidsWell, UINT uidsWellButton)
{
// Locals
HRESULT hr=S_OK;
ADRPARM rAdrParms={0};
LPWAB lpWab=0;
WCHAR wszRes1[255],
wszRes2[255],
wszRes3[255];
ULONG uRow;
LPWSTR rgwszWells[1] = { wszRes3 };
if (m_lpAdrList == NULL || m_cActualEntries == m_lpAdrList->cEntries)
{
// Lets grow my current address list by GROW_SIZE
CHECKHR (hr = HrGrowAdrlist (&m_lpAdrList, GROW_SIZE));
}
AthLoadStringW(uidsCaption, wszRes1, ARRAYSIZE(wszRes1));
AthLoadStringW(uidsWell, wszRes2, ARRAYSIZE(wszRes2));
AthLoadStringW(uidsWellButton, wszRes3, ARRAYSIZE(wszRes3));
rAdrParms.ulFlags = DIALOG_MODAL|MAPI_UNICODE;
rAdrParms.lpszCaption = (LPTSTR)wszRes1;
rAdrParms.lpszDestWellsTitle = (LPTSTR)wszRes2;
rAdrParms.cDestFields = 1;
rAdrParms.nDestFieldFocus = 0;
rAdrParms.lppszDestTitles = (LPTSTR*)rgwszWells;
rAdrParms.lpulDestComps = (ULONG *)&lRecipType;
CHECKHR(hr=HrCreateWabObject(&lpWab));
hr=lpWab->HrGeneralPickNames(hwndParent, &rAdrParms, &m_lpAdrList);
CHECKHR(hr);
//HACKHACK: ugh, this is nasty, the pal mayhave been realloced, or maybe
// our old pal, need to figure out how many real entries are in it...
m_cActualEntries=0;
if (m_lpAdrList)
{
for(uRow=0; uRow<m_lpAdrList->cEntries; uRow++)
if (m_lpAdrList->aEntries[uRow].cValues)
m_cActualEntries++;
}
exit:
ReleaseObj(lpWab);
return hr;
}
HRESULT CWabal::HrPickNames (HWND hwndParent, ULONG *rgulTypes, int cWells, int iFocus, BOOL fNews)
{
HRESULT hr;
LPWAB lpWab=0;
ULONG uRow;
if (m_lpAdrList == NULL || m_cActualEntries == m_lpAdrList->cEntries)
{
// Lets grow my current address list by GROW_SIZE
CHECKHR (hr = HrGrowAdrlist (&m_lpAdrList, GROW_SIZE));
}
CHECKHR(hr=HrCreateWabObject(&lpWab));
hr=lpWab->HrPickNames(hwndParent, rgulTypes, cWells, iFocus, fNews, &m_lpAdrList);
CHECKHR(hr);
//HACKHACK: ugh, this is nasty, the pal mayhave been realloced, or maybe
// our old pal, need to figure out how many real entries are in it...
m_cActualEntries=0;
if (m_lpAdrList)
{
for(uRow=0; uRow<m_lpAdrList->cEntries; uRow++)
if (m_lpAdrList->aEntries[uRow].cValues)
m_cActualEntries++;
}
exit:
ReleaseObj(lpWab);
return hr;
}
#ifdef ADDTOWAB_COPYENTRIES
HRESULT CWab::HrAddToWAB(HWND hwndOwner, LPADRINFO lpAdrInfo)
{
HRESULT hr;
HCURSOR hcur;
LPABCONT pabcWAB=NULL;
ULONG cbEidWAB,
ul;
LPENTRYID peidWAB=0;
SBinary bin;
ENTRYLIST el={0, &bin};
if (!lpAdrInfo)
return E_INVALIDARG;
hcur=SetCursor(LoadCursor(NULL, IDC_WAIT));
hr=m_lpAdrBook->GetPAB(&cbEidWAB, &peidWAB);
if (FAILED(hr))
goto error;
hr=m_lpAdrBook->OpenEntry(cbEidWAB, peidWAB, NULL,
0, &ul, (LPUNKNOWN *)&pabcWAB);
if (FAILED(hr))
goto error;
m_lpWabObject->FreeBuffer(peidWAB);
Assert(ul == MAPI_ABCONT);
bin.cb=lpAdrInfo->cbEID;
bin.lpb=lpAdrInfo->lpbEID;
hr=pabcWAB->CopyEntries(&el, (ULONG)hwndOwner, NULL, CREATE_CHECK_DUP_STRICT);
if (FAILED(hr))
goto error;
error:
ReleaseObj(pabcWAB);
if (hcur)
SetCursor(hcur);
return hr;
}
#endif
HRESULT CWab::HrAddToWAB(HWND hwndOwner, LPADRINFO lpAdrInfo, LPMAPIPROP * lppMailUser)
{
HRESULT hr;
HCURSOR hcur;
LPABCONT pabcWAB=NULL;
ULONG cbEidWAB,
ul;
LPENTRYID peidWAB=0;
LPMAPIPROP lpProps=0,
lpPropsUser=0;
DWORD cUsedValues;
SPropValue rgpv[3];
SPropTagArray ptaEID = {1, {PR_ENTRYID}};
LPSPropValue ppv=0,
ppvDefMailUser=0,
ppvUser=0;
ULONG cUserProps=0;
ENTRYLIST el;
SBinary sbin;
SizedSPropTagArray(1, ptaDefMailUser)=
{ 1, {PR_DEF_CREATE_MAILUSER} };
if (!lpAdrInfo)
return E_INVALIDARG;
hcur=SetCursor(LoadCursor(NULL, IDC_WAIT));
hr=m_lpAdrBook->GetPAB(&cbEidWAB, &peidWAB);
if (FAILED(hr))
goto error;
hr=m_lpAdrBook->OpenEntry(cbEidWAB, peidWAB, NULL,
0, &ul, (LPUNKNOWN *)&pabcWAB);
if (FAILED(hr))
goto error;
m_lpWabObject->FreeBuffer(peidWAB);
Assert(ul == MAPI_ABCONT);
hr=pabcWAB->GetProps((LPSPropTagArray)&ptaDefMailUser, 0, &ul, &ppvDefMailUser);
if (FAILED(hr) || !ppvDefMailUser || ppvDefMailUser->ulPropTag!=PR_DEF_CREATE_MAILUSER)
goto error;
hr=pabcWAB->CreateEntry(ppvDefMailUser->Value.bin.cb, (LPENTRYID)ppvDefMailUser->Value.bin.lpb,
CREATE_CHECK_DUP_STRICT, &lpProps);
if (FAILED(hr))
goto error;
if (lpAdrInfo->lpbEID)
{
// if we have an entry for the user (could be an LDAP search), then let's copy across all the props
// note. we still override these with the displayname props and possible cert props later on.
if (m_lpAdrBook->OpenEntry(lpAdrInfo->cbEID, (LPENTRYID)lpAdrInfo->lpbEID, &IID_IMAPIProp, 0, &ul, (LPUNKNOWN *)&lpPropsUser)==S_OK)
{
Assert (ul == MAPI_MAILUSER);
if (lpPropsUser->GetProps(NULL, 0, &cUserProps, &ppvUser)==S_OK)
{
for (ULONG u=0; u<cUserProps; u++)
if (ppvUser[u].ulPropTag == PR_ENTRYID)
ppvUser[u].ulPropTag = PR_NULL;
lpProps->SetProps(cUserProps, ppvUser, NULL);
m_lpWabObject->FreeBuffer(ppvUser);
}
lpPropsUser->Release();
}
}
rgpv[0].ulPropTag = PR_DISPLAY_NAME_W;
rgpv[0].Value.lpszW = lpAdrInfo->lpwszDisplay;
rgpv[1].ulPropTag = PR_EMAIL_ADDRESS_W;
rgpv[1].Value.lpszW = lpAdrInfo->lpwszAddress;
cUsedValues = 2;
if (lpAdrInfo->pMsg)
{
HCERTSTORE hc, hcMsg;
THUMBBLOB tbSigner = {0};
BLOB blSymCaps = {0};
FILETIME ftSigningTime = {0};
PCCERT_CONTEXT pcSigningCert = NULL;
PROPVARIANT var;
IMimeBody *pBody = NULL;
HBODY hBody = NULL;
// Does this message have a sender cert?
if (SUCCEEDED(GetSigningCert(lpAdrInfo->pMsg, &pcSigningCert, &tbSigner, &blSymCaps, &ftSigningTime)))
{
// Get the sender's cert from the message and add it to the AddressBook cert store
if (hc = CertOpenStore(CERT_STORE_PROV_SYSTEM_A,
X509_ASN_ENCODING, NULL,
CERT_SYSTEM_STORE_CURRENT_USER, c_szWABCertStore))
{
CertAddCertificateContextToStore(hc, pcSigningCert,
CERT_STORE_ADD_REPLACE_EXISTING, NULL);
CertFreeCertificateContext(pcSigningCert);
CertCloseStore(hc, 0);
}
// Add the CA certs
// Get the hcMsg property from the message
if(FAILED(hr = HrGetInnerLayer(lpAdrInfo->pMsg, &hBody)))
goto ex;
if (SUCCEEDED(lpAdrInfo->pMsg->BindToObject(hBody ? hBody : HBODY_ROOT, IID_IMimeBody, (void **)&pBody)))
{
#ifdef _WIN64
if (SUCCEEDED(pBody->GetOption(OID_SECURITY_HCERTSTORE_64, &var)))
{
hcMsg = (HCERTSTORE)(var.pulVal); // Closed in WM_DESTROY
#else // !_WIN64
if (SUCCEEDED(pBody->GetOption(OID_SECURITY_HCERTSTORE, &var)))
{
hcMsg = (HCERTSTORE) var.ulVal; // Closed in WM_DESTROY
#endif
if (hcMsg) // message store containing certs
{
hc = CertOpenStore(CERT_STORE_PROV_SYSTEM_A,
X509_ASN_ENCODING, NULL,
CERT_SYSTEM_STORE_CURRENT_USER, c_szCACertStore);
if (hc)
{
HrSaveCACerts(hc, hcMsg);
CertCloseStore(hc, 0);
}
CertCloseStore(hcMsg, 0); // was addref'd when we got it.
}
}
ReleaseObj(pBody);
}
ex:
if (SUCCEEDED(hr=ThumbprintToPropValue(&rgpv[cUsedValues],
&tbSigner,
&blSymCaps,
ftSigningTime,
TRUE))) // Since we are creating the entry, this must be default.
cUsedValues++;
if (tbSigner.pBlobData)
MemFree(tbSigner.pBlobData);
if (blSymCaps.pBlobData)
MemFree(blSymCaps.pBlobData);
}
}
hr=lpProps->SetProps(cUsedValues, rgpv, NULL);
if (FAILED(hr))
goto error;
hr=lpProps->SaveChanges(KEEP_OPEN_READONLY);
if (FAILED(hr))
{
// if (tbSigner.pBlobData)
// { // There is a cert. We should try to merge it into the existing entry.
// BUGBUG: NYI
//
// }
// else
goto error;
}
hr=lpProps->GetProps(&ptaEID, 0, &ul, &ppv);
if (!FAILED(hr) && ppv && ppv->ulPropTag==PR_ENTRYID)
{
hr=m_lpAdrBook->Details((ULONG_PTR *)&hwndOwner, NULL, NULL, ppv->Value.bin.cb, (LPENTRYID)ppv->Value.bin.lpb, NULL, NULL, NULL, 0);
}
if (lppMailUser)
{
*lppMailUser = lpProps;
}
else
{
ReleaseObj(lpProps);
}
if (hr==MAPI_E_USER_CANCEL)
{
// the user canceled details, blow away the new entry, silent fail
el.cValues=1;
el.lpbin=&ppv->Value.bin;
pabcWAB->DeleteEntries(&el, 0);
}
error:
ReleaseObj(pabcWAB);
if (ppv)
m_lpWabObject->FreeBuffer(ppv);
if (ppvDefMailUser)
m_lpWabObject->FreeBuffer(ppvDefMailUser);
if (hcur)
SetCursor(hcur);
return hr;
}
HRESULT CWab::HrUpdateWABEntry(LPADRINFO lpAdrInfo, DWORD mask)
{
HRESULT hr;
LPMAILUSER lpMailUser = NULL;
ULONG ulObjType;
ADRENTRY adrentry = {0};
if (!(lpAdrInfo->cbEID && lpAdrInfo->lpbEID))
return E_INVALIDARG;
if (FAILED(hr=m_lpAdrBook->OpenEntry(lpAdrInfo->cbEID, (LPENTRYID)lpAdrInfo->lpbEID,
NULL, MAPI_MODIFY, &ulObjType,
(LPUNKNOWN *)&lpMailUser)))
goto exit;
Assert(lpMailUser);
if (FAILED(hr = HrSetAdrEntry (m_lpWabObject, &adrentry, lpAdrInfo, mask)))
goto exit;
if (FAILED(hr = lpMailUser->SetProps(adrentry.cValues, adrentry.rgPropVals, NULL)))
goto exit;
hr = lpMailUser->SaveChanges(KEEP_OPEN_READONLY);
exit:
ReleaseObj(lpMailUser);
return hr;
}
HRESULT CWab::HrUpdateWABEntryNoEID(HWND hwndParent, LPADRINFO lpAdrInfo, DWORD mask)
{
HRESULT hr;
SizedADRLIST (1, adrlist) = {1, {0,0,NULL}};
DWORD i;
if (lpAdrInfo->lpbEID)
return E_INVALIDARG;
if (FAILED(hr = HrSetAdrEntry (m_lpWabObject, &adrlist.aEntries[0], lpAdrInfo, AIM_DISPLAY)))
goto exit;
if (FAILED(hr = m_lpAdrBook->ResolveName ((ULONG_PTR)hwndParent, MAPI_DIALOG, NULL, (LPADRLIST)&adrlist)))
goto exit;
for (i=0; i<adrlist.aEntries[0].cValues; i++)
{
if (PR_ENTRYID == adrlist.aEntries[0].rgPropVals[i].ulPropTag)
{
lpAdrInfo->cbEID = adrlist.aEntries[0].rgPropVals[i].Value.bin.cb;
lpAdrInfo->lpbEID = adrlist.aEntries[0].rgPropVals[i].Value.bin.lpb;
break;
}
}
if (!lpAdrInfo->lpbEID)
{
hr = TrapError(E_FAIL);
goto exit;
}
hr = HrUpdateWABEntry(lpAdrInfo, mask);
exit:
if (adrlist.aEntries[0].rgPropVals)
m_lpWabObject->FreeBuffer(adrlist.aEntries[0].rgPropVals);
lpAdrInfo->cbEID = 0;
lpAdrInfo->lpbEID = NULL;
return hr;
}
// =============================================================================
// CWab::HrGetAdrBook
// =============================================================================
HRESULT CWab::HrGetAdrBook(LPADRBOOK* lppAdrBook)
{
Assert(lppAdrBook);
if (!lppAdrBook)
return E_INVALIDARG;
*lppAdrBook = m_lpAdrBook;
return NOERROR;
}
// =============================================================================
// CWab::HrGetWabObject
// =============================================================================
HRESULT CWab::HrGetWabObject(LPWABOBJECT* lppWabObject)
{
Assert(lppWabObject);
if (!lppWabObject)
return E_INVALIDARG;
*lppWabObject = m_lpWabObject;
return NOERROR;
}
/***************************************************************************
Name : FTranslateAccelerator
Purpose : Give an open WAB window a change to look for accelerators.
Parameters: lpmsg -> lpmsg from the current event
Returns : BOOL - was the event used
***************************************************************************/
BOOL CWab::FTranslateAccelerator(LPMSG lpmsg)
{
if (m_adrParm.lpfnABSDI && m_hwnd && GetActiveWindow() == m_hwnd)
return ((m_adrParm.lpfnABSDI)((ULONG_PTR)m_hwnd, (LPVOID)lpmsg));
return FALSE;
}
/***************************************************************************
Name : OnClose
Purpose : We are closing the application. If the window is open, tell
it to close.
Parameters: none
Returns : HRESULT
***************************************************************************/
HRESULT CWab::OnClose()
{
DOUT ("CWab::OnClose");
if (m_hwnd)
SendMessage(m_hwnd, WM_CLOSE, 0, 0);
return S_OK;
}
HRESULT HrCloseWabWindow()
{
HRESULT hr = S_OK;
if (g_pWab)
hr = g_pWab->OnClose();
return hr;
}
#ifdef DEBUG
void DEBUGDumpAdrList(LPADRLIST pal)
{
char sz[2048];
WCHAR wsz[2048];
ULONG ul,
ulProp;
if (!pal)
{
OutputDebugString("<Empty Adrlist>\n\r");
return;
}
wnsprintf(sz, ARRAYSIZE(sz), "AdrList:: (%d entries)", pal->cEntries);
OutputDebugString(sz);
for(ul=0; ul<pal->cEntries; ul++)
{
wnsprintf(sz, ARRAYSIZE(sz), "\n\r %d) {cVal=%d, {", ul, pal->aEntries[ul].cValues);
OutputDebugString(sz);
for(ulProp=0; ulProp<pal->aEntries[ul].cValues; ulProp++)
{
switch(pal->aEntries[ul].rgPropVals[ulProp].ulPropTag)
{
case PR_ENTRYID:
OutputDebugString("EID");
break;
case PR_EMAIL_ADDRESS:
OutputDebugString("ADDRESS");
break;
case PR_EMAIL_ADDRESS_W:
OutputDebugString("ADDRESS_W");
break;
case PR_ADDRTYPE:
OutputDebugString("ADDRTYPE");
break;
case PR_ADDRTYPE_W:
OutputDebugString("ADDRTYPE_W");
break;
// If the prop is ansi, the output might be funky.
case PR_DISPLAY_NAME:
wnsprintf(sz, ARRAYSIZE(sz), "DISP(%s)", pal->aEntries[ul].rgPropVals[ulProp].Value.lpszA);
OutputDebugString(sz);
break;
case PR_DISPLAY_NAME_W:
wnsprintfW(wsz, ARRAYSIZE(wsz), L"DISP(%s)", pal->aEntries[ul].rgPropVals[ulProp].Value.lpszW);
OutputDebugStringWrapW(wsz);
break;
case PR_SURNAME:
OutputDebugString("SURNAME");
break;
case PR_SURNAME_W:
OutputDebugString("SURNAME_W");
break;
case PR_GIVEN_NAME:
OutputDebugString("GIVENNAME");
break;
case PR_GIVEN_NAME_W:
OutputDebugString("GIVENNAME_W");
break;
case PROP_ID(PR_RECIPIENT_TYPE):
wnsprintf(sz, ARRAYSIZE(sz), "RECIPTYPE(%d)", pal->aEntries[ul].rgPropVals[ulProp].Value.l);
OutputDebugString(sz);
break;
case PROP_ID(PR_SEARCH_KEY):
OutputDebugString("SEARCHKEY");
break;
case PROP_ID(PR_OBJECT_TYPE):
OutputDebugString("OBJTYPE");
break;
default:
wnsprintf(sz, ARRAYSIZE(sz), "<unknown> 0x%x", pal->aEntries[ul].rgPropVals[ulProp].ulPropTag);
OutputDebugString(sz);
break;
}
if (ulProp+1<pal->aEntries[ul].cValues)
OutputDebugString(", ");
}
OutputDebugString("}}");
}
OutputDebugString("\n\r");
}
#endif
HRESULT CWabal::HrAdrInfoFromRow(LPSRow lpsrw, LPADRINFO lpAdrInfo, LONG lRecipType)
{
LPSPropValue ppv;
ULONG ul,
cValues;
Assert(lpsrw);
Assert(lpAdrInfo);
lpAdrInfo->lpwszAddress = NULL;
lpAdrInfo->lpwszAddrType = NULL;
lpAdrInfo->lpwszDisplay = NULL;
lpAdrInfo->lpwszSurName = NULL;
lpAdrInfo->lpwszGivenName = NULL;
lpAdrInfo->lRecipType = lRecipType;
lpAdrInfo->fResolved = FALSE;
lpAdrInfo->fDistList = FALSE;
lpAdrInfo->fDefCertificate = FALSE;
lpAdrInfo->tbCertificate.pBlobData = (BYTE*)0;
lpAdrInfo->tbCertificate.cbSize = 0;
lpAdrInfo->blSymCaps.pBlobData = (BYTE*)0;
lpAdrInfo->blSymCaps.cbSize = 0;
lpAdrInfo->ftSigningTime.dwLowDateTime = lpAdrInfo->ftSigningTime.dwHighDateTime = 0;
lpAdrInfo->cbEID=0;
lpAdrInfo->lpbEID=0;
cValues=lpsrw->cValues;
ppv=lpsrw->lpProps;
AssertSz(cValues, "empty address??");
for(ul=0; ul<cValues; ul++, ppv++)
PropValToAdrInfo(ppv, lpAdrInfo);
DOUTL(4, "AddrEntry2AddrInfo: lRecip=%d", lpAdrInfo->lRecipType);
AssertSz(lpAdrInfo->lpwszAddress==NULL ||
lpAdrInfo->lRecipType != -1, "A resolved entry should have a recip type!");
return NOERROR;
}
void CWabal::PropValToAdrInfo(LPSPropValue ppv, LPADRINFO lpAdrInfo)
{
switch(ppv->ulPropTag)
{
case PR_SEND_INTERNET_ENCODING:
lpAdrInfo->fPlainText = (ppv->Value.l == BODY_ENCODING_TEXT);
break;
case PR_OBJECT_TYPE:
Assert(ppv->Value.l==MAPI_MAILUSER || ppv->Value.l==MAPI_DISTLIST);
lpAdrInfo->fDistList=(ppv->Value.l==MAPI_DISTLIST);
break;
case PR_EMAIL_ADDRESS:
AssertSz(FALSE, "Have to take care of this case.");
//Assert(!lpAdrInfo->lpszAddress);
//lpAdrInfo->lpszAddress = ppv->Value.lpszA;
break;
case PR_EMAIL_ADDRESS_W:
Assert(!lpAdrInfo->lpwszAddress);
lpAdrInfo->lpwszAddress = ppv->Value.lpszW;
break;
case PR_ADDRTYPE:
AssertSz(FALSE, "Have to take care of this case.");
//Assert(!lpAdrInfo->lpszAddrType);
//lpAdrInfo->lpszAddrType = ppv->Value.lpszA;
break;
case PR_ADDRTYPE_W:
Assert(!lpAdrInfo->lpwszAddrType);
lpAdrInfo->lpwszAddrType = ppv->Value.lpszW;
break;
case PR_RECIPIENT_TYPE:
Assert(lpAdrInfo->lRecipType==-1);
lpAdrInfo->lRecipType = ppv->Value.l;
break;
case PR_DISPLAY_NAME:
AssertSz(FALSE, "Have to take care of this case.");
//Assert(!lpAdrInfo->lpszDisplay);
//lpAdrInfo->lpszDisplay = ppv->Value.lpszA;
break;
case PR_DISPLAY_NAME_W:
Assert(!lpAdrInfo->lpwszDisplay);
lpAdrInfo->lpwszDisplay = ppv->Value.lpszW;
break;
case PR_SURNAME:
AssertSz(FALSE, "Have to take care of this case.");
//Assert(!lpAdrInfo->lpszSurName);
//lpAdrInfo->lpszSurName = ppv->Value.lpszA;
break;
case PR_GIVEN_NAME:
AssertSz(FALSE, "Have to take care of this case.");
//Assert(!lpAdrInfo->lpszGivenName);
//lpAdrInfo->lpszGivenName = ppv->Value.lpszA;
break;
case PR_SURNAME_W:
Assert(!lpAdrInfo->lpwszSurName);
lpAdrInfo->lpwszSurName = ppv->Value.lpszW;
break;
case PR_GIVEN_NAME_W:
Assert(!lpAdrInfo->lpwszGivenName);
lpAdrInfo->lpwszGivenName = ppv->Value.lpszW;
break;
case PR_ENTRYID:
lpAdrInfo->cbEID=ppv->Value.bin.cb;
lpAdrInfo->lpbEID=ppv->Value.bin.lpb;
lpAdrInfo->fResolved=TRUE; // it's resolved if it has an entryid
break;
case PR_USER_X509_CERTIFICATE:
// Assume only one value in cert array.
Assert(ppv->Value.MVbin.cValues == 1);
if (ppv->Value.MVbin.cValues)
{
BOOL fDefault = FALSE;
GetX509CertTags(&ppv->Value.MVbin.lpbin[0], &lpAdrInfo->tbCertificate, &lpAdrInfo->blSymCaps,
&lpAdrInfo->ftSigningTime, &fDefault);
lpAdrInfo->fDefCertificate = fDefault;
}
break;
}
}
HRESULT CWabal::HrExpandTo(LPWABAL lpWabal)
{
ADRINFO adrInfo;
LPSRowSet prwsDL=0;
HRESULT hr=S_OK;
SBinary eidDL;
DLSEARCHINFO DLSearch={0};
if (!lpWabal)
return E_INVALIDARG;
if (FGetFirst(&adrInfo))
do
{
if (adrInfo.fDistList)
{
eidDL.cb=adrInfo.cbEID;
eidDL.lpb=adrInfo.lpbEID;
if (!FDLVisted(eidDL, &DLSearch))
{
// this is a new distribution list, let's open it and scan..
// add this distlist to our searchlist, and recurse...
hr=HrAddToSearchList(eidDL, &DLSearch);
if (FAILED(hr))
goto error;
hr=HrGetDistListRows(eidDL, &prwsDL);
if (FAILED(hr))
{
hr = hrEmptyDistList;
goto error;
}
hr=HrAddDistributionList(lpWabal, prwsDL, adrInfo.lRecipType, &DLSearch);
if (FAILED(hr))
goto error;
m_lpWabObject->FreeBuffer(prwsDL);
prwsDL=NULL;
}
}
else
{
hr=lpWabal->HrAddEntry(&adrInfo, TRUE);
if (FAILED(hr))
goto error;
}
}
while(FGetNext(&adrInfo));
error:
if (prwsDL)
m_lpWabObject->FreeBuffer(prwsDL);
FreeSearchList(&DLSearch);
return hr;
}
HRESULT CWabal::HrAddDistributionList(LPWABAL lpWabal, LPSRowSet lprws, LONG lRecipType, PDLSEARCHINFO pDLSearch)
{
HRESULT hr=NOERROR;
ULONG ul;
LPSRowSet prwsDL=0;
ADRINFO adrInfo;
for(ul=0; ul<lprws->cRows; ul++)
{
if (lprws->aRow[ul].lpProps[AE_colObjectType].ulPropTag==PR_OBJECT_TYPE &&
lprws->aRow[ul].lpProps[AE_colObjectType].Value.l == MAPI_DISTLIST &&
lprws->aRow[ul].lpProps[AE_colEntryID].ulPropTag==PR_ENTRYID)
{
if (!FDLVisted(lprws->aRow[ul].lpProps[AE_colEntryID].Value.bin, pDLSearch))
{
// this is a new distribution list, let's open it and scan..
// add this distlist to our searchlist, and recurse...
hr=HrAddToSearchList(lprws->aRow[ul].lpProps[AE_colEntryID].Value.bin, pDLSearch);
if (FAILED(hr))
goto error;
hr=HrGetDistListRows(lprws->aRow[ul].lpProps[AE_colEntryID].Value.bin, &prwsDL);
if (FAILED(hr))
goto error;
hr=HrAddDistributionList(lpWabal, prwsDL, lRecipType, pDLSearch);
if (FAILED(hr))
goto error;
m_lpWabObject->FreeBuffer(prwsDL);
prwsDL=NULL;
}
}
else
if ( lprws->aRow[ul].lpProps[AE_colObjectType].ulPropTag==PR_OBJECT_TYPE &&
lprws->aRow[ul].lpProps[AE_colObjectType].Value.l == MAPI_MAILUSER )
{
// just a regular user...
hr=HrAdrInfoFromRow(&lprws->aRow[ul], &adrInfo, lRecipType);
if (FAILED(hr))
goto error;
hr=lpWabal->HrAddEntry(&adrInfo, TRUE);
if (FAILED(hr))
goto error;
}
}
error:
if (prwsDL)
m_lpWabObject->FreeBuffer(prwsDL);
return hr;
}
BOOL CWabal::FDLVisted(SBinary eidDL, PDLSEARCHINFO pDLSearch)
{
ULONG ul,
ulResult=0;
HRESULT hr;
for(ul=0; ul<pDLSearch->cValues; ul++)
{
hr=m_lpAdrBook->CompareEntryIDs(eidDL.cb, (LPENTRYID)eidDL.lpb,
pDLSearch->rgEid[ul].cb,
(LPENTRYID)pDLSearch->rgEid[ul].lpb, 0, &ulResult);
if ((!FAILED(hr)) && ulResult)
return TRUE;
}
return FALSE;
}
HRESULT CWabal::HrAddToSearchList(SBinary eidDL, PDLSEARCHINFO pDLSearch)
{
ULONG ulResult=0;
LPBYTE lpb=0;
if (pDLSearch->cValues==pDLSearch->cAlloc)
{
// time to grow...
if (!MemRealloc((LPVOID *)&pDLSearch->rgEid, sizeof(SBinary)*(pDLSearch->cAlloc+GROW_SIZE)))
return E_OUTOFMEMORY;
//ZeroInit the new stuff...
ZeroMemory(&pDLSearch->rgEid[pDLSearch->cAlloc], sizeof(SBinary)*GROW_SIZE);
pDLSearch->cAlloc+=GROW_SIZE;
}
if (!MemAlloc((LPVOID *)&lpb, eidDL.cb))
return E_OUTOFMEMORY;
pDLSearch->rgEid[pDLSearch->cValues].cb=eidDL.cb;
pDLSearch->rgEid[pDLSearch->cValues].lpb=lpb;
CopyMemory(lpb, eidDL.lpb, eidDL.cb);
pDLSearch->cValues++;
return NOERROR;
}
HRESULT CWabal::FreeSearchList(PDLSEARCHINFO pDLSearch)
{
ULONG ul;
if (pDLSearch)
{
for(ul=0; ul<pDLSearch->cValues; ul++)
if (pDLSearch->rgEid[ul].lpb)
MemFree(pDLSearch->rgEid[ul].lpb);
#ifdef DEBUG
for(ul=pDLSearch->cValues; ul<pDLSearch->cAlloc; ul++)
AssertSz(pDLSearch->rgEid[ul].cb==NULL && pDLSearch->rgEid[ul].lpb==NULL, "should be null!");
#endif
if (pDLSearch->rgEid)
MemFree(pDLSearch->rgEid);
}
return NOERROR;
}
HRESULT CWabal::HrGetDistListRows(SBinary eidDL, LPSRowSet *psrws)
{
HRESULT hr;
LPMAPITABLE ptblDistList=0;
ULONG ulObjType,
cRows=0;
LPDISTLIST pDistList=0;
Assert(m_lpAdrBook);
hr=m_lpAdrBook->OpenEntry(eidDL.cb, (LPENTRYID)eidDL.lpb, &IID_IDistList, 0, &ulObjType, (LPUNKNOWN *)&pDistList);
if (FAILED(hr))
goto cleanup;
Assert(pDistList);
hr=pDistList->GetContentsTable(MAPI_UNICODE, &ptblDistList);
if (FAILED(hr))
goto cleanup;
Assert(ptblDistList);
hr=ptblDistList->GetRowCount(0, &cRows);
if (FAILED(hr))
goto cleanup;
hr=ptblDistList->SetColumns((LPSPropTagArray)&AE_props, 0);
if (FAILED(hr))
goto cleanup;
hr=ptblDistList->QueryRows(cRows, 0, psrws);
if (FAILED(hr))
goto cleanup;
cleanup:
ReleaseObj(ptblDistList);
ReleaseObj(pDistList);
return hr;
}
HRESULT CWabal::HrGetPMP(ULONG cbEntryID, LPENTRYID lpEntryID, ULONG *lpul, LPMAPIPROP *lppmp)
{
return m_lpAdrBook->OpenEntry(cbEntryID, lpEntryID, &IID_IMAPIProp, 0, lpul, (LPUNKNOWN *)lppmp);
}
/***************************************************************************
Name : HrBuildCertSBinaryData
Purpose : Takes as input all the data needed for a cert entry
in PR_USER_X509_CERTIFICATE and returns a pointer to
memory that contains all the input data in the correct
format to be plugged in to the lpb member of an SBinary
structure. This memory should be Freed by the caller.
Parameters: bIsDefault - TRUE if this is the default cert
pblobCertThumbPrint - The actual certificate thumbprint
pblobSymCaps - symcaps blob
ftSigningTime - Signing time
lplpbData - receives the buffer with the data
lpcbData - receives size of the data
Returns : HRESULT
Comment :
***************************************************************************/
HRESULT HrBuildCertSBinaryData(
BOOL bIsDefault,
THUMBBLOB* pPrint,
BLOB * pSymCaps,
FILETIME ftSigningTime,
LPBYTE UNALIGNED FAR* lplpbData,
ULONG UNALIGNED FAR* lpcbData)
{
DWORD cbDefault, cbPrint, cbSymCaps;
HRESULT hr = S_OK;
LPCERTTAGS lpCurrentTag;
ULONG cbSize, cProps;
LPBYTE lpb = NULL;
cbDefault = sizeof(bIsDefault);
cbPrint = pPrint->cbSize;
cbSymCaps = pSymCaps->cbSize;
cProps = 2;
cbSize = LcbAlignLcb(cbDefault) + LcbAlignLcb(cbPrint);
if (cbSymCaps) {
cProps++;
cbSize += LcbAlignLcb(cbSymCaps);
}
if (ftSigningTime.dwLowDateTime || ftSigningTime.dwHighDateTime) {
cProps++;
cbSize += LcbAlignLcb(sizeof(FILETIME));
}
cbSize += LcbAlignLcb(cProps * SIZE_CERTTAGS);
if (!MemAlloc((LPVOID *)&lpb, cbSize))
{
hr = E_OUTOFMEMORY;
goto exit;
}
// Set the default property
lpCurrentTag = (LPCERTTAGS)lpb;
lpCurrentTag->tag = CERT_TAG_DEFAULT;
lpCurrentTag->cbData = (WORD) (SIZE_CERTTAGS + cbDefault);
memcpy(&lpCurrentTag->rgbData,
&bIsDefault,
cbDefault);
// Set the thumbprint property
lpCurrentTag = (LPCERTTAGS)((BYTE*)lpCurrentTag + LcbAlignLcb(lpCurrentTag->cbData));
lpCurrentTag->tag = CERT_TAG_THUMBPRINT;
lpCurrentTag->cbData = (WORD) (SIZE_CERTTAGS + cbPrint);
memcpy(&lpCurrentTag->rgbData, pPrint->pBlobData, cbPrint);
// Set the SymCaps property
if (cbSymCaps) {
lpCurrentTag = (LPCERTTAGS)((BYTE*)lpCurrentTag + LcbAlignLcb(lpCurrentTag->cbData));
lpCurrentTag->tag = CERT_TAG_SYMCAPS;
lpCurrentTag->cbData = (WORD) (SIZE_CERTTAGS + pSymCaps->cbSize);
memcpy(&lpCurrentTag->rgbData, pSymCaps->pBlobData, cbSymCaps);
}
// Signing time property
if (ftSigningTime.dwLowDateTime || ftSigningTime.dwHighDateTime) {
lpCurrentTag = (LPCERTTAGS)((BYTE*)lpCurrentTag + LcbAlignLcb(lpCurrentTag->cbData));
lpCurrentTag->tag = CERT_TAG_SIGNING_TIME;
lpCurrentTag->cbData = (WORD) (SIZE_CERTTAGS + sizeof(FILETIME));
memcpy(&lpCurrentTag->rgbData, &ftSigningTime, sizeof(FILETIME));
}
*lpcbData = cbSize;
*lplpbData = lpb;
exit:
return(hr);
}
HRESULT ThumbprintToPropValue(LPSPropValue ppv,
THUMBBLOB *pPrint,
BLOB *pSymCaps,
FILETIME ftSigningTime,
BOOL fDefPrint)
{
SBinary UNALIGNED *pSBin;
DWORD cbDefault, cbPrint, cbSymCaps;
HRESULT hr = S_OK;
LPCERTTAGS lpCurrentTag;
ULONG cbSize, cProps;
Assert(ppv && pPrint);
if (!pPrint->pBlobData)
return E_INVALIDARG;
ppv->ulPropTag = PR_USER_X509_CERTIFICATE;
ppv->Value.MVbin.cValues = 1;
if (!MemAlloc((LPVOID *)&ppv->Value.MVbin.lpbin, sizeof(SBinary)*ppv->Value.MVbin.cValues))
{
hr = E_OUTOFMEMORY;
goto exit;
}
pSBin = ppv->Value.MVbin.lpbin;
hr = HrBuildCertSBinaryData(
fDefPrint,
pPrint,
pSymCaps,
ftSigningTime,
&pSBin->lpb,
&pSBin->cb);
exit:
return hr;
}
ULONG CWabal::DeleteRecipType(LONG lRecipType)
{
ULONG ulNew = 0, ulRemoved;
for (ULONG ul = 0; ul < m_cActualEntries; ul++)
{
for (ULONG ulProp = 0; ulProp < m_lpAdrList->aEntries[ul].cValues; ulProp++)
{
if (m_lpAdrList->aEntries[ul].rgPropVals[ulProp].ulPropTag == PR_RECIPIENT_TYPE)
{
if (m_lpAdrList->aEntries[ul].rgPropVals[ulProp].Value.l != lRecipType)
m_lpAdrList->aEntries[ulNew++] = m_lpAdrList->aEntries[ul];
else
m_lpWabObject->FreeBuffer(m_lpAdrList->aEntries[ul].rgPropVals);
break;
}
}
}
ulRemoved = m_cActualEntries - ulNew;
if (ulRemoved)
ZeroMemory(&m_lpAdrList->aEntries[ulNew], ulRemoved * sizeof(ADRENTRY));
m_cActualEntries = ulNew;
return ulRemoved;
}
void CWabal::UnresolveOneOffs()
{
ULONG ulEntry, ulProp;
LPADRENTRY pae;
LPSPropValue pPropDisp, pPropEmail, pProp;
for (ulEntry = 0, pae = m_lpAdrList->aEntries; ulEntry < m_cActualEntries; ulEntry++, pae++)
{
pPropDisp = NULL;
pPropEmail = NULL;
for (ulProp = 0, pProp = pae->rgPropVals; ulProp < pae->cValues && !(pPropDisp && pPropEmail); ulProp++, pProp++)
{
AssertSz(pProp->ulPropTag != PR_DISPLAY_NAME, "Have more cases to find.");
AssertSz(pProp->ulPropTag != PR_EMAIL_ADDRESS, "Have more cases to find.");
if (pProp->ulPropTag == PR_DISPLAY_NAME_W)
pPropDisp = pProp;
else if (pProp->ulPropTag == PR_EMAIL_ADDRESS_W)
pPropEmail = pProp;
}
if (pPropDisp && pPropEmail)
{
if (!StrCmpW(pPropDisp->Value.lpszW, pPropEmail->Value.lpszW))
pPropEmail->ulPropTag = PR_NULL;
}
}
}
/***************************************************************************
Name : FindX509CertTag
Purpose : Finds a tag inside the USER_X509_CERTIFICATE SBinary
Parameters: lpsb -> SBinary for a particular cert
ulTag = tag to search for
pcbReturn -> returned size (data only).
Returns : pointer into SBinary data location for the tag.
Comment :
***************************************************************************/
LPBYTE FindX509CertTag(LPSBinary lpsb, ULONG ulTag, ULONG * pcbReturn) {
LPCERTTAGS lpCurrentTag = NULL;
LPBYTE lpbTagEnd = NULL;
LPBYTE lpbReturn = NULL;
*pcbReturn = 0;
Assert(lpsb->lpb[0] != 0x30); // Should have found this out before we got here.
if (lpsb && lpsb->cb && (lpsb->lpb[0] != 0x30))
{
lpCurrentTag = (LPCERTTAGS)lpsb->lpb;
lpbTagEnd = (LPBYTE)lpCurrentTag + lpsb->cb;
while ((LPBYTE)lpCurrentTag < lpbTagEnd && (ulTag != lpCurrentTag->tag))
{
if (lpCurrentTag->cbData == 0)
{
DOUTL(4, "Bad CertTag in PR_USER_X509_CERTIFICATE");
break; // Safety valve, prevent infinite loop if bad data
}
lpCurrentTag = (LPCERTTAGS)((BYTE*)lpCurrentTag + lpCurrentTag->cbData);
#ifdef _WIN64
lpCurrentTag = (LPCERTTAGS)MyPbAlignPb((BYTE*)lpCurrentTag);
#endif // _WIN64
}
// Did we find it?
if ((LPBYTE)lpCurrentTag < lpbTagEnd && ulTag == lpCurrentTag->tag && lpCurrentTag->cbData >= SIZE_CERTTAGS)
{
lpbReturn = (LPBYTE)lpCurrentTag->rgbData;
*pcbReturn = lpCurrentTag->cbData - SIZE_CERTTAGS;
}
}
return(lpbReturn);
}
/***************************************************************************
Name : GetX509CertTags
Purpose : Parses the PR_USER_X509_CERTIFICATE property value into
thumbprint, symcaps and signing time.
Parameters: lpsb -> SBinary for a particular cert
ptbCertificate -> returned thumbblob to write to. (required)
pblSymCaps -> returned symcaps blob. (optional)
pftSigningTime -> returned signing time (optional)
pfDefault -> returned default flag (optional)
Returns : HRESULT
Comment : Note that the blob props will be returned with pointers into
the lpsb data. Don't free them! Don't free the propvalue
prior to use!
***************************************************************************/
HRESULT GetX509CertTags(LPSBinary lpsb, THUMBBLOB * ptbCertificate, BLOB * pblSymCaps, LPFILETIME pftSigningTime, BOOL * pfDefault) {
HRESULT hr = S_OK;
LPBYTE pbData;
ULONG cbData = 0;
Assert(ptbCertificate);
// Initialize the return values
ptbCertificate->pBlobData = NULL;
ptbCertificate->cbSize = 0;
if (pblSymCaps) {
pblSymCaps->pBlobData = NULL;
pblSymCaps->cbSize = 0;
}
if (pftSigningTime) {
pftSigningTime->dwLowDateTime = pftSigningTime->dwHighDateTime = 0;
}
if (pfDefault) {
*pfDefault = FALSE;
}
// Find the thumbprint. No thumbprint, no use trying other tags.
if (pbData = FindX509CertTag(lpsb, CERT_TAG_THUMBPRINT, &cbData)) {
ptbCertificate->pBlobData = pbData;
ptbCertificate->cbSize = cbData;
// Symcaps tag
if (pblSymCaps && (pbData = FindX509CertTag(lpsb, CERT_TAG_SYMCAPS, &cbData))) {
pblSymCaps->pBlobData = pbData;
pblSymCaps->cbSize = cbData;
}
// Signing time tag
if (pftSigningTime && (pbData = FindX509CertTag(lpsb, CERT_TAG_SIGNING_TIME, &cbData))) {
memcpy(pftSigningTime, &pbData, min(sizeof(FILETIME), cbData));
}
// scan for "default" tag
if (pfDefault && (pbData = FindX509CertTag(lpsb, CERT_TAG_DEFAULT, &cbData))) {
memcpy((void*)pfDefault, pbData, min(cbData, sizeof(*pfDefault)));
}
}
return(hr);
}
void ImportWAB(HWND hwnd)
{
WABIMPORTPARAM wip;
HRESULT hr;
hr = HrInitWab(TRUE);
if (FAILED(hr))
return;
// Verify Globals
if (!g_fWabLoaded || !g_fWabInit)
return;
EnterCriticalSection (&g_rWabCritSect);
if (g_lpWabObject != NULL && g_lpAdrBook != NULL)
{
wip.cbSize = sizeof(WABIMPORTPARAM);
wip.lpAdrBook = g_lpAdrBook;
wip.hWnd = hwnd;
wip.ulFlags = MAPI_DIALOG;
wip.lpszFileName = NULL;
// this is really intuitive. let's cast a struct to a string! yippee!
g_lpWabObject->Import((LPSTR)&wip);
}
LeaveCriticalSection (&g_rWabCritSect);
}
void Wab_CoDecrement()
{
// bug #59420, can't freelibrary the wab inside the wndproc
// so we post a decrement message to our init window and cleanup
// when the stack is unwound
if (g_pInstance)
CoDecrementInit("WabWindow", NULL);
}