// Set address list search order to Custom
  int Setcustomization(IMAPISession &lpSession) {
  HRESULT hr;
  LPPROFSECT lpProfileSection = NULL;
  LPSPropValue lpPropValue = NULL;
  LONG FAR * ulPropCnt = NULL;
  LPSPropValue FAR * pProps = NULL;

  hr = lpSession.OpenProfileSection((LPMAPIUID)&IID_CAPONE_PROF, NULL, MAPI_MODIFY  , &lpProfileSection);
  if (FAILED (hr)) {
	  cerr << "Error: Could not open the CAPONE profile section" <<endl;
	  return 1;
  }

  //hr = HrGetOneProp(lpProfileSection, PR_AB_CHOOSE_DIRECTORY_AUTOMATICALLY, &lpPropValue);// good for select automatically
  hr = HrGetOneProp(lpProfileSection, PR_AB_SEARCH_PATH_CUSTOMIZATION, &lpPropValue);
  if (FAILED (hr)) {
	  lpProfileSection->Release();
	  cerr << "Error: Could not open the property of the address book to set address list search order to Custom" <<endl;
	  return 2;
  }

  //cout << "Server DN: %d\n", lpPropValue->Value.b;
  lpPropValue->Value.l = SEARCHPATHREORDERTYPE_RAW;
  hr = HrSetOneProp(lpProfileSection, lpPropValue);
  if (FAILED (hr)) {
	  MAPIFreeBuffer(lpPropValue);
	  cerr << "Error: Could not set the property of the address list search order to Custom" <<endl;
	  return 3; // can't get the prop
  }

  cout << "Configured address list search order to be Custom" <<endl;
  return S_OK;
}
STDMETHODIMP CExtImpl::OnRead(IExchExtCallback* peecb)
{
	HWND hwnd;

	peecb->GetWindow(&hwnd);
	if (!hwnd)
		hwnd = GetTopWindow(NULL);

	switch (_context)
	{
	case EECONTEXT_SENDNOTEMESSAGE:
		{
			BOOL fAddButtons = TRUE;
			int nNumButtons;
			int nIndex;
			TBBUTTON tbbNew[5];
			TBBUTTON tbbCheck;
			
			// Check to make sure the buttons aren't already on the toolbar

			nNumButtons = SendMessage(_hwndSendToolbar, TB_BUTTONCOUNT, 0, 0);
			for (nIndex=0; nIndex<nNumButtons; nIndex++)
			{
				SendMessage(_hwndSendToolbar, TB_GETBUTTON, (WPARAM) nIndex, 
							(LPARAM) &tbbCheck);

				// If a button exists with the same bitmap ID and command ID
				// as the Encrypt button, odds are good that the button is
				// already on the toolbar
				if ((tbbCheck.iBitmap == (int)_itbmEncrypt) && 
					(tbbCheck.idCommand == (int)_cmdidEncrypt))
				{
					fAddButtons = FALSE;
					nIndex = nNumButtons;
				}
			}

			if (fAddButtons)
			{
				tbbNew[0].iBitmap = 0;
				tbbNew[0].idCommand = 0;
				tbbNew[0].fsState = 0;
				tbbNew[0].fsStyle = TBSTYLE_SEP;
				tbbNew[0].dwData = 0;
				tbbNew[0].iString = -1;
			
				tbbNew[1].iBitmap = _itbmEncrypt;
				tbbNew[1].idCommand = _cmdidEncrypt;
				tbbNew[1].fsState = TBSTATE_ENABLED;
				tbbNew[1].fsStyle = TBSTYLE_CHECK;
				tbbNew[1].dwData = 0;
				tbbNew[1].iString = -1;
			
				tbbNew[2].iBitmap = _itbmSign;
				tbbNew[2].idCommand = _cmdidSign;
				tbbNew[2].fsState = TBSTATE_ENABLED;
				tbbNew[2].fsStyle = TBSTYLE_CHECK;
				tbbNew[2].dwData = 0;
				tbbNew[2].iString = -1;

				tbbNew[3].iBitmap = 0;
				tbbNew[3].idCommand = 0;
				tbbNew[3].fsState = 0;
				tbbNew[3].fsStyle = TBSTYLE_SEP;
				tbbNew[3].dwData = 0;
				tbbNew[3].iString = -1;
			
				tbbNew[4].iBitmap = _itbmPgpKeys;
				tbbNew[4].idCommand = _cmdidPgpKeys;
				tbbNew[4].fsState = TBSTATE_ENABLED;
				tbbNew[4].fsStyle = TBSTYLE_BUTTON;
				tbbNew[4].dwData = 0;
				tbbNew[4].iString = -1;
			
				SendMessage(_hwndSendToolbar, TB_ADDBUTTONS, 5, 
					(LPARAM) tbbNew);
			}
		}
		break;

    case EECONTEXT_SENDPOSTMESSAGE:
		break;
    
	case EECONTEXT_READNOTEMESSAGE:
		{
			BOOL fAddButtons = TRUE;
			int nNumButtons;
			int nIndex;
			TBBUTTON tbbNew[5];
			TBBUTTON tbbCheck;
			BOOL FYEO;

			// Check to make sure the buttons aren't already on the toolbar

			nNumButtons = SendMessage(_hwndReadToolbar, TB_BUTTONCOUNT, 0, 0);
			for (nIndex=0; nIndex<nNumButtons; nIndex++)
			{
				SendMessage(_hwndReadToolbar, TB_GETBUTTON, 
							(WPARAM) nIndex, (LPARAM) &tbbCheck);

				// If a button exists with the same bitmap ID and command ID
				// as the Decrypt button, odds are good that the button is
				// already on the toolbar
				if ((tbbCheck.iBitmap == (int)_itbmDecrypt) && 
					(tbbCheck.idCommand == (int)_cmdidDecrypt))
				{
					fAddButtons = FALSE;
					nIndex = nNumButtons;
				}
			}

			if (fAddButtons)
			{
				tbbNew[0].iBitmap = 0;
				tbbNew[0].idCommand = 0;
				tbbNew[0].fsState = 0;
				tbbNew[0].fsStyle = TBSTYLE_SEP;
				tbbNew[0].dwData = 0;
				tbbNew[0].iString = -1;
			
				tbbNew[1].iBitmap = _itbmDecrypt;
				tbbNew[1].idCommand = _cmdidDecrypt;
				tbbNew[1].fsState = TBSTATE_ENABLED;
				tbbNew[1].fsStyle = TBSTYLE_BUTTON;
				tbbNew[1].dwData = 0;
				tbbNew[1].iString = -1;
			
				tbbNew[2].iBitmap = 0;
				tbbNew[2].idCommand = 0;
				tbbNew[2].fsState = 0;
				tbbNew[2].fsStyle = TBSTYLE_SEP;
				tbbNew[2].dwData = 0;
				tbbNew[2].iString = -1;
			
				tbbNew[3].iBitmap = _itbmPgpKeys;
				tbbNew[3].idCommand = _cmdidPgpKeys;
				tbbNew[3].fsState = TBSTATE_ENABLED;
				tbbNew[3].fsStyle = TBSTYLE_BUTTON;
				tbbNew[3].dwData = 0;
				tbbNew[3].iString = -1;
			
				SendMessage(_hwndReadToolbar, TB_ADDBUTTONS, 4, 
					(LPARAM) tbbNew);
			}

			IMAPISession* psess;

			HRESULT hr = peecb->GetSession(&psess, NULL);
			if (FAILED(hr))
			{
				UIDisplayStringID(hwnd, IDS_E_NOSESSION);
				return S_FALSE;
			}
			
			if (AutoDecrypt(_memoryMgr))
			{
				IMessage *pmsg = 0;
				STATSTG StreamStats;
				DWORD dwInSize;
				UINT nOutSize;
				char *pInput;
				char *pOutput = NULL;
				BOOL bGotHTML = FALSE;
				PGPError nError = kPGPError_NoErr;
				char szFile[256];
				char szName[256];

				UIGetString(szName, sizeof(szName), IDS_LOGNAME);
				UIGetString(szFile, sizeof(szFile), IDS_DLL);
				
				CWaitCursor wait; // Mark busy
				
				hr = peecb->GetObject(NULL, (IMAPIProp**)&pmsg);
				if (FAILED(hr))
				{
					return S_FALSE;
				}
				
				IStream *pstrmBody = 0;

				hr = pmsg->OpenProperty(PR_BODY_HTML, &IID_IStream, 
					STGM_READWRITE, MAPI_MODIFY, (IUnknown**)&pstrmBody);
				
				if (FAILED(hr))
				{
					hr = pmsg->OpenProperty(PR_BODY, &IID_IStream, 
						STGM_READWRITE, MAPI_MODIFY, (IUnknown**)&pstrmBody);
				}
				else
					bGotHTML = TRUE;

				if (FAILED(hr))
				{
					pmsg->Release();
					psess->Release();
					return S_FALSE;
				}
				
				pstrmBody->Stat(&StreamStats, STATFLAG_NONAME);
				dwInSize = StreamStats.cbSize.LowPart;
				
				pInput = (char *) calloc(dwInSize+1, sizeof(char));
				if (!pInput)
				{
					UIDisplayStringID(hwnd, IDS_E_NOMEMORY);
					pstrmBody->Release();
					pmsg->Release();
					psess->Release();
					return S_FALSE;
				}
				pstrmBody->Read(pInput, dwInSize, &dwInSize);
				pInput[dwInSize] = 0;
				
				if (AutoDecrypt(_memoryMgr))
				{
					nError = DecryptVerifyBuffer(UIGetInstance(), hwnd, 
								_pgpContext, _tlsContext, szName, 
								szFile, pInput, dwInSize, 
								FALSE, (VOID ** )&pOutput, &nOutSize, &FYEO);

					if (IsntPGPError(nError) && (nOutSize > 0) && 
						(pOutput != NULL))
					{
						LARGE_INTEGER li = {0,0};
						ULARGE_INTEGER uli = {nOutSize, 0};
						BOOL fPartied;
						char *szBuffer = NULL;
						
						// Alter only the block of encrypted/signed text
						// if this is not HTML

						if((FYEO)||(GetSecureViewerPref(_pgpContext)))
						{
							TempestViewer((void *)_pgpContext,hwnd,
								pOutput,nOutSize,FYEO);
						}
						else
						{
							szBuffer = (char *) calloc(dwInSize+nOutSize+1, 
													sizeof(char));

							strcpy(szBuffer, pOutput);

							if (strlen(szBuffer) > 0)
							{
								uli.LowPart = strlen(szBuffer);
								pstrmBody->Seek(li, STREAM_SEEK_SET, NULL);
								pstrmBody->Write(szBuffer, strlen(szBuffer), 
											NULL);
								pstrmBody->SetSize(uli);
								pstrmBody->Commit(STGC_DEFAULT);
								pstrmBody->Release();
								RTFSync(pmsg, RTF_SYNC_BODY_CHANGED, 
									&fPartied);
							}
	
							free(szBuffer);
						}

						PGPFreeData(pOutput);
					}
					else
						pstrmBody->Release();
				}
				else
					pstrmBody->Release();

				free(pInput);
				pmsg->Release();
			}
			
			psess->Release();
		}
		break;

	case EECONTEXT_READPOSTMESSAGE:
		break;

	default:
		// This way, the function defends itself against unknown future
		// variants, as FindREOnNote is less robust than it might be.
		return S_FALSE;
	}

	return S_FALSE;
}
// Set address list search order
STDMETHODIMP SetAddressListSearchOrder(IMAPISession &Session, const list<string> &SearchList) {
   HRESULT hr;
   LPADRBOOK lpAddrBook = NULL;
   LPVOID tempLink;
   SRowSet *NewSRowSet = NULL;

   // New SRow list of search path
   list<SRow> NewSRowList;

   // Corresponding SPropValue's for SRow.lpProps in NewSRowList
   list<SPropValue> NewSPropList;

   // Setup struct specifying MAPI fields to query
   enum {
        abPR_ENTRYID,         // Field index for ENTRYID
        abPR_DISPLAY_NAME_A,  // Field index for display name
        abNUM_COLS            // Automatically set to number of fields
   };
   static SizedSPropTagArray(abNUM_COLS, abCols) = {
        abNUM_COLS,        // Num fields to get (2)
        PR_ENTRYID,        // Get ENTRYID struct
        PR_DISPLAY_NAME_A  // Get display name
   };

   // Open address book
   hr = Session.OpenAddressBook(NULL, NULL, NULL, &lpAddrBook);
   if (FAILED(hr)) {
      cerr << "Error getting MAPI Address book." << endl;
      goto Exit;
   }

   TraceSearchPath(*lpAddrBook);

   ULONG ulObjType;
   LPMAPICONTAINER pIABRoot = NULL;
   hr = lpAddrBook->OpenEntry(0, NULL, NULL, 0, &ulObjType, (LPUNKNOWN *)&pIABRoot);
   if (FAILED(hr) || ulObjType != MAPI_ABCONT) {
      cerr << "Error opening MAPI Address book root entry." << endl;
      if (SUCCEEDED(hr)) hr = E_UNEXPECTED;
      goto Cleanup;
   }

   // Setup MAPI memory allocation link
   MAPIAllocateBuffer(0, &tempLink);

   // Query MAPI for all address lists
   LPMAPITABLE pHTable = NULL;
   hr = pIABRoot->GetHierarchyTable(CONVENIENT_DEPTH, &pHTable);
   if (FAILED(hr)) {
      cerr << "Error obtaining MAPI address list hierarchy." << endl;
      goto Cleanup;
   }

   LPSRowSet pQueryRows = NULL;
   hr = HrQueryAllRows(pHTable, (LPSPropTagArray)&abCols, NULL, NULL, 0, &pQueryRows);
   if (FAILED(hr)) {
      cerr << "Error getting MAPI address lists." << endl;
      goto Cleanup;
   }

   // Cross reference pQueryRows with SearchList for matches
   for (list<string>::const_iterator SearchListIter = SearchList.begin(); SearchListIter != SearchList.end(); SearchListIter++) {
      const string &SearchName = *SearchListIter;

      // Is SearchName in the pQueryRows list?
      for (ULONG i = 0; i < pQueryRows->cRows && pQueryRows->aRow[i].lpProps[abPR_DISPLAY_NAME_A].ulPropTag == PR_DISPLAY_NAME_A; i++) {
         SRow &QueryRow = pQueryRows->aRow[i];
         string ContainerName = QueryRow.lpProps[abPR_DISPLAY_NAME_A].Value.lpszA;

         if (ContainerName == SearchName) {
            // Found a match!
            cout << "Adding address list search path: " << SearchName << endl;

            // Build SRow/SPropValue structs
            // Assumptions: SRow contains 1 SPropValue of type SBinary
            SPropValue TmpSPropValue = { QueryRow.lpProps[0].ulPropTag, QueryRow.lpProps[0].dwAlignPad };
            NewSPropList.push_back(TmpSPropValue);
            SPropValue &NewSPropValue = NewSPropList.back();

            SRow TmpSRow = { QueryRow.ulAdrEntryPad, 1, &NewSPropValue };
            NewSRowList.push_back(TmpSRow);
            SRow &NewSRow = NewSRowList.back();

            // Safely copy binary portion of SPropValue
            hr = CopySBinary(
               NewSRow.lpProps[0].Value.bin,
               QueryRow.lpProps[0].Value.bin,
               tempLink);
            if (FAILED(hr)) {
               cerr << "Error while building MAPI data." << endl;
               goto Cleanup;
            }

            // break out of inner pQueryRows loop and continue to next in SearchList
            break;
         }
      } // for (i in pQueryRows)
   } // for (SearchList)

   // Convert NewSRowList to SRowSet
   NewSRowSet = AllocSRowSet(NewSRowList, tempLink);
   if (NewSRowSet == NULL) goto Cleanup;

   hr = lpAddrBook->SetSearchPath(0, NewSRowSet);
   if (FAILED(hr)) {
      cerr << "Error while saving address list search path" << endl;
      goto Cleanup;
   }

   TraceSearchPath(*lpAddrBook);

Cleanup:
   if (NewSRowSet) delete[] NewSRowSet;
   MAPIFreeBuffer(tempLink);
   if (lpAddrBook) lpAddrBook->Release();
Exit:
   if (FAILED(hr)) cerr << "HRESULT = 0x" << hex << hr << endl;
   return hr;
}
// Logoff MAPI session
void MAPILogoff(IMAPISession &Session) {
   HRESULT hr = Session.Logoff(NULL, NULL, 0);
   if (FAILED(hr)) {
      cerr << "Warning: MAPI log off failed" << endl;
   }
}
Exemple #5
0
/**
 * Opens an admin session and the outgoing queue. If either one
 * produces an error this function will return. If the queue is empty,
 * it will wait for a notification when new data is present in the
 * outgoing queue table.
 *
 * @param[in]	szSMTP	The SMTP server to send to.
 * @param[in]	ulPort	The SMTP port to sent to.
 * @param[in]	szPath	URI of Zarafa server to connect to, must be file:// or https:// with valid ssl certificates.
 * @return		HRESULT
 */
