// High Level function to open a sub folder by iterating recursively (DFS) over all folders
// (use instead of manually calling GetHierarchy and GetNextSubFolder)
LPMAPIFOLDER CMAPIEx::OpenSubFolder(LPCTSTR szSubFolder, LPMAPIFOLDER pFolder) {
    LPMAPIFOLDER pSubFolder = NULL;
    LPMAPITABLE  pHierarchy;

    RELEASE(m_pHierarchy);
    pHierarchy = GetHierarchy(pFolder);
    if (pHierarchy) {
        CString      strFolder;
        LPMAPIFOLDER pRecurse = NULL;
        do {
            RELEASE(pSubFolder);
            m_pHierarchy = pHierarchy;
            pSubFolder   = GetNextSubFolder(strFolder, pFolder);
            if (pSubFolder) {
                if (!strFolder.CompareNoCase(szSubFolder)) break;
                m_pHierarchy = NULL;               // so we don't release it in subsequent drilldown
                pRecurse     = OpenSubFolder(szSubFolder, pSubFolder);
                if (pRecurse) {
                    RELEASE(pSubFolder);
                    pSubFolder = pRecurse;
                    break;
                }
            }
        } while (pSubFolder);
        RELEASE(pHierarchy);
        m_pHierarchy = NULL;
    }
    // this may occur many times depending on how deep the recursion is; make sure we haven't already assigned m_pFolder
    if (pSubFolder && (m_pFolder != pSubFolder)) {
        RELEASE(m_pFolder);
        m_pFolder = pSubFolder;
    }
    return pSubFolder;
}
// Deletes a sub folder and ALL sub folders/messages
BOOL CMAPIEx::DeleteSubFolder(LPCTSTR szSubFolder, LPMAPIFOLDER pFolder) {
    if (!pFolder) {
        pFolder = m_pFolder;
        if (!pFolder) return FALSE;
    }

    LPMAPIFOLDER pSubFolder = NULL;
    if (GetHierarchy(pFolder)) {
        CString strFolder;
        do {
            RELEASE(pSubFolder);
            pSubFolder = GetNextSubFolder(strFolder, pFolder);
            if (pSubFolder && !strFolder.CompareNoCase(szSubFolder)) break;
        } while (pSubFolder);
    }
    return DeleteSubFolder(pSubFolder, pFolder);
}
LPMAPIFOLDER CExMapi::GetContacts(LPMAPIFOLDER pFolder,LONG& folderCount,LONG& contactCount,LONG& skipCount,LONG& contactIndex,CObArray& contactArray,BOOL doLog)
{
	__recursionCount++;
	wchar_t buffer[5];
	_itow(__recursionCount,buffer,10);
	if(doLog)
	{
		if(__recursionCount > 1)
			m_logHelper.LogPAB(L"-------------------------------------");
		m_logHelper.LogPAB(L"Recursive Call No: "+CString(buffer));
		m_logHelper.LogPAB(L"-------------------------------------");
	}
	CString strFilterBy = m_pCtrl->GetPABSerachBy();
	CString strStartWith = m_pCtrl->GetPABSerachStartWith();
	strStartWith = strStartWith.MakeLower();
	ULONG pageSize;
	m_pCtrl->get_PABPageSize(&pageSize);
	LONG pageNumber = m_pCtrl->GetPABPageNumber();
	LONG startIndex = -1;
	if(pageSize>0)
	{
		startIndex = (pageSize * pageNumber) - pageSize;
	}

	LPMAPIFOLDER pSubFolder=NULL;
	LPMAPITABLE pHierarchy;
	CString strFolder;

	try
	{
		if(doLog)
			m_logHelper.LogPAB(L"RELEASE(m_pHierarchy); START");

		RELEASE(m_pHierarchy);
		
		if(doLog)
			m_logHelper.LogPAB(L"RELEASE(m_pHierarchy); END");

		if(doLog)
			m_logHelper.LogPAB(L"pHierarchy = GetHierarchy(pFolder); START");

		pHierarchy = GetHierarchy(pFolder);

		if(doLog)
			m_logHelper.LogPAB(L"pHierarchy = GetHierarchy(pFolder); END");

		if(pHierarchy) 
		{
			LPMAPIFOLDER pRecurse = NULL;
			do 
			{
				RELEASE(pSubFolder);
				m_pHierarchy = pHierarchy;			

				if(doLog)
					m_logHelper.LogPAB(L"pSubFolder = GetNextSubFolder(strFolder,pFolder); START");

				pSubFolder = GetNextSubFolder(strFolder,pFolder);

				if(doLog)
					m_logHelper.LogPAB(L"pSubFolder = GetNextSubFolder(strFolder,pFolder); END");
			
				if(pSubFolder) 
				{
					//if(strFolder == L"Deleted Items")
					//	continue;

					if(IsContactFolder(pSubFolder))
					{
						folderCount++;
	 					if(doLog)
							m_logHelper.LogPAB(L"if(GetContents(pSubFolder)) START");

						if(GetContents(pSubFolder))
						{
							if(doLog)
								m_logHelper.LogPAB(L"if(GetContents(pSubFolder)) END");

							SortContents(TABLE_SORT_ASCEND,PR_DISPLAY_NAME);
							//SortContents(TABLE_SORT_ASCEND,PR_SUBJECT);

							CString strText;
							CExMapiContact mapiContact;
							CString name;
							CString email;
							BOOL mustFilter = FALSE;
							mustFilter = strStartWith != "";
							
							if(doLog)
								m_logHelper.LogPAB(L"Start Reading Contact properties");

							while(GetNextContact(mapiContact) && !m_pCtrl->IsPABSearchAbort()) 
							{
								if(pageSize > 0)
								{
									if(contactCount == pageSize)
									{
										break;								
									}
								}

								contactIndex++;
								if(mustFilter)
								{
									if(strFilterBy == "Name")
									{
										mapiContact.GetName(name,PR_GIVEN_NAME);
										name = name.MakeLower();
										if(name.Find(strStartWith) != 0)				
										{
											continue;									
										}
									}

									if(strFilterBy == "Email")
									{
										mapiContact.GetEmail(email);
										email = email.MakeLower();
										if(email.Find(strStartWith) != 0)
										{
											continue;
										}
									}																
								}
								if(startIndex > 0 && skipCount < startIndex)
								{
									skipCount++;
									continue;								
								}

								CContact* pContact = new CContact();

								pContact->SetId(contactIndex);

								pContact->SetFolderName(strFolder);

								mapiContact.GetName(strText);
								pContact->SetFullName(strText);

								mapiContact.GetCompany(strText);
								pContact->SetCompany(strText);

								mapiContact.GetIMAddress(strText);
								pContact->SetIMAddress(strText);

								mapiContact.GetName(strText,PR_GIVEN_NAME);
								pContact->SetFirstName(strText);

								mapiContact.GetName(strText,PR_MIDDLE_NAME);
								pContact->SetMiddleName(strText);

								mapiContact.GetName(strText,PR_SURNAME);
								pContact->SetLastName(strText);

								mapiContact.GetEmail(strText);
								pContact->SetEmail(strText);	

								mapiContact.GetEmail(strText,2);//Email 2
								pContact->SetEmail2(strText);

								mapiContact.GetEmail(strText,3);//Email 3
								pContact->SetEmail3(strText);

								mapiContact.GetPhoneNumber(strText,PR_BUSINESS_TELEPHONE_NUMBER);
								pContact->SetBusinessPhone(strText);

								mapiContact.GetPhoneNumber(strText,PR_COMPANY_MAIN_PHONE_NUMBER);
								pContact->SetCompanyPhone(strText);

								mapiContact.GetPhoneNumber(strText,PR_BUSINESS_FAX_NUMBER);
								pContact->SetFax(strText);

								mapiContact.GetPhoneNumber(strText,PR_MOBILE_TELEPHONE_NUMBER);
								pContact->SetMobilePhone(strText);

								mapiContact.GetPhoneNumber(strText,PR_HOME_TELEPHONE_NUMBER);
								pContact->SetHomePhone(strText);

								if(m_pCtrl->FetchUnique())
								{
									BOOL isContactExist = FALSE;
									for(int i=0;i<contactArray.GetCount();i++)
									{
										CContact* pTemp = (CContact*)contactArray.GetAt(i);

										if(pContact->GetEmail() != "" && pTemp->GetEmail() == pContact->GetEmail())
										{
											isContactExist = TRUE;
											break;																	
										}
										else if(pContact->GetFullName() != "" && pTemp->GetFullName() == pContact->GetFullName())
										{
											isContactExist = TRUE;
											break;
										}
										else if(pContact->GetMobilePhone() != "" && pTemp->GetMobilePhone() == pContact->GetMobilePhone())
										{
											isContactExist = TRUE;
											break;
										}
										else if(pContact->GetHomePhone() != "" && pTemp->GetHomePhone() == pContact->GetHomePhone())
										{
											isContactExist = TRUE;
											break;
										}
										else if(pContact->GetBusinessPhone() != "" && pTemp->GetBusinessPhone() == pContact->GetBusinessPhone())
										{
											isContactExist = TRUE;
											break;
										}
									}

									if(isContactExist)
									{
										continue;
									}
								}														
								contactArray.Add(pContact);							
								contactCount++;							
							}
						}
					}

					m_pHierarchy = NULL; // so we don't release it in subsequent drilldown
					if(pageSize > 0)
					{
						if(contactCount == pageSize)
							break;								
					}
					
					if(__recursionCount < m_pCtrl->GetSubFOlderLevel())
					{
						pRecurse = GetContacts(pSubFolder,folderCount,contactCount,skipCount,contactIndex,contactArray,doLog);
					}
					if(pRecurse) 
					{
						RELEASE(pSubFolder);
						pSubFolder = pRecurse;
						break;
					}
				}
				else
				{
					__recursionCount = 1;
				}
				if(pageSize > 0)
				{
					if(contactCount == pageSize)
						break;								
				}

			} while(pSubFolder && !m_pCtrl->IsPABSearchAbort());
			RELEASE(pHierarchy);
			m_pHierarchy=NULL;
		}
		// this may occur many times depending on how deep the recursion is; make sure we haven't already assigned m_pFolder
		if(pSubFolder && m_pFolder!=pSubFolder) {
			RELEASE(m_pFolder);
			m_pFolder=pSubFolder;
		}
	}
	catch(_com_error &e)
	{
		if(doLog)
		{
			m_logHelper.LogPAB(L"GetContactFolderCount Exception Catch START:");
			m_logHelper.LogPAB(L"FolderName: " + strFolder );
			m_logHelper.LogPAB(e.ErrorMessage());
			m_logHelper.LogPAB(L"GetContactFolderCount Exception Catch END:");
		}
	}
	return pSubFolder;
} 
LPMAPIFOLDER CExMapi::GetContactCount(LPMAPIFOLDER pFolder,ULONG& count, BOOL doLog)
{
	__recursionCount++;
	wchar_t buffer[5];
	_itow(__recursionCount,buffer,10);
	if(doLog)
	{
		if(__recursionCount > 1)
			m_logHelper.LogPAB(L"-------------------------------------");
		m_logHelper.LogPAB(L"Recursive Call No: "+CString(buffer));
		m_logHelper.LogPAB(L"-------------------------------------");
	}
	CString strFolder;

	
	LPMAPIFOLDER pSubFolder=NULL;
	LPMAPITABLE pHierarchy;
	try
	{
		if(doLog)
			m_logHelper.LogPAB(L"RELEASE(m_pHierarchy) 1 START");

		RELEASE(m_pHierarchy);

		if(doLog)
			m_logHelper.LogPAB(L"RELEASE(m_pHierarchy) 1 END");

		if(doLog)
			m_logHelper.LogPAB(L"pHierarchy = GetHierarchy(pFolder) START");

		pHierarchy = GetHierarchy(pFolder);

		if(doLog)
			m_logHelper.LogPAB(L"pHierarchy = GetHierarchy(pFolder) END");

		if(pHierarchy) 
		{
			LPMAPIFOLDER pRecurse = NULL;
			do 
			{
				if(doLog)
					m_logHelper.LogPAB(L"RELEASE(pSubFolder) 1 START");

				RELEASE(pSubFolder);

				if(doLog)
					m_logHelper.LogPAB(L"RELEASE(pSubFolder) 1 END");

				m_pHierarchy = pHierarchy;
				if(doLog)
					m_logHelper.LogPAB(L"pSubFolder = GetNextSubFolder(strFolder,pFolder) START");

				pSubFolder = GetNextSubFolder(strFolder,pFolder);

				if(doLog)
					m_logHelper.LogPAB(L"pSubFolder = GetNextSubFolder(strFolder,pFolder) END");
				
				if(pSubFolder) 
				{
					if(strFolder == L"Deleted Items")
						continue;
					if(doLog)
						m_logHelper.LogPAB(L"if(IsContactFolder(pSubFolder)) START");

					if(IsContactFolder(pSubFolder))
					{
						if(doLog)
							m_logHelper.LogPAB(L"if(GetContents(pSubFolder)) START");
						if(GetContents(pSubFolder))
						{
							if(doLog)
								m_logHelper.LogPAB(L"GetRowCount() START");

							count += GetRowCount();

							if(doLog)
								m_logHelper.LogPAB(L"GetRowCount() END");
						}
						if(doLog)
							m_logHelper.LogPAB(L"if(GetContents(pSubFolder)) END");
					}
					if(doLog)
						m_logHelper.LogPAB(L"if(IsContactFolder(pSubFolder)) END");

					m_pHierarchy = NULL; // so we don't release it in subsequent drilldown

					if(__recursionCount < m_pCtrl->GetSubFOlderLevel())
					{	
						if(doLog)
							m_logHelper.LogPAB(L"pRecurse = GetContactFolderCount(pSubFolder,count) START");

						pRecurse = GetContactCount(pSubFolder,count,doLog);

						if(doLog)
							m_logHelper.LogPAB(L"pRecurse = GetContactFolderCount(pSubFolder,count) END");
					}

					if(pRecurse) 
					{
						if(doLog)
							m_logHelper.LogPAB(L"RELEASE(pSubFolder) 2 START");

						RELEASE(pSubFolder);

						if(doLog)
							m_logHelper.LogPAB(L"RELEASE(pSubFolder) 2 END");

						pSubFolder = pRecurse;
						break;
					}
				}
				else
				{
					__recursionCount = 1;
				}
			} while(pSubFolder&& !m_pCtrl->IsPABContactCoutningAbort());
			if(doLog)
				m_logHelper.LogPAB(L"RELEASE(m_pHierarchy) 2 START");

			RELEASE(pHierarchy);

			if(doLog)
				m_logHelper.LogPAB(L"RELEASE(m_pHierarchy) 2 END");

			m_pHierarchy=NULL;
		}
		// this may occur many times depending on how deep the recursion is; make sure we haven't already assigned m_pFolder
		if(pSubFolder && m_pFolder!=pSubFolder) {
			if(doLog)
				m_logHelper.LogPAB(L"RELEASE(m_pFolder) START");

			RELEASE(m_pFolder);

			if(doLog)
				m_logHelper.LogPAB(L"RELEASE(m_pFolder) END");

			m_pFolder=pSubFolder;
		}
	}
	catch(_com_error &e)
	{
		
		//TCHAR error[MAX_PATH];
		//e->GetErrorMessage(error,MAX_PATH);
		if(doLog)
		{
			m_logHelper.LogPAB(L"GetContactCount Exception Catch START:");
			m_logHelper.LogPAB(L"FolderName: " + strFolder );
			m_logHelper.LogPAB(e.ErrorMessage());
			m_logHelper.LogPAB(L"GetContactCount Exception Catch END:");
		}
	}
	return pSubFolder;
}