#include "wabobject.h"
enum {
ieidPR_DISPLAY_NAME = 0,
ieidPR_ENTRYID,
ieidPR_OBJECT_TYPE,
ieidMax
};
static const SizedSPropTagArray(ieidMax, ptaEid)=
{
ieidMax,
{
PR_DISPLAY_NAME,
PR_ENTRYID,
PR_OBJECT_TYPE,
}
};
enum {
iemailPR_DISPLAY_NAME = 0,
iemailPR_ENTRYID,
iemailPR_EMAIL_ADDRESS,
iemailPR_OBJECT_TYPE,
iemailMax
};
static const SizedSPropTagArray(iemailMax, ptaEmail)=
{
iemailMax,
{
PR_DISPLAY_NAME,
PR_ENTRYID,
PR_EMAIL_ADDRESS,
PR_OBJECT_TYPE
}
};
/*********************************************************************************/
// contructor for CWAB object
//
// pszFileName - FileName of WAB file to open
// if no file name is specified, opens the default
//
CWAB::CWAB(CString * pszFileName)
{
// Here we load the WAB Object and initialize it
m_bInitialized = FALSE;
m_lpPropArray = NULL;
m_ulcValues = 0;
m_SB.cb = 0;
m_SB.lpb = NULL;
{
TCHAR szWABDllPath[MAX_PATH];
DWORD dwType = 0;
ULONG cbData = sizeof(szWABDllPath);
HKEY hKey = NULL;
*szWABDllPath = '\0';
// First we look under the default WAB DLL path location in the
// Registry.
// WAB_DLL_PATH_KEY is defined in wabapi.h
//
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, WAB_DLL_PATH_KEY, 0, KEY_READ, &hKey))
RegQueryValueEx( hKey, "", NULL, &dwType, (LPBYTE) szWABDllPath, &cbData);
if(hKey) RegCloseKey(hKey);
// if the Registry came up blank, we do a loadlibrary on the wab32.dll
// WAB_DLL_NAME is defined in wabapi.h
//
m_hinstWAB = LoadLibrary( (lstrlen(szWABDllPath)) ? szWABDllPath : WAB_DLL_NAME );
}
if(m_hinstWAB)
{
// if we loaded the dll, get the entry point
//
m_lpfnWABOpen = (LPWABOPEN) GetProcAddress(m_hinstWAB, "WABOpen");
if(m_lpfnWABOpen)
{
HRESULT hr = E_FAIL;
WAB_PARAM wp = {0};
wp.cbSize = sizeof(WAB_PARAM);
wp.szFileName = (LPTSTR) (LPCTSTR) *pszFileName;
// if we choose not to pass in a WAB_PARAM object,
// the default WAB file will be opened up
//
hr = m_lpfnWABOpen(&m_lpAdrBook,&m_lpWABObject,&wp,0);
if(!hr)
m_bInitialized = TRUE;
}
}
}
// Destructor
//
CWAB::~CWAB()
{
if(m_SB.lpb)
LocalFree(m_SB.lpb);
if(m_bInitialized)
{
if(m_lpPropArray)
m_lpWABObject->FreeBuffer(m_lpPropArray);
if(m_lpAdrBook)
m_lpAdrBook->Release();
if(m_lpWABObject)
m_lpWABObject->Release();
if(m_hinstWAB)
FreeLibrary(m_hinstWAB);
}
}
// Opens a wab file and puts its contents into the specified list view
//
HRESULT CWAB::LoadWABContents(CListCtrl * pListView)
{
ULONG ulObjType = 0;
LPMAPITABLE lpAB = NULL;
LPTSTR * lppszArray=NULL;
ULONG cRows = 0;
LPSRowSet lpRow = NULL;
LPSRowSet lpRowAB = NULL;
LPABCONT lpContainer = NULL;
int cNumRows = 0;
int nRows=0;
HRESULT hr = E_FAIL;
ULONG lpcbEID;
LPENTRYID lpEID = NULL;
// Get the entryid of the root PAB container
//
hr = m_lpAdrBook->GetPAB( &lpcbEID, &lpEID);
ulObjType = 0;
// Open the root PAB container
// This is where all the WAB contents reside
//
hr = m_lpAdrBook->OpenEntry(lpcbEID,
(LPENTRYID)lpEID,
NULL,
0,
&ulObjType,
(LPUNKNOWN *)&lpContainer);
m_lpWABObject->FreeBuffer(lpEID);
lpEID = NULL;
if(HR_FAILED(hr))
goto exit;
// Get a contents table of all the contents in the
// WABs root container
//
hr = lpContainer->GetContentsTable( 0,
&lpAB);
if(HR_FAILED(hr))
goto exit;
// Order the columns in the ContentsTable to conform to the
// ones we want - which are mainly DisplayName, EntryID and
// ObjectType
// The table is gauranteed to set the columns in the order
// requested
//
hr =lpAB->SetColumns( (LPSPropTagArray)&ptaEid, 0 );
if(HR_FAILED(hr))
goto exit;
// Reset to the beginning of the table
//
hr = lpAB->SeekRow( BOOKMARK_BEGINNING, 0, NULL );
if(HR_FAILED(hr))
goto exit;
// Read all the rows of the table one by one
//
do {
hr = lpAB->QueryRows(1,0, &lpRowAB);
if(HR_FAILED(hr))
break;
if(lpRowAB)
{
cNumRows = lpRowAB->cRows;
if (cNumRows)
{
LPTSTR lpsz = lpRowAB->aRow[0].lpProps[ieidPR_DISPLAY_NAME].Value.lpszA;
LPENTRYID lpEID = (LPENTRYID) lpRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.lpb;
ULONG cbEID = lpRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.cb;
// There are 2 kinds of objects - the MAPI_MAILUSER contact object
// and the MAPI_DISTLIST contact object
// For the purposes of this sample, we will only consider MAILUSER
// objects
//
if(lpRowAB->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.l == MAPI_MAILUSER)
{
// We will now take the entry-id of each object and cache it
// on the listview item representing that object. This enables
// us to uniquely identify the object later if we need to
//
LPSBinary lpSB = NULL;
m_lpWABObject->AllocateBuffer(sizeof(SBinary), (LPVOID *) &lpSB);
if(lpSB)
{
m_lpWABObject->AllocateMore(cbEID, lpSB, (LPVOID *) &(lpSB->lpb));
if(!lpSB->lpb)
{
m_lpWABObject->FreeBuffer(lpSB);
continue;
}
CopyMemory(lpSB->lpb, lpEID, cbEID);
lpSB->cb = cbEID;
LV_ITEM lvi = {0};
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.iItem = pListView->GetItemCount();
lvi.iSubItem = 0;
lvi.pszText = lpsz;
lvi.lParam = (LPARAM) lpSB;
// Now add this item to the list view
pListView->InsertItem(&lvi);
}
}
}
FreeProws(lpRowAB );
}
}while ( SUCCEEDED(hr) && cNumRows && lpRowAB) ;
exit:
if ( lpContainer )
lpContainer->Release();
if ( lpAB )
lpAB->Release();
return hr;
}
// Clears the contents of the specified ListView
//
void CWAB::ClearWABLVContents(CListCtrl * pListView)
{
int i;
int nCount = pListView->GetItemCount();
if(nCount<=0)
return;
for(i=0;i<nCount;i++)
{
LV_ITEM lvi ={0};
lvi.mask = LVIF_PARAM;
lvi.iItem = i;
lvi.iSubItem = 0;
pListView->GetItem(&lvi);
if(lvi.lParam)
{
LPSBinary lpSB = (LPSBinary) lvi.lParam;
m_lpWABObject->FreeBuffer(lpSB);
}
}
pListView->DeleteAllItems();
}
void CWAB::FreeProws(LPSRowSet prows)
{
ULONGirow;
if (!prows)
return;
for (irow = 0; irow < prows->cRows; ++irow)
m_lpWABObject->FreeBuffer(prows->aRow[irow].lpProps);
m_lpWABObject->FreeBuffer(prows);
}
// When an item is selected in the listview, we
// cache its entry id as a special selected item
//
void CWAB::SetSelection(CListCtrl * pListView)
{
LV_ITEM lvi = {0};
// Get the Selected Item from the listview
lvi.mask = LVIF_PARAM;
lvi.iSubItem = 0;
lvi.iItem = pListView->GetNextItem(-1, LVNI_SELECTED);
if(lvi.iItem == -1)
return;
pListView->GetItem(&lvi);
if(lvi.lParam)
{
LPSBinary lpSB = (LPSBinary) lvi.lParam;
if(m_SB.lpb)
LocalFree(m_SB.lpb);
m_SB.cb = lpSB->cb;
m_SB.lpb = (LPBYTE) LocalAlloc(LMEM_ZEROINIT, m_SB.cb);
if(m_SB.lpb)
CopyMemory(m_SB.lpb, lpSB->lpb, m_SB.cb);
else
m_SB.cb = 0;
}
}
// Show details on the selected item
//
void CWAB::ShowSelectedItemDetails(HWND hWndParent)
{
HRESULT hr = S_OK;
// if we have a specially cached entryid ..
//
if(m_SB.cb && m_SB.lpb)
{
HWND hWnd = NULL;
LPSBinary lpSB = (LPSBinary) &m_SB;
hr = m_lpAdrBook->Details( (LPULONG) &hWnd,
NULL, NULL,
lpSB->cb,
(LPENTRYID) lpSB->lpb,
NULL, NULL,
NULL, 0);
}
return;
}
// Gets a SPropValue array for the selected item
// This array contains all the properties for that item
// though we could actually get a subset too if we
// wanted to
//
void CWAB::GetSelectedItemPropArray()
{
if(m_SB.lpb && m_SB.cb)
{
LPMAILUSER lpMailUser = NULL;
LPSBinary lpSB = (LPSBinary) &m_SB;
ULONG ulObjType = 0;
// Open the selected entry
//
m_lpAdrBook->OpenEntry(lpSB->cb,
(LPENTRYID) lpSB->lpb,
NULL, // interface
0, // flags
&ulObjType,
(LPUNKNOWN *)&lpMailUser);
if(lpMailUser)
{
// Flush away any old array we might have cached
//
if(m_lpPropArray)
m_lpWABObject->FreeBuffer(m_lpPropArray);
m_ulcValues = 0;
lpMailUser->GetProps(NULL, 0, &m_ulcValues, &m_lpPropArray);
lpMailUser->Release();
}
}
return;
}
// Loads the proptags for the selected entry into the
// PropTags list box
//
void CWAB::LoadPropTags(CListBox * pList)
{
if(!m_ulcValues || !m_lpPropArray)
return;
pList->ResetContent();
ULONG i;
TCHAR sz[32];
for(i=0;i<m_ulcValues;i++)
{
wsprintf(sz, "0x%.8x", m_lpPropArray[i].ulPropTag);
pList->SetItemData(pList->AddString(sz), m_lpPropArray[i].ulPropTag);
}
pList->SetCurSel(-1);
pList->SetCurSel(0);
}
// Sets the property value, if understandable, into the
// given edit box
//
void CWAB::SetPropString(CEdit * pEdit, ULONG ulPropTag)
{
pEdit->SetWindowText("");
if(!m_ulcValues || !m_lpPropArray)
return;
ULONG i;
for(i=0;i<m_ulcValues;i++)
{
if(m_lpPropArray[i].ulPropTag == ulPropTag)
{
switch(PROP_TYPE(ulPropTag))
{
case PT_TSTRING:
pEdit->SetWindowText(m_lpPropArray[i].Value.LPSZ);
break;
case PT_MV_TSTRING:
{
ULONG j;
LPSPropValue lpProp = &(m_lpPropArray[i]);
for(j=0;j<lpProp->Value.MVSZ.cValues;j++)
{
pEdit->ReplaceSel(lpProp->Value.MVSZ.LPPSZ[j]);
pEdit->ReplaceSel("\r\n");
}
}
break;
case PT_BINARY:
pEdit->SetWindowText("Binary data");
break;
case PT_I2:
case PT_LONG:
case PT_R4:
case PT_DOUBLE:
case PT_BOOLEAN:
{
TCHAR sz[256];
wsprintf(sz,"%d",m_lpPropArray[i].Value.l);
pEdit->SetWindowText(sz);
}
break;
default:
pEdit->SetWindowText("Unrecognized or undisplayable data");
break;
}
break;
}
}
}
enum {
icrPR_DEF_CREATE_MAILUSER = 0,
icrPR_DEF_CREATE_DL,
icrMax
};
const SizedSPropTagArray(icrMax, ptaCreate)=
{
icrMax,
{
PR_DEF_CREATE_MAILUSER,
PR_DEF_CREATE_DL,
}
};
// Gets the WABs default Template ID for MailUsers
// or DistLists. These Template IDs are needed for creating
// new mailusers and distlists
//
HRESULT CWAB::HrGetWABTemplateID(ULONG ulObjectType,
ULONG * lpcbEID,
LPENTRYID * lppEID)
{
LPABCONT lpContainer = NULL;
HRESULT hr = hrSuccess;
SCODE sc = ERROR_SUCCESS;
ULONG ulObjType = 0;
ULONG cbWABEID = 0;
LPENTRYID lpWABEID = NULL;
LPSPropValue lpCreateEIDs = NULL;
LPSPropValue lpNewProps = NULL;
ULONG cNewProps;
ULONG nIndex;
if ( (!m_lpAdrBook) ||
((ulObjectType != MAPI_MAILUSER) && (ulObjectType != MAPI_DISTLIST)) )
{
hr = MAPI_E_INVALID_PARAMETER;
goto out;
}
*lpcbEID = 0;
*lppEID = NULL;
if (HR_FAILED(hr = m_lpAdrBook->GetPAB( &cbWABEID,
&lpWABEID)))
{
goto out;
}
if (HR_FAILED(hr = m_lpAdrBook->OpenEntry(cbWABEID, // size of EntryID to open
lpWABEID, // EntryID to open
NULL, // interface
0, // flags
&ulObjType,
(LPUNKNOWN *)&lpContainer)))
{
goto out;
}
// Opened PAB container OK
// Get us the default creation entryids
if (HR_FAILED(hr = lpContainer->GetProps( (LPSPropTagArray)&ptaCreate,
0,
&cNewProps,
&lpCreateEIDs) ) )
{
goto out;
}
// Validate the properites
if ( lpCreateEIDs[icrPR_DEF_CREATE_MAILUSER].ulPropTag != PR_DEF_CREATE_MAILUSER ||
lpCreateEIDs[icrPR_DEF_CREATE_DL].ulPropTag != PR_DEF_CREATE_DL)
{
goto out;
}
if(ulObjectType == MAPI_DISTLIST)
nIndex = icrPR_DEF_CREATE_DL;
else
nIndex = icrPR_DEF_CREATE_MAILUSER;
*lpcbEID = lpCreateEIDs[nIndex].Value.bin.cb;
m_lpWABObject->AllocateBuffer(*lpcbEID, (LPVOID *) lppEID);
if (sc != S_OK)
{
hr = MAPI_E_NOT_ENOUGH_MEMORY;
goto out;
}
CopyMemory(*lppEID,lpCreateEIDs[nIndex].Value.bin.lpb,*lpcbEID);
out:
if (lpCreateEIDs)
m_lpWABObject->FreeBuffer(lpCreateEIDs);
if (lpContainer)
lpContainer->Release();
if (lpWABEID)
m_lpWABObject->FreeBuffer(lpWABEID);
return hr;
}
// Shows the NewEntry dialog to enable creating a new contact in the WAB
//
HRESULT CWAB::ShowNewEntryDialog(HWND hWndParent)
{
ULONG cbEID=0;
LPENTRYID lpEID=NULL;
HRESULT hr = hrSuccess;
ULONG cbTplEID = 0;
LPENTRYID lpTplEID = NULL;
// Get the template id which is needed to create the
// new object
//
if(HR_FAILED(hr = HrGetWABTemplateID( MAPI_MAILUSER,
&cbTplEID,
&lpTplEID)))
{
goto out;
}
// Display the New Entry dialog to create the new entry
//
if (HR_FAILED(hr = m_lpAdrBook->NewEntry((ULONG) hWndParent,
0,
0,NULL,
cbTplEID,lpTplEID,
&cbEID,&lpEID)))
{
goto out;
}
out:
return hr;
}
// Delete an entry from the WAB
//
HRESULT CWAB::DeleteEntry()
{
HRESULT hr = hrSuccess;
ULONG cbWABEID = 0;
LPENTRYID lpWABEID = NULL;
LPABCONT lpWABCont = NULL;
ULONG ulObjType;
SBinaryArray SBA;
hr = m_lpAdrBook->GetPAB( &cbWABEID,
&lpWABEID);
if(HR_FAILED(hr))
goto out;
hr = m_lpAdrBook->OpenEntry( cbWABEID, // size of EntryID to open
lpWABEID, // EntryID to open
NULL, // interface
0, // flags
&ulObjType,
(LPUNKNOWN *)&lpWABCont);
if(HR_FAILED(hr))
goto out;
SBA.cValues = 1;
SBA.lpbin = &m_SB;
hr = lpWABCont->DeleteEntries((LPENTRYLIST) &SBA, 0);
if(m_lpPropArray)
m_lpWABObject->FreeBuffer(m_lpPropArray);
m_lpPropArray = NULL;
m_ulcValues = 0;
out:
if(lpWABCont)
lpWABCont->Release();
if(lpWABEID)
m_lpWABObject->FreeBuffer(lpWABEID);
return hr;
}
// Gets the property value for specified String property
//
BOOL CWAB::GetStringPropVal(HWND hWnd, ULONG ulPropTag, LPTSTR sz, ULONG cbsz)
{
BOOL bRet = FALSE;
if(PROP_TYPE(ulPropTag) != PT_TSTRING)
{
MessageBox(hWnd, "This tool only supports modifying string type props right now",
"Error", MB_OK | MB_ICONINFORMATION);
goto out;
}
ULONG i;
// Since we already cached the proparray for the selected
// item, all we need to do is look in the cached proparray
// for the requested proptag
//
for(i=0;i<m_ulcValues;i++)
{
if(m_lpPropArray[i].ulPropTag == ulPropTag)
{
LPTSTR lp = m_lpPropArray[i].Value.LPSZ;
ULONG nLen = (ULONG) lstrlen(lp);
if(nLen >= cbsz)
{
CopyMemory(sz, lp, cbsz-1);
sz[cbsz-1]='\0';
}
else
lstrcpy(sz,lp);
break;
}
}
bRet = TRUE;
out:
return bRet;
}
// Sets a single string property onto a mailuser object
//
BOOL CWAB::SetSingleStringProp(HWND hWnd, ULONG ulPropTag, LPTSTR sz)
{
SPropValue Prop;
BOOL bRet = FALSE;
if(PROP_TYPE(ulPropTag) != PT_TSTRING)
{
MessageBox(hWnd, "This version of the tool can only set string properties.",
"Error", MB_OK | MB_ICONINFORMATION);
goto out;
}
Prop.ulPropTag = ulPropTag;
Prop.Value.LPSZ = sz;
// Open the cached entry and get a mailuser object
// representing that entry
//
if(m_SB.lpb && m_SB.cb)
{
LPMAILUSER lpMailUser = NULL;
LPSBinary lpSB = (LPSBinary) &m_SB;
ULONG ulObjType = 0;
// To modify an object, make sure to specify the
// MAPI_MODIFY flag otherwise the object is always
// opened read-only be default
//
m_lpAdrBook->OpenEntry(lpSB->cb,
(LPENTRYID) lpSB->lpb,
NULL, // interface
MAPI_MODIFY, // flags
&ulObjType,
(LPUNKNOWN *)&lpMailUser);
if(lpMailUser)
{
// Knock out this prop if it exists so we can overwrite it
//
{
SPropTagArray SPTA;
SPTA.cValues = 1;
SPTA.aulPropTag[0] = ulPropTag;
lpMailUser->DeleteProps(&SPTA, NULL);
}
// Set the new property on the mailuser
//
if (!HR_FAILED(lpMailUser->SetProps(1, &Prop, NULL)))
{
// **NOTE** if you dont call SaveChanges, the
// changes are not saved (duh). Also if you didnt
// open the object with the MAPI_MODIFY flag, you
// are likely to get an ACCESS_DENIED error
//
lpMailUser->SaveChanges(0);
bRet = TRUE;
}
lpMailUser->Release();
}
}
out:
GetSelectedItemPropArray();
return bRet;
}