#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_hWndModelessWABWindow = 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_hWndModelessWABWindow) DestroyWindow(m_hWndModelessWABWindow); 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;iGetItem(&lvi); if(lvi.lParam) { LPSBinary lpSB = (LPSBinary) lvi.lParam; m_lpWABObject->FreeBuffer(lpSB); } } pListView->DeleteAllItems(); } void CWAB::FreeProws(LPSRowSet prows) { ULONG irow; 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;iSetItemData(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;iSetWindowText(m_lpPropArray[i].Value.LPSZ); break; case PT_MV_TSTRING: { ULONG j; LPSPropValue lpProp = &(m_lpPropArray[i]); for(j=0;jValue.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= 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; } void STDMETHODCALLTYPE TestDismissFunction(ULONG ulUIParam, LPVOID lpvContext) { LPDWORD lpdw = (LPDWORD) lpvContext; return; } DWORD dwContext = 77; // Shows the Address Book // void CWAB::ShowAddressBook(HWND hWnd) { ADRPARM AdrParm = {0}; AdrParm.lpszCaption = "WABTool Address Book View"; AdrParm.cDestFields = 0; AdrParm.ulFlags = DIALOG_SDI; AdrParm.lpvDismissContext = &dwContext; AdrParm.lpfnDismiss = &TestDismissFunction; AdrParm.lpfnABSDI = NULL; m_lpAdrBook->Address( (ULONG *) &m_hWndModelessWABWindow, &AdrParm, NULL); }