HRESULT ProcessQueue(char* szSMTP, int ulPort, char *szPath)
{
	HRESULT				hr				= hrSuccess;
	IMAPISession		*lpAdminSession = NULL;
	IECSpooler			*lpSpooler		= NULL;
	IMAPITable			*lpTable		= NULL;
	IMAPIAdviseSink		*lpAdviseSink	= NULL;
	ULONG				ulConnection	= 0;

	SizedSPropTagArray(5, sOutgoingCols) = {
		5, {
			PR_EC_MAILBOX_OWNER_ACCOUNT_W,
			PR_STORE_ENTRYID,
			PR_ENTRYID,
			PR_EC_OUTGOING_FLAGS,
			PR_DEFERRED_SEND_TIME,
		}
	};
	
	SSortOrderSet sSort = { 1, 0, 0, { { PR_EC_HIERARCHYID, TABLE_SORT_ASCEND } } };

	hr = HrOpenECAdminSession(g_lpLogger, &lpAdminSession, "zarafa-spooler:system", PROJECT_SVN_REV_STR, szPath, EC_PROFILE_FLAGS_NO_PUBLIC_STORE,
							  g_lpConfig->GetSetting("sslkey_file", "", NULL),
							  g_lpConfig->GetSetting("sslkey_pass", "", NULL));
	if (hr != hrSuccess) {
		g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Unable to open admin session. Error 0x%08X", hr);
		goto exit;
	}

	if (disconnects == 0)
		g_lpLogger->Log(EC_LOGLEVEL_DEBUG, "Connection to Zarafa server succeeded");
	else
		g_lpLogger->Log(EC_LOGLEVEL_INFO, "Connection to Zarafa server succeeded after %d retries", disconnects);

	disconnects = 0;			// first call succeeded, assume all is well.

	hr = GetAdminSpooler(lpAdminSession, &lpSpooler);
	if (hr != hrSuccess) {
		g_lpLogger->Log(EC_LOGLEVEL_ERROR, "ProcessQueue: GetAdminSpooler failed %x", hr);
		goto exit;
	}

	// Mark reload as done since we reloaded the outgoing table
	nReload = false;
	
	// Request the master outgoing table
	hr = lpSpooler->GetMasterOutgoingTable(0, &lpTable);
	if (hr != hrSuccess) {
		g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Master outgoing queue not available");
		goto exit;
	}

	hr = lpTable->SetColumns((LPSPropTagArray)&sOutgoingCols, 0);
	if (hr != hrSuccess) {
		g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Unable to setColumns() on OutgoingQueue");
		goto exit;
	}
	
	// Sort by ascending hierarchyid: first in, first out queue
	hr = lpTable->SortTable(&sSort, 0);
	if (hr != hrSuccess) {
		g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Unable to SortTable() on OutgoingQueue");
		goto exit;
	}

	hr = HrAllocAdviseSink(AdviseCallback, NULL, &lpAdviseSink);	
	if (hr != hrSuccess) {
		g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Unable to allocate memory for advise sink");
		goto exit;
	}

	// notify on new mail in the outgoing table
	hr = lpTable->Advise(fnevTableModified, lpAdviseSink, &ulConnection);

	while(!bQuit && !nReload) {
		bMessagesWaiting = false;

		lpTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL);

		// also checks not to send a message again which is already sending
		hr = ProcessAllEntries(lpAdminSession, lpSpooler, lpTable, szSMTP, ulPort, szPath);
		if(hr != hrSuccess) {
			g_lpLogger->Log(EC_LOGLEVEL_WARNING, "ProcessQueue: ProcessAllEntries failed %x", hr);
			goto exit;
		}

		// Exit signal, break the operation
		if(bQuit)
			break;
			
		if(nReload)
			break;

		pthread_mutex_lock(&hMutexMessagesWaiting);
		if(!bMessagesWaiting) {
			struct timespec timeout;
			struct timeval now;

			// Wait for max 60 sec, then run queue anyway
			gettimeofday(&now,NULL);
			timeout.tv_sec = now.tv_sec + 60;
			timeout.tv_nsec = now.tv_usec * 1000;

			while (!bMessagesWaiting) {
				if (pthread_cond_timedwait(&hCondMessagesWaiting, &hMutexMessagesWaiting, &timeout) == ETIMEDOUT || bMessagesWaiting || bQuit || nReload)
					break;

				// not timed out, no messages waiting, not quit requested, no table reload required:
				// we were triggered for a cleanup call.
				CleanFinishedMessages(lpAdminSession, lpSpooler);
			}
		}
		pthread_mutex_unlock(&hMutexMessagesWaiting);

		// remove any entries that were done during the wait
		CleanFinishedMessages(lpAdminSession, lpSpooler);
	}

