/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include "nscore.h" #include "nsOE5File.h" #include "wabobject.h" #include 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 } }; typedef struct { bool multiLine; ULONG tag; char * pLDIF; } AddrImportField; #define kExtraUserFields 10 AddrImportField extraUserFields[kExtraUserFields] = { {true, PR_COMMENT, "description:"}, {false, PR_BUSINESS_TELEPHONE_NUMBER, "telephonenumber:"}, {false, PR_HOME_TELEPHONE_NUMBER, "homephone:"}, {false, PR_COMPANY_NAME, "o:"}, {false, PR_TITLE, "title:"}, {false, PR_BUSINESS_FAX_NUMBER, "facsimiletelephonenumber:"}, {false, PR_LOCALITY, "locality:"}, {false, PR_STATE_OR_PROVINCE, "st:"}, {true, PR_STREET_ADDRESS, "streetaddress:"}, {false, PR_POSTAL_CODE, "postalcode:"} }; #define kWhitespace " \t\b\r\n" #define TR_OUTPUT_EOL "\r\n" #define kLDIFPerson "objectclass: top" TR_OUTPUT_EOL "objectclass: person" TR_OUTPUT_EOL #define kLDIFGroup "objectclass: top" TR_OUTPUT_EOL "objectclass: groupOfNames" TR_OUTPUT_EOL /*********************************************************************************/ // contructor for CWAB object // // pszFileName - FileName of WAB file to open // if no file name is specified, opens the default // CWAB::CWAB(nsIFile *file) { // Here we load the WAB Object and initialize it m_pUniBuff = NULL; m_uniBuffLen = 0; m_bInitialized = false; m_lpAdrBook = NULL; m_lpWABObject = NULL; m_hinstWAB = 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 (dwType == REG_EXPAND_SZ) { // Expand the environment variables DWORD bufferSize = ExpandEnvironmentStrings(szWABDllPath, NULL, 0); if (bufferSize && bufferSize < MAX_PATH) { TCHAR tmp[MAX_PATH]; ExpandEnvironmentStrings(szWABDllPath, tmp, bufferSize); _tcscpy(szWABDllPath, tmp); } else { // This is an error condition. Nothing else is initialized yet, so simply return. return; } } } else { if (GetSystemDirectory(szWABDllPath, MAX_PATH)) { _tcsncat(szWABDllPath, WAB_DLL_NAME, std::min(_tcslen(WAB_DLL_NAME), MAX_PATH - _tcslen(szWABDllPath) - 1)); } else { // Yet another error condition. return; } } 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) { char fName[2] = {0, 0}; HRESULT hr = E_FAIL; WAB_PARAM wp = {0}; wp.cbSize = sizeof(WAB_PARAM); if (file != nullptr) { nsCString path; file->GetNativePath(path); wp.szFileName = (LPTSTR) ToNewCString(path); } else wp.szFileName = (LPTSTR) fName; // 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_pUniBuff) delete [] m_pUniBuff; if(m_bInitialized) { if(m_lpAdrBook) m_lpAdrBook->Release(); if(m_lpWABObject) m_lpWABObject->Release(); if(m_hinstWAB) FreeLibrary(m_hinstWAB); } } HRESULT CWAB::IterateWABContents(CWabIterator *pIter, int *pDone) { if (!m_bInitialized || !m_lpAdrBook) return E_FAIL; ULONG ulObjType = 0; LPMAPITABLE lpAB = NULL; ULONG cRows = 0; LPSRowSet lpRowAB = NULL; LPABCONT lpContainer = NULL; int cNumRows = 0; nsresult keepGoing; HRESULT hr = E_FAIL; ULONG lpcbEID = 0; LPENTRYID lpEID = NULL; ULONG rowCount = 0; ULONG curCount = 0; nsString uniStr; // Get the entryid of the root PAB container // hr = m_lpAdrBook->GetPAB(&lpcbEID, &lpEID); if (HR_FAILED(hr)) goto exit; 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; hr = lpAB->GetRowCount(0, &rowCount); if (HR_FAILED(hr)) rowCount = 100; if (rowCount == 0) rowCount = 1; // 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 // CStrToUnicode(lpsz, uniStr); keepGoing = pIter->EnumUser(uniStr.get(), lpEID, cbEID); curCount++; if (pDone) { *pDone = (curCount * 100) / rowCount; if (*pDone > 100) *pDone = 100; } } } FreeProws(lpRowAB); } } while (SUCCEEDED(hr) && cNumRows && lpRowAB && NS_SUCCEEDED(keepGoing)) ; hr = lpAB->SeekRow(BOOKMARK_BEGINNING, 0, NULL); if(HR_FAILED(hr)) goto exit; // Read all the rows of the table one by one // keepGoing = NS_OK; 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_DISTLIST) { LPABCONT distListContainer = NULL; // 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 // hr = m_lpAdrBook->OpenEntry(cbEID, lpEID, NULL, 0,&ulObjType,(LPUNKNOWN *)&distListContainer); LPMAPITABLE distListTable = NULL; // Get a contents table of the dist list // hr = distListContainer->GetContentsTable(0, &distListTable); if (lpAB) { hr = distListTable->GetRowCount(0, &rowCount); if (HR_FAILED(hr)) rowCount = 100; if (rowCount == 0) rowCount = 1; // 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 = distListTable->SetColumns((LPSPropTagArray)&ptaEid, 0); CStrToUnicode(lpsz, uniStr); keepGoing = pIter->EnumList(uniStr.get(), lpEID, cbEID, distListTable); curCount++; if (pDone) { *pDone = (curCount * 100) / rowCount; if (*pDone > 100) *pDone = 100; } } if (distListContainer) distListContainer->Release(); if (distListTable) distListTable->Release(); } } FreeProws(lpRowAB); } } while (SUCCEEDED(hr) && cNumRows && lpRowAB && NS_SUCCEEDED(keepGoing)) ; exit: if (lpContainer) lpContainer->Release(); if (lpAB) lpAB->Release(); return hr; } 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); } LPDISTLIST CWAB::GetDistList(ULONG cbEid, LPENTRYID pEid) { if (!m_bInitialized || !m_lpAdrBook) return NULL; LPDISTLIST lpDistList = NULL; ULONG ulObjType; m_lpAdrBook->OpenEntry(cbEid, pEid, NULL, 0, &ulObjType, (LPUNKNOWN *)&lpDistList); return lpDistList; } LPSPropValue CWAB::GetListProperty(LPDISTLIST pUser, ULONG tag) { if (!pUser) return NULL; int sz = CbNewSPropTagArray(1); SPropTagArray *pTag = (SPropTagArray *) new char[sz]; pTag->cValues = 1; pTag->aulPropTag[0] = tag; LPSPropValue lpProp = NULL; ULONG cValues = 0; HRESULT hr = pUser->GetProps(pTag, 0, &cValues, &lpProp); delete [] pTag; if (HR_FAILED(hr) || (cValues != 1)) { if (lpProp) m_lpWABObject->FreeBuffer(lpProp); return NULL; } return lpProp; } LPMAILUSER CWAB::GetUser(ULONG cbEid, LPENTRYID pEid) { if (!m_bInitialized || !m_lpAdrBook) return NULL; LPMAILUSER lpMailUser = NULL; ULONG ulObjType; m_lpAdrBook->OpenEntry(cbEid, pEid, NULL, 0, &ulObjType, (LPUNKNOWN *)&lpMailUser); return lpMailUser; } LPSPropValue CWAB::GetUserProperty(LPMAILUSER pUser, ULONG tag) { if (!pUser) return NULL; ULONG uTag = tag; /* Getting Unicode does not help with getting the right international charset. Windoze bloze. */ /* if (PROP_TYPE(uTag) == PT_STRING8) { uTag = CHANGE_PROP_TYPE(tag, PT_UNICODE); } */ int sz = CbNewSPropTagArray(1); SPropTagArray *pTag = (SPropTagArray *) new char[sz]; pTag->cValues = 1; pTag->aulPropTag[0] = uTag; LPSPropValue lpProp = NULL; ULONG cValues = 0; HRESULT hr = pUser->GetProps(pTag, 0, &cValues, &lpProp); if (HR_FAILED(hr) || (cValues != 1)) { if (lpProp) m_lpWABObject->FreeBuffer(lpProp); lpProp = NULL; if (uTag != tag) { pTag->cValues = 1; pTag->aulPropTag[0] = tag; cValues = 0; hr = pUser->GetProps(pTag, 0, &cValues, &lpProp); if (HR_FAILED(hr) || (cValues != 1)) { if (lpProp) m_lpWABObject->FreeBuffer(lpProp); lpProp = NULL; } } } delete [] pTag; return lpProp; } void CWAB::CStrToUnicode(const char *pStr, nsString& result) { result.Truncate(); int wLen = MultiByteToWideChar(CP_ACP, 0, pStr, -1, wwc(m_pUniBuff), 0); if (wLen >= m_uniBuffLen) { if (m_pUniBuff) delete [] m_pUniBuff; m_pUniBuff = new char16_t[wLen + 64]; m_uniBuffLen = wLen + 64; } if (wLen) { MultiByteToWideChar(CP_ACP, 0, pStr, -1, wwc(m_pUniBuff), m_uniBuffLen); result = m_pUniBuff; } } // If the value is a string, get it... void CWAB::GetValueString(LPSPropValue pVal, nsString& val) { val.Truncate(); if (!pVal) return; switch(PROP_TYPE(pVal->ulPropTag)) { case PT_STRING8: CStrToUnicode((const char *) (pVal->Value.lpszA), val); break; case PT_UNICODE: val = (char16_t *) (pVal->Value.lpszW); break; case PT_MV_STRING8: { nsString tmp; ULONG j; for(j = 0; j < pVal->Value.MVszA.cValues; j++) { CStrToUnicode((const char *) (pVal->Value.MVszA.lppszA[j]), tmp); val += tmp; val.Append(NS_ConvertASCIItoUTF16(TR_OUTPUT_EOL)); } break; } case PT_MV_UNICODE: { ULONG j; for(j = 0; j < pVal->Value.MVszW.cValues; j++) { val += (char16_t *) (pVal->Value.MVszW.lppszW[j]); val.Append(NS_ConvertASCIItoUTF16(TR_OUTPUT_EOL)); } break; } case PT_I2: case PT_LONG: case PT_R4: case PT_DOUBLE: case PT_BOOLEAN: { /* TCHAR sz[256]; wsprintf(sz,"%d", pVal->Value.l); val = sz; */ break; } case PT_BINARY: break; default: break; } val.Trim(kWhitespace, true, true); } void CWAB::GetValueTime(LPSPropValue pVal, PRTime& val) { if (!pVal) return; if (PROP_TYPE(pVal->ulPropTag) != PT_SYSTIME) return; nsOE5File::FileTimeToPRTime(&pVal->Value.ft, &val); } bool CWAB::IsAvailable() { if (!m_bInitialized || !m_lpAdrBook) return false; ULONG lpcbEID = 0; LPENTRYID lpEID = NULL; HRESULT hr = m_lpAdrBook->GetPAB(&lpcbEID, &lpEID); if (HR_FAILED(hr)) return false; ULONG ulObjType = 0; LPABCONT lpContainer = NULL; hr = m_lpAdrBook->OpenEntry(lpcbEID, (LPENTRYID)lpEID, NULL, 0, &ulObjType, (LPUNKNOWN *)&lpContainer); m_lpWABObject->FreeBuffer(lpEID); LPMAPITABLE lpAB = NULL; hr = lpContainer->GetContentsTable(0, &lpAB); if(HR_FAILED(hr)) { lpContainer->Release(); return false; } ULONG rowCount = 0; hr = lpAB->GetRowCount(0, &rowCount); lpContainer->Release(); lpAB->Release(); return (rowCount != 0); } /* BOOL CWabIterateProcess::SanitizeMultiLine(CString& val) { val.TrimLeft(); val.TrimRight(); int idx = val.FindOneOf("\x0D\x0A"); if (idx == -1) return FALSE; // needs encoding U32 bufSz = UMimeEncode::GetBufferSize(val.GetLength()); P_U8 pBuf = new U8[bufSz]; U32 len = UMimeEncode::ConvertBuffer((PC_U8)((PC_S8)val), val.GetLength(), pBuf, 66, 52, "\x0D\x0A "); pBuf[len] = 0; val = pBuf; delete pBuf; return TRUE; } BOOL CWabIterateProcess::EnumUser(LPCTSTR pName, LPENTRYID pEid, ULONG cbEid) { TRACE1("User: %s\n", pName); LPMAILUSER pUser = m_pWab->GetUser(cbEid, pEid); // Get the "required" strings first CString lastName; CString firstName; CString eMail; CString nickName; CString middleName; if (!pUser) { UDialogs::ErrMessage1(IDS_ENTRY_ERROR, pName); return FALSE; } LPSPropValue pProp = m_pWab->GetUserProperty(pUser, PR_EMAIL_ADDRESS); if (pProp) { m_pWab->GetValueString(pProp, eMail); SanitizeValue(eMail); m_pWab->FreeProperty(pProp); } pProp = m_pWab->GetUserProperty(pUser, PR_GIVEN_NAME); if (pProp) { m_pWab->GetValueString(pProp, firstName); SanitizeValue(firstName); m_pWab->FreeProperty(pProp); } pProp = m_pWab->GetUserProperty(pUser, PR_SURNAME); if (pProp) { m_pWab->GetValueString(pProp, lastName); SanitizeValue(lastName); m_pWab->FreeProperty(pProp); } pProp = m_pWab->GetUserProperty(pUser, PR_MIDDLE_NAME); if (pProp) { m_pWab->GetValueString(pProp, middleName); SanitizeValue(middleName); m_pWab->FreeProperty(pProp); } pProp = m_pWab->GetUserProperty(pUser, PR_NICKNAME); if (pProp) { m_pWab->GetValueString(pProp, nickName); SanitizeValue(nickName); m_pWab->FreeProperty(pProp); } if (nickName.IsEmpty()) nickName = pName; if (firstName.IsEmpty()) { firstName = nickName; middleName.Empty(); lastName.Empty(); } if (lastName.IsEmpty()) middleName.Empty(); if (eMail.IsEmpty()) eMail = nickName; // We now have the required fields // write them out followed by any optional fields! BOOL result = TRUE; if (m_recordsDone) result = m_out.WriteEol(); CString line; CString header; line.LoadString(IDS_LDIF_DN_START); line += firstName; if (!middleName.IsEmpty()) { line += ' '; line += middleName; } if (!lastName.IsEmpty()) { line += ' '; line += lastName; } header.LoadString(IDS_LDIF_DN_MIDDLE); line += header; line += eMail; result = result && m_out.WriteStr(line); result = result && m_out.WriteEol(); line.LoadString(IDS_FIELD_LDIF_FULLNAME); line += ' '; line += firstName; if (!middleName.IsEmpty()) { line += ' '; line += middleName; } if (!lastName.IsEmpty()) { line += ' '; line += lastName; } result = result && m_out.WriteStr(line); result = result && m_out.WriteEol(); line.LoadString(IDS_FIELD_LDIF_GIVENNAME); line += ' '; line += firstName; result = result && m_out.WriteStr(line); result = result && m_out.WriteEol(); if (!lastName.IsEmpty()) { line.LoadString(IDS_FIELD_LDIF_LASTNAME); if (!middleName.IsEmpty()) { line += ' '; line += middleName; } line += ' '; line += lastName; result = result && m_out.WriteStr(line); result = result && m_out.WriteEol(); } result = result && m_out.WriteStr(kLDIFPerson); line.LoadString(IDS_FIELD_LDIF_EMAIL); line += ' '; line += eMail; result = result && m_out.WriteStr(line); result = result && m_out.WriteEol(); line.LoadString(IDS_FIELD_LDIF_NICKNAME); line += ' '; line += nickName; result = result && m_out.WriteStr(line); result = result && m_out.WriteEol(); // Do all of the extra fields! CString value; BOOL encoded = FALSE; for (int i = 0; i < kExtraUserFields; i++) { value.Empty(); pProp = m_pWab->GetUserProperty(pUser, extraUserFields[i].tag); if (pProp) { m_pWab->GetValueString(pProp, value); m_pWab->FreeProperty(pProp); } if (extraUserFields[i].multiLine) { encoded = SanitizeMultiLine(value); } else SanitizeValue(value); if (!value.IsEmpty()) { line = extraUserFields[i].pLDIF; if (encoded) { line += ": "; encoded = FALSE; } else line += ' '; line += value; result = result && m_out.WriteStr(line); result = result && m_out.WriteEol(); } } m_pWab->ReleaseUser(pUser); if (!result) { UDialogs::ErrMessage0(IDS_ADDRESS_SAVE_ERROR); } m_totalDone += kValuePerUser; m_recordsDone++; return result; } */ /* BOOL CWabIterateProcess::EnumList(LPCTSTR pName, LPENTRYID pEid, ULONG cbEid) { TRACE1("List: %s\n", pName); LPDISTLIST pList = m_pWab->GetDistList(cbEid, pEid); if (!pList) { UDialogs::ErrMessage1(IDS_ENTRY_ERROR, pName); return FALSE; } // Find out if this is just a regular entry or a true list... CString eMail; LPSPropValue pProp = m_pWab->GetListProperty(pList, PR_EMAIL_ADDRESS); if (pProp) { m_pWab->GetValueString(pProp, eMail); SanitizeValue(eMail); m_pWab->FreeProperty(pProp); // Treat this like a regular entry... if (!eMail.IsEmpty()) { m_pWab->ReleaseDistList(pList); return WriteListUserEntry(pName, eMail); } } // This may very well be a list, find the entries... m_pListTable = OpenDistList(pList); if (m_pListTable) { m_pList = pList; m_listName = pName; m_listDone = 0; m_listHeaderDone = FALSE; m_state = kEnumListState; } else { m_pWab->ReleaseDistList(pList); m_recordsDone++; m_totalDone += kValuePerUser; } return TRUE; } BOOL CWabIterateProcess::EnumNextListUser(BOOL *pDone) { HRESULT hr; int cNumRows = 0; LPSRowSet lpRowAB = NULL; BOOL keepGoing = TRUE; if (!m_pListTable) return FALSE; hr = m_pListTable->QueryRows(1, 0, &lpRowAB); if(HR_FAILED(hr)) { UDialogs::ErrMessage0(IDS_ERROR_READING_WAB); return FALSE; } 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; if(lpRowAB->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.l == MAPI_DISTLIST) { keepGoing = HandleListList(lpsz, lpEID, cbEID); } else if (lpRowAB->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.l == MAPI_MAILUSER) { keepGoing = HandleListUser(lpsz, lpEID, cbEID); } } m_pWab->FreeProws(lpRowAB); } if (!cNumRows || !lpRowAB) { *pDone = TRUE; m_pListTable->Release(); m_pListTable = NULL; if (m_pList) m_pWab->ReleaseDistList(m_pList); m_pList = NULL; if (m_listDone < kValuePerUser) m_totalDone += (kValuePerUser - m_listDone); m_recordsDone++; return keepGoing; } if (!keepGoing) return FALSE; if (m_listDone < kValuePerUser) { m_listDone++; m_totalDone++; } return TRUE; } BOOL CWabIterateProcess::HandleListList(LPCTSTR pName, LPENTRYID lpEid, ULONG cbEid) { BOOL result; LPDISTLIST pList = m_pWab->GetDistList(cbEid, lpEid); if (!pList) { UDialogs::ErrMessage1(IDS_ENTRY_ERROR, pName); return FALSE; } CString eMail; LPSPropValue pProp = m_pWab->GetListProperty(pList, PR_EMAIL_ADDRESS); if (pProp) { m_pWab->GetValueString(pProp, eMail); SanitizeValue(eMail); m_pWab->FreeProperty(pProp); // Treat this like a regular entry... if (!eMail.IsEmpty()) { // write out a member based on pName and eMail result = WriteGroupMember(pName, eMail); m_pWab->ReleaseDistList(pList); return result; } } // iterate the list and add each member to the top level list LPMAPITABLE pTable = OpenDistList(pList); if (!pTable) { TRACE0("Error opening table for list\n"); m_pWab->ReleaseDistList(pList); UDialogs::ErrMessage1(IDS_ENTRY_ERROR, pName); return FALSE; } int cNumRows = 0; LPSRowSet lpRowAB = NULL; HRESULT hr; BOOL keepGoing = TRUE; do { hr = pTable->QueryRows(1, 0, &lpRowAB); if(HR_FAILED(hr)) { UDialogs::ErrMessage0(IDS_ERROR_READING_WAB); pTable->Release(); m_pWab->ReleaseDistList(pList); return FALSE; } 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; if(lpRowAB->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.l == MAPI_DISTLIST) { keepGoing = HandleListList(lpsz, lpEID, cbEID); } else if (lpRowAB->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.l == MAPI_MAILUSER) { keepGoing = HandleListUser(lpsz, lpEID, cbEID); } } m_pWab->FreeProws(lpRowAB); } } while (keepGoing && cNumRows && lpRowAB); pTable->Release(); m_pWab->ReleaseDistList(pList); return keepGoing; } BOOL CWabIterateProcess::HandleListUser(LPCTSTR pName, LPENTRYID lpEid, ULONG cbEid) { // Get the basic properties for building the member line LPMAILUSER pUser = m_pWab->GetUser(cbEid, lpEid); // Get the "required" strings first CString lastName; CString firstName; CString eMail; CString nickName; CString middleName; if (!pUser) { UDialogs::ErrMessage1(IDS_ENTRY_ERROR, pName); return FALSE; } LPSPropValue pProp = m_pWab->GetUserProperty(pUser, PR_EMAIL_ADDRESS); if (pProp) { m_pWab->GetValueString(pProp, eMail); SanitizeValue(eMail); m_pWab->FreeProperty(pProp); } pProp = m_pWab->GetUserProperty(pUser, PR_GIVEN_NAME); if (pProp) { m_pWab->GetValueString(pProp, firstName); SanitizeValue(firstName); m_pWab->FreeProperty(pProp); } pProp = m_pWab->GetUserProperty(pUser, PR_SURNAME); if (pProp) { m_pWab->GetValueString(pProp, lastName); SanitizeValue(lastName); m_pWab->FreeProperty(pProp); } pProp = m_pWab->GetUserProperty(pUser, PR_MIDDLE_NAME); if (pProp) { m_pWab->GetValueString(pProp, middleName); SanitizeValue(middleName); m_pWab->FreeProperty(pProp); } pProp = m_pWab->GetUserProperty(pUser, PR_NICKNAME); if (pProp) { m_pWab->GetValueString(pProp, nickName); SanitizeValue(nickName); m_pWab->FreeProperty(pProp); } if (nickName.IsEmpty()) nickName = pName; if (firstName.IsEmpty()) { firstName = nickName; middleName.Empty(); lastName.Empty(); } if (lastName.IsEmpty()) middleName.Empty(); if (eMail.IsEmpty()) eMail = nickName; m_pWab->ReleaseUser(pUser); CString name = firstName; if (!middleName.IsEmpty()) { name += ' '; name += middleName; } if (!lastName.IsEmpty()) { name += ' '; name += lastName; } return WriteGroupMember(name, eMail); } BOOL CWabIterateProcess::WriteGroupMember(const char *pName, const char *pEmail) { CString middle; CString line; BOOL result; // Check for the header first if (!m_listHeaderDone) { if (m_recordsDone) result = m_out.WriteEol(); else result = TRUE; line.LoadString(IDS_LDIF_DN_START); line += m_listName; line += TR_OUTPUT_EOL; middle.LoadString(IDS_FIELD_LDIF_FULLNAME); line += middle; line += m_listName; line += TR_OUTPUT_EOL; if (!result || !m_out.WriteStr(line) || !m_out.WriteStr(kLDIFGroup)) { UDialogs::ErrMessage0(IDS_ADDRESS_SAVE_ERROR); return FALSE; } m_listHeaderDone = TRUE; } line.LoadString(IDS_FIELD_LDIF_MEMBER_START); line += pName; middle.LoadString(IDS_LDIF_DN_MIDDLE); line += middle; line += pEmail; line += TR_OUTPUT_EOL; if (!m_out.WriteStr(line)) { UDialogs::ErrMessage0(IDS_ADDRESS_SAVE_ERROR); return FALSE; } if (m_listDone < kValuePerUser) { m_listDone++; m_totalDone++; } return TRUE; } */