LPWSTR getFolderName(IMsgStore* pStore, ULONG cbEntryID, LPENTRYID lpEntryID) { HRESULT hRes = E_FAIL; ULONG ulObjType = MAPI_FOLDER; LPMAPIFOLDER lpFolder = NULL; // Get parent folder hRes = pStore->OpenEntry(cbEntryID, lpEntryID, 0, 0, &ulObjType, (LPUNKNOWN*)&lpFolder); if (hRes != S_OK) { return NULL; } SizedSPropTagArray(2, ptaFolder) = {2, {PR_DISPLAY_NAME, PR_ENTRYID}}; LPSPropValue rgFolderProps = NULL; ULONG cValues = 0; // Get parent folder properties hRes = lpFolder->GetProps((LPSPropTagArray)&ptaFolder, MAPI_UNICODE, &cValues, &rgFolderProps); if (hRes != S_OK) { lpFolder->Release(); return NULL; } // folder name return rgFolderProps[0].Value.lpszW; }
BOOL CMapiApi::GetStoreFolders( ULONG cbEid, LPENTRYID lpEid, CMapiFolderList& folders, int startDepth) { // Fill in the array with the folders in the given store if (!m_initialized || !m_lpSession) { MAPI_TRACE0( "MAPI not initialized for GetStoreFolders\n"); return( FALSE); } m_lpMdb = NULL; CMsgStore * pStore = FindMessageStore( cbEid, lpEid); BOOL bResult = FALSE; LPSPropValue pVal; if (pStore && pStore->Open( m_lpSession, &m_lpMdb)) { // Successful open, do the iteration of the store pVal = GetMapiProperty( m_lpMdb, PR_IPM_SUBTREE_ENTRYID); if (pVal) { ULONG cbEntry; LPENTRYID pEntry; LPMAPIFOLDER lpSubTree = NULL; if (GetEntryIdFromProp( pVal, cbEntry, pEntry)) { // Open up the folder! bResult = OpenEntry( cbEntry, pEntry, (LPUNKNOWN *)&lpSubTree); MAPIFreeBuffer( pEntry); if (bResult && lpSubTree) { // Iterate the subtree with the results going into the folder list CGetStoreFoldersIter iterHandler( this, folders, startDepth); bResult = IterateHierarchy( &iterHandler, lpSubTree); lpSubTree->Release(); } else { MAPI_TRACE0( "GetStoreFolders: Error opening sub tree.\n"); } } else { MAPI_TRACE0( "GetStoreFolders: Error getting entryID from sub tree property val.\n"); } } else { MAPI_TRACE0( "GetStoreFolders: Error getting sub tree property.\n"); } } else { MAPI_TRACE0( "GetStoreFolders: Error opening message store.\n"); } return( bResult); }
void DumpFidMid( _In_z_ LPWSTR lpszProfile, _In_ LPMDB lpMDB, _In_z_ LPWSTR lpszFid, _In_z_ LPWSTR lpszMid) { // FID/MID lookups only succeed online, so go ahead and force it RegKeys[regKeyMAPI_NO_CACHE].ulCurDWORD = true; RegKeys[regkeyMDB_ONLINE].ulCurDWORD = true; DebugPrint(DBGGeneric,"DumpFidMid: Outputting from profile %ws. FID: %ws, MID: %ws\n", lpszProfile, lpszFid, lpszMid); HRESULT hRes = S_OK; LPMAPIFOLDER lpFolder = NULL; if (lpMDB) { // Open root container. WC_H(CallOpenEntry( lpMDB, NULL, NULL, NULL, NULL, // open root container NULL, MAPI_BEST_ACCESS, NULL, (LPUNKNOWN*)&lpFolder)); } if (lpFolder) { CFindFidMid MyFindFidMid; MyFindFidMid.InitMDB(lpMDB); MyFindFidMid.InitFolder(lpFolder); MyFindFidMid.InitFidMid(lpszFid,lpszMid); MyFindFidMid.ProcessFolders( true, true, true); } if (lpFolder) lpFolder->Release(); } // DumpFidMid
BOOL CMapiApi::HandleHierarchyItem( ULONG oType, ULONG cb, LPENTRYID pEntry) { if (oType == MAPI_FOLDER) { LPMAPIFOLDER pFolder; if (OpenEntry( cb, pEntry, (LPUNKNOWN *) &pFolder)) { LPSPropValue pVal; pVal = GetMapiProperty( pFolder, PR_DISPLAY_NAME); ReportStringProp( "Folder name:", pVal); IterateContents( NULL, pFolder); IterateHierarchy( NULL, pFolder); pFolder->Release(); } else { MAPI_TRACE0( " Folder type - error opening\n"); } } else MAPI_TRACE1( " ObjectType: %ld\n", oType); return( TRUE); }
BOOL CGetStoreFoldersIter::HandleHierarchyItem( ULONG oType, ULONG cb, LPENTRYID pEntry) { if (oType == MAPI_FOLDER) { LPMAPIFOLDER pFolder; if (m_pApi->OpenEntry( cb, pEntry, (LPUNKNOWN *) &pFolder)) { LPSPropValue pVal; nsString name; pVal = m_pApi->GetMapiProperty( pFolder, PR_CONTAINER_CLASS); if (pVal) m_pApi->GetStringFromProp( pVal, name); else name.Truncate(); if ((name.IsEmpty() && m_isMail) || (!ExcludeFolderClass(name.get()))) { pVal = m_pApi->GetMapiProperty( pFolder, PR_DISPLAY_NAME); m_pApi->GetStringFromProp( pVal, name); CMapiFolder *pNewFolder = new CMapiFolder(name.get(), cb, pEntry, m_depth); m_pList->AddItem( pNewFolder); pVal = m_pApi->GetMapiProperty( pFolder, PR_FOLDER_TYPE); MAPI_TRACE2( "Type: %d, name: %s\n", m_pApi->GetLongFromProp( pVal), (const char *)name); // m_pApi->ListProperties( pFolder); CGetStoreFoldersIter nextIter( m_pApi, *m_pList, m_depth + 1, m_isMail); m_pApi->IterateHierarchy( &nextIter, pFolder); } pFolder->Release(); } else { MAPI_TRACE0( "GetStoreFolders - HandleHierarchyItem: Error opening folder entry.\n"); return( FALSE); } } else MAPI_TRACE1( "GetStoreFolders - HandleHierarchyItem: Unhandled ObjectType: %ld\n", oType); return( TRUE); }
void CMapiApi::GetStoreInfo( CMapiFolder *pFolder, long *pSzContents) { HRESULT hr; LPMDB lpMdb; if (pSzContents) *pSzContents = 0; if (!OpenStore( pFolder->GetCBEntryID(), pFolder->GetEntryID(), &lpMdb)) return; LPSPropValue pVal; /* pVal = GetMapiProperty( lpMdb, PR_DISPLAY_NAME); ReportStringProp( " Message store name:", pVal); pVal = GetMapiProperty( lpMdb, PR_MDB_PROVIDER); ReportUIDProp( " Message store provider:", pVal); pVal = GetMapiProperty( lpMdb, PR_COMMENT); ReportStringProp( " Message comment:", pVal); pVal = GetMapiProperty( lpMdb, PR_ACCESS_LEVEL); ReportLongProp( " Message store Access Level:", pVal); pVal = GetMapiProperty( lpMdb, PR_STORE_SUPPORT_MASK); ReportLongProp( " Message store support mask:", pVal); pVal = GetMapiProperty( lpMdb, PR_STORE_STATE); ReportLongProp( " Message store state:", pVal); pVal = GetMapiProperty( lpMdb, PR_OBJECT_TYPE); ReportLongProp( " Message store object type:", pVal); pVal = GetMapiProperty( lpMdb, PR_VALID_FOLDER_MASK); ReportLongProp( " Message store valid folder mask:", pVal); pVal = GetMapiProperty( lpMdb, 0x8001001e); ReportStringProp( " Message prop 0x8001001e:", pVal); // This key appears to be the OMI Account Manager account that corresponds // to this message store. This is important for IMAP accounts // since we may not want to import messages from an IMAP store! // Seems silly if you ask me! // In order to test this, we'll need the registry key to look under to determine // if it contains the "IMAP Server" value, if it does then we are an // IMAP store, if not, then we are a non-IMAP store - which may always mean // a regular store that should be imported. pVal = GetMapiProperty( lpMdb, 0x80000003); ReportLongProp( " Message prop 0x80000003:", pVal); // ListProperties( lpMdb); */ pVal = GetMapiProperty( lpMdb, PR_IPM_SUBTREE_ENTRYID); if (pVal) { ULONG cbEntry; LPENTRYID pEntry; LPMAPIFOLDER lpSubTree = NULL; if (GetEntryIdFromProp( pVal, cbEntry, pEntry)) { // Open up the folder! ULONG ulObjType; hr = lpMdb->OpenEntry( cbEntry, pEntry, NULL, 0, &ulObjType, (LPUNKNOWN *) &lpSubTree); MAPIFreeBuffer( pEntry); if (SUCCEEDED( hr) && lpSubTree) { // Find out if there are any contents in the // tree. LPMAPITABLE lpTable; hr = lpSubTree->GetHierarchyTable( 0, &lpTable); if (HR_FAILED(hr)) { MAPI_TRACE2( "GetStoreInfo: GetHierarchyTable failed: 0x%lx, %d\n", (long)hr, (int)hr); } else { ULONG rowCount; hr = lpTable->GetRowCount( 0, &rowCount); lpTable->Release(); if (SUCCEEDED( hr) && pSzContents) *pSzContents = (long) rowCount; } lpSubTree->Release(); } } } }
HRESULT RunStoreValidation(char* strHost, char* strUser, char* strPass, char *strAltUser, bool bPublic, CHECKMAP checkmap) { HRESULT hr = hrSuccess; LPMAPISESSION lpSession = NULL; LPMDB lpStore = NULL; LPMDB lpAltStore = NULL; LPMDB lpReadStore = NULL; LPMAPIFOLDER lpRootFolder = NULL; LPMAPITABLE lpHierarchyTable = NULL; LPSRowSet lpRows = NULL; ULONG ulObjectType; ULONG ulCount; LPEXCHANGEMANAGESTORE lpIEMS = NULL; // user ULONG cbUserStoreEntryID = 0; LPENTRYID lpUserStoreEntryID = NULL; wstring strwUsername; wstring strwAltUsername; wstring strwPassword; std::set<std::string> setFolderIgnore; LPSPropValue lpAddRenProp = NULL; ULONG cbEntryIDSrc = 0; LPENTRYID lpEntryIDSrc = NULL; ECLogger *const lpLogger = new ECLogger_File(EC_LOGLEVEL_FATAL, 0, "-"); hr = MAPIInitialize(NULL); if (hr != hrSuccess) { cout << "Unable to initialize session" << endl; goto exit; } // input from commandline is current locale if (strUser) strwUsername = convert_to<wstring>(strUser); if (strPass) strwPassword = convert_to<wstring>(strPass); if (strAltUser) strwAltUsername = convert_to<wstring>(strAltUser); hr = HrOpenECSession(lpLogger, &lpSession, "zarafa-fsck", PROJECT_SVN_REV_STR, strwUsername.c_str(), strwPassword.c_str(), (const char *)strHost, 0, NULL, NULL); lpLogger->Release(); if(hr != hrSuccess) { cout << "Wrong username or password." << endl; goto exit; } if (bPublic) { hr = HrOpenECPublicStore(lpSession, &lpStore); if (hr != hrSuccess) { cout << "Failed to open public store." << endl; goto exit; } } else { hr = HrOpenDefaultStore(lpSession, &lpStore); if (hr != hrSuccess) { cout << "Failed to open default store." << endl; goto exit; } } if (!strwAltUsername.empty()) { hr = lpStore->QueryInterface(IID_IExchangeManageStore, (void **)&lpIEMS); if (hr != hrSuccess) { cout << "Cannot open ExchangeManageStore object" << endl; goto exit; } hr = lpIEMS->CreateStoreEntryID(L"", (LPTSTR)strwAltUsername.c_str(), MAPI_UNICODE | OPENSTORE_HOME_LOGON, &cbUserStoreEntryID, &lpUserStoreEntryID); if (hr != hrSuccess) { cout << "Cannot get user store id for user" << endl; goto exit; } hr = lpSession->OpenMsgStore(0, cbUserStoreEntryID, lpUserStoreEntryID, NULL, MDB_WRITE | MDB_NO_DIALOG | MDB_NO_MAIL | MDB_TEMPORARY, &lpAltStore); if (hr != hrSuccess) { cout << "Cannot open user store of user" << endl; goto exit; } lpReadStore = lpAltStore; } else { lpReadStore = lpStore; } hr = lpReadStore->OpenEntry(0, NULL, &IID_IMAPIFolder, 0, &ulObjectType, (IUnknown **)&lpRootFolder); if(hr != hrSuccess) { cout << "Failed to open root folder." << endl; goto exit; } if (HrGetOneProp(lpRootFolder, PR_IPM_OL2007_ENTRYIDS /*PR_ADDITIONAL_REN_ENTRYIDS_EX*/, &lpAddRenProp) == hrSuccess && Util::ExtractSuggestedContactsEntryID(lpAddRenProp, &cbEntryIDSrc, &lpEntryIDSrc) == hrSuccess) { setFolderIgnore.insert(string((const char*)lpEntryIDSrc, cbEntryIDSrc)); } hr = lpRootFolder->GetHierarchyTable(CONVENIENT_DEPTH, &lpHierarchyTable); if (hr != hrSuccess) { cout << "Failed to open hierarchy." << endl; goto exit; } /* * Check if we have found at least *something*. */ hr = lpHierarchyTable->GetRowCount(0, &ulCount); if(hr != hrSuccess) { cout << "Failed to count number of rows." << endl; goto exit; } else if (!ulCount) { cout << "No entries inside Calendar." << endl; goto exit; } /* * Loop through each row/entry and validate. */ while (true) { hr = lpHierarchyTable->QueryRows(20, 0, &lpRows); if (hr != hrSuccess) break; if (lpRows->cRows == 0) break; for (ULONG i = 0; i < lpRows->cRows; i++) RunFolderValidation(setFolderIgnore, lpRootFolder, &lpRows->aRow[i], checkmap); if (lpRows) { FreeProws(lpRows); lpRows = NULL; } } exit: if (lpUserStoreEntryID) MAPIFreeBuffer(lpUserStoreEntryID); if (lpIEMS) lpIEMS->Release(); if (lpRows) { FreeProws(lpRows); lpRows = NULL; } if (lpEntryIDSrc) MAPIFreeBuffer(lpEntryIDSrc); if (lpAddRenProp) MAPIFreeBuffer(lpAddRenProp); if(lpHierarchyTable) lpHierarchyTable->Release(); if (lpRootFolder) lpRootFolder->Release(); if (lpAltStore) lpAltStore->Release(); if (lpStore) lpStore->Release(); if (lpSession) lpSession->Release(); MAPIUninitialize(); return hr; }
HRESULT RunFolderValidation(const std::set<std::string> &setFolderIgnore, LPMAPIFOLDER lpRootFolder, LPSRow lpRow, CHECKMAP checkmap) { HRESULT hr = hrSuccess; LPSPropValue lpItemProperty = NULL; LPMAPIFOLDER lpFolder = NULL; ZarafaFsck *lpFsck = NULL; ULONG ulObjectType = 0; string strName; string strClass; ULONG ulFolderType = 0; lpItemProperty = PpropFindProp(lpRow->lpProps, lpRow->cValues, PR_ENTRYID); if (!lpItemProperty) { cout << "Row does not contain an EntryID." << endl; goto exit; } hr = lpRootFolder->OpenEntry(lpItemProperty->Value.bin.cb, (LPENTRYID)lpItemProperty->Value.bin.lpb, &IID_IMAPIFolder, 0, &ulObjectType, (IUnknown**)&lpFolder); if (hr != hrSuccess) { cout << "Failed to open EntryID." << endl; goto exit; } /* * Detect folder name and class. */ hr = DetectFolderDetails(lpFolder, &strName, &strClass, &ulFolderType); if (hr != hrSuccess) { if (!strName.empty()) { cout << "Unknown class, skipping entry"; cout << " \"" << strName << "\"" << endl; } else cout << "Failed to detect folder details." << endl; goto exit; } if (setFolderIgnore.find(string((const char*)lpItemProperty->Value.bin.lpb, lpItemProperty->Value.bin.cb)) != setFolderIgnore.end()) { cout << "Ignoring folder: "; cout << "\"" << strName << "\" (" << strClass << ")" << endl; goto exit; } if (ulFolderType != FOLDER_GENERIC) { cout << "Ignoring search folder: "; cout << "\"" << strName << "\" (" << strClass << ")" << endl; goto exit; } for (CHECKMAP_I i = checkmap.begin(); i != checkmap.end(); ++i) { if (i->first == strClass) { lpFsck = i->second; break; } } if (lpFsck) lpFsck->ValidateFolder(lpFolder, strName); else { cout << "Ignoring folder: "; cout << "\"" << strName << "\" (" << strClass << ")" << endl; } exit: if(lpFolder) lpFolder->Release(); return hr; }
ULONGLONG ComputeFolderSize( _In_z_ LPWSTR lpszProfile, _In_ LPMAPIFOLDER lpFolder, _In_ ULONG ulFolder, _In_z_ LPWSTR lpszFolder) { DebugPrint(DBGGeneric,"ComputeFolderSize: Calculating size (including subfolders) for folder %u / %ws from profile %ws \n", ulFolder, lpszFolder?lpszFolder:L"", lpszProfile); // printf("ComputeFolderSize: Calculating size (including subfolders) for folder %i / %ws from profile %ws \n", ulFolder, lpszFolder?lpszFolder:L"", lpszProfile); HRESULT hRes = S_OK; if (lpFolder) { LPMAPITABLE lpTable = NULL; LPSRowSet lpRow = NULL; ULONG i = 0; ULONGLONG ullSize = 0; enum { ePR_DISPLAY_NAME_W, ePR_ENTRYID, ePR_FOLDER_TYPE, NUM_COLS }; static const SizedSPropTagArray(NUM_COLS, rgColProps) = { NUM_COLS, PR_DISPLAY_NAME_W, PR_ENTRYID, PR_FOLDER_TYPE, }; // Size of this folder ullSize += ComputeSingleFolderSize(lpFolder); // Size of children WC_MAPI(lpFolder->GetHierarchyTable(MAPI_DEFERRED_ERRORS, &lpTable)); if (SUCCEEDED(hRes) && lpTable) { WC_MAPI(lpTable->SetColumns((LPSPropTagArray)&rgColProps, TBL_ASYNC)); if (!FAILED(hRes)) for (;;) { hRes = S_OK; if (lpRow) FreeProws(lpRow); lpRow = NULL; WC_MAPI(lpTable->QueryRows( 50, NULL, &lpRow)); if (FAILED(hRes) || !lpRow || !lpRow->cRows) break; for (i = 0; i < lpRow->cRows; i++) { hRes = S_OK; // Don't look at search folders if (PR_FOLDER_TYPE == lpRow->aRow[i].lpProps[ePR_FOLDER_TYPE].ulPropTag && FOLDER_SEARCH == lpRow->aRow[i].lpProps[ePR_FOLDER_TYPE].Value.ul) { continue; } if (PR_ENTRYID == lpRow->aRow[i].lpProps[ePR_ENTRYID].ulPropTag) { ULONG ulObjType = NULL; LPMAPIFOLDER lpSubfolder = NULL; WC_MAPI(lpFolder->OpenEntry(lpRow->aRow[i].lpProps[ePR_ENTRYID].Value.bin.cb, (LPENTRYID)lpRow->aRow[i].lpProps[ePR_ENTRYID].Value.bin.lpb, NULL, MAPI_BEST_ACCESS, &ulObjType, (LPUNKNOWN *) &lpSubfolder)); if (SUCCEEDED(hRes) && lpSubfolder) { LPWSTR szDisplayName = L""; if (PR_DISPLAY_NAME_W == lpRow->aRow[i].lpProps[ePR_DISPLAY_NAME_W].ulPropTag) { szDisplayName = lpRow->aRow[i].lpProps[ePR_DISPLAY_NAME_W].Value.lpszW; } ullSize += ComputeFolderSize(lpszProfile, lpSubfolder, 0, szDisplayName); } if (lpSubfolder) lpSubfolder->Release(); } } } if (lpRow) FreeProws(lpRow); } if (lpTable) lpTable->Release(); return ullSize; } return 0; } // ComputeFolderSize
void DumpHierarchyTable( _In_z_ LPWSTR lpszProfile, _In_ LPMAPIFOLDER lpFolder, _In_ ULONG ulFolder, _In_z_ LPWSTR lpszFolder, _In_ ULONG ulDepth) { if (0 == ulDepth) { DebugPrint(DBGGeneric,"DumpHierarchyTable: Outputting hierarchy table for folder %u / %ws from profile %ws \n", ulFolder, lpszFolder?lpszFolder:L"", lpszProfile); } HRESULT hRes = S_OK; if (lpFolder) { LPMAPITABLE lpTable = NULL; LPSRowSet lpRow = NULL; ULONG i = 0; enum { ePR_DISPLAY_NAME_W, ePR_ENTRYID, NUM_COLS }; static const SizedSPropTagArray(NUM_COLS, rgColProps) = { NUM_COLS, PR_DISPLAY_NAME_W, PR_ENTRYID, }; WC_MAPI(lpFolder->GetHierarchyTable(MAPI_DEFERRED_ERRORS, &lpTable)); if (SUCCEEDED(hRes) && lpTable) { WC_MAPI(lpTable->SetColumns((LPSPropTagArray)&rgColProps, TBL_ASYNC)); if (!FAILED(hRes)) for (;;) { hRes = S_OK; if (lpRow) FreeProws(lpRow); lpRow = NULL; WC_MAPI(lpTable->QueryRows( 50, NULL, &lpRow)); if (FAILED(hRes) || !lpRow || !lpRow->cRows) break; for (i = 0; i < lpRow->cRows; i++) { hRes = S_OK; if (ulDepth >= 1) { ULONG iTab = 0; for (iTab = 0; iTab < ulDepth; iTab++) { printf(" "); } } if (PR_DISPLAY_NAME_W == lpRow->aRow[i].lpProps[ePR_DISPLAY_NAME_W].ulPropTag) { printf("%ws\n",lpRow->aRow[i].lpProps[ePR_DISPLAY_NAME_W].Value.lpszW); } if (PR_ENTRYID == lpRow->aRow[i].lpProps[ePR_ENTRYID].ulPropTag) { ULONG ulObjType = NULL; LPMAPIFOLDER lpSubfolder = NULL; WC_MAPI(lpFolder->OpenEntry(lpRow->aRow[i].lpProps[ePR_ENTRYID].Value.bin.cb, (LPENTRYID)lpRow->aRow[i].lpProps[ePR_ENTRYID].Value.bin.lpb, NULL, MAPI_BEST_ACCESS, &ulObjType, (LPUNKNOWN *) &lpSubfolder)); if (SUCCEEDED(hRes) && lpSubfolder) { DumpHierarchyTable(lpszProfile, lpSubfolder, 0, L"", ulDepth + 1); } if (lpSubfolder) lpSubfolder->Release(); } } } if (lpRow) FreeProws(lpRow); } if (lpTable) lpTable->Release(); } } // DumpHierarchyTable
// Finds an arbitrarily nested folder in the indicated store given its // path name. HRESULT HrMAPIFindFolderExW( _In_ LPMDB lpMDB, // Open message store _In_z_ LPCWSTR lpszFolderPath, // folder path _Out_opt_ ULONG* lpcbeid, // pointer to count of bytes in entry ID _Deref_out_opt_ LPENTRYID* lppeid) // pointer to entry ID pointer { DebugPrint(DBGGeneric,"HrMAPIFindFolderExW: Locating path \"%ws\"\n", lpszFolderPath); HRESULT hRes = S_OK; LPMAPIFOLDER lpRootFolder = NULL; ULONG cbeid = 0; LPENTRYID lpeid = NULL; if (!lpcbeid || !lppeid) return MAPI_E_INVALID_PARAMETER; *lpcbeid = 0; *lppeid = NULL; if (!lpMDB) return MAPI_E_INVALID_PARAMETER; ULONG ulFolderCount = 0; LPWSTR* lppszFolderList = NULL; WC_H(HrSplitPath(lpszFolderPath, &ulFolderCount, &lppszFolderList)); // Check for literal property name if (ulFolderCount && lppszFolderList && lppszFolderList[0] && lppszFolderList[0][0] == L'@') { WC_H(HrLookupRootFolderW(lpMDB, lppszFolderList[0]+1, &cbeid, &lpeid)); if (SUCCEEDED(hRes)) { ulFolderCount--; if (ulFolderCount) { lppszFolderList = &lppszFolderList[1]; } } else { // Can we handle the case where one of our constants like DEFAULT_CALENDAR was passed? // We can parse the constant and call OpenDefaultFolder, then later not call OpenEntry for the root } } // If we have any subfolders, chase them if (SUCCEEDED(hRes) && ulFolderCount) { ULONG ulObjType = 0; WC_MAPI(lpMDB->OpenEntry( cbeid, lpeid, NULL, MAPI_BEST_ACCESS | MAPI_DEFERRED_ERRORS, &ulObjType, (LPUNKNOWN*)&lpRootFolder)); if (SUCCEEDED(hRes) && MAPI_FOLDER == ulObjType) { // Free before re-use MAPIFreeBuffer(lpeid); // Find the subfolder in question WC_H(HrMAPIFindSubfolderExW( lpRootFolder, ulFolderCount, lppszFolderList, &cbeid, &lpeid)); } if (lpRootFolder) lpRootFolder->Release(); } if (SUCCEEDED(hRes)) { *lpcbeid = cbeid; *lppeid = lpeid; } MAPIFreeBuffer(lppszFolderList); return hRes; } // HrMAPIFindFolderExW
// Finds an arbitrarily nested folder in the indicated folder given // a hierarchical list of subfolders. HRESULT HrMAPIFindSubfolderExW( _In_ LPMAPIFOLDER lpRootFolder, // open root folder ULONG ulFolderCount, // count of hierarchical list of subfolders to navigate LPWSTR* lppszFolderList, // hierarchical list of subfolders to navigate _Out_opt_ ULONG* lpcbeid, // pointer to count of bytes in entry ID _Deref_out_opt_ LPENTRYID* lppeid) // pointer to entry ID pointer { HRESULT hRes = S_OK; LPMAPIFOLDER lpParentFolder = lpRootFolder; LPMAPIFOLDER lpChildFolder = NULL; ULONG cbeid = 0; LPENTRYID lpeid = NULL; ULONG ulObjType = 0; ULONG i = 0; if (!lpcbeid || !lppeid) return MAPI_E_INVALID_PARAMETER; if (!ulFolderCount || !lppszFolderList) return MAPI_E_INVALID_PARAMETER; for (i = 0; i < ulFolderCount; i++) { // Free entryid before re-use. MAPIFreeBuffer(lpeid); WC_H(HrMAPIFindFolderW(lpParentFolder, lppszFolderList[i], &cbeid, &lpeid)); if (FAILED(hRes)) break; // Only OpenEntry if needed for next tier of folder path. if (lppszFolderList[i+1] != NULL) { WC_MAPI(lpParentFolder->OpenEntry( cbeid, lpeid, NULL, MAPI_DEFERRED_ERRORS, &ulObjType, (LPUNKNOWN*)&lpChildFolder)); if (FAILED(hRes) || ulObjType != MAPI_FOLDER) { MAPIFreeBuffer(lpeid); hRes = MAPI_E_CALL_FAILED; break; } } // No longer need the parent folder // (Don't release the folder that was passed!) if (i > 0) { if (lpParentFolder) lpParentFolder->Release(); } lpParentFolder = lpChildFolder; lpChildFolder = NULL; } // Success! *lpcbeid = cbeid; *lppeid = lpeid; return hRes; } // HrMAPIFindSubfolderExW
wstring MAPIFolder::FindFolderPath() { // return if no session object to compare ids if (!m_session) return L""; HRESULT hr = S_OK; ULONG ulResult = FALSE; wstring wstrPath = m_displayname; LPSPropValue pPropVal = NULL; ULONG ulType = 0; LPMAPIFOLDER lpMAPIFolder = NULL; SBinary prevEntryID = { 0 }; // Make copy of prev EntryID CopyEntryID(m_EntryID, prevEntryID); // Get parent ENTRYID if (SUCCEEDED(hr = HrGetOneProp(m_folder, PR_PARENT_ENTRYID, &pPropVal))) { while (!ulResult) { // compare entryID with previous m_session->CompareEntryIDs(&prevEntryID, &pPropVal->Value.bin, ulResult); // Free PrevEntryID FreeEntryID(prevEntryID); if (ulResult) { if (pPropVal) MAPIFreeBuffer(pPropVal); continue; } // Get Parent MAPI Folder if (SUCCEEDED(hr = m_session->OpenEntry(pPropVal->Value.bin.cb, (LPENTRYID)pPropVal->Value.bin.lpb, NULL, 0, &ulType, (LPUNKNOWN *)&lpMAPIFolder))) { // Get parent folder name LPSPropValue pDisplayPropVal = NULL; if (SUCCEEDED(hr = HrGetOneProp(lpMAPIFolder, PR_DISPLAY_NAME, &pDisplayPropVal))) { std::wstring tempath = pDisplayPropVal->Value.lpszW; // need to parse the parent folder names for forward slash std::wstring::size_type i = tempath.find(L"/"); while (i != std::wstring::npos && i < tempath.size()) { tempath.replace(i, wcslen(L"/"),CONST_FORWDSLASH); i += wcslen(L"/"); i = tempath.find( L"/", i); } //wstrPath = wstrPath + L"/" + pDisplayPropVal->Value.lpszW; wstrPath = wstrPath + L"/" + tempath; MAPIFreeBuffer(pDisplayPropVal); pDisplayPropVal = NULL; } // Make copy of prev EntryID CopyEntryID(pPropVal->Value.bin, prevEntryID); // free parent folder entryID MAPIFreeBuffer(pPropVal); pPropVal = NULL; // Get parent's parent entry ID if (!SUCCEEDED(hr = HrGetOneProp(lpMAPIFolder, PR_PARENT_ENTRYID, &pPropVal))) ulResult = TRUE; // free parent folder lpMAPIFolder->Release(); lpMAPIFolder = NULL; } else { ulResult = TRUE; } } } wstrPath = Zimbra::MAPI::Util::ReverseDelimitedString(wstrPath, L"/"); if (wstrPath.length() > 2) { size_t npos = wstrPath.find('/', 1); if (npos != std::string::npos) { wstrPath.replace(1, (npos-1), L"MAPIRoot"); } } //check for any earlier masking of "/" and restore it /* size_t cnst_pos = wstrPath.find(CONST_FORWDSLASH); if(std::wstring::npos != cnst_pos) { wstrPath.replace(cnst_pos,wcslen(CONST_FORWDSLASH),L"/"); } */ std::wstring::size_type i = wstrPath.find(CONST_FORWDSLASH); while (i != std::wstring::npos && i < wstrPath.size()) { wstrPath.replace(i, wcslen(CONST_FORWDSLASH), L"/"); i += wcslen(L"/"); i = wstrPath.find( CONST_FORWDSLASH, i); } return wstrPath; }