在做sms備份的時候,我們首先考慮的是採用mapi的形式將sms的具體內容讀出來在還原的時候寫回去,事實證明,這種方法是可行但是不可取的!
這裡先看看mapi是怎麼讀取的,這個過程中參考了無聊客寫的東西,並得到我們老員工的指點。
定義以下兩個宏,方便使用:
#define EXIT_ON_FAILED(_hr)/
if (FAILED(_hr))/
{ /
goto FuncExit; /
}
#define RELEASE_OBJ(s) /
if (s != NULL) /
{ /
s->Release(); /
s = NULL; /
}
初始化mapi :
HRESULT InitMAPI( )
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
MAPIInitialize(NULL);
// First logon to the store.
MAPILogonEx(NULL, NULL, NULL, NULL, &m_pSession);
if( !m_pSession )
return E_FAIL ;
return S_OK ;
}
// Get the message stores table
hr = m_pSession->GetMsgStoresTable(MAPI_UNICODE, &pStoresTable);
// 定義ULONG ProgColumns[] = { 2, PR_ENTRYID, PR_DISPLAY_NAME };來得到屬性
hr = pStoresTable->SetColumns((LPSPropTagArray)&ProgColumns, 0);
EXIT_ON_FAILED(hr);
以上初始化mapi並擷取store以及table!
下面使用QueryRows方法來擷取我們需要的特定的store
while(SUCCEEDED(pStoresTable->QueryRows(1, 0, &pStoresRows)))
{
if (pStoresRows->cRows != 1)
break;
else if ((pStoresRows->aRow[0].cValues < 1)
|| (pStoresRows->aRow[0].lpProps[0].ulPropTag != PR_ENTRYID))
break ;
else
{
if (_tcsicmp(pStoresRows->aRow[0].lpProps[1].Value.lpszW, _T("SMS")) == 0)
//這裡是擷取SMS資訊的,而其他的還有ActiveSyne、MMS(等等,如果有相應帳戶的話...)
{
ULONG ulMesageType;
hr = m_pSession->OpenEntry(pStoresRows->aRow[0].lpProps[0].Value.bin.cb,
(LPENTRYID)pStoresRows->aRow[0].lpProps[0].Value.bin.lpb,
NULL,
NULL,
&ulMesageType,
(LPUNKNOWN*)&pSMSStore);
//得到該store後,後面要用該store來擷取IMessage對象
EXIT_ON_FAILED(hr);
break;
}
FreeProws(pStoresRows);
pStoresRows = NULL;
}
}
if( pStoresRows )
{
FreeProws(pStoresRows);
pStoresRows = NULL;
}
RELEASE_OBJ( pStoresTable );
釋放對象儘早做吧,下面就用得到的SMS store來擷取SMS的屬性以及其他的SMS的Folder.
ULONG ProgColumns_SubTree[] = { 1, PR_IPM_SUBTREE_ENTRYID };
SPropValue * pProgValue_SubFolders = NULL;
// Get Root Folder
hr = pSMSStore->GetProps((LPSPropTagArray) ProgColumns_SubTree, MAPI_UNICODE, &ulValues, &pProgValue_SubTree);
EXIT_ON_FAILED(hr);
hr = pSMSStore->OpenEntry(pProgValue_SubTree[0].Value.bin.cb, (LPENTRYID)pProgValue_SubTree[0].Value.bin.lpb,
NULL,
NULL,
NULL,
(LPUNKNOWN*)&pSMSFolder);
MAPIFreeBuffer(pProgValue_SubTree);
//has sub folder or not
hr = pSMSFolder->GetProps((LPSPropTagArray) ProgColumns_SubFolders, MAPI_UNICODE, &ulValues, &pProgValue_SubFolders);
if( pProgValue_SubFolders[0].Value.b > 0 )
//判斷該foler 下是否有sub folder,有則進一步擷取message
hr = pFolder->GetContentsTable(0, &pContentsTable);
hr = pContentsTable->SetColumns((LPSPropTagArray)&ProgColumns_Contents, 0);
//基本同上面,擷取Table的方式有變,查錯的步驟省略
hr = pFolder->OpenEntry( pRows->aRow[0].lpProps[0].Value.bin.cb,
(LPENTRYID)pRows->aRow[0].lpProps[0].Value.bin.lpb,
NULL,
MAPI_BEST_ACCESS,
&ulMesageType,
(LPUNKNOWN*)&pMessage);
//得到message,下面便可以對message操作了。
//SMS中,利用MAPI讀出來的分兩部分處理,一是連絡人部分,另外是內容部分。SMS的內容存放在SUBJECT屬性下,而到了OutLook資訊中,SUBJECT部分則存放了資訊的主題,而內容要採取Istream的方式讀取。由於outlook的稍微複雜點,所以下面是寫出了outlook的讀取方式,儲存在自己定義的BackupTemp結構體中
hr = pMessage->GetProps((LPSPropTagArray) ProgColomns, MAPI_UNICODE, &ulCount, &pProgValue);
if (SUCCEEDED(hr))
{
if (pProgValue[0].ulPropTag == PR_SENDER_EMAIL_ADDRESS)
wcscpy( pBackupTemp->bkupHeader.szAddress , pProgValue[0].Value.lpszW);
if (pProgValue[1].ulPropTag == PR_SUBJECT)
wcscpy( pBackupTemp->bkupHeader.szSubject , pProgValue[1].Value.lpszW);
if (pProgValue[2].ulPropTag == PR_MESSAGE_DELIVERY_TIME)
pBackupTemp->bkupHeader.ftEmailTime = pProgValue[2].Value.ft;
MAPIFreeBuffer(pProgValue);
}
hr = pMessage->OpenProperty( PR_BODY, &IID_IStream, MAPI_BEST_ACCESS, NULL,
(LPUNKNOWN*) &pStream);
if(hr == S_OK)
{
pStream->Read(pBackupTemp->bkupHeader.szBody, 1024*sizeof(WCHAR), &ulNumChars);
}
本方法下面讀去mail的附件以及mms內容都比較的複雜,而且在還原的時候沒辦法兼顧所以對象的屬性(一個pim連絡人的屬性就有四十多項),不適合備份!
接下來我要做的事情又與mapi有關,我會來完善這篇文章並不斷地修正
另外讀取pim.vol的辦法我也會講明,不過對於備份來講,pim檔案可以直接拷貝還原,所以就不需要那麼麻煩了
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/leimiaomiao/archive/2007/05/31/1632897.aspx