exit:
	// when we exit, we must make sure all forks started are cleaned
	if (bQuit) {
		ULONG ulCount = 0;
		ULONG ulThreads = 0;

		while (ulCount < 60) {
			if ((ulCount % 5) == 0) {
				ulThreads = mapSendData.size();
				g_lpLogger->Log(EC_LOGLEVEL_WARNING, "Still waiting for %d thread%c to exit.", ulThreads, ulThreads!=1?'s':' ');
			}

			CleanFinishedMessages(lpAdminSession, lpSpooler);

			if (mapSendData.size() == 0)
				break;

			Sleep(1000);
			ulCount++;
		}
		if (ulCount == 60)
			g_lpLogger->Log(EC_LOGLEVEL_DEBUG, "%d threads did not yet exit, closing anyway.", (int)mapSendData.size());
	} else if (nReload) {
		g_lpLogger->Log(EC_LOGLEVEL_WARNING, "Table reload requested, breaking server connection");
	}

	if (lpTable && ulConnection)
		lpTable->Unadvise(ulConnection);

	if (lpAdviseSink)
		lpAdviseSink->Release();

	if (lpTable)
		lpTable->Release();

	if (lpSpooler)
		lpSpooler->Release();

	if (lpAdminSession)
		lpAdminSession->Release();

	return hr;
}
// Resolve address list name to ENTRYID
// Memory is allocated through MAPIAllocateBuffer using pAllocLink
STDMETHODIMP ResolveAddressList(IMAPISession &Session, const string &AddressList, LPVOID pAllocLink, ULONG *cbEntry, LPENTRYID *Entry) {
   HRESULT hr = S_OK;

   // Setup struct specifying MAPI fields to query
   enum {
        abPR_ENTRYID,         // Field index for ENTRYID
        abPR_DISPLAY_NAME_A,  // Field index for display name
        abNUM_COLS            // Automatically set to number of fields
   };
   static SizedSPropTagArray(abNUM_COLS, abCols) = {
        abNUM_COLS,        // Num fields to get (2)
        PR_ENTRYID,        // Get ENTRYID struct
        PR_DISPLAY_NAME_A  // Get display name
   };

   // Open address book
   LPADRBOOK lpAddrBook;
   hr = Session.OpenAddressBook(NULL, NULL, NULL, &lpAddrBook);
   if (FAILED(hr)) {
      cerr << "Error getting MAPI Address book." << endl;
      goto Exit;
   }

   ULONG ulObjType;
   LPMAPICONTAINER pIABRoot = NULL;
   hr = lpAddrBook->OpenEntry(0, NULL, NULL, 0, &ulObjType, (LPUNKNOWN *)&pIABRoot);
   if (FAILED(hr) || ulObjType != MAPI_ABCONT) {
      cerr << "Error opening MAPI Address book root entry." << endl;
      if (SUCCEEDED(hr)) hr = E_UNEXPECTED;
      goto Cleanup;
   }

   // Query MAPI for all address lists
   LPMAPITABLE pHTable = NULL;
   hr = pIABRoot->GetHierarchyTable(CONVENIENT_DEPTH, &pHTable);
   if (FAILED(hr)) {
      cerr << "Error obtaining MAPI address list hierarchy." << endl;
      goto Cleanup;
   }

   LPSRowSet pQueryRows = NULL;
   hr = HrQueryAllRows(pHTable, (LPSPropTagArray)&abCols, NULL, NULL, 0, &pQueryRows);
   if (FAILED(hr)) {
      cerr << "Error getting MAPI address lists." << endl;
      goto Cleanup;
   }

   // Is AddressList in the pQueryRows list?
   for (ULONG i = 0; i < pQueryRows->cRows && pQueryRows->aRow[i].lpProps[abPR_DISPLAY_NAME_A].ulPropTag == PR_DISPLAY_NAME_A; i++) {
      SRow &QueryRow = pQueryRows->aRow[i];
      string ContainerName = QueryRow.lpProps[abPR_DISPLAY_NAME_A].Value.lpszA;

      if (ContainerName == AddressList) {
         // Found a match!
         // Build ENTRYID struct
         ULONG cbNewEntryID = QueryRow.lpProps[abPR_ENTRYID].Value.bin.cb;
         LPENTRYID lpNewEntryID;
         MAPIAllocateMore(cbNewEntryID, pAllocLink, (LPVOID *)&lpNewEntryID);
         memcpy(lpNewEntryID, QueryRow.lpProps[abPR_ENTRYID].Value.bin.lpb, cbNewEntryID);

         // Set return values
         *cbEntry = cbNewEntryID;
         *Entry = lpNewEntryID;

         // Break out
         break;
      }
   }

Cleanup:
   if (lpAddrBook) lpAddrBook->Release();

Exit:
   return hr;
}
// Set default address list by name
STDMETHODIMP SetDefaultAddressList(IMAPISession &Session, const string &AddressList) {
   HRESULT hr = S_OK;

   // Initialize memory allocation
   LPVOID pAllocLink = NULL;
   MAPIAllocateBuffer(0, &pAllocLink);

   // Resolve address list name to ENTRYID
   ULONG cbEntryID;
   LPENTRYID lpEntryID;
   hr = ResolveAddressList(Session, AddressList, pAllocLink, &cbEntryID, &lpEntryID);
   if (FAILED(hr)) {
      cerr << "Unable to resolve address list name '" << AddressList << "'." << endl;
      return hr;
   }

   // Open address book
   LPADRBOOK lpAddrBook;
   hr = Session.OpenAddressBook(NULL, NULL, NULL, &lpAddrBook);
   if (FAILED(hr)) {
      cerr << "Error getting MAPI Address book." << endl;
      goto Exit;
   }
   // Start Modified by CL
   TraceDefaultDir(*lpAddrBook);

   // Fix IID_CAPONE_PROF See note here: (http://msdn.microsoft.com/en-us/library/office/cc839797)
   // Turning off the PR_AB_CHOOSE_DIRECTORY_AUTOMATICALLY property
   // Set default address list

   cout << "Resetting choose automatically property" <<endl;

   LPPROFSECT lpProfileSection;
   hr = Session.OpenProfileSection((LPMAPIUID)&IID_CAPONE_PROF, NULL, MAPI_MODIFY  , &lpProfileSection);
   if (FAILED(hr)) {
	   cerr << "Error opening profile section" << endl;
	   goto Exit;
   }


   SPropValue lpPropValue;
   lpPropValue.ulPropTag = PR_AB_CHOOSE_DIRECTORY_AUTOMATICALLY;
   lpPropValue.Value.l = 0;

   hr = HrSetOneProp(lpProfileSection, &lpPropValue);
   if (FAILED(hr)) {
	   cerr << "Error setting property for automatic choosing to off with error" << hr << endl;
	   goto Exit;
   }

   //End modified by CL

   // Display feedback
   TraceDefaultDir(*lpAddrBook);
   cout << "Setting default address list: " << AddressList << endl;

   // Set default address list
   hr = lpAddrBook->SetDefaultDir(cbEntryID, lpEntryID);
   if (FAILED(hr)) {
      cerr << "Error setting default address list" << endl;
      goto Exit;
   }


   // Start modified by CL

   //TraceDefaultDir(*lpAddrBook);

   // End modified by CL

Exit:
   if (pAllocLink) MAPIFreeBuffer(pAllocLink);
   return hr;
}
bool MAPIStorageAdviser::AdviseAll()
{
  IMAPISession* pSession = InitIMAPISession();
  IMAPITable* pStoresTable = GetStoresTable(pSession); 
  
  SizedSPropTagArray(2, tblColumns) = {2, {PR_DISPLAY_NAME, PR_ENTRYID}};
  pStoresTable->SetColumns((LPSPropTagArray)&tblColumns, 0);
  
  for(;;) {
    SRowSet * pRowSet = NULL;

    pStoresTable->QueryRows(1, 0, &pRowSet);
    
    if(pRowSet->cRows != 1)
      break;

    ASSERT(pRowSet->aRow[0].cValues == tblColumns.cValues);
    SPropValue* pVal = pRowSet->aRow[0].lpProps;

    ASSERT(pVal[0].ulPropTag == PR_DISPLAY_NAME);
    ASSERT(pVal[1].ulPropTag == PR_ENTRYID);

    LPWSTR lpStoreName = pRowSet->aRow[0].lpProps[0].Value.lpszW;

    // Open Store
    LPBYTE pEntry = (LPBYTE)pRowSet->aRow[0].lpProps[1].Value.bin.lpb;
    ULONG ulStoreBytes = pRowSet->aRow[0].lpProps[1].Value.bin.cb;

    IMsgStore* pStore = _GetStoreFromEntryID(pSession, ulStoreBytes, pEntry);
    if (pStore == NULL)
    {
      continue;
    }
    
	if (AddSink(pStore) == true) {
	}else{
	}

    pStore->Release();
    
    FreeProws(pRowSet);
  }
  
  pStoresTable->Release();
  pSession->Release();
  
  return true;
}