nsresult nsOEAddressIterator::EnumUser(const char16_t * pName, LPENTRYID pEid, ULONG cbEid)
{
  IMPORT_LOG1("User: %S\n", pName);
  nsresult   rv = NS_OK;
  
  if (m_database) {
    LPMAILUSER  pUser = m_pWab->GetUser(cbEid, pEid);
    if (pUser) {
      // Get a new row from the database!
      nsCOMPtr <nsIMdbRow> newRow;
      rv = m_database->GetNewRow(getter_AddRefs(newRow));
      NS_ENSURE_SUCCESS(rv, rv);
      if (newRow && BuildCard(pName, newRow, pUser))
      {
        rv = m_database->AddCardRowToDB(newRow);
        NS_ENSURE_SUCCESS(rv, rv);
        IMPORT_LOG0("* Added entry to address book database\n");
        nsString  eMail;

        LPSPropValue  pProp = m_pWab->GetUserProperty(pUser, PR_EMAIL_ADDRESS);
        if (pProp) 
        {
          m_pWab->GetValueString(pProp, eMail);
          SanitizeValue(eMail);
          m_pWab->FreeProperty(pProp);
          m_listRows.Put(eMail, newRow);
        }
      }
      m_pWab->ReleaseUser(pUser);
    }
  }  
  
  return rv;
}
nsresult nsOutlookMail::CreateList(const PRUnichar * pName,
                                   nsIAddrDatabase *pDb,
                                   LPMAPIPROP pUserList,
                                   nsIImportFieldMap *pFieldMap)
{
  // If no name provided then we're done.
  if (!pName || !(*pName))
    return NS_OK;

  nsresult rv = NS_ERROR_FAILURE;
  // Make sure we have db to work with.
  if (!pDb)
    return rv;

  nsCOMPtr <nsIMdbRow> newListRow;
  rv = pDb->GetNewListRow(getter_AddRefs(newListRow));
  NS_ENSURE_SUCCESS(rv, rv);
  nsAutoCString column;
  LossyCopyUTF16toASCII(nsDependentString(pName), column);
  rv = pDb->AddListName(newListRow, column.get());
  NS_ENSURE_SUCCESS(rv, rv);

  HRESULT             hr;
  LPSPropValue value = NULL;
  ULONG valueCount = 0;

  LPSPropTagArray properties = NULL;
  m_mapi.MAPIAllocateBuffer(CbNewSPropTagArray(1),
    (void **)&properties);
  properties->cValues = 1;
  properties->aulPropTag [0] = m_mapi.GetEmailPropertyTag(pUserList, 0x8054);
  hr = pUserList->GetProps(properties, 0, &valueCount, &value);
  m_mapi.MAPIFreeBuffer(properties);
  if (HR_FAILED(hr))
    return NS_ERROR_FAILURE;
  if (!value)
    return NS_ERROR_NOT_AVAILABLE;
  // XXX from here out, value must be freed with MAPIFreeBuffer 

  SBinaryArray *sa=(SBinaryArray *)&value->Value.bin;
  if (!sa || !sa->lpbin) {
    m_mapi.MAPIFreeBuffer(value);
    return NS_ERROR_NULL_POINTER;
  }

  LPENTRYID    lpEid;
  ULONG        cbEid;
  int32_t        idx;
  LPMESSAGE        lpMsg;
  nsCString        type;
  LPSPropValue    pVal;
  nsString        subject;
  uint32_t total;

  total=sa->cValues;
  for (idx = 0; idx < sa->cValues; idx++)
  {
    lpEid= (LPENTRYID) sa->lpbin[idx].lpb;
    cbEid = sa->lpbin[idx].cb;

    if (!m_mapi.OpenEntry(cbEid, lpEid, (LPUNKNOWN *) &lpMsg))
    {

      IMPORT_LOG1("*** Error opening messages in mailbox: %S\n", pName);
      m_mapi.MAPIFreeBuffer(value);
      return NS_ERROR_FAILURE;
    }
    // This is a contact, add it to the address book!
    subject.Truncate();
    pVal = m_mapi.GetMapiProperty(lpMsg, PR_SUBJECT);
    if (pVal)
      m_mapi.GetStringFromProp(pVal, subject);

    nsCOMPtr <nsIMdbRow> newRow;
    nsCOMPtr <nsIMdbRow> oldRow;
    pDb->GetNewRow(getter_AddRefs(newRow));
    if (newRow) {
      if (BuildCard(subject.get(), pDb, newRow, lpMsg, pFieldMap))
      {
        nsCOMPtr <nsIAbCard> userCard;
        nsCOMPtr <nsIAbCard> newCard;
        userCard = do_CreateInstance(NS_ABMDBCARD_CONTRACTID, &rv);
        NS_ENSURE_SUCCESS(rv, rv);
        pDb->InitCardFromRow(userCard,newRow);

        //add card to db
        bool bl=false;
        pDb->FindRowByCard(userCard,getter_AddRefs(oldRow));
        if (oldRow)
          newRow = oldRow;
        else
          pDb->AddCardRowToDB(newRow);

        //add card list
        pDb->AddListCardColumnsToRow(userCard,
                                     newListRow,idx+1, getter_AddRefs(newCard),
                                     true, nullptr, nullptr);
      }
    }
  }
  m_mapi.MAPIFreeBuffer(value);

  rv = pDb->AddCardRowToDB(newListRow);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = pDb->SetListAddressTotal(newListRow, total);
  rv = pDb->AddListDirNode(newListRow);
  return rv;
}
nsresult nsOutlookMail::ImportAddresses(uint32_t *pCount, uint32_t *pTotal, const PRUnichar *pName, uint32_t id, nsIAddrDatabase *pDb, nsString& errors)
{
  if (id >= (uint32_t)(m_addressList.GetSize())) {
    IMPORT_LOG0("*** Bad address identifier, unable to import\n");
    return NS_ERROR_FAILURE;
  }

  uint32_t  dummyCount = 0;
  if (pCount)
    *pCount = 0;
  else
    pCount = &dummyCount;

  CMapiFolder *pFolder;
  if (id > 0) {
    int32_t idx = (int32_t) id;
    idx--;
    while (idx >= 0) {
      pFolder = m_addressList.GetItem(idx);
      if (pFolder->IsStore()) {
        OpenMessageStore(pFolder);
        break;
      }
      idx--;
    }
  }

  pFolder = m_addressList.GetItem(id);
  OpenMessageStore(pFolder);
  if (!m_lpMdb) {
    IMPORT_LOG1("*** Unable to obtain mapi message store for address book: %S\n", pName);
    return NS_ERROR_FAILURE;
  }

  if (pFolder->IsStore())
    return NS_OK;

  nsresult  rv;

  nsCOMPtr<nsIImportFieldMap>    pFieldMap;

  nsCOMPtr<nsIImportService> impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
  if (NS_SUCCEEDED(rv)) {
    rv = impSvc->CreateNewFieldMap(getter_AddRefs(pFieldMap));
  }

  CMapiFolderContents    contents(m_lpMdb, pFolder->GetCBEntryID(), pFolder->GetEntryID());

  BOOL      done = FALSE;
  ULONG      cbEid;
  LPENTRYID    lpEid;
  ULONG      oType;
  LPMESSAGE    lpMsg;
  nsCString    type;
  LPSPropValue  pVal;
  nsString    subject;

  while (!done) {
    (*pCount)++;

    if (!contents.GetNext(&cbEid, &lpEid, &oType, &done)) {
      IMPORT_LOG1("*** Error iterating address book: %S\n", pName);
      return NS_ERROR_FAILURE;
    }

    if (pTotal && (*pTotal == 0))
      *pTotal = contents.GetCount();

    if (!done && (oType == MAPI_MESSAGE)) {
      if (!m_mapi.OpenMdbEntry(m_lpMdb, cbEid, lpEid, (LPUNKNOWN *) &lpMsg)) {
        IMPORT_LOG1("*** Error opening messages in mailbox: %S\n", pName);
        return NS_ERROR_FAILURE;
      }

      // Get the PR_MESSAGE_CLASS attribute,
      // ensure that it is IPM.Contact
      pVal = m_mapi.GetMapiProperty(lpMsg, PR_MESSAGE_CLASS);
      if (pVal) {
        type.Truncate();
        m_mapi.GetStringFromProp(pVal, type);
        if (type.EqualsLiteral("IPM.Contact")) {
          // This is a contact, add it to the address book!
          subject.Truncate();
          pVal = m_mapi.GetMapiProperty(lpMsg, PR_SUBJECT);
          if (pVal)
            m_mapi.GetStringFromProp(pVal, subject);

          nsIMdbRow* newRow = nullptr;
          pDb->GetNewRow(&newRow);
          // FIXME: Check with Candice about releasing the newRow if it
          // isn't added to the database.  Candice's code in nsAddressBook
          // never releases it but that doesn't seem right to me!
          if (newRow) {
            if (BuildCard(subject.get(), pDb, newRow, lpMsg, pFieldMap)) {
              pDb->AddCardRowToDB(newRow);
            }
          }
        }
        else if (type.EqualsLiteral("IPM.DistList"))
        {
          // This is a list/group, add it to the address book!
          subject.Truncate();
          pVal = m_mapi.GetMapiProperty(lpMsg, PR_SUBJECT);
          if (pVal)
            m_mapi.GetStringFromProp(pVal, subject);
          CreateList(subject.get(), pDb, lpMsg, pFieldMap);
        }
      }

      lpMsg->Release();
    }
  }

  rv = pDb->Commit(nsAddrDBCommitType::kLargeCommit);
  return rv;
}