void CMapiFolderList::DumpList( void)
{
  CMapiFolder *pFolder;
  nsString  str;
  int      depth;
  char    prefix[256];

  MAPI_TRACE0( "Folder List ---------------------------------\n");
  for (int i = 0; i < m_array.Count(); i++) {
    pFolder = (CMapiFolder *)GetAt( i);
    depth = pFolder->GetDepth();
    pFolder->GetDisplayName( str);
    depth *= 2;
    if (depth > 255)
      depth = 255;
    memset( prefix, ' ', depth);
    prefix[depth] = 0;
#ifdef MAPI_DEBUG
        char *ansiStr = ToNewCString(str);
    MAPI_TRACE2( "%s%s: ", prefix, ansiStr);
    NS_Free(ansiStr);
#endif
    pFolder->GetFilePath( str);
#ifdef MAPI_DEBUG
        ansiStr = ToNewCString(str);
    MAPI_TRACE2( "depth=%d, filePath=%s\n", pFolder->GetDepth(), ansiStr);
    NS_Free(ansiStr);
#endif
  }
  MAPI_TRACE0( "---------------------------------------------\n");
}
BOOL CMapiFolderContents::SetUpIter( void)
{
  // First, open up the MAPIFOLDER object
  ULONG    ulObjType;
  HRESULT    hr;
  hr = m_lpMdb->OpenEntry( m_fCbEid, (LPENTRYID) m_fLpEid, NULL, 0, &ulObjType, (LPUNKNOWN *) &m_lpFolder);

  if (FAILED(hr) || !m_lpFolder) {
    m_lpFolder = NULL;
    m_lastError = hr;
    MAPI_TRACE2( "CMapiFolderContents OpenEntry failed: 0x%lx, %d\n", (long)hr, (int)hr);
    return( FALSE);
  }

  if (ulObjType != MAPI_FOLDER) {
    m_lastError = -1;
    MAPI_TRACE0( "CMapiFolderContents - bad object type, not a folder.\n");
    return( FALSE);
  }


  hr = m_lpFolder->GetContentsTable( 0, &m_lpTable);
  if (FAILED(hr) || !m_lpTable) {
    m_lastError = hr;
    m_lpTable = NULL;
    MAPI_TRACE2( "CMapiFolderContents - GetContentsTable failed: 0x%lx, %d\n", (long)hr, (int)hr);
    return( FALSE);
  }

  hr = m_lpTable->GetRowCount( 0, &m_count);
  if (FAILED(hr)) {
    m_lastError = hr;
    MAPI_TRACE0( "CMapiFolderContents - GetRowCount failed\n");
    return( FALSE);
  }

  hr = m_lpTable->SetColumns( (LPSPropTagArray)&ptaEid, 0);
  if (FAILED(hr)) {
    m_lastError = hr;
    MAPI_TRACE2( "CMapiFolderContents - SetColumns failed: 0x%lx, %d\n", (long)hr, (int)hr);
    return( FALSE);
  }

  hr = m_lpTable->SeekRow( BOOKMARK_BEGINNING, 0, NULL);
  if (FAILED(hr)) {
    m_lastError = hr;
    MAPI_TRACE2( "CMapiFolderContents - SeekRow failed: 0x%lx, %d\n", (long)hr, (int)hr);
    return( FALSE);
  }

  return( TRUE);
}
Exemple #3
0
BOOL CMapiMessage::IterateAttachTable( void)
{
  LPMAPITABLE lpTable = m_pAttachTable;
  ULONG rowCount;
  HRESULT hr = lpTable->GetRowCount( 0, &rowCount);
  if (!rowCount) {
    return( TRUE);
  }

  hr = lpTable->SetColumns( (LPSPropTagArray)&ptaEid, 0);
  if (FAILED(hr)) {
    MAPI_TRACE2( "SetColumns for attachment table failed: 0x%lx, %d\r\n", (long)hr, (int)hr);
    return( FALSE);
  }

  hr = lpTable->SeekRow( BOOKMARK_BEGINNING, 0, NULL);
  if (FAILED(hr)) {
    MAPI_TRACE2( "SeekRow for attachment table failed: 0x%lx, %d\r\n", (long)hr, (int)hr);
    return( FALSE);
  }

  int cNumRows = 0;
  LPSRowSet lpRow;
  BOOL bResult = TRUE;
  do {

    lpRow = NULL;
    hr = lpTable->QueryRows( 1, 0, &lpRow);

    if(HR_FAILED(hr)) {
      MAPI_TRACE2( "QueryRows for attachment table failed: 0x%lx, %d\n", (long)hr, (int)hr);
      bResult = FALSE;
      break;
    }

    if (lpRow) {
      cNumRows = lpRow->cRows;

      if (cNumRows) {
        DWORD aNum = lpRow->aRow[0].lpProps[ieidPR_ATTACH_NUM].Value.ul;
        m_attachNums.AppendElement(aNum);
        MAPI_TRACE1( "\t\t****Attachment found - #%d\r\n", (int)aNum);
      }
      CMapiApi::FreeProws( lpRow);
    }

  } while ( SUCCEEDED(hr) && cNumRows && lpRow);

  return( bResult);
}
CMsgStore *  CMapiApi::FindMessageStore( ULONG cbEid, LPENTRYID lpEid)
{
  if (!m_lpSession) {
    MAPI_TRACE0( "FindMessageStore called before session is open\n");
    m_lastError = -1;
    return( NULL);
  }

  ULONG    result;
  HRESULT    hr;
  CMsgStore *  pStore;
  for (int i = 0; i < m_pStores->Count(); i++) {
    pStore = (CMsgStore *) m_pStores->ElementAt( i);
    hr = m_lpSession->CompareEntryIDs( cbEid, lpEid, pStore->GetCBEntryID(), pStore->GetLPEntryID(),
                      0, &result);
    if (HR_FAILED( hr)) {
      MAPI_TRACE2( "CompareEntryIDs failed: 0x%lx, %d\n", (long)hr, (int)hr);
      m_lastError = hr;
      return( NULL);
    }
    if ( result) {
      return( pStore);
    }
  }

  pStore = new CMsgStore( cbEid, lpEid);
  AddMessageStore( pStore);
  return( pStore);
}
CMapiApi::~CMapiApi()
{
  m_clients--;
  if (!m_clients) {
    HRESULT  hr;

    ClearMessageStores();
    delete m_pStores;
    m_pStores = NULL;

    m_lpMdb = NULL;

    if (m_lpSession) {
      hr = m_lpSession->Logoff( NULL, 0, 0);
      if (FAILED(hr)) {
        MAPI_TRACE2( "Logoff failed: 0x%lx, %d\n", (long)hr, (int)hr);
      }
      m_lpSession->Release();
      m_lpSession = NULL;
    }

    if (m_initialized) {
      MAPIUninitialize();
      m_initialized = FALSE;
    }

    UnloadMapi();

    if (m_pUniBuff)
      delete [] m_pUniBuff;
    m_pUniBuff = NULL;
    m_uniBuffLen = 0;
  }
}
void CMapiApi::ListProperties( LPMAPIPROP lpProp, BOOL getValues)
{
  LPSPropTagArray    pArray;
  HRESULT        hr = lpProp->GetPropList( 0, &pArray);
  if (FAILED(hr)) {
    MAPI_TRACE0( "    Unable to retrieve property list\n");
    return;
  }
  ULONG count = 0;
  LPMAPINAMEID FAR * lppPropNames;
  SPropTagArray    tagArray;
  LPSPropTagArray lpTagArray = &tagArray;
  tagArray.cValues = (ULONG)1;
  nsCString  desc;
  for (ULONG i = 0; i < pArray->cValues; i++) {
    GetPropTagName( pArray->aulPropTag[i], desc);
    if (getValues) {
      tagArray.aulPropTag[0] = pArray->aulPropTag[i];
      hr = lpProp->GetNamesFromIDs(&lpTagArray, nsnull, 0, &count, &lppPropNames);
      if (hr == S_OK)
        MAPIFreeBuffer(lppPropNames);

      LPSPropValue pVal = GetMapiProperty( lpProp, pArray->aulPropTag[i]);
      if (pVal) {
        desc += ", ";
        ListPropertyValue( pVal, desc);
        MAPIFreeBuffer( pVal);
      }
    }
    MAPI_TRACE2( "    Tag #%d: %s\n", (int)i, (const char *)desc);
  }

  MAPIFreeBuffer( pArray);
}
void CMapiApi::ReportUIDProp( const char *pTag, LPSPropValue pVal)
{
  if ( pVal && (PROP_TYPE( pVal->ulPropTag) == PT_BINARY)) {
    if (pVal->Value.bin.cb != 16) {
      MAPI_TRACE1( "%s - INVALID, expecting 16 bytes of binary data for UID\n", pTag);
    }
    else {
      nsIID  uid;
      memcpy( &uid, pVal->Value.bin.lpb, 16);
      char *  pStr = uid.ToString();
      if (pStr) {
        MAPI_TRACE2( "%s %s\n", pTag, (const char *)pStr);
        NS_Free( pStr);
      }
    }
  }
  else if (pVal && (PROP_TYPE( pVal->ulPropTag) == PT_NULL)) {
    MAPI_TRACE1( "%s {NULL}\n", pTag);
  }
  else if (pVal && (PROP_TYPE( pVal->ulPropTag) == PT_ERROR)) {
    MAPI_TRACE1( "%s {Error retrieving property}\n", pTag);
  }
  else {
    MAPI_TRACE1( "%s invalid value, expecting binary\n", pTag);
  }
  if (pVal)
    MAPIFreeBuffer( pVal);
}
BOOL CMapiApi::LogOn( void)
{
  if (!m_initialized) {
    MAPI_TRACE0( "Tried to LogOn before initializing MAPI\n");
    return( FALSE);
  }

  if (m_lpSession)
    return( TRUE);

  HRESULT hr;

  hr = MAPILogonEx(  0, // might need to be passed in HWND
            NULL, // profile name, 64 char max (LPTSTR)
            NULL, // profile password, 64 char max (LPTSTR)
            // MAPI_NEW_SESSION | MAPI_NO_MAIL | MAPI_LOGON_UI | MAPI_EXPLICIT_PROFILE,
            // MAPI_NEW_SESSION | MAPI_NO_MAIL | MAPI_LOGON_UI,
            // MAPI_NO_MAIL | MAPI_LOGON_UI,
            MAPI_NO_MAIL | MAPI_USE_DEFAULT | MAPI_EXTENDED | MAPI_NEW_SESSION,
            &m_lpSession);

  if (FAILED(hr)) {
    m_lpSession = NULL;
    MAPI_TRACE2( "LogOn failed: 0x%lx, %d\n", (long)hr, (int)hr);
    return( FALSE);
  }

  MAPI_TRACE0( "MAPI Logged on\n");
  return( TRUE);
}
BOOL CMapiFolderContents::GetNext( ULONG *pcbEid, LPENTRYID *ppEid, ULONG *poType, BOOL *pDone)
{
  *pDone = FALSE;
  if (m_failure)
    return( FALSE);
  if (!m_lpFolder) {
    if (!SetUpIter()) {
      m_failure = TRUE;
      return( FALSE);
    }
    if (!m_count) {
      *pDone = TRUE;
      return( TRUE);
    }
  }

  int      cNumRows = 0;
  LPSRowSet  lpRow = NULL;
  HRESULT    hr = m_lpTable->QueryRows( 1, 0, &lpRow);

  if(HR_FAILED( hr)) {
    m_lastError = hr;
    m_failure = TRUE;
    MAPI_TRACE2( "CMapiFolderContents - QueryRows failed: 0x%lx, %d\n", (long)hr, (int)hr);
    return( FALSE);
  }

  if(lpRow) {
    cNumRows = lpRow->cRows;
    if (cNumRows) {
            LPENTRYID  lpEID = (LPENTRYID) lpRow->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.lpb;
            ULONG    cbEID = lpRow->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.cb;
      ULONG    oType = lpRow->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.ul;

      if (m_lastCbEid != cbEID) {
        if (m_lastLpEid)
          delete m_lastLpEid;
        m_lastLpEid = new BYTE[cbEID];
        m_lastCbEid = cbEID;
      }
      memcpy( m_lastLpEid, lpEID, cbEID);

      *ppEid = (LPENTRYID) m_lastLpEid;
      *pcbEid = cbEID;
      *poType = oType;
    }
    else
      *pDone = TRUE;
    CMapiApi::FreeProws( lpRow);
    }
  else
    *pDone = TRUE;

  return( TRUE);
}
BOOL CMapiApi::OpenMdbEntry( LPMDB lpMdb, ULONG cbEntry, LPENTRYID pEntryId, LPUNKNOWN *ppOpen)
{
  ULONG    ulObjType;
  HRESULT    hr;
  hr = m_lpSession->OpenEntry(cbEntry,
              pEntryId,
              NULL,
              0,
              &ulObjType,
              (LPUNKNOWN *) ppOpen);
  if (FAILED(hr)) {
    MAPI_TRACE2( "OpenMdbEntry failed: 0x%lx, %d\n", (long)hr, (int)hr);
    return( FALSE);
  }
  return( TRUE);
}
void CMapiApi::ReportStringProp( const char *pTag, LPSPropValue pVal)
{
  if ( pVal && (PROP_TYPE( pVal->ulPropTag) == PT_TSTRING)) {
    nsCString val((LPCTSTR) (pVal->Value.LPSZ));
    MAPI_TRACE2( "%s %s\n", pTag, (const char *)val);
  }
  else if (pVal && (PROP_TYPE( pVal->ulPropTag) == PT_NULL)) {
    MAPI_TRACE1( "%s {NULL}\n", pTag);
  }
  else if (pVal && (PROP_TYPE( pVal->ulPropTag) == PT_ERROR)) {
    MAPI_TRACE1( "%s {Error retrieving property}\n", pTag);
  }
  else {
    MAPI_TRACE1( "%s invalid value, expecting string\n", pTag);
  }
  if (pVal)
    MAPIFreeBuffer( pVal);
}
BOOL CMapiApi::Initialize( void)
{
  if (m_initialized)
    return( TRUE);

  HRESULT    hr;

  hr = MAPIInitialize( NULL);

  if (FAILED(hr)) {
    MAPI_TRACE2( "MAPI Initialize failed: 0x%lx, %d\n", (long)hr, (int)hr);
    return( FALSE);
  }

  m_initialized = TRUE;
  MAPI_TRACE0( "MAPI Initialized\n");

  return( TRUE);
}
BOOL CMsgStore::Open( LPMAPISESSION pSession, LPMDB *ppMdb)
{
  if ( m_lpMdb) {
    if (ppMdb)
      *ppMdb = m_lpMdb;
    return( TRUE);
  }

  BOOL bResult = TRUE;
  HRESULT hr = pSession->OpenMsgStore( NULL, m_cbEid, (LPENTRYID)m_lpEid, NULL, MDB_NO_MAIL, &m_lpMdb);    // MDB pointer
  if (HR_FAILED( hr)) {
    m_lpMdb = NULL;
    MAPI_TRACE2( "OpenMsgStore failed: 0x%lx, %d\n", (long)hr, (int)hr);
    bResult = FALSE;
  }

  if (ppMdb)
    *ppMdb = m_lpMdb;
  return( bResult);
}
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();
      }
    }
  }
}
BOOL CMapiApi::IterateStores( CMapiFolderList& stores)
{
  stores.ClearAll();

  if (!m_lpSession) {
    MAPI_TRACE0( "IterateStores called before session is open\n");
    m_lastError = -1;
    return( FALSE);
  }


  HRESULT    hr;

  /* -- Some Microsoft sample code just to see if things are working --- *//*

  ULONG    cbEIDStore;
  LPENTRYID  lpEIDStore;

    hr = HrMAPIFindDefaultMsgStore( m_lpSession, &cbEIDStore, &lpEIDStore);
    if (HR_FAILED(hr)) {
        MAPI_TRACE0( "Default message store not found\n");
    // MessageBox(NULL,"Message Store Not Found",NULL,MB_OK);
    }
  else {
    LPMDB  lpStore;
    MAPI_TRACE0( "Default Message store FOUND\n");
    hr = m_lpSession->OpenMsgStore( NULL, cbEIDStore,
                                  lpEIDStore, NULL,
                                  MDB_NO_MAIL | MDB_NO_DIALOG, &lpStore);
    if (HR_FAILED(hr)) {
      MAPI_TRACE1( "Unable to open default message store: 0x%lx\n", hr);
    }
    else {
      MAPI_TRACE0( "Default message store OPENED\n");
      lpStore->Release();
    }
   }
     */



  LPMAPITABLE  lpTable;

  hr = m_lpSession->GetMsgStoresTable( 0, &lpTable);
  if (FAILED(hr)) {
    MAPI_TRACE0( "GetMsgStoresTable failed\n");
    m_lastError = hr;
    return( FALSE);
  }


  ULONG rowCount;
  hr = lpTable->GetRowCount( 0, &rowCount);
  MAPI_TRACE1( "MsgStores Table rowCount: %ld\n", rowCount);

  hr = lpTable->SetColumns( (LPSPropTagArray)&ptaTbl, 0);
  if (FAILED(hr)) {
    lpTable->Release();
    MAPI_TRACE2( "SetColumns failed: 0x%lx, %d\n", (long)hr, (int)hr);
    m_lastError = hr;
    return( FALSE);
  }

  hr = lpTable->SeekRow( BOOKMARK_BEGINNING, 0, NULL);
  if (FAILED(hr)) {
    lpTable->Release();
    MAPI_TRACE2( "SeekRow failed: 0x%lx, %d\n", (long)hr, (int)hr);
    m_lastError = hr;
    return( FALSE);
  }

  int      cNumRows = 0;
  LPSRowSet  lpRow;
  BOOL    keepGoing = TRUE;
  BOOL    bResult = TRUE;
  do {

    lpRow = NULL;
    hr = lpTable->QueryRows( 1, 0, &lpRow);

        if(HR_FAILED(hr)) {
      MAPI_TRACE2( "QueryRows failed: 0x%lx, %d\n", (long)hr, (int)hr);
            bResult = FALSE;
      m_lastError = hr;
      break;
    }

        if(lpRow) {
            cNumRows = lpRow->cRows;

        if (cNumRows) {
        LPCTSTR    lpStr = (LPCTSTR) lpRow->aRow[0].lpProps[itblPR_DISPLAY_NAME].Value.LPSZ;
                LPENTRYID  lpEID = (LPENTRYID) lpRow->aRow[0].lpProps[itblPR_ENTRYID].Value.bin.lpb;
                ULONG    cbEID = lpRow->aRow[0].lpProps[itblPR_ENTRYID].Value.bin.cb;

        // In the future, GetStoreInfo needs to somehow return
        // whether or not the store is from an IMAP server.
        // Currently, GetStoreInfo opens the store and attempts
        // to get the hierarchy tree.  If the tree is empty or
        // does not exist, then szContents will be zero.  We'll
        // assume that any store that doesn't have anything in
        // it's hierarchy tree is not a store we want to import -
        // there would be nothing to import from anyway!
        // Currently, this does exclude IMAP server accounts
        // which is the desired behaviour.

                int         strLen = strlen(lpStr);
                PRUnichar * pwszStr = (PRUnichar *) nsMemory::Alloc((strLen + 1) * sizeof(WCHAR));
                if (!pwszStr) {
                    // out of memory
                    FreeProws( lpRow);
                    lpTable->Release();
                    return FALSE;
                }
                ::MultiByteToWideChar(CP_ACP, 0, lpStr, strlen(lpStr) + 1, pwszStr, (strLen + 1) * sizeof(WCHAR));
        CMapiFolder *pFolder = new CMapiFolder( pwszStr, cbEID, lpEID, 0, MAPI_STORE);
                nsMemory::Free(pwszStr);

        long szContents = 1;
         GetStoreInfo( pFolder, &szContents);

        MAPI_TRACE1( "    DisplayName: %s\n", lpStr);
        if (szContents) {
          stores.AddItem( pFolder);
        }
        else {
          delete pFolder;
          MAPI_TRACE0( "    ^^^^^ Not added to store list\n");
        }

        keepGoing = TRUE;
        }
      FreeProws( lpRow);
        }

  } while ( SUCCEEDED(hr) && cNumRows && lpRow && keepGoing);

  lpTable->Release();

  return( bResult);
}
BOOL CMapiApi::IterateHierarchy( CMapiHierarchyIter *pIter, LPMAPIFOLDER pFolder, ULONG flags)
{
  // flags can be CONVENIENT_DEPTH or 0
  // CONVENIENT_DEPTH will return all depths I believe instead
  // of just children
  HRESULT    hr;
  LPMAPITABLE  lpTable;
  hr = pFolder->GetHierarchyTable( flags, &lpTable);
  if (HR_FAILED(hr)) {
    m_lastError = hr;
    MAPI_TRACE2( "IterateHierarchy: GetContentsTable failed: 0x%lx, %d\n", (long)hr, (int)hr);
    return( FALSE);
  }

  ULONG rowCount;
  hr = lpTable->GetRowCount( 0, &rowCount);
  if (!rowCount) {
    lpTable->Release();
    return( TRUE);
  }

  hr = lpTable->SetColumns( (LPSPropTagArray)&ptaEid, 0);
  if (HR_FAILED(hr)) {
    m_lastError = hr;
    lpTable->Release();
    MAPI_TRACE2( "IterateHierarchy: SetColumns failed: 0x%lx, %d\n", (long)hr, (int)hr);
    return( FALSE);
  }

  hr = lpTable->SeekRow( BOOKMARK_BEGINNING, 0, NULL);
  if (HR_FAILED(hr)) {
    m_lastError = hr;
    lpTable->Release();
    MAPI_TRACE2( "IterateHierarchy: SeekRow failed: 0x%lx, %d\n", (long)hr, (int)hr);
    return( FALSE);
  }

  int      cNumRows = 0;
  LPSRowSet  lpRow;
  BOOL    keepGoing = TRUE;
  BOOL    bResult = TRUE;
  do {

    lpRow = NULL;
    hr = lpTable->QueryRows( 1, 0, &lpRow);

        if(HR_FAILED(hr)) {
      MAPI_TRACE2( "QueryRows failed: 0x%lx, %d\n", (long)hr, (int)hr);
      m_lastError = hr;
            bResult = FALSE;
      break;
    }

        if(lpRow) {
            cNumRows = lpRow->cRows;

        if (cNumRows) {
                LPENTRYID  lpEntry = (LPENTRYID) lpRow->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.lpb;
                ULONG    cb = lpRow->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.cb;
        ULONG    oType = lpRow->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.ul;

        if (pIter)
          keepGoing = pIter->HandleHierarchyItem( oType, cb, lpEntry);
        else
          keepGoing = HandleHierarchyItem( oType, cb, lpEntry);

        }
      FreeProws( lpRow);
        }

  } while ( SUCCEEDED(hr) && cNumRows && lpRow && keepGoing);

  lpTable->Release();

  if (bResult && !keepGoing)
    bResult = FALSE;

  return( bResult);
}
BOOL CMapiApi::IterateContents( CMapiContentIter *pIter, LPMAPIFOLDER pFolder, ULONG flags)
{
  // flags can be 0 or MAPI_ASSOCIATED
  // MAPI_ASSOCIATED is usually used for forms and views

  HRESULT    hr;
  LPMAPITABLE  lpTable;
  hr = pFolder->GetContentsTable( flags, &lpTable);
  if (FAILED(hr)) {
    MAPI_TRACE2( "GetContentsTable failed: 0x%lx, %d\n", (long)hr, (int)hr);
    return( FALSE);
  }

  ULONG rowCount;
  hr = lpTable->GetRowCount( 0, &rowCount);
  if (!rowCount) {
    MAPI_TRACE0( "  Empty Table\n");
  }

  hr = lpTable->SetColumns( (LPSPropTagArray)&ptaEid, 0);
  if (FAILED(hr)) {
    lpTable->Release();
    MAPI_TRACE2( "SetColumns failed: 0x%lx, %d\n", (long)hr, (int)hr);
    return( FALSE);
  }

  hr = lpTable->SeekRow( BOOKMARK_BEGINNING, 0, NULL);
  if (FAILED(hr)) {
    lpTable->Release();
    MAPI_TRACE2( "SeekRow failed: 0x%lx, %d\n", (long)hr, (int)hr);
    return( FALSE);
  }

  int      cNumRows = 0;
  LPSRowSet  lpRow;
  BOOL    keepGoing = TRUE;
  BOOL    bResult = TRUE;
  do {
    lpRow = NULL;
    hr = lpTable->QueryRows( 1, 0, &lpRow);
    if(HR_FAILED(hr)) {
      MAPI_TRACE2( "QueryRows failed: 0x%lx, %d\n", (long)hr, (int)hr);
      bResult = FALSE;
      break;
    }

    if(lpRow) {
      cNumRows = lpRow->cRows;
      if (cNumRows) {
        LPENTRYID  lpEID = (LPENTRYID) lpRow->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.lpb;
        ULONG    cbEID = lpRow->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.cb;
        ULONG    oType = lpRow->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.ul;
        keepGoing = HandleContentsItem( oType, cbEID, lpEID);
        MAPI_TRACE1( "    ObjectType: %ld\n", oType);
      }
      FreeProws( lpRow);
    }

  } while ( SUCCEEDED(hr) && cNumRows && lpRow && keepGoing);

  lpTable->Release();
  return( bResult);
}
Exemple #19
0
BOOL CMapiMessage::GetAttachmentInfo( int idx)
{
  ClearTempAttachFile();

  BOOL bResult = TRUE;
  if ((idx < 0) || (idx >= (int)m_attachNums.Length())) {
    return( FALSE);
  }

  DWORD aNum = m_attachNums[idx];
  LPATTACH lpAttach = NULL;
  HRESULT hr = m_lpMsg->OpenAttach( aNum, NULL, 0, &lpAttach);
  if (HR_FAILED( hr)) {
    MAPI_TRACE2( "\t\t****Attachment error, unable to open attachment: %d, 0x%lx\r\n", idx, hr);
    return( FALSE);
  }

  LPSPropValue pVal;
  pVal = CMapiApi::GetMapiProperty( lpAttach, PR_ATTACH_MIME_TAG);
  if (pVal)
    CMapiApi::GetStringFromProp( pVal, m_attachMimeType);
  else
    m_attachMimeType.Truncate();

  pVal = CMapiApi::GetMapiProperty( lpAttach, PR_ATTACH_METHOD);
  if (pVal) {
    LONG aMethod = CMapiApi::GetLongFromProp( pVal);
    if ((aMethod == ATTACH_BY_REF_ONLY) || (aMethod == ATTACH_BY_REFERENCE) || (aMethod == ATTACH_BY_REF_RESOLVE)) {
      m_attachPath.Truncate();
      pVal = CMapiApi::GetMapiProperty( lpAttach, PR_ATTACH_PATHNAME);
      if (pVal)
        CMapiApi::GetStringFromProp( pVal, m_attachPath);
      MAPI_TRACE2("\t\t** Attachment #%d by ref: %s\r\n",
                  idx, m_attachPath.get());
      m_ownsAttachFile = FALSE;
    }
    else if (aMethod == ATTACH_BY_VALUE) {
      MAPI_TRACE1( "\t\t** Attachment #%d by value.\r\n", idx);
      bResult = CopyBinAttachToFile( lpAttach);
    }
    else if (aMethod == ATTACH_OLE) {
      MAPI_TRACE1( "\t\t** Attachment #%d by OLE - yuck!!!\r\n", idx);
    }
    else if (aMethod == ATTACH_EMBEDDED_MSG) {
      MAPI_TRACE1( "\t\t** Attachment #%d by Embedded Message??\r\n", idx);
    }
    else {
      MAPI_TRACE2( "\t\t** Attachment #%d unknown attachment method - 0x%lx\r\n", idx, aMethod);
      bResult = FALSE;
    }
  }
  else
    bResult = FALSE;

  nsCString fName, fExt;
  pVal = CMapiApi::GetMapiProperty( lpAttach, PR_ATTACH_LONG_FILENAME);
  if (pVal)
    CMapiApi::GetStringFromProp( pVal, fName);
  pVal = CMapiApi::GetMapiProperty( lpAttach, PR_ATTACH_EXTENSION);
  if (pVal)
    CMapiApi::GetStringFromProp( pVal, fExt);
  pVal = CMapiApi::GetMapiProperty( lpAttach, PR_ATTACH_SIZE);
  long sz = 0;
  if (pVal)
    sz = CMapiApi::GetLongFromProp( pVal);

  /*
    // I have no idea how this tag is used, how to interpret it's value, etc.
    // Fortunately, the Microsoft documentation is ABSOLUTELY NO HELP AT ALL.  In fact,
    // if one goes by the docs and sample code, this tag is completely 100% useless.  I'm
    // sure it has some important meaning which will one day be obvious, but for now,
    // it is ignored.
        pVal = CMapiApi::GetMapiProperty( lpAttach, PR_ATTACH_TAG);
       if (pVal) {
        ::MAPIFreeBuffer( pVal);
      }
  */

  MAPI_TRACE1("\t\t\t--- Mime type: %s\r\n", m_attachMimeType.get());
  MAPI_TRACE2("\t\t\t--- File name: %s, extension: %s\r\n",
              fName.get(), fExt.get());
  MAPI_TRACE1("\t\t\t--- Size: %ld\r\n", sz);

  if (fExt.IsEmpty()) {
    int idx = fName.RFindChar( '.');
    if (idx != -1)
      fName.Right( fExt, fName.Length() - idx);
  }

  if ((fName.RFindChar( '.') == -1) && !fExt.IsEmpty()) {
    fName += ".";
    fName += fExt;
  }

  m_attachFileName = fName;

  if (m_attachMimeType.IsEmpty()) {
    PRUint8 *pType = NULL;
    if (!fExt.IsEmpty()) {
      pType = CMimeTypes::GetMimeType( fExt);
    }
    if (pType)
      m_attachMimeType = (PC_S8)pType;
    else
      m_attachMimeType = "application/octet-stream";
  }

  pVal = CMapiApi::GetMapiProperty( lpAttach, PR_ATTACH_TRANSPORT_NAME);
  if (pVal) {
    CMapiApi::GetStringFromProp( pVal, fName);
    MAPI_TRACE1("\t\t\t--- Transport name: %s\r\n", fName.get());
  }

  lpAttach->Release();

  return( bResult);
}
Exemple #20
0
bool CMapiMessage::AddAttachment(DWORD aNum)
{
  LPATTACH lpAttach = NULL;
  HRESULT hr = m_lpMsg->OpenAttach(aNum, NULL, 0, &lpAttach);
  if (HR_FAILED(hr)) {
    MAPI_TRACE2("\t\t****Attachment error, unable to open attachment: %d, 0x%lx\r\n", idx, hr);
    return false;
  }

  bool bResult = false;
  attach_data *data = new attach_data;
  ULONG aMethod;
  if (data) {
    bResult = true;

    // 1. Get the file that contains the attachment data
    LPSPropValue pVal = CMapiApi::GetMapiProperty(lpAttach, PR_ATTACH_METHOD);
    if (pVal) {
      aMethod = CMapiApi::GetLongFromProp(pVal);
      switch (aMethod) {
      case ATTACH_BY_VALUE:
        MAPI_TRACE1("\t\t** Attachment #%d by value.\r\n", aNum);
        bResult = CopyBinAttachToFile(lpAttach, getter_AddRefs(data->tmp_file));
        data->delete_file = true;
        break;
      case ATTACH_BY_REFERENCE:
      case ATTACH_BY_REF_RESOLVE:
      case ATTACH_BY_REF_ONLY:
        pVal = CMapiApi::GetMapiProperty(lpAttach, PR_ATTACH_PATHNAME_W);
        if (pVal) {
          nsCString path;
          CMapiApi::GetStringFromProp(pVal, path);
          nsresult rv;
          data->tmp_file = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
          if (NS_FAILED(rv) || !data->tmp_file) {
            MAPI_TRACE0("*** Error creating file spec for attachment\n");
            bResult = false;
          }
          else data->tmp_file->InitWithNativePath(path);
        }
        MAPI_TRACE2("\t\t** Attachment #%d by ref: %s\r\n",
          aNum, m_attachPath.get());
        break;
      case ATTACH_EMBEDDED_MSG:
        MAPI_TRACE1("\t\t** Attachment #%d by Embedded Message??\r\n", aNum);
        // Convert the embedded IMessage from PR_ATTACH_DATA_OBJ to rfc822 attachment
        // (see http://msdn.microsoft.com/en-us/library/cc842329.aspx)
        // This is a recursive call.
        bResult = CopyMsgAttachToFile(lpAttach, getter_AddRefs(data->tmp_file));
        data->delete_file = true;
        break;
      case ATTACH_OLE:
        MAPI_TRACE1("\t\t** Attachment #%d by OLE - yuck!!!\r\n", aNum);
        break;
      default:
        MAPI_TRACE2("\t\t** Attachment #%d unknown attachment method - 0x%lx\r\n", aNum, aMethod);
        bResult = false;
      }
    }
    else
      bResult = false;

    if (bResult)
      bResult = data->tmp_file;

    if (bResult) {
      bool isFile = false;
      bool exists = false;
      data->tmp_file->Exists(&exists);
      data->tmp_file->IsFile(&isFile);

      if (!exists || !isFile) {
        bResult = false;
        MAPI_TRACE0("Attachment file does not exist\n");
      }
    }

    if (bResult)
      bResult = GetURL(data->tmp_file, getter_AddRefs(data->orig_url));

    if (bResult) {
      // Now we have the file; proceed to the other properties

      data->encoding = NS_strdup(ENCODING_BINARY);

      nsString fname, fext;
      pVal = CMapiApi::GetMapiProperty(lpAttach, PR_ATTACH_LONG_FILENAME_W);
      if (!pVal)
        pVal = CMapiApi::GetMapiProperty(lpAttach, PR_ATTACH_FILENAME_W);
      CMapiApi::GetStringFromProp(pVal, fname);
      pVal = CMapiApi::GetMapiProperty(lpAttach, PR_ATTACH_EXTENSION_W);
      CMapiApi::GetStringFromProp(pVal, fext);
      MAPI_TRACE2("\t\t\t--- File name: %s, extension: %s\r\n",
        fname.get(), fext.get());

      if (fext.IsEmpty()) {
        int idx = fname.RFindChar(L'.');
        if (idx != -1)
          fext = Substring(fname, idx);
      }
      else if (fname.RFindChar(L'.') == -1) {
        fname += L".";
        fname += fext;
      }
      if (fname.IsEmpty()) {
        // If no description use "Attachment i" format.
        fname = L"Attachment ";
        fname.AppendInt(static_cast<uint32_t>(aNum));
      }
      data->real_name = ToNewUTF8String(fname);

      nsCString tmp;
       // We have converted it to the rfc822 document
      if (aMethod == ATTACH_EMBEDDED_MSG) {
        data->type = NS_strdup(MESSAGE_RFC822);
      } else {
        pVal = CMapiApi::GetMapiProperty(lpAttach, PR_ATTACH_MIME_TAG_A);
        CMapiApi::GetStringFromProp(pVal, tmp);
        MAPI_TRACE1("\t\t\t--- Mime type: %s\r\n", tmp.get());
        if (tmp.IsEmpty()) {
          uint8_t *pType = NULL;
          if (!fext.IsEmpty()) {
            pType = CMimeTypes::GetMimeType(fext);
          }
          if (pType)
            data->type = NS_strdup((PC_S8)pType);
          else
            data->type = NS_strdup(APPLICATION_OCTET_STREAM);
        }
        else
          data->type = ToNewCString(tmp);
      }

      pVal = CMapiApi::GetMapiProperty(lpAttach, PR_ATTACH_CONTENT_ID_A);
      CMapiApi::GetStringFromProp(pVal, tmp);
      if (!tmp.IsEmpty())
        data->cid = ToNewCString(tmp);
    }
    if (bResult) {
      // Now we need to decide if this attachment is embedded or not.
      // At first, I tried to simply check for the presence of the Content-Id.
      // But it turned out that this method is unreliable, since there exist cases
      // when an attachment has a Content-Id while isn't embedded (even in a message
      // with a plain-text body!). So next I tried to look for <img> tags that contain
      // the found Content-Id. But this is unreliable, too, because there exist cases
      // where other places of HTML reference the embedded messages (e.g. it may be
      // a background of a table cell, or some CSS; further, it is possible that the
      // reference to an embedded object is not in the main body, but in another
      // embedded object - like body references a CSS attachment that in turn references
      // a picture as a background of its element). From the other hand, it's unreliable
      // to relax the search criteria to any occurence of the Content-Id string in the body -
      // partly because the string may be simply in a text or other non-referencing part,
      // partly because of the abovementioned possibility that the reference is outside
      // the body at all.
      // There exist the PR_ATTACH_FLAGS property of the attachment. The MS documentation
      // tells about two possible flags in it: ATT_INVISIBLE_IN_HTML and ATT_INVISIBLE_IN_RTF.
      // There is at least one more undocumented flag: ATT_MHTML_REF. Some sources in Internet
      // suggest simply check for the latter flag to distinguish between the embedded
      // and ordinary attachments. But my observations indicate that even if the flags
      // don't include ATT_MHTML_REF, the attachment is still may be embedded.
      // However, my observations always show that the message is embedded if the flags
      // is not 0.
      // So now I will simply test for the non-zero flags to decide whether the attachment
      // is embedded or not. Possible advantage is reliability (I hope).
      // Another advantage is that it's much faster than search the body for Content-Id.

      DWORD flags = 0;

      pVal = CMapiApi::GetMapiProperty(lpAttach, PR_ATTACH_FLAGS);
      if (pVal)
        flags = CMapiApi::GetLongFromProp(pVal);
      if (m_bodyIsHtml && data->cid && (flags != 0)) // this is the embedded attachment
        m_embattachments.push_back(data);
      else // this is ordinary attachment
        m_stdattachments.push_back(data);
    }
    else {
      delete data;
    }
  }

  lpAttach->Release();
  return bResult;
}