Back to index

lightning-sunbird  0.9+nobinonly
MapiApi.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037  
00038 #include "MapiDbgLog.h"
00039 #include "MapiApi.h"
00040 
00041 #include "nsCRT.h"
00042 #include "prprf.h"
00043 #include "nsReadableUtils.h"
00044 #include "nsUnicharUtils.h"
00045 
00046 
00047 int                  CMapiApi::m_clients = 0;
00048 BOOL          CMapiApi::m_initialized = PR_FALSE;
00049 nsVoidArray   *CMapiApi::m_pStores = NULL;
00050 LPMAPISESSION CMapiApi::m_lpSession = NULL;
00051 LPMDB         CMapiApi::m_lpMdb = NULL;
00052 HRESULT              CMapiApi::m_lastError;
00053 PRUnichar *   CMapiApi::m_pUniBuff = NULL;
00054 int                  CMapiApi::m_uniBuffLen = 0;
00055 /*
00056 Type: 1, name: Calendar, class: IPF.Appointment
00057 Type: 1, name: Contacts, class: IPF.Contact
00058 Type: 1, name: Journal, class: IPF.Journal
00059 Type: 1, name: Notes, class: IPF.StickyNote
00060 Type: 1, name: Tasks, class: IPF.Task
00061 Type: 1, name: Drafts, class: IPF.Note
00062 */
00063 
00064 HINSTANCE     CMapiApi::m_hMapi32 = NULL;
00065 
00066 LPMAPIUNINITIALIZE          gpMapiUninitialize = NULL;
00067 LPMAPIINITIALIZE            gpMapiInitialize = NULL;
00068 LPMAPIALLOCATEBUFFER gpMapiAllocateBuffer = NULL;
00069 LPMAPIFREEBUFFER            gpMapiFreeBuffer = NULL;
00070 LPMAPILOGONEX               gpMapiLogonEx = NULL;
00071 LPOPENSTREAMONFILE          gpMapiOpenStreamOnFile = NULL;
00072 
00073 BOOL CMapiApi::LoadMapiEntryPoints( void)
00074 {
00075        if (!(gpMapiUninitialize = (LPMAPIUNINITIALIZE) GetProcAddress( m_hMapi32, "MAPIUninitialize")))
00076               return( FALSE);
00077        if (!(gpMapiInitialize = (LPMAPIINITIALIZE) GetProcAddress( m_hMapi32, "MAPIInitialize")))
00078               return( FALSE);
00079        if (!(gpMapiAllocateBuffer = (LPMAPIALLOCATEBUFFER) GetProcAddress( m_hMapi32, "MAPIAllocateBuffer")))
00080               return( FALSE);
00081        if (!(gpMapiFreeBuffer = (LPMAPIFREEBUFFER) GetProcAddress( m_hMapi32, "MAPIFreeBuffer")))
00082               return( FALSE);
00083        if (!(gpMapiLogonEx = (LPMAPILOGONEX) GetProcAddress( m_hMapi32, "MAPILogonEx")))
00084               return( FALSE);
00085        if (!(gpMapiOpenStreamOnFile = (LPOPENSTREAMONFILE) GetProcAddress( m_hMapi32, "OpenStreamOnFile")))
00086               return( FALSE);
00087 
00088        return( TRUE);
00089 }
00090 
00091 void CMapiApi::MAPIUninitialize( void)
00092 {
00093        if (m_hMapi32 && gpMapiUninitialize)
00094               (*gpMapiUninitialize)();
00095 }
00096 
00097 HRESULT CMapiApi::MAPIInitialize( LPVOID lpInit)
00098 {
00099        if (m_hMapi32 && gpMapiInitialize)
00100               return( (*gpMapiInitialize)( lpInit));
00101        return( MAPI_E_NOT_INITIALIZED);
00102 }
00103 
00104 SCODE CMapiApi::MAPIAllocateBuffer( ULONG cbSize, LPVOID FAR * lppBuffer)
00105 {
00106        if (m_hMapi32 && gpMapiAllocateBuffer)
00107               return( (*gpMapiAllocateBuffer)( cbSize, lppBuffer));
00108        return( MAPI_E_NOT_INITIALIZED);
00109 }
00110  
00111 ULONG CMapiApi::MAPIFreeBuffer( LPVOID lpBuff)
00112 {
00113        if (m_hMapi32 && gpMapiFreeBuffer)
00114               return( (*gpMapiFreeBuffer)( lpBuff));
00115        return( MAPI_E_NOT_INITIALIZED);
00116 }
00117 
00118 HRESULT CMapiApi::MAPILogonEx( ULONG ulUIParam, LPTSTR lpszProfileName, LPTSTR lpszPassword, FLAGS flFlags, LPMAPISESSION FAR * lppSession)
00119 {
00120        if (m_hMapi32 && gpMapiLogonEx)
00121               return( (*gpMapiLogonEx)( ulUIParam, lpszProfileName, lpszPassword, flFlags, lppSession));
00122        return( MAPI_E_NOT_INITIALIZED);
00123 }
00124 
00125 HRESULT CMapiApi::OpenStreamOnFile( LPALLOCATEBUFFER lpAllocateBuffer, LPFREEBUFFER lpFreeBuffer, ULONG ulFlags, LPTSTR lpszFileName, LPTSTR lpszPrefix, LPSTREAM FAR * lppStream)
00126 {
00127        if (m_hMapi32 && gpMapiOpenStreamOnFile)
00128               return( (*gpMapiOpenStreamOnFile)( lpAllocateBuffer, lpFreeBuffer, ulFlags, lpszFileName, lpszPrefix, lppStream));
00129        return( MAPI_E_NOT_INITIALIZED);
00130 }
00131 
00132 void CMapiApi::FreeProws( LPSRowSet prows)
00133 {
00134        ULONG         irow;
00135        if (!prows)
00136               return;
00137        for (irow = 0; irow < prows->cRows; ++irow)
00138               MAPIFreeBuffer( prows->aRow[irow].lpProps);
00139        MAPIFreeBuffer( prows);
00140 }
00141 
00142 
00143 
00144 
00145 BOOL CMapiApi::LoadMapi( void)
00146 {
00147        if (m_hMapi32)
00148               return( TRUE);
00149        
00150        HINSTANCE     hInst = ::LoadLibrary( "MAPI32.DLL");
00151        if (!hInst)
00152               return( FALSE);
00153        FARPROC pProc = GetProcAddress( hInst, "MAPIGetNetscapeVersion");
00154        if (pProc) {
00155               ::FreeLibrary( hInst);
00156               hInst = ::LoadLibrary( "MAPI32BAK.DLL");
00157               if (!hInst)
00158                      return( FALSE);
00159        }
00160 
00161        m_hMapi32 = hInst;
00162        return( LoadMapiEntryPoints());
00163 }
00164 
00165 void CMapiApi::UnloadMapi( void)
00166 {
00167        if (m_hMapi32)
00168               ::FreeLibrary( m_hMapi32);
00169        m_hMapi32 = NULL;
00170 }
00171 
00172 CMapiApi::CMapiApi()
00173 {
00174        m_clients++;
00175        LoadMapi();
00176        if (!m_pStores)
00177               m_pStores = new nsVoidArray();
00178 }
00179 
00180 CMapiApi::~CMapiApi()
00181 {
00182        m_clients--;
00183        if (!m_clients) {
00184               HRESULT       hr;
00185               
00186               ClearMessageStores();
00187               delete m_pStores;
00188               m_pStores = NULL;
00189 
00190               m_lpMdb = NULL;
00191 
00192               if (m_lpSession) {
00193                      hr = m_lpSession->Logoff( NULL, 0, 0);
00194                      if (FAILED(hr)) {
00195                             MAPI_TRACE2( "Logoff failed: 0x%lx, %d\n", (long)hr, (int)hr);
00196                      }
00197                      m_lpSession->Release();
00198                      m_lpSession = NULL;
00199               }
00200 
00201               if (m_initialized) {
00202                      MAPIUninitialize();
00203                      m_initialized = FALSE;
00204               }
00205 
00206               UnloadMapi();
00207               
00208               if (m_pUniBuff)
00209                      delete [] m_pUniBuff;
00210               m_pUniBuff = NULL;
00211               m_uniBuffLen = 0;
00212        }
00213 }
00214 
00215 void CMapiApi::CStrToUnicode( const char *pStr, nsString& result)
00216 {
00217        result.Truncate( 0);
00218        int wLen = MultiByteToWideChar( CP_ACP, 0, pStr, -1, m_pUniBuff, 0);
00219        if (wLen >= m_uniBuffLen) {
00220               if (m_pUniBuff)
00221                      delete [] m_pUniBuff;
00222               m_pUniBuff = new PRUnichar[wLen + 64];
00223               m_uniBuffLen = wLen + 64;
00224        }
00225        if (wLen) {
00226               MultiByteToWideChar( CP_ACP, 0, pStr, -1, m_pUniBuff, m_uniBuffLen);
00227               result = m_pUniBuff;
00228        }
00229 }
00230 
00231 BOOL CMapiApi::Initialize( void)
00232 {
00233        if (m_initialized)
00234               return( TRUE);
00235 
00236        HRESULT              hr;
00237 
00238        hr = MAPIInitialize( NULL);
00239 
00240        if (FAILED(hr)) {
00241               MAPI_TRACE2( "MAPI Initialize failed: 0x%lx, %d\n", (long)hr, (int)hr);
00242               return( FALSE);
00243        }
00244        
00245        m_initialized = TRUE;
00246        MAPI_TRACE0( "MAPI Initialized\n");
00247 
00248        return( TRUE);
00249 }
00250 
00251 BOOL CMapiApi::LogOn( void)
00252 {
00253        if (!m_initialized) {
00254               MAPI_TRACE0( "Tried to LogOn before initializing MAPI\n");
00255               return( FALSE);
00256        }
00257        
00258        if (m_lpSession)
00259               return( TRUE);
00260 
00261        HRESULT hr;
00262 
00263        hr = MAPILogonEx(    0, // might need to be passed in HWND
00264                                           NULL, // profile name, 64 char max (LPTSTR)
00265                                           NULL, // profile password, 64 char max (LPTSTR)
00266                                           // MAPI_NEW_SESSION | MAPI_NO_MAIL | MAPI_LOGON_UI | MAPI_EXPLICIT_PROFILE,
00267                                           // MAPI_NEW_SESSION | MAPI_NO_MAIL | MAPI_LOGON_UI,
00268                                           // MAPI_NO_MAIL | MAPI_LOGON_UI,
00269                                           MAPI_NO_MAIL | MAPI_USE_DEFAULT | MAPI_EXTENDED | MAPI_NEW_SESSION,
00270                                           &m_lpSession);
00271 
00272        if (FAILED(hr)) {
00273               m_lpSession = NULL;
00274               MAPI_TRACE2( "LogOn failed: 0x%lx, %d\n", (long)hr, (int)hr);
00275               return( FALSE);
00276        }
00277 
00278        MAPI_TRACE0( "MAPI Logged on\n");
00279 
00280 
00281        return( TRUE);
00282 }
00283 
00284 class CGetStoreFoldersIter : public CMapiHierarchyIter {
00285 public:
00286        CGetStoreFoldersIter( CMapiApi *pApi, CMapiFolderList& folders, int depth, BOOL isMail = TRUE);
00287        
00288        virtual BOOL HandleHierarchyItem( ULONG oType, ULONG cb, LPENTRYID pEntry);
00289 
00290 protected:
00291        BOOL   ExcludeFolderClass( const PRUnichar *pName);
00292 
00293        BOOL                        m_isMail;
00294        CMapiApi *                  m_pApi;
00295        CMapiFolderList *    m_pList;
00296        int                                m_depth;
00297 };
00298 
00299 CGetStoreFoldersIter::CGetStoreFoldersIter( CMapiApi *pApi, CMapiFolderList& folders, int depth, BOOL isMail)
00300 {
00301        m_pApi = pApi;
00302        m_pList = &folders;
00303        m_depth = depth;
00304        m_isMail = isMail;
00305 }
00306 
00307 BOOL CGetStoreFoldersIter::ExcludeFolderClass( const PRUnichar *pName)
00308 {
00309        BOOL bResult;
00310     nsDependentString pNameStr(pName);
00311        if (m_isMail) {
00312               bResult = FALSE;
00313         if (pNameStr.EqualsLiteral("IPF.Appointment"))
00314                      bResult = TRUE;
00315               else if (pNameStr.EqualsLiteral("IPF.Contact"))
00316                      bResult = TRUE;
00317               else if (pNameStr.EqualsLiteral("IPF.Journal"))
00318                      bResult = TRUE;
00319         else if (pNameStr.EqualsLiteral("IPF.StickyNote"))
00320                      bResult = TRUE;
00321               else if (pNameStr.EqualsLiteral("IPF.Task"))
00322                      bResult = TRUE;
00323               // else if (!stricmp( pName, "IPF.Note"))
00324               //     bResult = TRUE;
00325        }
00326        else {
00327               bResult = TRUE;
00328               if (pNameStr.EqualsLiteral("IPF.Contact"))
00329                      bResult = FALSE;
00330        }
00331 
00332        return( bResult);
00333 }
00334 
00335 BOOL CGetStoreFoldersIter::HandleHierarchyItem( ULONG oType, ULONG cb, LPENTRYID pEntry)
00336 {
00337        if (oType == MAPI_FOLDER) {
00338               LPMAPIFOLDER pFolder;
00339               if (m_pApi->OpenEntry( cb, pEntry, (LPUNKNOWN *) &pFolder)) {
00340                      LPSPropValue         pVal;
00341                      nsString                    name;
00342 
00343                      pVal = m_pApi->GetMapiProperty( pFolder, PR_CONTAINER_CLASS);
00344                      if (pVal)
00345                             m_pApi->GetStringFromProp( pVal, name);
00346                      else
00347                             name.Truncate();
00348 
00349                      if ((name.IsEmpty() && m_isMail) || (!ExcludeFolderClass(name.get()))) {
00350                             pVal = m_pApi->GetMapiProperty( pFolder, PR_DISPLAY_NAME);
00351                             m_pApi->GetStringFromProp( pVal, name);
00352                             CMapiFolder   *pNewFolder = new CMapiFolder(name.get(), cb, pEntry, m_depth);
00353                             m_pList->AddItem( pNewFolder);
00354                             
00355                             pVal = m_pApi->GetMapiProperty( pFolder, PR_FOLDER_TYPE);
00356                             MAPI_TRACE2( "Type: %d, name: %s\n", m_pApi->GetLongFromProp( pVal), (const char *)name);
00357                             // m_pApi->ListProperties( pFolder);
00358                      
00359                             CGetStoreFoldersIter nextIter( m_pApi, *m_pList, m_depth + 1, m_isMail);
00360                             m_pApi->IterateHierarchy( &nextIter, pFolder);
00361                      }
00362                      pFolder->Release();
00363               }
00364               else {
00365                      MAPI_TRACE0( "GetStoreFolders - HandleHierarchyItem: Error opening folder entry.\n");
00366                      return( FALSE);
00367               }
00368        }
00369        else {
00370               MAPI_TRACE1( "GetStoreFolders - HandleHierarchyItem: Unhandled ObjectType: %ld\n", oType);
00371        }
00372 
00373        return( TRUE);
00374 }
00375 
00376 
00377 BOOL CMapiApi::GetStoreFolders( ULONG cbEid, LPENTRYID lpEid, CMapiFolderList& folders, int startDepth)
00378 {
00379        // Fill in the array with the folders in the given store
00380        if (!m_initialized || !m_lpSession) {
00381               MAPI_TRACE0( "MAPI not initialized for GetStoreFolders\n");
00382               return( FALSE);
00383        }
00384        
00385        m_lpMdb = NULL;
00386 
00387        CMsgStore *          pStore = FindMessageStore( cbEid, lpEid);
00388        BOOL                 bResult = FALSE;
00389        LPSPropValue  pVal;
00390 
00391        if (pStore && pStore->Open( m_lpSession, &m_lpMdb)) {
00392               // Successful open, do the iteration of the store
00393               pVal = GetMapiProperty( m_lpMdb, PR_IPM_SUBTREE_ENTRYID);
00394               if (pVal) {
00395                      ULONG                cbEntry;
00396                      LPENTRYID            pEntry;
00397                      LPMAPIFOLDER  lpSubTree = NULL;
00398 
00399                      if (GetEntryIdFromProp( pVal, cbEntry, pEntry)) {
00400                             // Open up the folder!
00401                             bResult = OpenEntry( cbEntry, pEntry, (LPUNKNOWN *)&lpSubTree);
00402                             MAPIFreeBuffer( pEntry);
00403                             if (bResult && lpSubTree) {
00404                                    // Iterate the subtree with the results going into the folder list
00405                                    CGetStoreFoldersIter iterHandler( this, folders, startDepth);
00406                                    bResult = IterateHierarchy( &iterHandler, lpSubTree);
00407                                    lpSubTree->Release();
00408                             }
00409                             else {
00410                                    MAPI_TRACE0( "GetStoreFolders: Error opening sub tree.\n");
00411                             }
00412                      }
00413                      else {
00414                             MAPI_TRACE0( "GetStoreFolders: Error getting entryID from sub tree property val.\n");
00415                      }
00416               }
00417               else {
00418                      MAPI_TRACE0( "GetStoreFolders: Error getting sub tree property.\n");
00419               }
00420        }
00421        else {
00422               MAPI_TRACE0( "GetStoreFolders: Error opening message store.\n");
00423        }
00424 
00425        return( bResult);
00426 }
00427 
00428 BOOL CMapiApi::GetStoreAddressFolders( ULONG cbEid, LPENTRYID lpEid, CMapiFolderList& folders)
00429 {
00430        // Fill in the array with the folders in the given store
00431        if (!m_initialized || !m_lpSession) {
00432               MAPI_TRACE0( "MAPI not initialized for GetStoreAddressFolders\n");
00433               return( FALSE);
00434        }
00435        
00436        m_lpMdb = NULL;
00437 
00438        CMsgStore *          pStore = FindMessageStore( cbEid, lpEid);
00439        BOOL                 bResult = FALSE;
00440        LPSPropValue  pVal;
00441 
00442        if (pStore && pStore->Open( m_lpSession, &m_lpMdb)) {
00443               // Successful open, do the iteration of the store
00444               pVal = GetMapiProperty( m_lpMdb, PR_IPM_SUBTREE_ENTRYID);
00445               if (pVal) {
00446                      ULONG                cbEntry;
00447                      LPENTRYID            pEntry;
00448                      LPMAPIFOLDER  lpSubTree = NULL;
00449 
00450                      if (GetEntryIdFromProp( pVal, cbEntry, pEntry)) {
00451                             // Open up the folder!
00452                             bResult = OpenEntry( cbEntry, pEntry, (LPUNKNOWN *)&lpSubTree);
00453                             MAPIFreeBuffer( pEntry);
00454                             if (bResult && lpSubTree) {
00455                                    // Iterate the subtree with the results going into the folder list
00456                                    CGetStoreFoldersIter iterHandler( this, folders, 1, FALSE);
00457                                    bResult = IterateHierarchy( &iterHandler, lpSubTree);
00458                                    lpSubTree->Release();
00459                             }
00460                             else {
00461                                    MAPI_TRACE0( "GetStoreAddressFolders: Error opening sub tree.\n");
00462                             }
00463                      }
00464                      else {
00465                             MAPI_TRACE0( "GetStoreAddressFolders: Error getting entryID from sub tree property val.\n");
00466                      }
00467               }
00468               else {
00469                      MAPI_TRACE0( "GetStoreAddressFolders: Error getting sub tree property.\n");
00470               }
00471        }
00472        else {
00473               MAPI_TRACE0( "GetStoreAddressFolders: Error opening message store.\n");
00474        }
00475 
00476        return( bResult);
00477 }
00478 
00479 
00480 BOOL CMapiApi::OpenStore( ULONG cbEid, LPENTRYID lpEid, LPMDB *ppMdb)
00481 {
00482        if (!m_lpSession) {
00483               MAPI_TRACE0( "OpenStore called before a session was opened\n");
00484               return( FALSE);
00485        }
00486 
00487        CMsgStore *          pStore = FindMessageStore( cbEid, lpEid);
00488        if (pStore && pStore->Open( m_lpSession, ppMdb))
00489               return( TRUE);
00490        return( FALSE);
00491 }
00492 
00493 
00494 BOOL CMapiApi::OpenEntry( ULONG cbEntry, LPENTRYID pEntryId, LPUNKNOWN *ppOpen)
00495 {
00496        if (!m_lpMdb) {
00497               MAPI_TRACE0( "OpenEntry called before the message store is open\n");
00498               return( FALSE);
00499        }
00500        
00501        return( OpenMdbEntry( m_lpMdb, cbEntry, pEntryId, ppOpen));
00502 }
00503 
00504 BOOL CMapiApi::OpenMdbEntry( LPMDB lpMdb, ULONG cbEntry, LPENTRYID pEntryId, LPUNKNOWN *ppOpen)
00505 {      
00506        ULONG         ulObjType;
00507        HRESULT              hr;
00508     hr = m_lpSession->OpenEntry(cbEntry,
00509                                                         pEntryId,
00510                                                         NULL,
00511                                                         0,
00512                                                         &ulObjType,
00513                                                         (LPUNKNOWN *) ppOpen);
00514        if (FAILED(hr)) {
00515               MAPI_TRACE2( "OpenMdbEntry failed: 0x%lx, %d\n", (long)hr, (int)hr);
00516               return( FALSE);
00517        }
00518        return( TRUE);
00519 }
00520 
00521 enum {
00522     ieidPR_ENTRYID = 0,
00523        ieidPR_OBJECT_TYPE,
00524     ieidMax
00525 };
00526 
00527 static const SizedSPropTagArray(ieidMax, ptaEid)=
00528 {
00529     ieidMax,
00530     {
00531         PR_ENTRYID,
00532               PR_OBJECT_TYPE,
00533     }
00534 };
00535 
00536 BOOL CMapiApi::IterateContents( CMapiContentIter *pIter, LPMAPIFOLDER pFolder, ULONG flags)
00537 {
00538        // flags can be 0 or MAPI_ASSOCIATED
00539        // MAPI_ASSOCIATED is usually used for forms and views
00540 
00541        HRESULT              hr;
00542        LPMAPITABLE   lpTable;
00543        hr = pFolder->GetContentsTable( flags, &lpTable);
00544        if (FAILED(hr)) {
00545               MAPI_TRACE2( "GetContentsTable failed: 0x%lx, %d\n", (long)hr, (int)hr);
00546               return( FALSE);
00547        }
00548 
00549        ULONG rowCount;
00550        hr = lpTable->GetRowCount( 0, &rowCount);
00551        if (!rowCount) {
00552               MAPI_TRACE0( "  Empty Table\n");
00553        }
00554 
00555        hr = lpTable->SetColumns( (LPSPropTagArray)&ptaEid, 0);
00556        if (FAILED(hr)) {
00557               lpTable->Release();
00558               MAPI_TRACE2( "SetColumns failed: 0x%lx, %d\n", (long)hr, (int)hr);
00559               return( FALSE);
00560        }
00561 
00562        hr = lpTable->SeekRow( BOOKMARK_BEGINNING, 0, NULL);
00563        if (FAILED(hr)) {
00564               lpTable->Release();
00565               MAPI_TRACE2( "SeekRow failed: 0x%lx, %d\n", (long)hr, (int)hr);
00566               return( FALSE);
00567        }
00568 
00569        int                  cNumRows = 0;
00570        LPSRowSet     lpRow;
00571        BOOL          keepGoing = TRUE;
00572        BOOL          bResult = TRUE;
00573        do {
00574               
00575               lpRow = NULL;
00576               hr = lpTable->QueryRows( 1, 0, &lpRow);
00577 
00578         if(HR_FAILED(hr)) {
00579                      MAPI_TRACE2( "QueryRows failed: 0x%lx, %d\n", (long)hr, (int)hr);
00580             bResult = FALSE;
00581                      break;
00582               }
00583 
00584         if(lpRow) {
00585             cNumRows = lpRow->cRows;
00586 
00587                   if (cNumRows) {
00588                 LPENTRYID   lpEID = (LPENTRYID) lpRow->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.lpb;
00589                 ULONG              cbEID = lpRow->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.cb;
00590                             ULONG         oType = lpRow->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.ul;
00591 
00592                 keepGoing = HandleContentsItem( oType, cbEID, lpEID);
00593                             MAPI_TRACE1( "    ObjectType: %ld\n", oType);
00594                   }
00595                      FreeProws( lpRow);          
00596         }
00597 
00598        } while ( SUCCEEDED(hr) && cNumRows && lpRow && keepGoing);
00599 
00600        lpTable->Release();
00601 
00602        return( bResult);
00603 }
00604 
00605 BOOL CMapiApi::HandleContentsItem( ULONG oType, ULONG cb, LPENTRYID pEntry)
00606 {
00607        if (oType == MAPI_MESSAGE) {
00608               LPMESSAGE pMsg;
00609               if (OpenEntry( cb, pEntry, (LPUNKNOWN *) &pMsg)) {
00610                      LPSPropValue pVal;
00611                      pVal = GetMapiProperty( pMsg, PR_SUBJECT);
00612                      ReportStringProp( "PR_SUBJECT:", pVal);
00613                      pVal = GetMapiProperty( pMsg, PR_DISPLAY_BCC);
00614                      ReportStringProp( "PR_DISPLAY_BCC:", pVal);
00615                      pVal = GetMapiProperty( pMsg, PR_DISPLAY_CC);
00616                      ReportStringProp( "PR_DISPLAY_CC:", pVal);
00617                      pVal = GetMapiProperty( pMsg, PR_DISPLAY_TO);
00618                      ReportStringProp( "PR_DISPLAY_TO:", pVal);
00619                      pVal = GetMapiProperty( pMsg, PR_MESSAGE_CLASS);
00620                      ReportStringProp( "PR_MESSAGE_CLASS:", pVal);
00621                      ListProperties( pMsg);
00622                      pMsg->Release();
00623               }
00624               else {
00625                      MAPI_TRACE0( "    Folder type - error opening\n");
00626               }
00627        }
00628        else
00629               MAPI_TRACE1( "    ObjectType: %ld\n", oType);
00630 
00631        return( TRUE);
00632 }
00633 
00634 void CMapiApi::ListProperties( LPMAPIPROP lpProp, BOOL getValues)
00635 {
00636        LPSPropTagArray             pArray;
00637        HRESULT                            hr = lpProp->GetPropList( 0, &pArray);
00638        if (FAILED(hr)) {
00639               MAPI_TRACE0( "    Unable to retrieve property list\n");
00640               return;
00641        }
00642   ULONG count = 0;
00643   LPMAPINAMEID FAR * lppPropNames;
00644   SPropTagArray             tagArray;
00645   LPSPropTagArray lpTagArray = &tagArray;
00646   tagArray.cValues = (ULONG)1;
00647        nsCString     desc;
00648        for (ULONG i = 0; i < pArray->cValues; i++) {
00649               GetPropTagName( pArray->aulPropTag[i], desc);
00650               if (getValues) {
00651       tagArray.aulPropTag[0] = pArray->aulPropTag[i];
00652       hr = lpProp->GetNamesFromIDs(&lpTagArray, nsnull, 0, &count, &lppPropNames); 
00653       if (hr == S_OK)
00654         MAPIFreeBuffer(lppPropNames);
00655 
00656                      LPSPropValue pVal = GetMapiProperty( lpProp, pArray->aulPropTag[i]);
00657                      if (pVal) {
00658                             desc += ", ";
00659                             ListPropertyValue( pVal, desc);
00660                             MAPIFreeBuffer( pVal);
00661                      }
00662               }
00663               MAPI_TRACE2( "    Tag #%d: %s\n", (int)i, (const char *)desc);
00664        }
00665 
00666   MAPIFreeBuffer( pArray);
00667 }
00668 
00669 ULONG CMapiApi::GetEmailPropertyTag(LPMAPIPROP lpProp, LONG nameID)
00670 {
00671 static GUID emailGUID = {
00672    0x00062004, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46
00673 };
00674 
00675   MAPINAMEID mapiNameID;
00676   mapiNameID.lpguid = &emailGUID;
00677   mapiNameID.ulKind = MNID_ID;
00678   mapiNameID.Kind.lID = nameID;
00679 
00680   LPMAPINAMEID lpMapiNames = &mapiNameID;
00681   LPSPropTagArray lpMailTagArray = nsnull;
00682 
00683   HRESULT result = lpProp->GetIDsFromNames(1L, &lpMapiNames, 0, &lpMailTagArray);
00684   if (result == S_OK)
00685   {
00686     ULONG lTag = lpMailTagArray->aulPropTag[0];
00687     MAPIFreeBuffer(lpMailTagArray);
00688     return lTag;
00689   }
00690   else
00691     return 0L;
00692 }
00693 
00694 BOOL CMapiApi::HandleHierarchyItem( ULONG oType, ULONG cb, LPENTRYID pEntry)
00695 {
00696        if (oType == MAPI_FOLDER) {
00697               LPMAPIFOLDER pFolder;
00698               if (OpenEntry( cb, pEntry, (LPUNKNOWN *) &pFolder)) {
00699                      LPSPropValue pVal;
00700                      pVal = GetMapiProperty( pFolder, PR_DISPLAY_NAME);
00701                      ReportStringProp( "Folder name:", pVal);
00702                      IterateContents( NULL, pFolder);
00703                      IterateHierarchy( NULL, pFolder);
00704                      pFolder->Release();
00705               }
00706               else {
00707                      MAPI_TRACE0( "    Folder type - error opening\n");
00708               }
00709        }
00710        else
00711               MAPI_TRACE1( "    ObjectType: %ld\n", oType);
00712 
00713        return( TRUE);
00714 }
00715 
00716 BOOL CMapiApi::IterateHierarchy( CMapiHierarchyIter *pIter, LPMAPIFOLDER pFolder, ULONG flags)
00717 {
00718        // flags can be CONVENIENT_DEPTH or 0
00719        // CONVENIENT_DEPTH will return all depths I believe instead
00720        // of just children
00721        HRESULT              hr;
00722        LPMAPITABLE   lpTable;
00723        hr = pFolder->GetHierarchyTable( flags, &lpTable);
00724        if (HR_FAILED(hr)) {
00725               m_lastError = hr;
00726               MAPI_TRACE2( "IterateHierarchy: GetContentsTable failed: 0x%lx, %d\n", (long)hr, (int)hr);
00727               return( FALSE);
00728        }
00729 
00730        ULONG rowCount;
00731        hr = lpTable->GetRowCount( 0, &rowCount);
00732        if (!rowCount) {
00733               lpTable->Release();
00734               return( TRUE);
00735        }
00736 
00737        hr = lpTable->SetColumns( (LPSPropTagArray)&ptaEid, 0);
00738        if (HR_FAILED(hr)) {
00739               m_lastError = hr;
00740               lpTable->Release();
00741               MAPI_TRACE2( "IterateHierarchy: SetColumns failed: 0x%lx, %d\n", (long)hr, (int)hr);
00742               return( FALSE);
00743        }
00744 
00745        hr = lpTable->SeekRow( BOOKMARK_BEGINNING, 0, NULL);
00746        if (HR_FAILED(hr)) {
00747               m_lastError = hr;
00748               lpTable->Release();
00749               MAPI_TRACE2( "IterateHierarchy: SeekRow failed: 0x%lx, %d\n", (long)hr, (int)hr);
00750               return( FALSE);
00751        }
00752 
00753        int                  cNumRows = 0;
00754        LPSRowSet     lpRow;
00755        BOOL          keepGoing = TRUE;
00756        BOOL          bResult = TRUE;
00757        do {
00758               
00759               lpRow = NULL;
00760               hr = lpTable->QueryRows( 1, 0, &lpRow);
00761 
00762         if(HR_FAILED(hr)) {
00763                      MAPI_TRACE2( "QueryRows failed: 0x%lx, %d\n", (long)hr, (int)hr);
00764                      m_lastError = hr;
00765             bResult = FALSE;
00766                      break;
00767               }
00768 
00769         if(lpRow) {
00770             cNumRows = lpRow->cRows;
00771 
00772                   if (cNumRows) {
00773                 LPENTRYID   lpEntry = (LPENTRYID) lpRow->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.lpb;
00774                 ULONG              cb = lpRow->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.cb;
00775                             ULONG         oType = lpRow->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.ul;
00776                             
00777                             if (pIter)
00778                                    keepGoing = pIter->HandleHierarchyItem( oType, cb, lpEntry);
00779                             else
00780                                    keepGoing = HandleHierarchyItem( oType, cb, lpEntry);
00781 
00782                   }
00783                      FreeProws( lpRow);          
00784         }
00785 
00786        } while ( SUCCEEDED(hr) && cNumRows && lpRow && keepGoing);
00787 
00788        lpTable->Release();
00789        
00790        if (bResult && !keepGoing)
00791               bResult = FALSE;
00792 
00793        return( bResult);
00794 }
00795 
00796 
00797 enum {
00798        itblPR_DISPLAY_NAME,
00799     itblPR_ENTRYID,
00800     itblMax
00801 };
00802 
00803 static const SizedSPropTagArray(itblMax, ptaTbl)=
00804 {
00805     itblMax,
00806     {
00807               PR_DISPLAY_NAME,
00808         PR_ENTRYID,
00809     }
00810 };
00811 
00812 BOOL CMapiApi::IterateStores( CMapiFolderList& stores)
00813 {
00814        stores.ClearAll();
00815 
00816        if (!m_lpSession) {
00817               MAPI_TRACE0( "IterateStores called before session is open\n");
00818               m_lastError = -1;
00819               return( FALSE);
00820        }
00821 
00822 
00823        HRESULT              hr;
00824        
00825        /* -- Some Microsoft sample code just to see if things are working --- *//*
00826 
00827        ULONG         cbEIDStore;
00828        LPENTRYID     lpEIDStore;
00829 
00830     hr = HrMAPIFindDefaultMsgStore( m_lpSession, &cbEIDStore, &lpEIDStore);
00831     if (HR_FAILED(hr)) {
00832         MAPI_TRACE0( "Default message store not found\n");
00833               // MessageBox(NULL,"Message Store Not Found",NULL,MB_OK);
00834     }
00835        else {
00836               LPMDB  lpStore;
00837               MAPI_TRACE0( "Default Message store FOUND\n");
00838               hr = m_lpSession->OpenMsgStore( NULL, cbEIDStore,
00839                                   lpEIDStore, NULL,
00840                                   MDB_NO_MAIL | MDB_NO_DIALOG, &lpStore);
00841               if (HR_FAILED(hr)) {
00842                      MAPI_TRACE1( "Unable to open default message store: 0x%lx\n", hr);
00843               }
00844               else {
00845                      MAPI_TRACE0( "Default message store OPENED\n");
00846                      lpStore->Release();
00847               }
00848         }
00849      */
00850 
00851 
00852 
00853        LPMAPITABLE   lpTable;
00854 
00855        hr = m_lpSession->GetMsgStoresTable( 0, &lpTable);
00856        if (FAILED(hr)) {
00857               MAPI_TRACE0( "GetMsgStoresTable failed\n");
00858               m_lastError = hr;
00859               return( FALSE);
00860        }
00861 
00862 
00863        ULONG rowCount;
00864        hr = lpTable->GetRowCount( 0, &rowCount);
00865        MAPI_TRACE1( "MsgStores Table rowCount: %ld\n", rowCount);
00866 
00867        hr = lpTable->SetColumns( (LPSPropTagArray)&ptaTbl, 0);
00868        if (FAILED(hr)) {
00869               lpTable->Release();
00870               MAPI_TRACE2( "SetColumns failed: 0x%lx, %d\n", (long)hr, (int)hr);
00871               m_lastError = hr;
00872               return( FALSE);
00873        }
00874 
00875        hr = lpTable->SeekRow( BOOKMARK_BEGINNING, 0, NULL);
00876        if (FAILED(hr)) {
00877               lpTable->Release();
00878               MAPI_TRACE2( "SeekRow failed: 0x%lx, %d\n", (long)hr, (int)hr);
00879               m_lastError = hr;
00880               return( FALSE);
00881        }
00882 
00883        int                  cNumRows = 0;
00884        LPSRowSet     lpRow;
00885        BOOL          keepGoing = TRUE;
00886        BOOL          bResult = TRUE;
00887        do {
00888               
00889               lpRow = NULL;
00890               hr = lpTable->QueryRows( 1, 0, &lpRow);
00891 
00892         if(HR_FAILED(hr)) {
00893                      MAPI_TRACE2( "QueryRows failed: 0x%lx, %d\n", (long)hr, (int)hr);
00894             bResult = FALSE;
00895                      m_lastError = hr;
00896                      break;
00897               }
00898 
00899         if(lpRow) {
00900             cNumRows = lpRow->cRows;
00901 
00902                   if (cNumRows) {
00903                             LPCTSTR              lpStr = (LPCTSTR) lpRow->aRow[0].lpProps[itblPR_DISPLAY_NAME].Value.LPSZ;
00904                 LPENTRYID   lpEID = (LPENTRYID) lpRow->aRow[0].lpProps[itblPR_ENTRYID].Value.bin.lpb;
00905                 ULONG              cbEID = lpRow->aRow[0].lpProps[itblPR_ENTRYID].Value.bin.cb;
00906 
00907                             // In the future, GetStoreInfo needs to somehow return
00908                             // whether or not the store is from an IMAP server.
00909                             // Currently, GetStoreInfo opens the store and attempts
00910                             // to get the hierarchy tree.  If the tree is empty or
00911                             // does not exist, then szContents will be zero.  We'll
00912                             // assume that any store that doesn't have anything in
00913                             // it's hierarchy tree is not a store we want to import - 
00914                             // there would be nothing to import from anyway!
00915                             // Currently, this does exclude IMAP server accounts
00916                             // which is the desired behaviour.
00917 
00918                 int         strLen = strlen(lpStr);
00919                 PRUnichar * pwszStr = (PRUnichar *) nsMemory::Alloc((strLen + 1) * sizeof(WCHAR));
00920                 if (!pwszStr) {
00921                     // out of memory
00922                     FreeProws( lpRow);
00923                     lpTable->Release();
00924                     return FALSE;
00925                 }
00926                 ::MultiByteToWideChar(CP_ACP, 0, lpStr, strlen(lpStr) + 1, pwszStr, (strLen + 1) * sizeof(WCHAR));
00927                             CMapiFolder *pFolder = new CMapiFolder( pwszStr, cbEID, lpEID, 0, MAPI_STORE);
00928                 nsMemory::Free(pwszStr);
00929 
00930                             long szContents = 1;
00931                             GetStoreInfo( pFolder, &szContents);
00932 
00933                             MAPI_TRACE1( "    DisplayName: %s\n", lpStr);
00934                             if (szContents) {
00935                                    stores.AddItem( pFolder);
00936                             }
00937                             else {
00938                                    delete pFolder;
00939                                    MAPI_TRACE0( "    ^^^^^ Not added to store list\n");
00940                             }
00941 
00942                             keepGoing = TRUE;
00943                   }
00944                      FreeProws( lpRow);          
00945         }
00946 
00947        } while ( SUCCEEDED(hr) && cNumRows && lpRow && keepGoing);
00948 
00949        lpTable->Release();
00950 
00951        return( bResult);
00952 }
00953 
00954 void CMapiApi::GetStoreInfo( CMapiFolder *pFolder, long *pSzContents)
00955 {
00956        HRESULT       hr;
00957        LPMDB  lpMdb;
00958 
00959        if (pSzContents)
00960               *pSzContents = 0;
00961 
00962        if (!OpenStore( pFolder->GetCBEntryID(), pFolder->GetEntryID(), &lpMdb))
00963               return;
00964        
00965        LPSPropValue pVal;
00966        /*
00967        pVal = GetMapiProperty( lpMdb, PR_DISPLAY_NAME);
00968        ReportStringProp( "    Message store name:", pVal);
00969        pVal = GetMapiProperty( lpMdb, PR_MDB_PROVIDER);
00970        ReportUIDProp( "    Message store provider:", pVal);
00971        pVal = GetMapiProperty( lpMdb, PR_COMMENT);
00972        ReportStringProp( "    Message comment:", pVal);
00973        pVal = GetMapiProperty( lpMdb, PR_ACCESS_LEVEL);
00974        ReportLongProp( "    Message store Access Level:", pVal);
00975        pVal = GetMapiProperty( lpMdb, PR_STORE_SUPPORT_MASK);
00976        ReportLongProp( "    Message store support mask:", pVal);
00977        pVal = GetMapiProperty( lpMdb, PR_STORE_STATE);
00978        ReportLongProp( "    Message store state:", pVal);
00979        pVal = GetMapiProperty( lpMdb, PR_OBJECT_TYPE);
00980        ReportLongProp( "    Message store object type:", pVal);
00981        pVal = GetMapiProperty( lpMdb, PR_VALID_FOLDER_MASK);
00982        ReportLongProp( "    Message store valid folder mask:", pVal);
00983        
00984        pVal = GetMapiProperty( lpMdb, 0x8001001e);
00985        ReportStringProp( "    Message prop 0x8001001e:", pVal);
00986 
00987        // This key appears to be the OMI Account Manager account that corresponds
00988        // to this message store.  This is important for IMAP accounts
00989        // since we may not want to import messages from an IMAP store!
00990        // Seems silly if you ask me!
00991        // In order to test this, we'll need the registry key to look under to determine
00992        // if it contains the "IMAP Server" value, if it does then we are an
00993        // IMAP store, if not, then we are a non-IMAP store - which may always mean
00994        // a regular store that should be imported.
00995 
00996        pVal = GetMapiProperty( lpMdb, 0x80000003);
00997        ReportLongProp( "    Message prop 0x80000003:", pVal);
00998 
00999        // ListProperties( lpMdb);
01000        */
01001 
01002        pVal = GetMapiProperty( lpMdb, PR_IPM_SUBTREE_ENTRYID);
01003        if (pVal) {
01004               ULONG                cbEntry;
01005               LPENTRYID            pEntry;
01006               LPMAPIFOLDER  lpSubTree = NULL;
01007 
01008               if (GetEntryIdFromProp( pVal, cbEntry, pEntry)) {
01009                      // Open up the folder!
01010                      ULONG         ulObjType;
01011                      hr = lpMdb->OpenEntry( cbEntry, pEntry, NULL, 0, &ulObjType, (LPUNKNOWN *) &lpSubTree);
01012                      MAPIFreeBuffer( pEntry);
01013                      if (SUCCEEDED( hr) && lpSubTree) {
01014                             // Find out if there are any contents in the 
01015                             // tree.
01016                             LPMAPITABLE   lpTable;
01017                             hr = lpSubTree->GetHierarchyTable( 0, &lpTable);
01018                             if (HR_FAILED(hr)) {
01019                                    MAPI_TRACE2( "GetStoreInfo: GetHierarchyTable failed: 0x%lx, %d\n", (long)hr, (int)hr);
01020                             }
01021                             else {
01022                                    ULONG rowCount;
01023                                    hr = lpTable->GetRowCount( 0, &rowCount);
01024                                    lpTable->Release();
01025                                    if (SUCCEEDED( hr) && pSzContents)
01026                                           *pSzContents = (long) rowCount;
01027                             }
01028 
01029                             lpSubTree->Release();
01030                      }
01031               }
01032        }
01033 }
01034 
01035 
01036 void CMapiApi::ClearMessageStores( void)
01037 {
01038        if (m_pStores) {
01039               CMsgStore *   pStore;
01040               for (int i = 0; i < m_pStores->Count(); i++) {
01041                      pStore = (CMsgStore *) m_pStores->ElementAt( i);
01042                      delete pStore;
01043               }
01044               m_pStores->Clear();
01045        }
01046 }
01047 
01048 void CMapiApi::AddMessageStore( CMsgStore *pStore)
01049 {
01050        if (m_pStores)
01051               m_pStores->AppendElement( pStore);
01052 }
01053 
01054 CMsgStore *   CMapiApi::FindMessageStore( ULONG cbEid, LPENTRYID lpEid)
01055 {
01056        if (!m_lpSession) {
01057               MAPI_TRACE0( "FindMessageStore called before session is open\n");
01058               m_lastError = -1;
01059               return( NULL);
01060        }
01061 
01062        ULONG         result;
01063        HRESULT              hr;
01064        CMsgStore *   pStore;
01065        for (int i = 0; i < m_pStores->Count(); i++) {
01066               pStore = (CMsgStore *) m_pStores->ElementAt( i);
01067               hr = m_lpSession->CompareEntryIDs( cbEid, lpEid, pStore->GetCBEntryID(), pStore->GetLPEntryID(),
01068                                                                              0, &result);
01069               if (HR_FAILED( hr)) {
01070                      MAPI_TRACE2( "CompareEntryIDs failed: 0x%lx, %d\n", (long)hr, (int)hr);
01071                      m_lastError = hr;
01072                      return( NULL);
01073               }
01074               if ( result) {
01075                      return( pStore);
01076               }
01077        }
01078        
01079        pStore = new CMsgStore( cbEid, lpEid);
01080        AddMessageStore( pStore);
01081        return( pStore);
01082 }
01083 
01084 // --------------------------------------------------------------------
01085 // Utility stuff
01086 // --------------------------------------------------------------------
01087 
01088 LPSPropValue CMapiApi::GetMapiProperty( LPMAPIPROP pProp, ULONG tag)
01089 {
01090        if (!pProp)
01091               return( NULL);
01092 
01093        int    sz = CbNewSPropTagArray( 1);
01094        SPropTagArray *pTag = (SPropTagArray *) new char[sz];
01095        pTag->cValues = 1;
01096        pTag->aulPropTag[0] = tag;
01097        LPSPropValue  lpProp = NULL;
01098        ULONG  cValues = 0;
01099        HRESULT hr = pProp->GetProps( pTag, 0, &cValues, &lpProp);
01100        delete [] pTag;
01101        if (HR_FAILED( hr) || (cValues != 1)) {
01102               if (lpProp)
01103                      MAPIFreeBuffer( lpProp);
01104               return( NULL);
01105        }
01106        else {
01107               if (PROP_TYPE( lpProp->ulPropTag) == PT_ERROR) {
01108                      if (lpProp->Value.l == MAPI_E_NOT_FOUND) {
01109                             MAPIFreeBuffer( lpProp);
01110                             lpProp = NULL;
01111                      }
01112               }
01113        }
01114 
01115        return( lpProp);
01116 }
01117 
01118 BOOL CMapiApi::IsLargeProperty( LPSPropValue pVal)
01119 {
01120        if ((PROP_TYPE( pVal->ulPropTag) == PT_ERROR) && (pVal->Value.l == E_OUTOFMEMORY)) {
01121               return( TRUE);
01122        }
01123        return( FALSE);
01124 }
01125 
01126 BOOL CMapiApi::GetLargeStringProperty( LPMAPIPROP pProp, ULONG tag, nsCString& val)
01127 {
01128        LPSTREAM      lpStream;
01129        HRESULT              hr = pProp->OpenProperty( tag, &IID_IStream, 0, 0, (LPUNKNOWN *)&lpStream);
01130        if (HR_FAILED( hr))
01131               return( FALSE);
01132        STATSTG              st;
01133        BOOL bResult = TRUE;
01134        hr = lpStream->Stat( &st, STATFLAG_NONAME);
01135        if (HR_FAILED( hr))
01136               bResult = FALSE;
01137        else {
01138               if (!st.cbSize.QuadPart)
01139                      st.cbSize.QuadPart = 1;
01140               char *pVal = new char[ (int) st.cbSize.QuadPart + 1];
01141               // val.SetCapacity( (int) st.cbSize.QuadPart);
01142               if (pVal) {
01143                      ULONG  sz;
01144                      hr = lpStream->Read( pVal, (ULONG) st.cbSize.QuadPart, &sz);
01145                      if (HR_FAILED( hr)) {
01146                             bResult = FALSE;
01147                             *pVal = 0;
01148                             sz = 0;
01149                      }
01150                      else
01151                             pVal[(int) st.cbSize.QuadPart] = 0;
01152                      val = pVal;
01153                      delete [] pVal;
01154               }
01155               else
01156                      bResult = FALSE;
01157        }
01158        
01159        lpStream->Release();
01160 
01161        return( bResult);
01162 }
01163 
01164 BOOL CMapiApi::GetLargeStringProperty( LPMAPIPROP pProp, ULONG tag, nsString& val)
01165 {
01166        nsCString     result;
01167        if (GetLargeStringProperty( pProp, tag, result)) {
01168               CStrToUnicode( result.get(), val);
01169               return( TRUE);
01170        }
01171 
01172        return( FALSE);
01173 }
01174 // If the value is a string, get it...
01175 BOOL CMapiApi::GetEntryIdFromProp( LPSPropValue pVal, ULONG& cbEntryId, LPENTRYID& lpEntryId, BOOL delVal)
01176 {
01177        if (!pVal)
01178               return( FALSE);
01179        
01180        BOOL bResult = TRUE;
01181     switch( PROP_TYPE( pVal->ulPropTag)) {
01182               case PT_BINARY:
01183                      cbEntryId = pVal->Value.bin.cb;
01184                      MAPIAllocateBuffer( cbEntryId, (LPVOID *) &lpEntryId);
01185                      memcpy( lpEntryId, pVal->Value.bin.lpb, cbEntryId);
01186               break;
01187 
01188               default:
01189                      MAPI_TRACE0( "EntryId not in BINARY prop value\n");
01190                      bResult = FALSE;
01191         break;
01192     }
01193 
01194        if (pVal && delVal)
01195               MAPIFreeBuffer( pVal);
01196 
01197        return( bResult);
01198 }
01199 
01200 BOOL CMapiApi::GetStringFromProp( LPSPropValue pVal, nsCString& val, BOOL delVal)
01201 {
01202        BOOL bResult = TRUE;
01203        if ( pVal && (PROP_TYPE( pVal->ulPropTag) == PT_STRING8)) {
01204               val = pVal->Value.lpszA;
01205        }
01206        else if ( pVal && (PROP_TYPE( pVal->ulPropTag) == PT_UNICODE)) {
01207               val.AssignWithConversion((PRUnichar *) pVal->Value.lpszW);
01208        }
01209        else if (pVal && (PROP_TYPE( pVal->ulPropTag) == PT_NULL)) {
01210               val.Truncate();
01211        }
01212        else if (pVal && (PROP_TYPE( pVal->ulPropTag) == PT_ERROR)) {
01213               val.Truncate();
01214               bResult = FALSE;
01215        }
01216        else {
01217               if (pVal) {
01218                      MAPI_TRACE1( "GetStringFromProp: invalid value, expecting string - %d\n", (int) PROP_TYPE( pVal->ulPropTag));
01219               }
01220               else {
01221                      MAPI_TRACE0( "GetStringFromProp: invalid value, expecting string, got null pointer\n");
01222               }
01223               val.Truncate();
01224               bResult = FALSE;
01225        }
01226        if (pVal && delVal)
01227               MAPIFreeBuffer( pVal);
01228 
01229        return( bResult);
01230 }
01231 
01232 BOOL CMapiApi::GetStringFromProp( LPSPropValue pVal, nsString& val, BOOL delVal)
01233 {
01234        BOOL bResult = TRUE;
01235        if ( pVal && (PROP_TYPE( pVal->ulPropTag) == PT_STRING8)) {
01236               CStrToUnicode( (const char *)pVal->Value.lpszA, val);
01237        }
01238        else if ( pVal && (PROP_TYPE( pVal->ulPropTag) == PT_UNICODE)) {
01239               val = (PRUnichar *) pVal->Value.lpszW;
01240        }
01241        else if (pVal && (PROP_TYPE( pVal->ulPropTag) == PT_NULL)) {
01242               val.Truncate();
01243        }
01244        else if (pVal && (PROP_TYPE( pVal->ulPropTag) == PT_ERROR)) {
01245               val.Truncate();
01246               bResult = FALSE;
01247        }
01248        else {
01249               if (pVal) {
01250                      MAPI_TRACE1( "GetStringFromProp: invalid value, expecting string - %d\n", (int) PROP_TYPE( pVal->ulPropTag));
01251               }
01252               else {
01253                      MAPI_TRACE0( "GetStringFromProp: invalid value, expecting string, got null pointer\n");
01254               }
01255               val.Truncate();
01256               bResult = FALSE;
01257        }
01258        if (pVal && delVal)
01259               MAPIFreeBuffer( pVal);
01260 
01261        return( bResult);
01262 }
01263 
01264 
01265 LONG CMapiApi::GetLongFromProp( LPSPropValue pVal, BOOL delVal)
01266 {
01267        LONG val = 0;
01268        if ( pVal && (PROP_TYPE( pVal->ulPropTag) == PT_LONG)) {
01269               val = pVal->Value.l;
01270        }
01271        else if (pVal && (PROP_TYPE( pVal->ulPropTag) == PT_NULL)) {
01272               val = 0;
01273        }
01274        else if (pVal && (PROP_TYPE( pVal->ulPropTag) == PT_ERROR)) {
01275               val = 0;
01276               MAPI_TRACE0( "GetLongFromProp: Error retrieving property\n");
01277        }
01278        else {
01279               MAPI_TRACE0( "GetLongFromProp: invalid value, expecting long\n");
01280        }
01281        if (pVal && delVal)
01282               MAPIFreeBuffer( pVal);
01283 
01284        return( val);
01285 }
01286 
01287 
01288 void CMapiApi::ReportUIDProp( const char *pTag, LPSPropValue pVal)
01289 {
01290        if ( pVal && (PROP_TYPE( pVal->ulPropTag) == PT_BINARY)) {
01291               if (pVal->Value.bin.cb != 16) {
01292                      MAPI_TRACE1( "%s - INVALID, expecting 16 bytes of binary data for UID\n", pTag);
01293               }
01294               else {
01295                      nsIID  uid;
01296                      memcpy( &uid, pVal->Value.bin.lpb, 16);
01297                      char * pStr = uid.ToString();
01298                      if (pStr) {
01299                             MAPI_TRACE2( "%s %s\n", pTag, (const char *)pStr);
01300                             nsCRT::free( pStr);
01301                      }
01302               }
01303        }
01304        else if (pVal && (PROP_TYPE( pVal->ulPropTag) == PT_NULL)) {
01305               MAPI_TRACE1( "%s {NULL}\n", pTag);
01306        }
01307        else if (pVal && (PROP_TYPE( pVal->ulPropTag) == PT_ERROR)) {
01308               MAPI_TRACE1( "%s {Error retrieving property}\n", pTag);
01309        }
01310        else {
01311               MAPI_TRACE1( "%s invalid value, expecting binary\n", pTag);
01312        }
01313        if (pVal)
01314               MAPIFreeBuffer( pVal);
01315 }
01316 
01317 void CMapiApi::ReportLongProp( const char *pTag, LPSPropValue pVal)
01318 {
01319        if ( pVal && (PROP_TYPE( pVal->ulPropTag) == PT_LONG)) {
01320               nsCString     num;
01321               nsCString     num2;
01322 
01323               num.AppendInt( (PRInt32) pVal->Value.l);
01324               num2.AppendInt( (PRInt32) pVal->Value.l, 16);
01325               MAPI_TRACE3( "%s %s, 0x%s\n", pTag, num, num2);
01326        }
01327        else if (pVal && (PROP_TYPE( pVal->ulPropTag) == PT_NULL)) {
01328               MAPI_TRACE1( "%s {NULL}\n", pTag);
01329        }
01330        else if (pVal && (PROP_TYPE( pVal->ulPropTag) == PT_ERROR)) {
01331               MAPI_TRACE1( "%s {Error retrieving property}\n", pTag);
01332        }
01333        else if (pVal && (PROP_TYPE( pVal->ulPropTag) == PT_ERROR)) {
01334               MAPI_TRACE1( "%s {Error retrieving property}\n", pTag);
01335        }
01336        else {
01337               MAPI_TRACE1( "%s invalid value, expecting long\n", pTag);
01338        }
01339        if (pVal)
01340               MAPIFreeBuffer( pVal);
01341 }
01342 
01343 void CMapiApi::ReportStringProp( const char *pTag, LPSPropValue pVal)
01344 {
01345        if ( pVal && (PROP_TYPE( pVal->ulPropTag) == PT_TSTRING)) {
01346               nsCString val((LPCTSTR) (pVal->Value.LPSZ));
01347               MAPI_TRACE2( "%s %s\n", pTag, (const char *)val);
01348        }
01349        else if (pVal && (PROP_TYPE( pVal->ulPropTag) == PT_NULL)) {
01350               MAPI_TRACE1( "%s {NULL}\n", pTag);
01351        }
01352        else if (pVal && (PROP_TYPE( pVal->ulPropTag) == PT_ERROR)) {
01353               MAPI_TRACE1( "%s {Error retrieving property}\n", pTag);
01354        }
01355        else {
01356               MAPI_TRACE1( "%s invalid value, expecting string\n", pTag);
01357        }
01358        if (pVal)
01359               MAPIFreeBuffer( pVal);
01360 }
01361 
01362 void CMapiApi::GetPropTagName( ULONG tag, nsCString& s)
01363 {
01364        char numStr[256];
01365        PR_snprintf( numStr, 256, "0x%lx, %ld", tag, tag);
01366        s = numStr;
01367        switch( tag) {
01368 #include "mapitagstrs.cpp"
01369        }
01370        s += ", data: ";
01371        switch( PROP_TYPE( tag)) {
01372               case PT_UNSPECIFIED: s += "PT_UNSPECIFIED"; break;
01373               case PT_NULL: s += "PT_NULL"; break;
01374               case PT_I2: s += "PT_I2"; break;
01375               case PT_LONG: s += "PT_LONG"; break;
01376               case PT_R4: s += "PT_R4"; break;
01377               case PT_DOUBLE: s += "PT_DOUBLE"; break;
01378               case PT_CURRENCY: s += "PT_CURRENCY"; break;
01379               case PT_APPTIME: s += "PT_APPTIME"; break;
01380               case PT_ERROR: s += "PT_ERROR"; break;
01381               case PT_BOOLEAN: s += "PT_BOOLEAN"; break;
01382               case PT_OBJECT: s += "PT_OBJECT"; break;
01383               case PT_I8: s += "PT_I8"; break;
01384               case PT_STRING8: s += "PT_STRING8"; break;
01385               case PT_UNICODE: s += "PT_UNICODE"; break;
01386               case PT_SYSTIME: s += "PT_SYSTIME"; break;
01387               case PT_CLSID: s += "PT_CLSID"; break;
01388               case PT_BINARY: s += "PT_BINARY"; break;
01389               case PT_MV_I2: s += "PT_MV_I2"; break;
01390               case PT_MV_LONG: s += "PT_MV_LONG"; break;
01391               case PT_MV_R4: s += "PT_MV_R4"; break;
01392               case PT_MV_DOUBLE: s += "PT_MV_DOUBLE"; break;
01393               case PT_MV_CURRENCY: s += "PT_MV_CURRENCY"; break;
01394               case PT_MV_APPTIME: s += "PT_MV_APPTIME"; break;
01395               case PT_MV_SYSTIME: s += "PT_MV_SYSTIME"; break;
01396               case PT_MV_STRING8: s += "PT_MV_STRING8"; break;
01397               case PT_MV_BINARY: s += "PT_MV_BINARY"; break;
01398               case PT_MV_UNICODE: s += "PT_MV_UNICODE"; break;
01399               case PT_MV_CLSID: s += "PT_MV_CLSID"; break;
01400               case PT_MV_I8: s += "PT_MV_I8"; break;
01401               default:
01402                      s += "Unknown";
01403        }
01404 }
01405 
01406 void ReplaceEolChars( nsCString& s)
01407 {
01408        int                         idx;
01409        nsCString            t;
01410        nsCString            rt;
01411 
01412        while ((idx = s.Find( "\x0D")) != -1) {
01413               s.Left( t, idx);
01414               t += "\\n";
01415               s.Right( rt, s.Length() - idx - 1);
01416               t += rt;
01417               s = t;
01418        }
01419        while ((idx = s.Find( "\x0A")) != -1) {
01420               s.Left( t, idx);
01421               t += "\\r";
01422               s.Right( rt, s.Length() - idx - 1);
01423               t += rt;
01424               s = t;
01425        }
01426 }
01427 
01428 void CMapiApi::ListPropertyValue( LPSPropValue pVal, nsCString& s)
01429 {
01430        nsCString            strVal;
01431        char                 nBuff[64];
01432        nsCString            t;
01433 
01434        s += "value: ";
01435        switch (PROP_TYPE( pVal->ulPropTag)) {
01436               case PT_STRING8:
01437                      GetStringFromProp( pVal, strVal, FALSE);
01438                      if (strVal.Length() > 60) {
01439                             strVal.Left( t, 60);
01440                             strVal = t;
01441                             strVal += "...";
01442                      }
01443                      ReplaceEolChars( strVal);
01444                      s += strVal;
01445               break;
01446               case PT_LONG:
01447                      s.AppendInt( (PRInt32) pVal->Value.l);
01448                      s += ", 0x";
01449                      s.AppendInt( (PRInt32) pVal->Value.l, 16);
01450                      s += nBuff;
01451               break;
01452               case PT_BOOLEAN:
01453                      if (pVal->Value.b)
01454                             s += "True";
01455                      else
01456                             s += "False";
01457               break;
01458               case PT_NULL:
01459                      s += "--NULL--";
01460               break;
01461               case PT_SYSTIME: {
01462                      /*
01463                      COleDateTime  tm( pVal->Value.ft);
01464                      s += tm.Format();
01465                      */
01466                      s += "-- Figure out how to format time in mozilla, PT_SYSTIME --";
01467               }
01468               break;
01469               default:
01470                s += "?";
01471        }
01472 }
01473 
01474 
01475 
01476 // -------------------------------------------------------------------
01477 // Folder list stuff
01478 // -------------------------------------------------------------------
01479 CMapiFolderList::CMapiFolderList()
01480 {
01481 }
01482 
01483 CMapiFolderList::~CMapiFolderList()
01484 {
01485        ClearAll();
01486 }
01487 
01488 void CMapiFolderList::AddItem( CMapiFolder *pFolder)
01489 {
01490        EnsureUniqueName( pFolder);
01491        GenerateFilePath( pFolder);
01492        m_array.AppendElement( pFolder);
01493 }
01494 
01495 void CMapiFolderList::ChangeName( nsString& name)
01496 {
01497        if (name.IsEmpty()) {
01498               name.AssignLiteral("1");
01499               return;
01500        }
01501        PRUnichar lastC = name.Last();
01502        if ((lastC >= '0') && (lastC <= '9')) {
01503               lastC++;
01504               if (lastC > '9') {
01505                      lastC = '1';
01506                      name.SetCharAt( lastC, name.Length() - 1);
01507                      name.AppendLiteral("0");
01508               }
01509               else {
01510                      name.SetCharAt( lastC, name.Length() - 1);
01511               }
01512        }
01513        else {
01514               name.AppendLiteral(" 2");
01515        }
01516 }
01517 
01518 void CMapiFolderList::EnsureUniqueName( CMapiFolder *pFolder)
01519 {
01520        // For everybody in the array before me with the SAME
01521        // depth, my name must be unique
01522        CMapiFolder * pCurrent;
01523        int                         i;
01524        BOOL                 done;
01525        nsString             name;
01526        nsString             cName;
01527 
01528        pFolder->GetDisplayName( name);
01529        do {
01530               done = TRUE;
01531               i = m_array.Count() - 1;
01532               while (i >= 0) {
01533                      pCurrent = (CMapiFolder *)GetAt(i);
01534                      if (pCurrent->GetDepth() == pFolder->GetDepth()) {
01535                             pCurrent->GetDisplayName(cName);
01536                             if (cName.Equals(name, nsCaseInsensitiveStringComparator())) {
01537                                    ChangeName(name);
01538                                    pFolder->SetDisplayName(name.get());
01539                                    done = FALSE;
01540                                    break;
01541                             }
01542                      }
01543                      else if (pCurrent->GetDepth() < pFolder->GetDepth())
01544                             break;
01545                      i--;
01546               }
01547        } while (!done);
01548 }
01549 
01550 void CMapiFolderList::GenerateFilePath( CMapiFolder *pFolder)
01551 {
01552        // A file path, includes all of my parent's path, plus mine
01553        nsString             name;
01554        nsString             path;
01555        if (!pFolder->GetDepth()) {
01556               pFolder->GetDisplayName( name);
01557               pFolder->SetFilePath(name.get());
01558               return;
01559        }
01560 
01561        CMapiFolder * pCurrent;
01562        int                         i = m_array.Count() - 1;
01563        while (i >= 0) {
01564               pCurrent = (CMapiFolder *) GetAt( i);
01565               if (pCurrent->GetDepth() == (pFolder->GetDepth() - 1)) {
01566                      pCurrent->GetFilePath( path);
01567                      path.AppendLiteral(".sbd\\");
01568                      pFolder->GetDisplayName( name);
01569                      path += name;
01570                      pFolder->SetFilePath(path.get());
01571                      return;
01572               }
01573               i--;
01574        }
01575        pFolder->GetDisplayName( name);
01576        pFolder->SetFilePath(name.get());
01577 }
01578 
01579 void CMapiFolderList::ClearAll( void)
01580 {
01581        CMapiFolder *pFolder;
01582        for (int i = 0; i < m_array.Count(); i++) {
01583               pFolder = (CMapiFolder *)GetAt( i);
01584               delete pFolder;
01585        }
01586        m_array.Clear();
01587 }
01588 
01589 void CMapiFolderList::DumpList( void)
01590 {
01591        CMapiFolder *pFolder;
01592        nsString      str;
01593        int                  depth;
01594        char          prefix[256];
01595 
01596        MAPI_TRACE0( "Folder List ---------------------------------\n");
01597        for (int i = 0; i < m_array.Count(); i++) {
01598               pFolder = (CMapiFolder *)GetAt( i);
01599               depth = pFolder->GetDepth();
01600               pFolder->GetDisplayName( str);
01601               depth *= 2;
01602               if (depth > 255)
01603                      depth = 255;
01604               memset( prefix, ' ', depth);
01605               prefix[depth] = 0;
01606 #ifdef MAPI_DEBUG
01607         char *ansiStr = ToNewCString(str);
01608               MAPI_TRACE2( "%s%s: ", prefix, ansiStr);
01609               nsCRT::free(ansiStr);
01610 #endif
01611               pFolder->GetFilePath( str);
01612 #ifdef MAPI_DEBUG
01613         ansiStr = ToNewCString(str);
01614               MAPI_TRACE2( "depth=%d, filePath=%s\n", pFolder->GetDepth(), ansiStr);
01615               nsCRT::free(ansiStr);
01616 #endif
01617        }
01618        MAPI_TRACE0( "---------------------------------------------\n");
01619 }
01620 
01621 
01622 CMapiFolder::CMapiFolder()
01623 {
01624        m_objectType = MAPI_FOLDER;
01625        m_cbEid = 0;
01626        m_lpEid = NULL;
01627        m_depth = 0;
01628        m_doImport = TRUE;
01629 }
01630 
01631 CMapiFolder::CMapiFolder( const PRUnichar *pDisplayName, ULONG cbEid, LPENTRYID lpEid, int depth, LONG oType)
01632 {
01633        m_cbEid = 0;
01634        m_lpEid = NULL;
01635        SetDisplayName( pDisplayName);
01636        SetEntryID( cbEid, lpEid);
01637        SetDepth( depth);
01638        SetObjectType( oType);
01639        SetDoImport( TRUE);
01640 }
01641 
01642 CMapiFolder::CMapiFolder( const CMapiFolder *pCopyFrom)
01643 {
01644        m_lpEid = NULL;
01645        m_cbEid = 0;
01646        SetDoImport( pCopyFrom->GetDoImport());
01647        SetDisplayName(pCopyFrom->m_displayName.get());
01648        SetObjectType( pCopyFrom->GetObjectType());
01649        SetEntryID( pCopyFrom->GetCBEntryID(), pCopyFrom->GetEntryID());
01650        SetDepth( pCopyFrom->GetDepth());
01651        SetFilePath(pCopyFrom->m_mailFilePath.get());
01652 }
01653 
01654 CMapiFolder::~CMapiFolder()
01655 {
01656        if (m_lpEid)
01657               delete m_lpEid;
01658 }
01659 
01660 void CMapiFolder::SetEntryID( ULONG cbEid, LPENTRYID lpEid)
01661 {
01662        if (m_lpEid)
01663               delete m_lpEid;
01664        m_lpEid = NULL;
01665        m_cbEid = cbEid;
01666        if (cbEid) {
01667               m_lpEid = new BYTE[cbEid];
01668               memcpy( m_lpEid, lpEid, cbEid);
01669        }
01670 }
01671 
01672 // ---------------------------------------------------------------------
01673 // Message store stuff
01674 // ---------------------------------------------------------------------
01675 
01676 
01677 CMsgStore::CMsgStore( ULONG cbEid, LPENTRYID lpEid)
01678 {
01679        m_lpEid = NULL;
01680        m_lpMdb = NULL;
01681        SetEntryID( cbEid, lpEid);
01682 }
01683 
01684 CMsgStore::~CMsgStore()
01685 {
01686        if (m_lpEid)
01687               delete m_lpEid;
01688 
01689        if (m_lpMdb) {
01690               ULONG flags = LOGOFF_NO_WAIT;
01691               HRESULT hr = m_lpMdb->StoreLogoff( &flags);
01692               m_lpMdb->Release();
01693               m_lpMdb = NULL;
01694        }
01695 }
01696 
01697 void CMsgStore::SetEntryID( ULONG cbEid, LPENTRYID lpEid)
01698 {
01699        HRESULT              hr;
01700 
01701        if (m_lpEid)
01702               delete m_lpEid;
01703 
01704        m_lpEid = NULL;
01705        if (cbEid) {
01706               m_lpEid = new BYTE[cbEid];
01707               memcpy( m_lpEid, lpEid, cbEid);
01708        }
01709        m_cbEid = cbEid;
01710 
01711        if (m_lpMdb) {
01712               ULONG flags = LOGOFF_NO_WAIT;
01713               hr = m_lpMdb->StoreLogoff( &flags);
01714               m_lpMdb->Release();
01715               m_lpMdb = NULL;
01716        }
01717 }
01718 
01719 BOOL CMsgStore::Open( LPMAPISESSION pSession, LPMDB *ppMdb)
01720 {
01721        if ( m_lpMdb) {
01722               if (ppMdb)
01723                      *ppMdb = m_lpMdb;
01724               return( TRUE);
01725        }
01726 
01727        BOOL bResult = TRUE;
01728        HRESULT hr = pSession->OpenMsgStore( NULL, m_cbEid, (LPENTRYID)m_lpEid, NULL, MDB_NO_MAIL, &m_lpMdb);    // MDB pointer
01729        if (HR_FAILED( hr)) {
01730               m_lpMdb = NULL;
01731               MAPI_TRACE2( "OpenMsgStore failed: 0x%lx, %d\n", (long)hr, (int)hr);
01732               bResult = FALSE;
01733        }
01734 
01735        if (ppMdb)
01736               *ppMdb = m_lpMdb;
01737        return( bResult);
01738 }
01739 
01740 
01741 
01742 // ------------------------------------------------------------
01743 // Contents Iterator
01744 // -----------------------------------------------------------
01745 
01746 
01747 CMapiFolderContents::CMapiFolderContents( LPMDB lpMdb, ULONG cbEid, LPENTRYID lpEid)
01748 {
01749        m_lpMdb = lpMdb;
01750        m_fCbEid = cbEid;
01751        m_fLpEid = new BYTE[cbEid];
01752        memcpy( m_fLpEid, lpEid, cbEid);
01753        m_count = 0;
01754        m_iterCount = 0;
01755        m_failure = FALSE;
01756        m_lastError = 0;
01757        m_lpFolder = NULL;
01758        m_lpTable = NULL;
01759        m_lastLpEid = NULL;
01760        m_lastCbEid = 0;
01761 }
01762 
01763 CMapiFolderContents::~CMapiFolderContents()
01764 {
01765        if (m_lastLpEid)
01766               delete m_lastLpEid;
01767        delete m_fLpEid;
01768        if (m_lpTable)
01769               m_lpTable->Release();
01770        if (m_lpFolder)
01771               m_lpFolder->Release();
01772 }
01773 
01774 
01775 BOOL CMapiFolderContents::SetUpIter( void)
01776 {
01777        // First, open up the MAPIFOLDER object
01778        ULONG         ulObjType;
01779        HRESULT              hr;
01780        hr = m_lpMdb->OpenEntry( m_fCbEid, (LPENTRYID) m_fLpEid, NULL, 0, &ulObjType, (LPUNKNOWN *) &m_lpFolder);
01781 
01782        if (FAILED(hr) || !m_lpFolder) {
01783               m_lpFolder = NULL;
01784               m_lastError = hr;
01785               MAPI_TRACE2( "CMapiFolderContents OpenEntry failed: 0x%lx, %d\n", (long)hr, (int)hr);
01786               return( FALSE);
01787        }
01788 
01789        if (ulObjType != MAPI_FOLDER) {
01790               m_lastError = -1;
01791               MAPI_TRACE0( "CMapiFolderContents - bad object type, not a folder.\n");
01792               return( FALSE);
01793        }
01794 
01795 
01796        hr = m_lpFolder->GetContentsTable( 0, &m_lpTable);
01797        if (FAILED(hr) || !m_lpTable) {
01798               m_lastError = hr;
01799               m_lpTable = NULL;
01800               MAPI_TRACE2( "CMapiFolderContents - GetContentsTable failed: 0x%lx, %d\n", (long)hr, (int)hr);
01801               return( FALSE);
01802        }
01803 
01804        hr = m_lpTable->GetRowCount( 0, &m_count);
01805        if (FAILED(hr)) {
01806               m_lastError = hr;
01807               MAPI_TRACE0( "CMapiFolderContents - GetRowCount failed\n");
01808               return( FALSE);
01809        }
01810 
01811        hr = m_lpTable->SetColumns( (LPSPropTagArray)&ptaEid, 0);
01812        if (FAILED(hr)) {
01813               m_lastError = hr;
01814               MAPI_TRACE2( "CMapiFolderContents - SetColumns failed: 0x%lx, %d\n", (long)hr, (int)hr);
01815               return( FALSE);
01816        }
01817 
01818        hr = m_lpTable->SeekRow( BOOKMARK_BEGINNING, 0, NULL);
01819        if (FAILED(hr)) {
01820               m_lastError = hr;
01821               MAPI_TRACE2( "CMapiFolderContents - SeekRow failed: 0x%lx, %d\n", (long)hr, (int)hr);
01822               return( FALSE);
01823        }
01824        
01825        return( TRUE);
01826 }
01827 
01828 
01829 BOOL CMapiFolderContents::GetNext( ULONG *pcbEid, LPENTRYID *ppEid, ULONG *poType, BOOL *pDone)
01830 {
01831        *pDone = FALSE;
01832        if (m_failure)
01833               return( FALSE);
01834        if (!m_lpFolder) {
01835               if (!SetUpIter()) {
01836                      m_failure = TRUE;
01837                      return( FALSE);
01838               }
01839               if (!m_count) {
01840                      *pDone = TRUE;
01841                      return( TRUE);
01842               }
01843        }
01844 
01845        int                  cNumRows = 0;        
01846        LPSRowSet     lpRow = NULL;
01847        HRESULT              hr = m_lpTable->QueryRows( 1, 0, &lpRow);
01848 
01849        if(HR_FAILED( hr)) {
01850               m_lastError = hr;
01851               m_failure = TRUE;
01852               MAPI_TRACE2( "CMapiFolderContents - QueryRows failed: 0x%lx, %d\n", (long)hr, (int)hr);
01853               return( FALSE);
01854        }
01855 
01856        if(lpRow) {
01857               cNumRows = lpRow->cRows;
01858               if (cNumRows) {
01859             LPENTRYID       lpEID = (LPENTRYID) lpRow->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.lpb;
01860             ULONG           cbEID = lpRow->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.cb;
01861                      ULONG         oType = lpRow->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.ul;
01862                      
01863                      if (m_lastCbEid != cbEID) {
01864                             if (m_lastLpEid)
01865                                    delete m_lastLpEid;
01866                             m_lastLpEid = new BYTE[cbEID];
01867                             m_lastCbEid = cbEID;
01868                      }
01869                      memcpy( m_lastLpEid, lpEID, cbEID);
01870 
01871                      *ppEid = (LPENTRYID) m_lastLpEid;
01872                      *pcbEid = cbEID;
01873                      *poType = oType;
01874               }
01875               else
01876                      *pDone = TRUE;
01877               CMapiApi::FreeProws( lpRow);              
01878     }
01879        else
01880               *pDone = TRUE;
01881 
01882        return( TRUE);
01883 }
01884