none
Help requested on folder move in a wrapped PST RRS feed

  • Question

  • Dear All,

    I think most of you knows about the Wrapped PST sample (http://outlookmapisamples.codeplex.com/) maintained by S. Griffin. I built it and ran it successfully.

    To go further, I tried to wrap also the store's folders. To do so, I created 2 new simple wrapper class for IMSLogon and IMAPIFolder.

    IMSProvider::Logon gave me the opportunity to wrap IMSLogon and I could wrap the IMAPIFolder result in these functions :
    - IMSLogon::OpenEntry
    - IMsgStore::OpenEntry 
    - IMAPIFolder::OpenEntry.

    Everything seems OK but there is a big issue : in Outlook, when I move  a folder (in the same store), the MAPI folder is deleted from its former place and is recreated in the new place. Of course, visually, in Outlook it is not noticeable, but the MAPI folder moved is actually recreated.
    It is very frustrating, I've been working on this case for several days and I'm going mad.

    I can share my source code if it is necessary.

    Hope someone could help me.

    Thursday, November 8, 2012 4:19 PM

Answers

  • Some people in the above mailing list gave me the answer.

    It seems that it is the way it works, they suggested to hook CopyFolder method.

    Regards

    Saturday, November 10, 2012 3:40 AM

All replies

  • Hi Patrick,

    Thanks for posting in the MSDN Forum.

    Would you please share your code? Let's do further research based on that.

    Have a good day,

    Tom


    Tom Xu [MSFT]
    MSDN Community Support | Feedback to us

    Friday, November 9, 2012 5:46 AM
    Moderator
  • Hi Tom,

    Below, are the updates I've made in CMSProvider::Logon and CMsgStore::OpenEntry

    STDMETHODIMP CMSProvider::Logon(...)
    {
    ...
    	LPMSLOGON lpMsLogon = NULL; // Added by PVA
    ...
    	if (SUCCEEDED(hRes))
    	{
    		ulFlags = (ulFlags & ~MDB_OST_LOGON_ANSI) | MDB_OST_LOGON_UNICODE;
    
    		hRes = m_pPSTMS->Logon(
    			pMySup,
    			ulUIParam,
    			pszProfileName,
    			cbEntryID,
    			pEntryID,
    			ulFlags,
    			pInterface,
    			pcbSpoolSecurity,
    			ppbSpoolSecurity,
    			ppMAPIError,
    			&lpMsLogon,
    			// Modified by PVA
    			//ppMSLogon,
    			&lpPSTMDB);
    	}
    ...
    	*ppMDB = pWrappedMDB;
    
    	//Added by PVA
    	if (lpMsLogon)
    	{
    		*ppMSLogon = (LPMSLOGON) new CMsLogon(lpMsLogon);
    	}
    	else
    	{
    		*ppMSLogon = NULL;
    	}
    
    	if (lpProfSect) lpProfSect->Release();
    
    	if (lpMsLogon)
    	{
    		lpMsLogon = NULL;
    	}
    
    	return hRes;
    } // CMSProvider::Logon
    STDMETHODIMP CMsgStore::OpenEntry (...)
    {
    	Log(true,"CMsgStore::OpenEntry\n");
    	HRESULT hRes = S_OK;
    
    	LPUNKNOWN lpUnknown = NULL;
    
    	if (SUCCEEDED(hRes = m_pPSTMsgStore->OpenEntry(
    		cbEntryID,
    		pEntryID,
    		pInterface,
    		ulFlags,
    		pulObjType,
    		&lpUnknown)))
    	{
    		switch (*pulObjType) {
    			case MAPI_FOLDER:
    				*ppUnk = (LPMAPIFOLDER) new CMAPIFolder((LPMAPIFOLDER) lpUnknown);
    				break;
    			default:
    				*ppUnk = lpUnknown;
    				break;
    		}
    
    	}
    
    	if (lpUnknown)
    	{
    		lpUnknown = NULL;
    	}
    
    	Log(true,"CMsgStore::OpenEntry returned 0x%08X\n", hRes);
    	return hRes;
    }

    Thank you for your interest.

    Patrick

    Friday, November 9, 2012 11:17 AM
  • The code for CMAPIFolder.h

    #pragma once
    
    #if !defined(C_MAPI_FOLDER_H)
    #define C_MAPI_FOLDER_H
    
    class CMAPIFolder : public IMAPIFolder
    {
    public:
    ///////////////////////////////////////////////////////////////////////////////
    // Interface virtual member functions
    //
    	MAPI_IUNKNOWN_METHODS(IMPL);
    	MAPI_IMAPIPROP_METHODS(IMPL);
    	MAPI_IMAPICONTAINER_METHODS(IMPL);
    	MAPI_IMAPIFOLDER_METHODS(IMPL);
    
    	CMAPIFolder(LPMAPIFOLDER);
    	~CMAPIFolder();
    
    private:
        ULONG m_cRef;
    	LPMAPIFOLDER m_pMapiFolder;
    };
    
    #endif // !defined (C_MAPI_FOLDER_H)

    and for CMAPIFolder.cpp

    #include "stdafx.h"
    
    CMAPIFolder::CMAPIFolder(LPMAPIFOLDER lpMAPIFolder) : m_pMapiFolder(lpMAPIFolder), m_cRef(1)
    {
    }
    
    CMAPIFolder::~CMAPIFolder()
    {
    }
    
    STDMETHODIMP_(ULONG) CMAPIFolder::AddRef()
    {
    	if (!m_pMapiFolder)
    	{
    		return NULL;
    	}
    	else 
    	{
    		InterlockedIncrement((LONG *) &m_cRef);
    		ULONG ulRef = m_pMapiFolder->AddRef();
    		return ulRef;
    	}
    }
    
    STDMETHODIMP_(ULONG) CMAPIFolder::Release()
    {
    	if (!m_pMapiFolder)
    	{
    		return NULL;
    	}
    	else
    	{
    		ULONG ulRef = m_pMapiFolder->Release();
    						
    		if (InterlockedDecrement((LONG *) &m_cRef) == 0) {
    			m_pMapiFolder = NULL;
    			delete this;
    			return 0;
    		}
    
    		return ulRef;
    	}
    }
    
    STDMETHODIMP CMAPIFolder::QueryInterface(REFIID riid, LPVOID *lppvObj)
    {
    	if (!m_pMapiFolder) return E_NOINTERFACE;
    
    	if (riid == IID_IMAPIFolder || riid == IID_IUnknown)
    	{
    		*lppvObj = (LPVOID)this;
    		AddRef();
    
    		return S_OK;
    	}
    
    	return m_pMapiFolder->QueryInterface(riid, lppvObj);
    }
    
    STDMETHODIMP CMAPIFolder::CreateMessage(LPCIID lpInterface, ULONG ulFlags, LPMESSAGE FAR *lppMessage)
    {
    	return m_pMapiFolder->CreateMessage(lpInterface, ulFlags, lppMessage);
    }
    	
    STDMETHODIMP CMAPIFolder::CopyMessages(LPENTRYLIST lpMsgList, LPCIID lpInterface, LPVOID lpDestFolder, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags)
    {
    	return m_pMapiFolder->CopyMessages(lpMsgList, lpInterface, lpDestFolder, ulUIParam, lpProgress, ulFlags);
    }
    	
    STDMETHODIMP CMAPIFolder::DeleteMessages(LPENTRYLIST lpMsgList, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags)
    {
    	return m_pMapiFolder->DeleteMessages(lpMsgList, ulUIParam, lpProgress, ulFlags);
    }
    	
    STDMETHODIMP CMAPIFolder::CreateFolder(ULONG ulFolderType, LPTSTR lpszFolderName, LPTSTR lpszFolderComment, LPCIID lpInterface, ULONG ulFlags, LPMAPIFOLDER FAR *lppFolder)
    {
    	return m_pMapiFolder->CreateFolder(ulFolderType, lpszFolderName, lpszFolderComment, lpInterface, ulFlags, lppFolder);
    }
    	
    STDMETHODIMP CMAPIFolder::CopyFolder(ULONG cbEntryID, LPENTRYID lpEntryID, LPCIID lpInterface, LPVOID lpDestFolder, LPTSTR lpszNewFolderName, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags)
    {
    	return m_pMapiFolder->CopyFolder(cbEntryID, lpEntryID, lpInterface, lpDestFolder, lpszNewFolderName, ulUIParam, lpProgress, ulFlags);
    }
    	
    STDMETHODIMP CMAPIFolder::DeleteFolder(ULONG cbEntryID, LPENTRYID lpEntryID, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags)
    {
    	return m_pMapiFolder->DeleteFolder(cbEntryID, lpEntryID, ulUIParam, lpProgress, ulFlags);
    }
    	
    STDMETHODIMP CMAPIFolder::SetReadFlags(LPENTRYLIST lpMsgList, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags)
    {
    	return m_pMapiFolder->SetReadFlags(lpMsgList, ulUIParam, lpProgress, ulFlags);
    }
    	
    STDMETHODIMP CMAPIFolder::GetMessageStatus(ULONG cbEntryID, LPENTRYID lpEntryID, ULONG ulFlags, ULONG FAR * lpulMessageStatus)
    {
    	return m_pMapiFolder->GetMessageStatus(cbEntryID, lpEntryID, ulFlags, lpulMessageStatus);
    }
    	
    STDMETHODIMP CMAPIFolder::SetMessageStatus(ULONG cbEntryID, LPENTRYID lpEntryID, ULONG ulNewStatus, ULONG ulNewStatusMask, ULONG FAR * lpulOldStatus)
    {
    	return m_pMapiFolder->SetMessageStatus(cbEntryID, lpEntryID, ulNewStatus, ulNewStatusMask, lpulOldStatus);
    }
    	
    STDMETHODIMP CMAPIFolder::SaveContentsSort(LPSSortOrderSet lpSortCriteria, ULONG ulFlags)
    {
    	return m_pMapiFolder->SaveContentsSort(lpSortCriteria, ulFlags);
    }
    	
    STDMETHODIMP CMAPIFolder::EmptyFolder(ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags)
    {
    	return m_pMapiFolder->EmptyFolder(ulUIParam, lpProgress, ulFlags);
    }
    
    STDMETHODIMP CMAPIFolder::GetContentsTable(ULONG ulFlags, LPMAPITABLE FAR *lppTable)
    {
    	return m_pMapiFolder->GetContentsTable(ulFlags, lppTable);
    }
    
    STDMETHODIMP CMAPIFolder::GetHierarchyTable(ULONG ulFlags, LPMAPITABLE FAR *lppTable)
    {
    	return m_pMapiFolder->GetHierarchyTable(ulFlags, lppTable);
    }
    
    STDMETHODIMP CMAPIFolder::OpenEntry(ULONG cbEntryID, LPENTRYID lpEntryID, LPCIID lpInterface, ULONG ulFlags, ULONG FAR *lpulObjType, LPUNKNOWN FAR *lppUnk)
    {
    	HRESULT hRes = S_OK;
    
    	LPUNKNOWN lpUnknown = NULL;
    
    	if (SUCCEEDED(hRes = m_pMapiFolder->OpenEntry(cbEntryID, lpEntryID, lpInterface, ulFlags, lpulObjType, &lpUnknown)))
    	{
    		switch (*lpulObjType) {
    			case MAPI_FOLDER:
    				*lppUnk = (LPMAPIFOLDER) new CMAPIFolder((LPMAPIFOLDER) lpUnknown);
    				break;
    			default:
    				*lppUnk = lpUnknown;
    				break;
    		}
    	}
    
    	if (lpUnknown)
    	{
    		lpUnknown = NULL;
    	}
    		
    	return hRes;
    }
    
    STDMETHODIMP CMAPIFolder::SetSearchCriteria(LPSRestriction lpRestriction, LPENTRYLIST lpContainerList, ULONG ulSearchFlags)
    {
    	return m_pMapiFolder->SetSearchCriteria(lpRestriction, lpContainerList, ulSearchFlags);
    }
    
    STDMETHODIMP CMAPIFolder::GetSearchCriteria(ULONG ulFlags, LPSRestriction FAR *lppRestriction, LPENTRYLIST FAR *lppContainerList, ULONG FAR *lpulSearchState)
    {
    	return m_pMapiFolder->GetSearchCriteria(ulFlags, lppRestriction, lppContainerList, lpulSearchState);
    }
    
    STDMETHODIMP CMAPIFolder::GetLastError(HRESULT hError, ULONG ulFlags, LPMAPIERROR *ppMAPIError)
    {
    	return m_pMapiFolder->GetLastError(hError, ulFlags, ppMAPIError);
    }
    
    STDMETHODIMP CMAPIFolder::SaveChanges(ULONG ulFlags)
    {
    	return m_pMapiFolder->SaveChanges(ulFlags);
    }
    
    STDMETHODIMP CMAPIFolder::GetProps(LPSPropTagArray pPropTagArray, ULONG ulFlags, ULONG *pcValues, LPSPropValue *ppPropArray)
    {
    	return m_pMapiFolder->GetProps(pPropTagArray, ulFlags, pcValues, ppPropArray);
    }
    
    STDMETHODIMP CMAPIFolder::GetPropList(ULONG ulFlags, LPSPropTagArray *ppAllTags)
    {
    	return m_pMapiFolder->GetPropList(ulFlags, ppAllTags);
    }
    
    STDMETHODIMP CMAPIFolder::OpenProperty(ULONG ulPropTag, LPCIID piid, ULONG ulInterfaceOptions, ULONG ulFlags, LPUNKNOWN *ppUnk)
    {
    	return m_pMapiFolder->OpenProperty(ulPropTag, piid, ulInterfaceOptions, ulFlags, ppUnk);
    }
    
    STDMETHODIMP CMAPIFolder::SetProps(ULONG cValues, LPSPropValue pPropArray, LPSPropProblemArray *ppProblems)
    {
    	return m_pMapiFolder->SetProps(cValues, pPropArray, ppProblems);
    }
    
    STDMETHODIMP CMAPIFolder::DeleteProps(LPSPropTagArray pPropTagArray, LPSPropProblemArray *ppProblems)
    {
    	return m_pMapiFolder->DeleteProps(pPropTagArray, ppProblems);
    }
    
    STDMETHODIMP CMAPIFolder::CopyTo(ULONG ciidExclude, LPCIID rgiidExclude, LPSPropTagArray pExcludeProps, ULONG ulUIParam, LPMAPIPROGRESS pProgress, LPCIID pInterface, LPVOID pDestObj, ULONG ulFlags, LPSPropProblemArray *ppProblems)
    {
    	return m_pMapiFolder->CopyTo(ciidExclude, rgiidExclude, pExcludeProps, ulUIParam, pProgress, pInterface, pDestObj, ulFlags, ppProblems);
    }
    
    STDMETHODIMP CMAPIFolder::CopyProps(LPSPropTagArray pIncludeProps, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, LPCIID pInterface, LPVOID pDestObj, ULONG ulFlags, LPSPropProblemArray *ppProblems)
    {
    	return m_pMapiFolder->CopyProps(pIncludeProps, ulUIParam, lpProgress, pInterface, pDestObj, ulFlags, ppProblems);
    }
    
    STDMETHODIMP CMAPIFolder::GetNamesFromIDs(LPSPropTagArray *ppPropTags, LPGUID pPropSetGuid, ULONG ulFlags, ULONG *pcPropNames, LPMAPINAMEID **pppPropNames)
    {
    	return m_pMapiFolder->GetNamesFromIDs(ppPropTags, pPropSetGuid, ulFlags, pcPropNames, pppPropNames);
    }
    
    STDMETHODIMP CMAPIFolder::GetIDsFromNames(ULONG cPropNames, LPMAPINAMEID *ppPropNames, ULONG ulFlags, LPSPropTagArray *ppPropTags)
    {
    	return m_pMapiFolder->GetIDsFromNames(cPropNames, ppPropNames, ulFlags, ppPropTags);
    }

    Friday, November 9, 2012 11:19 AM
  • The code for CmsLogon.h

    #pragma once
    
    #if !defined(C_MS_LOGON_H)
    #define C_MS_LOGON_H
    
    class CMsLogon : public IMSLogon
    {
    public:
    ///////////////////////////////////////////////////////////////////////////////
    // Interface virtual member functions
    //
        MAPI_IUNKNOWN_METHODS(IMPL);
    
    	STDMETHODIMP GetLastError(HRESULT, ULONG, LPMAPIERROR *);
    	STDMETHODIMP Advise(ULONG, LPENTRYID, ULONG, LPMAPIADVISESINK, ULONG *);
    	STDMETHODIMP Unadvise(ULONG);
    	STDMETHODIMP CompareEntryIDs(ULONG, LPENTRYID, ULONG, LPENTRYID, ULONG, ULONG *);
    	STDMETHODIMP OpenEntry(ULONG, LPENTRYID, LPCIID, ULONG, ULONG *, LPUNKNOWN *);
    	STDMETHODIMP Logoff(ULONG FAR *);
    	STDMETHODIMP OpenStatusEntry(LPCIID, ULONG, ULONG FAR *, LPVOID FAR *);
    
        CMsLogon(LPMSLOGON);
        ~CMsLogon();
    
    private:
        ULONG m_cRef;
    	LPMSLOGON m_pMsLogon;
    };
    
    #endif // !defined (C_MS_LOGON_H)

    and for CMsLogon.cpp

    #include "stdafx.h"
    
    CMsLogon::CMsLogon(LPMSLOGON lpMsLogon) : m_pMsLogon(lpMsLogon), m_cRef(1)
    {
    }
    
    CMsLogon::~CMsLogon()
    {
    }
    
    STDMETHODIMP_(ULONG) CMsLogon::AddRef()
    {
    	if (!m_pMsLogon)
    	{
    		return NULL;
    	}
    	else 
    	{
    		InterlockedIncrement((LONG *) &m_cRef);
    		ULONG ulRef = m_pMsLogon->AddRef();
    		return ulRef;
    	}
    }
    
    STDMETHODIMP_(ULONG) CMsLogon::Release()
    {
    	if (!m_pMsLogon)
    	{
    		return NULL;
    	}
    	else
    	{
    		ULONG ulRef = m_pMsLogon->Release();
    						
    		if (InterlockedDecrement((LONG *) &m_cRef) == 0) {
    			m_pMsLogon = NULL;
    			delete this;
    			return 0;
    		}
    
    		return ulRef;
    	}
    }
    
    STDMETHODIMP CMsLogon::QueryInterface(REFIID riid, LPVOID *lppvObj)
    {
    	if (!m_pMsLogon) return E_NOINTERFACE;
    
    	if (riid == IID_IMSLogon  || riid == IID_IUnknown)
    	{
    		*lppvObj = (LPVOID)this;
    		AddRef();
    
    		return S_OK;
    	}
    
    	return m_pMsLogon->QueryInterface(riid, lppvObj);
    }
    
    STDMETHODIMP CMsLogon::GetLastError(HRESULT hError, ULONG ulFlags, LPMAPIERROR *lppMAPIError)
    {
    	return m_pMsLogon->GetLastError(hError, ulFlags, lppMAPIError);
    }
    
    STDMETHODIMP CMsLogon::Advise(ULONG cbEntryID, LPENTRYID lpEntryID, ULONG ulEventMask, LPMAPIADVISESINK lpAdviseSink, ULONG *lpulConnection)
    {
    	return m_pMsLogon->Advise(cbEntryID, lpEntryID, ulEventMask, lpAdviseSink, lpulConnection);
    }
    
    STDMETHODIMP CMsLogon::Unadvise(ULONG ulConnection)
    {
    	return m_pMsLogon->Unadvise(ulConnection);
    }
    
    STDMETHODIMP CMsLogon::CompareEntryIDs(ULONG cbEntryID1, LPENTRYID lpEntryID1, ULONG cbEntryID2, LPENTRYID lpEntryID2, ULONG ulFlags, ULONG *lpulResult)
    {
    	return m_pMsLogon->CompareEntryIDs(cbEntryID1, lpEntryID1, cbEntryID2, lpEntryID2, ulFlags, lpulResult);
    }
    
    STDMETHODIMP CMsLogon::OpenEntry(ULONG cbEntryID, LPENTRYID lpEntryID, LPCIID lpInterface, ULONG ulFlags, ULONG *lpulObjType, LPUNKNOWN *lppUnk)
    {
    	HRESULT hRes = S_OK;
    
    	LPUNKNOWN lpUnknown = NULL;
    
    	if (SUCCEEDED(hRes = m_pMsLogon->OpenEntry(cbEntryID, lpEntryID, lpInterface, ulFlags, lpulObjType, &lpUnknown)))
    	{
    		switch (*lpulObjType) {
    			case MAPI_FOLDER:
    				*lppUnk = (LPMAPIFOLDER) new CMAPIFolder((LPMAPIFOLDER) lpUnknown);
    				break;
    			default:
    				*lppUnk = lpUnknown;
    				break;
    		}
    	}
    
    	if (lpUnknown)
    	{
    		lpUnknown = NULL;
    	}
    		
    	return hRes;
    }
    
    STDMETHODIMP CMsLogon::Logoff(ULONG FAR *lpulFlags)
    {
    	return m_pMsLogon->Logoff(lpulFlags);
    }
    
    STDMETHODIMP CMsLogon::OpenStatusEntry(LPCIID lpInterface, ULONG ulFlags, ULONG FAR *lpulObjType, LPVOID FAR *lppEntry)
    {
    	return m_pMsLogon->OpenStatusEntry(lpInterface, ulFlags, lpulObjType, lppEntry);
    }
    

    Friday, November 9, 2012 11:20 AM
  • I do nto know what is causing this prroblem, but try to post at http://peach.ease.lsoft.com/archives/mapi-l.html - quite a few people there have experience with the wrapped PST provider.


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.4 is now available!

    Friday, November 9, 2012 2:13 PM
  • Some people in the above mailing list gave me the answer.

    It seems that it is the way it works, they suggested to hook CopyFolder method.

    Regards

    Saturday, November 10, 2012 3:40 AM