// -------------------------------------------------------------------------------- // Mimetest.cpp // // This is a console app that has various types of functions that highlight the // most typical ways to use mimeole. This console app also acts as a test program // for mimeole, but does not actually do anything. // // Here are the files you need to use mimeole: // // mimeole.h - This is the main header file. It is generated from mimeole.idl. // mimeole.idl - This is the interface definition file. It has a little bit of // documentation. A client should use this file to find out info // about mimeole interfaces, data types, utility functions, etc. // inetcomm.dll - This is the DLL that contains the implementation of everything // in mimeole.h. You should run regsvr32.exe on inetcomm.dll. // msoert2.dll - inetcomm.dll statically links to this dll. msoert2 is the Microsoft // Outlook Express runtime library. msoert2.dll is part of the Outlook // Express installation. This DLL does not require any registration. // shlwapi.dll - inetcomm.dll statically links to this dll. shlwapi is part of the // Internet Explorer installation. shlwapi does not require any // registration. // mlang.dll - inetcomm.dll will dynamically load this dll. mlang is used to support // various character set translations. mlang stands for multi-language. // This DLL is part of the Internet Explorer installation. You should // run regsvr32.exe on mlang.dll to register it. // urlmon.dll - inetcomm.dll will dynamically load this dll. urlmon is used by // inetcomm to support various parts of MHTML as well as rendering // MHTML inside of the IE browser. // SMIME - SMIME support in mimeole requires the crypto API, which is part of // the IE installation. // Notes: shlwapi and msoert2, as well as any other DLLs that inetcomm.dll statically // links to must be either in the same directory as inetcomm.dll, or be located // in a directory that is in the system path. // // The DLLs that inetcomm dynamically load are not required. Inetcomm will still // work, although certain functionality will be disabled. // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // To use mimeole objects, per COM rules, you must have one file in your project that // has the #define INITGUID line, and then include mimeole.h. This will cause all of // the CLSIDs and IIDs to be defined. // -------------------------------------------------------------------------------- #define INITGUID // -------------------------------------------------------------------------------- // This is simply my precompiled header // -------------------------------------------------------------------------------- #include "pch.h" #include #include // -------------------------------------------------------------------------------- // Part of the initguid process // -------------------------------------------------------------------------------- #include // -------------------------------------------------------------------------------- // Primary mimeole header file // -------------------------------------------------------------------------------- #include #define DEFINE_HOTSTORE // -------------------------------------------------------------------------------- // I'm disable various parts of MOSERT so that I can use it from within this test // program. // -------------------------------------------------------------------------------- #define MSOERT_NO_PROTSTOR #define MSOERT_NO_BYTESTM #define MSOERT_NO_STRPARSE #define MSOERT_NO_ENUMFMT #define MSOERT_NO_CLOGFILE #define MSOERT_NO_DATAOBJ // -------------------------------------------------------------------------------- // I know you don't have this, but you can if you want it. This header has a bunch // of slick macros. I will try not to use too many of them. // -------------------------------------------------------------------------------- #include "d:\\athena\\inc\\msoert.h" // -------------------------------------------------------------------------------- // Test function Prototypes // -------------------------------------------------------------------------------- HRESULT MimeTestAppendRfc822(IMimeMessage **ppMessage); HRESULT MimeTestSettingContentLocation(IMimeMessage **ppMessage); HRESULT MimeTestGetMultiValueAddressProp(IMimeMessage **ppMessage); HRESULT MimeTestLookupCharsetHandle(LPCSTR pszCharset, LPHCHARSET phCharset); HRESULT MimeTestSettingReplyTo(IMimeMessage **ppMessage); HRESULT MimeTestSplitMessageIntoParts(void); HRESULT MimeTestRecombineMessageParts(LPWSTR *prgpszFile, ULONG cFiles); HRESULT MimeTestIsContentType(IMimeMessage **ppMessage); HRESULT MimeTestBodyStream(IMimeMessage **ppMessage); HRESULT MimeTestDeleteBody(IMimeMessage **ppMessage); HRESULT MimeTestEnumHeaderTable(IMimeMessage **ppMessage); HRESULT MimeTestCDO(IMimeMessage **ppMessage); // -------------------------------------------------------------------------------- // Utility functions used by mimetest // -------------------------------------------------------------------------------- HRESULT DumpStreamToConsole(IStream *pStream); HRESULT ReportError(LPCSTR pszFunction, INT nLine, LPCSTR pszErrorText, HRESULT hrResult); HRESULT ReportStatus(LPCSTR pszStatusText); HRESULT CreateMimeMessage(IMimeMessage **ppMessage); HRESULT SaveMimeMessage(IMimeMessage *pMessage, MIMESAVETYPE savetype, IStream **ppStream); // -------------------------------------------------------------------------------- // Testing Switches // -------------------------------------------------------------------------------- // #define TEST_MimeTestAppendRfc822 // #define TEST_MimeTestSettingContentLocation // #define TEST_MimeTestGetMultiValueAddressProp // #define TEST_MimeTestSettingReplyTo // #define TEST_MimeTestSplitMessageIntoParts // #define TEST_MimeTestIsContentType // #define TEST_MimeTestBodyStream // #define TEST_MimeTestDeleteBody // #define TEST_MimeTestEnumHeaderTable #define TEST_MimeTestCDO // -------------------------------------------------------------------------------- // MimeTest Entry Point // -------------------------------------------------------------------------------- void __cdecl main(int argc, char *argv[]) { // Locals HRESULT hr; IMimeMessage *pMessage=NULL; // You must always call this if you are going to use COM hr = CoInitialize(NULL); if (FAILED(hr)) { ReportError("main", __LINE__, "CoInitialize failed.", hr); exit(1); } IDatabaseTable *pTable; HROWSET hRowset; MESSAGEINFO Message; CoCreateInstance(CLSID_DatabaseTable, NULL, CLSCTX_INPROC_SERVER, IID_IDatabaseTable, (LPVOID *)&pTable); pTable->Open("d:\\store\\00000004.dbx", 0, &g_MessageTableSchema, NULL); pTable->CreateRowset(IINDEX_SUBJECT, 0, &hRowset); while (S_OK == pTable->QueryRowset(hRowset, 1, (LPVOID *)&Message, NULL)) { printf("%08d: %s\n", Message.idMessage, Message.pszSubject); pTable->FreeRecord(&Message); } pTable->CloseRowset(&hRowset); pTable->Release(); exit(1); // ---------------------------------------------------------------------------- // TEST_MimeTestCDO // ---------------------------------------------------------------------------- #ifdef TEST_MimeTestCDO MimeTestCDO(NULL); #endif // ---------------------------------------------------------------------------- // TEST_MimeTestEnumHeaderTable // ---------------------------------------------------------------------------- #ifdef TEST_MimeTestEnumHeaderTable hr = MimeTestEnumHeaderTable(NULL); if (FAILED(hr)) { ReportError("main", __LINE__, "MimeTestEnumHeaderTable failed.", hr); goto exit; } #endif // ---------------------------------------------------------------------------- // TEST_MimeTestDeleteBody // ---------------------------------------------------------------------------- #ifdef TEST_MimeTestDeleteBody hr = MimeTestDeleteBody(NULL); if (FAILED(hr)) { ReportError("main", __LINE__, "MimeTestDeleteBody failed.", hr); goto exit; } #endif // ---------------------------------------------------------------------------- // TEST_MimeTestBodyStream // ---------------------------------------------------------------------------- #ifdef TEST_MimeTestBodyStream hr = MimeTestBodyStream(NULL); if (FAILED(hr)) { ReportError("main", __LINE__, "MimeTestBodyStream failed.", hr); goto exit; } #endif // ---------------------------------------------------------------------------- // TEST_MimeTestIsContentType // ---------------------------------------------------------------------------- #ifdef TEST_MimeTestIsContentType hr = MimeTestIsContentType(NULL); if (FAILED(hr)) { ReportError("main", __LINE__, "MimeTestIsContentType failed.", hr); goto exit; } #endif // ---------------------------------------------------------------------------- // TEST_MimeTestAppendRfc822 // ---------------------------------------------------------------------------- #ifdef TEST_MimeTestAppendRfc822 hr = MimeTestAppendRfc822(NULL); if (FAILED(hr)) { ReportError("main", __LINE__, "MimeTestAppendRfc822 failed.", hr); goto exit; } #endif // ---------------------------------------------------------------------------- // TEST_MimeTestGetMultiValueAddressProp // ---------------------------------------------------------------------------- #ifdef TEST_MimeTestGetMultiValueAddressProp hr = MimeTestGetMultiValueAddressProp(NULL); if (FAILED(hr)) { ReportError("main", __LINE__, "MimeTestAppendRfc822 failed.", hr); goto exit; } #endif // ---------------------------------------------------------------------------- // TEST_MimeTestSettingContentLocation // ---------------------------------------------------------------------------- #ifdef TEST_MimeTestSettingContentLocation hr = MimeTestSettingContentLocation(NULL); if (FAILED(hr)) { ReportError("main", __LINE__, "MimeTestSettingContentLocation failed.", hr); goto exit; } #endif // ---------------------------------------------------------------------------- // TEST_MimeTestSettingReplyTo // ---------------------------------------------------------------------------- #ifdef TEST_MimeTestSettingReplyTo hr = MimeTestSettingReplyTo(NULL); if (FAILED(hr)) { ReportError("main", __LINE__, "MimeTestSettingReplyTo failed.", hr); goto exit; } #endif // ---------------------------------------------------------------------------- // TEST_MimeTestSplitMessageIntoParts // ---------------------------------------------------------------------------- #ifdef TEST_MimeTestSplitMessageIntoParts hr = MimeTestSplitMessageIntoParts(); if (FAILED(hr)) { ReportError("main", __LINE__, "MimeTestSplitMessageIntoParts failed.", hr); goto exit; } #endif exit: // Cleanup if (pMessage) pMessage->Release(); // I called CoInitialize, so lets call this... CoUninitialize(); // Done exit(1); } // -------------------------------------------------------------------------------- // MimeTestCDO // -------------------------------------------------------------------------------- //#define RAID_17675 #define RAID_20406 //#define RAID_29961 HRESULT MimeTestCDO(IMimeMessage **ppMessage) { // Locals HRESULT hr=S_OK; IMimeMessage *pMessage=NULL; IPersistFile *pPersistFile=NULL; PROPVARIANT Variant; LPSTR psz; FINDBODY FindBody={0}; HBODY hBody; HCHARSET hCharset; IMimeBody *pBody=NULL; IMimeInternational *pInternat=NULL; // Create a message object hr = CreateMimeMessage(&pMessage); if (FAILED(hr)) goto exit; #ifdef RAID_29961 hr = CoCreateInstance(CLSID_IMimeInternational, NULL, CLSCTX_INPROC_SERVER, IID_IMimeInternational, (LPVOID *)&pInternat); if (FAILED(hr)) goto exit; hr = pMessage->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile); if (FAILED(hr)) goto exit; hr = pPersistFile->Load(L"j:\\test\\raid29961.eml", STGM_READ | STGM_SHARE_DENY_NONE); if (FAILED(hr)) goto exit; FindBody.pszPriType = "text"; FindBody.pszSubType = "plain"; hr = pMessage->FindFirst(&FindBody, &hBody); if (FAILED(hr)) goto exit; hr = pMessage->BindToObject(hBody, IID_IMimeBody, (LPVOID *)&pBody); if (FAILED(hr)) goto exit; hr = pInternat->FindCharset("iso-8859-7", &hCharset); if (FAILED(hr)) goto exit; hr = pBody->SetCharset(hCharset, CSET_APPLY_ALL); if (FAILED(hr)) goto exit; pBody->Release(); pBody = NULL; hr = pMessage->FindNext(&FindBody, &hBody); if (FAILED(hr)) goto exit; hr = pMessage->BindToObject(hBody, IID_IMimeBody, (LPVOID *)&pBody); if (FAILED(hr)) goto exit; hr = pInternat->FindCharset("iso-8859-4", &hCharset); if (FAILED(hr)) goto exit; hr = pBody->SetCharset(hCharset, CSET_APPLY_ALL); if (FAILED(hr)) goto exit; pBody->Release(); pBody = NULL; hr = pInternat->FindCharset("iso-8859-3", &hCharset); if (FAILED(hr)) goto exit; hr = pMessage->SetCharset(hCharset, CSET_APPLY_UNTAGGED); if (FAILED(hr)) goto exit; hr = pPersistFile->Save(L"j:\\test\\raid29961_saved.eml", FALSE); if (FAILED(hr)) goto exit; #endif #ifdef RAID_17675 // Get an IPersistFile hr = pMessage->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile); if (FAILED(hr)) goto exit; // Load hr = pPersistFile->Load(L"c:\\test\\cdo.eml", STGM_READ | STGM_SHARE_DENY_NONE); if (FAILED(hr)) goto exit; ZeroMemory(&Variant, sizeof(PROPVARIANT)); Variant.vt = VT_EMPTY; hr = pMessage->SetProp("par:content-type:charset", 0, &Variant); // if (FAILED(hr)) // goto exit; Variant.vt = VT_LPSTR; hr = pMessage->GetProp("par:content-type:charset", 0, &Variant); if (FAILED(hr)) goto exit; #endif // RAID_17675 #ifdef RAID_20406 // Get an IPersistFile hr = pMessage->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile); if (FAILED(hr)) goto exit; // Load hr = pPersistFile->Load(L"c:\\test\\address.eml", STGM_READ | STGM_SHARE_DENY_NONE); if (FAILED(hr)) goto exit; pMessage->GetAddressFormat(IAT_TO, AFT_DISPLAY_FRIENDLY, &psz); printf("AFT_DISPLAY_FRIENDLY: %s\n", psz); CoTaskMemFree(psz); pMessage->GetAddressFormat(IAT_TO, AFT_DISPLAY_EMAIL, &psz); printf("AFT_DISPLAY_EMAIL: %s\n", psz); CoTaskMemFree(psz); pMessage->GetAddressFormat(IAT_TO, AFT_DISPLAY_BOTH, &psz); printf("AFT_DISPLAY_BOTH: %s\n", psz); CoTaskMemFree(psz); pMessage->GetAddressFormat(IAT_TO, AFT_RFC822_DECODED, &psz); printf("AFT_RFC822_DECODED: %s\n", psz); CoTaskMemFree(psz); pMessage->GetAddressFormat(IAT_TO, AFT_RFC822_ENCODED, &psz); printf("AFT_RFC822_ENCODED: %s\n", psz); CoTaskMemFree(psz); pMessage->GetAddressFormat(IAT_TO, AFT_RFC822_TRANSMIT, &psz); printf("AFT_RFC822_TRANSMIT: %s\n", psz); CoTaskMemFree(psz); #endif // RAID_20406 exit: // Cleanup if (pMessage) pMessage->Release(); if (pPersistFile) pPersistFile->Release(); if (pInternat) pInternat->Release(); // Done return(hr); } // -------------------------------------------------------------------------------- // MimeTestEnumHeaderTable // -------------------------------------------------------------------------------- HRESULT MimeTestEnumHeaderTable(IMimeMessage **ppMessage) { // Locals HRESULT hr=S_OK; IMimeMessage *pMessage=NULL; IPersistFile *pPersistFile=NULL; IMimeHeaderTable *pTable=NULL; IMimeEnumHeaderRows *pEnum=NULL; ENUMHEADERROW Row; // Create a message object hr = CreateMimeMessage(&pMessage); if (FAILED(hr)) { ReportError("MimeTestEnumHeaderTable", __LINE__, "CreateMimeMessage failed.", hr); goto exit; } // Get an IPersistFile hr = pMessage->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile); if (FAILED(hr)) { ReportError("MimeTestEnumHeaderTable", __LINE__, "IMimeMessage::QueryInterface(IID_IPersistFile) failed.", hr); goto exit; } // Load hr = pPersistFile->Load(L"c:\\test\\multiadd.eml", STGM_READ | STGM_SHARE_DENY_NONE); if (FAILED(hr)) { ReportError("MimeTestEnumHeaderTable", __LINE__, "IPersistFile::Load failed.", hr); goto exit; } // Get Enumerator hr = pMessage->BindToObject(HBODY_ROOT, IID_IMimeHeaderTable, (LPVOID *)&pTable); if (FAILED(hr)) { ReportError("MimeTestEnumHeaderTable", __LINE__, "pMessage->BindToObject(HBODY_ROOT, IID_IMimeHeaderTable, ...) failed.", hr); goto exit; } // EnumRows hr = pTable->EnumRows(NULL, 0, &pEnum); if (FAILED(hr)) { ReportError("MimeTestEnumHeaderTable", __LINE__, "pTable->EnumRows failed.", hr); goto exit; } // Loop while (S_OK == pEnum->Next(1, &Row, NULL)) { printf("%s: %s\n", Row.pszHeader, Row.pszData); CoTaskMemFree(Row.pszHeader); CoTaskMemFree(Row.pszData); } // Return a message object if (ppMessage) { (*ppMessage) = pMessage; (*ppMessage)->AddRef(); } exit: // Cleanup if (pPersistFile) pPersistFile->Release(); if (pMessage) pMessage->Release(); if (pTable) pTable->Release(); if (pEnum) pEnum->Release(); // Done return hr; } // -------------------------------------------------------------------------------- // MimeTestDeleteBody // -------------------------------------------------------------------------------- HRESULT MimeTestDeleteBody(IMimeMessage **ppMessage) { // Locals HRESULT hr=S_OK; IMimeMessage *pMessage=NULL; IPersistFile *pPersistFile=NULL; HBODY hBody; // Create a message object hr = CreateMimeMessage(&pMessage); if (FAILED(hr)) { ReportError("MimeTestDeleteBody", __LINE__, "CreateMimeMessage failed.", hr); goto exit; } // Get an IPersistFile hr = pMessage->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile); if (FAILED(hr)) { ReportError("MimeTestDeleteBody", __LINE__, "IMimeMessage::QueryInterface(IID_IPersistFile) failed.", hr); goto exit; } // Load hr = pPersistFile->Load(L"d:\\test\\delbody.eml", STGM_READ | STGM_SHARE_DENY_NONE); if (FAILED(hr)) { ReportError("MimeTestDeleteBody", __LINE__, "IPersistFile::Load failed.", hr); goto exit; } // Load hr = pPersistFile->Load(L"d:\\test\\delbody.eml", STGM_READ | STGM_SHARE_DENY_NONE); if (FAILED(hr)) { ReportError("MimeTestDeleteBody", __LINE__, "IPersistFile::Load failed.", hr); goto exit; } goto exit; // Get the root body hr = pMessage->GetBody(IBL_ROOT, NULL, &hBody); if (FAILED(hr)) { ReportError("MimeTestDeleteBody", __LINE__, "pMessage->GetBody failed.", hr); goto exit; } // Get the root body hr = pMessage->GetBody(IBL_FIRST, hBody, &hBody); if (FAILED(hr)) { ReportError("MimeTestDeleteBody", __LINE__, "pMessage->GetBody failed.", hr); goto exit; } // Delete the Root hr = pMessage->DeleteBody(hBody, DELETE_PROMOTE_CHILDREN); if (FAILED(hr)) { ReportError("MimeTestDeleteBody", __LINE__, "pMessage->DeleteBody failed.", hr); goto exit; } // Get the root body hr = pMessage->GetBody(IBL_ROOT, NULL, &hBody); if (FAILED(hr)) { ReportError("MimeTestDeleteBody", __LINE__, "pMessage->GetBody failed.", hr); goto exit; } // Delete the Root hr = pMessage->DeleteBody(hBody, 0); if (FAILED(hr)) { ReportError("MimeTestDeleteBody", __LINE__, "pMessage->DeleteBody failed.", hr); goto exit; } // Return a message object if (ppMessage) { (*ppMessage) = pMessage; (*ppMessage)->AddRef(); } exit: // Cleanup if (pPersistFile) pPersistFile->Release(); if (pMessage) pMessage->Release(); // Done return hr; } // -------------------------------------------------------------------------------- // MimeTestBodyStream // -------------------------------------------------------------------------------- #if 0 HRESULT MimeTestBodyStream(IMimeMessage **ppMessage) { // Locals HRESULT hr=S_OK; IMimeMessage *pMessage=NULL; IStream *pStmSave=NULL; IStream *pStmBody=NULL; IStream *pStmText=NULL; IStream *pStmTxtOut=NULL; IMimeBody *pBody=NULL; PROPVARIANT rVariant; IWaveAudio *pWave=NULL; IWaveStream *pStmWave=NULL; DWORD cAttach; HBODY hBody; HBODY *prghAttach=NULL; DWORD cb; DWORD dw; // Create a message object hr = CreateMimeMessage(&pMessage); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "CreateMimeMessage failed.", hr); goto exit; } // Create a stream in which to save the message... hr = CreateStreamOnHGlobal(NULL, TRUE, &pStmText); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "CreateStreamOnHGlobal failed", hr); goto exit; } // Write some text into pStmText hr = pStmText->Write("Testing BodyStream.", lstrlen("Testing BodyStream."), NULL); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "pStmText->Write failed", hr); goto exit; } // Commit pStmText->Commit(STGC_DEFAULT); // Rewind it HrRewindStream(pStmText); // Set the text body hr = pMessage->SetTextBody(TXT_PLAIN, IET_BINARY, NULL, pStmText, NULL); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "pMessage->SetTextBody failed", hr); goto exit; } // Attach a file hr = pMessage->AttachFile("d:\\waveedit\\test.wav", NULL, NULL); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "IMimeMessage::AttachFile failed.", hr); goto exit; } // Save that bad boy to a stream hr = CreateTempFileStream(&pStmSave); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "CreateTempFileStream failed.", hr); goto exit; } // Save the message hr = pMessage->Save(pStmSave, TRUE); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "pMessage->Save failed.", hr); goto exit; } // Commit pStmSave->Commit(STGC_DEFAULT); // Release pMessage pMessage->Release(); pMessage = NULL; // Rewind pStmSave HrRewindStream(pStmSave); // Create a new message object hr = CreateMimeMessage(&pMessage); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "CreateMimeMessage failed.", hr); goto exit; } // Load that message object hr = pMessage->Load(pStmSave); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "IMimeMessage::Load failed.", hr); goto exit; } // Get the text body hr = pMessage->GetTextBody(TXT_PLAIN, IET_BINARY, &pStmTxtOut, &hBody); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "pMessage->GetTextBody failed.", hr); goto exit; } // Get the attachment, should be the wave file hr = pMessage->GetAttachments(&cAttach, &prghAttach); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "pMessage->GetAttachments failed.", hr); goto exit; } // Get the root body hr = pMessage->BindToObject(prghAttach[0], IID_IMimeBody, (LPVOID *)&pBody); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "IMimeMessage::BindToObject failed.", hr); goto exit; } // Get the data stream hr = pBody->SaveToFile(IET_BINARY, "d:\\waveedit\\test.new"); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "IMimeBody::GetData failed.", hr); goto exit; } // Get the data stream hr = pBody->GetData(IET_BINARY, &pStmBody); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "IMimeBody::GetData failed.", hr); goto exit; } // Feed this into waveedit #if 0 hr = CreateWaveEditObject(IID_IWaveAudio, (LPVOID *)&pWave); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "CreateWaveEditObject failed.", hr); goto exit; } // Get pStmWave hr = pWave->QueryInterface(IID_IWaveStream, (LPVOID *)&pStmWave); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "pWave->QueryInterface(IID_IWaveStream...) failed.", hr); goto exit; } // Open the stream hr = pStmWave->StreamOpen(pStmBody); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "pStmWave->StreamOpen failed.", hr); goto exit; } pWave->GetNumSamples(&dw); // Play it hr = pWave->Play(WAVE_MAPPER, 0, dw); if (FAILED(hr)) { ReportError("MimeTestBodyStream", __LINE__, "pStmWave->Play failed.", hr); goto exit; } #endif Sleep(8000); exit: // Cleanup if (pMessage) pMessage->Release(); if (pBody) pBody->Release(); if (pStmBody) pStmBody->Release(); if (pStmSave) pStmSave->Release(); if (pWave) pWave->Release(); if (pStmWave) pStmWave->Release(); if (pStmText) pStmText->Release(); if (pStmTxtOut) pStmTxtOut->Release(); if (prghAttach) CoTaskMemFree(prghAttach); // Done return hr; } #endif // -------------------------------------------------------------------------------- // MimeTestIsContentType // -------------------------------------------------------------------------------- HRESULT MimeTestIsContentType(IMimeMessage **ppMessage) { // Locals HRESULT hr=S_OK; IMimeMessage *pMessage=NULL; IPersistFile *pPersistFile=NULL; HBODY hBody; // Create a message object hr = CreateMimeMessage(&pMessage); if (FAILED(hr)) { ReportError("MimeTestIsContentType", __LINE__, "CreateMimeMessage failed.", hr); goto exit; } // Get an IPersistFile hr = pMessage->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile); if (FAILED(hr)) { ReportError("MimeTestIsContentType", __LINE__, "IMimeMessage::QueryInterface(IID_IPersistFile) failed.", hr); goto exit; } // Load hr = pPersistFile->Load(L"d:\\test\\vlad.eml", STGM_READ | STGM_SHARE_DENY_NONE); if (FAILED(hr)) { ReportError("MimeTestIsContentType", __LINE__, "IPersistFile::Load failed.", hr); goto exit; } // Get the root body hr = pMessage->GetBody(IBL_ROOT, NULL, &hBody); // Test for content-Type hr = pMessage->IsContentType(hBody, "multipart", NULL); if (S_OK == hr) printf("The root body of the message is a multipart."); else if (S_FALSE == hr) printf("The root body of the message is NOT a multipart."); // Return a message object if (ppMessage) { (*ppMessage) = pMessage; (*ppMessage)->AddRef(); } exit: // Cleanup if (pPersistFile) pPersistFile->Release(); if (pMessage) pMessage->Release(); // Done return hr; } // -------------------------------------------------------------------------------- // MimeTestSplitMessageIntoParts - How to split a large message into smaller parts // -------------------------------------------------------------------------------- HRESULT MimeTestSplitMessageIntoParts(void) { // Locals HRESULT hr=S_OK; IMimeMessageParts *pParts=NULL; IMimeEnumMessageParts *pEnumParts=NULL; IMimeMessage *pMessage=NULL; IMimeMessage *pMsgPart=NULL; IStream *pStream=NULL; IPersistFile *pPersistFile=NULL; ULONG c; ULONG cFiles=0; ULONG i; LPWSTR *prgpszFile=NULL; PROPVARIANT rVariant; // Init the variant ZeroMemory(&rVariant, sizeof(PROPVARIANT)); // Create a message object hr = CreateMimeMessage(&pMessage); if (FAILED(hr)) { ReportError("MimeTestSplitMessageIntoParts", __LINE__, "CreateMimeMessage failed.", hr); goto exit; } // Attach a large file hr = pMessage->AttachFile("c:\\winnt\\winnt256.bmp", NULL, NULL); if (FAILED(hr)) { ReportError("MimeTestSplitMessageIntoParts", __LINE__, "IMimeMessage::AttachFile(...) failed.", hr); goto exit; } // Split the message into parts hr = pMessage->SplitMessage(65536, &pParts); if (FAILED(hr)) { ReportError("MimeTestSplitMessageIntoParts", __LINE__, "IMimeMessage::SplitMessage(...) failed.", hr); goto exit; } // Get the number of parts hr = pParts->CountParts(&cFiles); if (FAILED(hr)) { ReportError("MimeTestSplitMessageIntoParts", __LINE__, "IMimeMessageParts::EnumParts(...) failed.", hr); goto exit; } // Allocate an array prgpszFile = (LPWSTR *)CoTaskMemAlloc(sizeof(LPWSTR) * cFiles); if (NULL == prgpszFile) { ReportError("MimeTestSplitMessageIntoParts", __LINE__, "CoTaskMemAlloc Failed.", hr); goto exit; } // Init ZeroMemory(prgpszFile, sizeof(LPWSTR) * cFiles); // Enumerate the parts hr = pParts->EnumParts(&pEnumParts); if (FAILED(hr)) { ReportError("MimeTestSplitMessageIntoParts", __LINE__, "IMimeMessageParts::EnumParts(...) failed.", hr); goto exit; } // INit loop var i = 0; // Enumerate the parts while (SUCCEEDED(pEnumParts->Next(1, &pMsgPart, &c)) && 1 == c) { // Setup the variant rVariant.vt = VT_LPWSTR; // Get a filename, in unicode hr = pMsgPart->GetBodyProp(HBODY_ROOT, PIDTOSTR(PID_ATT_GENFNAME), 0, &rVariant); if (FAILED(hr)) { ReportError("MimeTestSplitMessageIntoParts", __LINE__, "IMimeMessage::GetBodyProp(HBODY_ROOT, PID_ATT_GENFNAME (Unicode), ...) failed.", hr); goto exit; } // QI for IPersistFile hr = pMsgPart->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile); if (FAILED(hr)) { ReportError("MimeTestSplitMessageIntoParts", __LINE__, "IMimeMessage::QueryInterface(IID_IPersistFile, ...) failed.", hr); goto exit; } // Get the message source and dump to file... hr = pPersistFile->Save(rVariant.pwszVal, FALSE); if (FAILED(hr)) { ReportError("MimeTestSplitMessageIntoParts", __LINE__, "IPersistFile::Save(...) failed.", hr); goto exit; } // Save the filename prgpszFile[i++] = rVariant.pwszVal; rVariant.pwszVal = NULL; // Release the message pMsgPart->Release(); pMsgPart = NULL; pPersistFile->Release(); pPersistFile = NULL; } // Lets recombine those message parts MimeTestRecombineMessageParts(prgpszFile, cFiles); exit: // Cleanup if (pStream) pStream->Release(); if (pMessage) pMessage->Release(); if (pParts) pParts->Release(); if (pEnumParts) pEnumParts->Release(); if (pMsgPart) pMsgPart->Release(); if (pPersistFile) pPersistFile->Release(); if (rVariant.pwszVal) CoTaskMemFree(rVariant.pwszVal); if (prgpszFile) { for (i=0; iQueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile); if (FAILED(hr)) { ReportError("MimeTestRecombineMessageParts", __LINE__, "IMimeMessage::QueryInterface(IID_IPersistFile, ...) failed.", hr); goto exit; } // Get the message source and dump to file... hr = pPersistFile->Load(prgpszFile[i], STGM_READ | STGM_SHARE_DENY_NONE); if (FAILED(hr)) { ReportError("MimeTestRecombineMessageParts", __LINE__, "IPersistFile::Load(...) failed.", hr); goto exit; } // Add the message into the parts list hr = pParts->AddPart(pMsgPart); if (FAILED(hr)) { ReportError("MimeTestRecombineMessageParts", __LINE__, "IMimeMessageParts::AddPart(...) failed.", hr); goto exit; } // Cleanup pMsgPart->Release(); pMsgPart = NULL; pPersistFile->Release(); pPersistFile = NULL; } // Combine all the parts into a new message hr = pParts->CombineParts(&pMessage); if (FAILED(hr)) { ReportError("MimeTestRecombineMessageParts", __LINE__, "IMimeMessageParts::CombineParts(...) failed.", hr); goto exit; } // Get an IPersistFile hr = pMessage->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile); if (FAILED(hr)) { ReportError("MimeTestRecombineMessageParts", __LINE__, "IMimeMessage::QueryInterface(IID_IPersistFile, ...) failed.", hr); goto exit; } // Get the message source and dump to file... hr = pPersistFile->Save(L"combined.eml", FALSE); if (FAILED(hr)) { ReportError("MimeTestRecombineMessageParts", __LINE__, "IPersistFile::Save(...) failed.", hr); goto exit; } exit: // Cleanup if (pParts) pParts->Release(); if (pMsgPart) pMsgPart->Release(); if (pMessage) pMessage->Release(); if (pPersistFile) pPersistFile->Release(); // Done return hr; } // -------------------------------------------------------------------------------- // MimeTestLookupCharsetHandle // -------------------------------------------------------------------------------- HRESULT MimeTestLookupCharsetHandle(LPCSTR pszCharset, LPHCHARSET phCharset) { // Locals HRESULT hr=S_OK; INETCSETINFO rCharset; IMimeInternational *pInternat=NULL; // Create a message object hr = CoCreateInstance(CLSID_IMimeInternational, NULL, CLSCTX_INPROC_SERVER, IID_IMimeInternational, (LPVOID *)&pInternat); if (FAILED(hr)) { ReportError("MimeTestLookupCharsetHandle", __LINE__, "CoCreateInstance(CLSID_IMimeInternational, ...) failed.", hr); goto exit; } // Look for character set hr = pInternat->FindCharset(pszCharset, phCharset); if (FAILED(hr)) { ReportError("MimeTestLookupCharsetHandle", __LINE__, "IMimeInternational::FindCharset(...) failed.", hr); goto exit; } // Lets lookup some character set information hr = pInternat->GetCharsetInfo(*phCharset, &rCharset); if (FAILED(hr)) { ReportError("MimeTestLookupCharsetHandle", __LINE__, "IMimeInternational::GetCharsetInfo(...) failed.", hr); goto exit; } // Print some stuff printf("Charset Name: %s, Windows Codepage: %d, Internet Codepage: %d\n", rCharset.szName, rCharset.cpiWindows, rCharset.cpiInternet); exit: // Clenaup if (pInternat) pInternat->Release(); // Done return hr; } // -------------------------------------------------------------------------------- // MimeTestSettingContentLocation - How to set the Content-Location header // -------------------------------------------------------------------------------- HRESULT MimeTestSettingContentLocation(IMimeMessage **ppMessage) { // Locals HRESULT hr=S_OK; IMimeMessage *pMessage=NULL; IStream *pStream=NULL; PROPVARIANT rVariant; HCHARSET hCharset; // Create a message object hr = CreateMimeMessage(&pMessage); if (FAILED(hr)) { ReportError("MimeTestSettingContentLocation", __LINE__, "CreateMimeMessage failed.", hr); goto exit; } // Setup a variant, I can pass in unicode or ansi rVariant.vt = VT_LPWSTR; rVariant.pwszVal = L"http://www.microsoft.com"; // Set the Content-Location of the message hr = pMessage->SetProp(PIDTOSTR(PID_HDR_CNTLOC), 0, &rVariant); if (FAILED(hr)) { ReportError("MimeTestSettingContentLocation", __LINE__, "IMimeMessage::SetProp(PIDTOSTR(PID_HDR_CNTLOC), 0, ...) failed.", hr); goto exit; } // Setup a variant, I can pass in unicode or ansi rVariant.vt = VT_LPSTR; rVariant.pszVal = "\"Ken Dacey\" "; // Set the Content-Location of the message hr = pMessage->SetProp(PIDTOSTR(PID_HDR_FROM), 0, &rVariant); if (FAILED(hr)) { ReportError("MimeTestSettingContentLocation", __LINE__, "IMimeMessage::SetProp(PIDTOSTR(PID_HDR_FROM), 0, ...) failed.", hr); goto exit; } // I could also set the content-location like this: // // 1) pMessage->SetBodyProp(HBODY_ROOT, PIDTOSTR(PID_HDR_CNTLOC), 0, &rVariant); // // 2) pMessage->BindToObject(HBODY_ROOT, IID_IMimePropertySet, (LPVOID *)&pProps); // pProps->SetProp(PIDTOSTR(PID_HDR_CNTLOC), 0, &rVariant); // Lets save the message in UTF-7 #if 0 hr = MimeTestLookupCharsetHandle("utf-8", &hCharset); if (FAILED(hr)) { ReportError("MimeTestSettingContentLocation", __LINE__, "MimeTestLookupCharsetHandle(\"utf-7\", ...) failed.", hr); goto exit; } // Set the charset onto the message hr = pMessage->SetCharset(hCharset, CSET_APPLY_ALL); if (FAILED(hr)) { ReportError("MimeTestSettingContentLocation", __LINE__, "IMimeMessage::SetCharset(\"utf-7\", CSET_APPLY_ALL) failed.", hr); goto exit; } #endif // Save the mime message to a stream hr = SaveMimeMessage(pMessage, SAVE_RFC1521, &pStream); if (FAILED(hr)) { ReportError("MimeTestSettingContentLocation", __LINE__, "SaveMimeMessage(...) failed.", hr); goto exit; } // Dump the stream to the console, and then wait for input so that the user can view it... ReportStatus("\n"); DumpStreamToConsole(pStream); // Return a message object if (ppMessage) { (*ppMessage) = pMessage; (*ppMessage)->AddRef(); } exit: // Cleanup if (pStream) pStream->Release(); if (pMessage) pMessage->Release(); // Done return hr; } // -------------------------------------------------------------------------------- // MimeTestSettingReplyTo - How to set the Reply-To header // -------------------------------------------------------------------------------- HRESULT MimeTestSettingReplyTo(IMimeMessage **ppMessage) { // Locals HRESULT hr=S_OK; IMimeMessage *pMessage=NULL; IStream *pStream=NULL; PROPVARIANT rVariant; // Create a message object hr = CreateMimeMessage(&pMessage); if (FAILED(hr)) { ReportError("MimeTestSettingReplyTo", __LINE__, "CreateMimeMessage failed.", hr); goto exit; } // Setup a variant, I can pass in unicode or ansi rVariant.vt = VT_LPWSTR; rVariant.pwszVal = L"Steven Bailey "; // Set the Content-Location of the message hr = pMessage->SetProp(PIDTOSTR(PID_HDR_REPLYTO), 0, &rVariant); if (FAILED(hr)) { ReportError("MimeTestSettingReplyTo", __LINE__, "IMimeMessage::SetProp(PIDTOSTR(PID_HDR_REPLYTO), 0, ...) failed.", hr); goto exit; } // Save the mime message to a stream hr = SaveMimeMessage(pMessage, SAVE_RFC1521, &pStream); if (FAILED(hr)) { ReportError("MimeTestSettingContentLocation", __LINE__, "SaveMimeMessage(...) failed.", hr); goto exit; } // Dump the stream to the console, and then wait for input so that the user can view it... ReportStatus("\n"); DumpStreamToConsole(pStream); // Return a message object if (ppMessage) { (*ppMessage) = pMessage; (*ppMessage)->AddRef(); } exit: // Cleanup if (pStream) pStream->Release(); if (pMessage) pMessage->Release(); // Done return hr; } // -------------------------------------------------------------------------------- // MimeTestGetMultiValueAddressProp // -------------------------------------------------------------------------------- HRESULT MimeTestGetMultiValueAddressProp(IMimeMessage **ppMessage) { // Locals HRESULT hr=S_OK; PROPVARIANT rVariant; IMimeMessage *pMessage=NULL; // Create a message with some addresses in it hr = MimeTestAppendRfc822(&pMessage); if (FAILED(hr)) { ReportError("MimeTestGetMultiValueAddressProp", __LINE__, "MimeTestAppendRfc822 failed.", hr); goto exit; } // Setup the Variant rVariant.vt = VT_LPSTR; // Get PID_HDR_TO hr = pMessage->GetProp(PIDTOSTR(PID_HDR_TO), 0, &rVariant); if (FAILED(hr)) { ReportError("MimeTestGetMultiValueAddressProp", __LINE__, "IMimeMessage::GetProp(PIDTOSTR(PID_HDR_TO), ...) failed.", hr); goto exit; } // Printf It printf("PID_HDR_TO = %s\n", rVariant.pszVal); // Free it CoTaskMemFree(rVariant.pszVal); exit: // Cleanup if (pMessage) pMessage->Release(); // Done return hr; } // -------------------------------------------------------------------------------- // MimeTestAppendRfc822 - Test IMimeAddressTable::AppendRfc822 // -------------------------------------------------------------------------------- HRESULT MimeTestAppendRfc822(IMimeMessage **ppMessage) { // Locals HRESULT hr=S_OK; IMimeMessage *pMessage=NULL; IMimeAddressTable *pAdrTable=NULL; IStream *pStream=NULL; // Create a message object hr = CreateMimeMessage(&pMessage); if (FAILED(hr)) { ReportError("MimeTestAppendRfc822", __LINE__, "CreateMimeMessage failed.", hr); goto exit; } // Get the address table for the message. The address table should only be used on the root body object. hr = pMessage->BindToObject(HBODY_ROOT, IID_IMimeAddressTable, (LPVOID *)&pAdrTable); if (FAILED(hr)) { ReportError("MimeTestAppendRfc822", __LINE__, "IMimeMessage::BindToObject(HBDOY_ROOT, IID_IMimeAddressTable, ...) failed.", hr); goto exit; } // Append an RFC 822 formatted addresses hr = pAdrTable->AppendRfc822(IAT_TO, IET_DECODED, "test1 "); if (FAILED(hr)) { ReportError("MimeTestAppendRfc822", __LINE__, "IMimeAddressTable::AppendRfc822(...) failed.", hr); goto exit; } // Append an RFC 822 formatted addresses hr = pAdrTable->AppendRfc822(IAT_TO, IET_DECODED, "to2 "); if (FAILED(hr)) { ReportError("MimeTestAppendRfc822", __LINE__, "IMimeAddressTable::AppendRfc822(...) failed.", hr); goto exit; } // Append an RFC 822 formatted addresses hr = pAdrTable->AppendRfc822(IAT_TO, IET_DECODED, "to3 "); if (FAILED(hr)) { ReportError("MimeTestAppendRfc822", __LINE__, "IMimeAddressTable::AppendRfc822(...) failed.", hr); goto exit; } // Save the mime message to a stream hr = SaveMimeMessage(pMessage, SAVE_RFC1521, &pStream); if (FAILED(hr)) { ReportError("MimeTestAppendRfc822", __LINE__, "SaveMimeMessage(...) failed.", hr); goto exit; } // Dump the stream to the console, and then wait for input so that the user can view it... ReportStatus("\n"); DumpStreamToConsole(pStream); // Return a message object if (ppMessage) { (*ppMessage) = pMessage; (*ppMessage)->AddRef(); } exit: // Cleanup if (pStream) pStream->Release(); if (pAdrTable) pAdrTable->Release(); if (pMessage) pMessage->Release(); // Done return hr; } // -------------------------------------------------------------------------------- // CreateMimeMessage - Basic way of creating a COM object. // -------------------------------------------------------------------------------- HRESULT CreateMimeMessage(IMimeMessage **ppMessage) { // Locals HRESULT hr; // Create a message object hr = CoCreateInstance(CLSID_IMimeMessage, NULL, CLSCTX_INPROC_SERVER, IID_IMimeMessage, (LPVOID *)ppMessage); if (FAILED(hr)) { ReportError("CreateMimeMessage", __LINE__, "CoCreateInstance(CLSID_IMimeMessage, ...) failed.", hr); goto exit; } // You must always initnew the message object hr = (*ppMessage)->InitNew(); if (FAILED(hr)) { ReportError("CreateMimeMessage", __LINE__, "IMimeMessage::InitNew() failed.", hr); goto exit; } exit: // Done return hr; } // -------------------------------------------------------------------------------- // Saves a MIME message // -------------------------------------------------------------------------------- HRESULT SaveMimeMessage(IMimeMessage *pMessage, MIMESAVETYPE savetype, IStream **ppStream) { // Locals HRESULT hr; PROPVARIANT rOption; // Set the save format option into the message object. The OID_xxx types are defined // in mimeole.idl. Go to that file for more information. rOption.vt = VT_UI4; rOption.ulVal = savetype; hr = pMessage->SetOption(OID_SAVE_FORMAT, &rOption); if (FAILED(hr)) { ReportError("SaveMimeMessage", __LINE__, "IMimeMessage::SetOption(OID_SAVE_FORMAT, ...) failed", hr); goto exit; } // Create a stream in which to save the message... hr = CreateStreamOnHGlobal(NULL, TRUE, ppStream); if (FAILED(hr)) { ReportError("SaveMimeMessage", __LINE__, "CreateStreamOnHGlobal failed", hr); goto exit; } // Call the save method on IMimeMessage. Mimeole will call commit on the stream object. // After this call, the stream will be positioned at the end. hr = pMessage->Save(*ppStream, TRUE); if (FAILED(hr)) { ReportError("SaveMimeMessage", __LINE__, "IMimeMessage::Save(...) failed", hr); goto exit; } exit: // Done return hr; } // -------------------------------------------------------------------------------- // ReportError - Simple function to report an error that has an HRESULT // -------------------------------------------------------------------------------- HRESULT ReportError(LPCSTR pszFunction, INT nLine, LPCSTR pszErrorText, HRESULT hrResult) { printf("Error(HR = 0x%08X) in %s on line %d - %s\n", hrResult, pszFunction, nLine, pszErrorText); return hrResult; } // -------------------------------------------------------------------------------- // ReportStatus - Simple function to report a string to the user // -------------------------------------------------------------------------------- HRESULT ReportStatus(LPCSTR pszStatusText) { printf("Status: %s\n", pszStatusText); return S_OK; } // -------------------------------------------------------------------------------- // DumpStreamToConsole // -------------------------------------------------------------------------------- HRESULT DumpStreamToConsole(IStream *pStream) { // Locals HRESULT hr=S_OK; BYTE rgbBuffer[2048]; ULONG cbRead; // This is an msoert function HrStreamSeekSet(pStream, 0); while(1) { // Read a block from the stream hr = pStream->Read(rgbBuffer, sizeof(rgbBuffer), &cbRead); if (FAILED(hr)) { ReportError("DumpStreamToConsole", __LINE__, "DumpStreamToConsole - IStream::Read failed.", hr); break; } // If nothing read, then were done if (0 == cbRead) break; // Print it printf("%s", (LPSTR)rgbBuffer); } // Finaly LF printf("\n"); // Done return hr; } /* DWORD i=1; DWORD dw; CHAR szDate[255]; HROWSET hRowset; FOLDERINFO Folder; MESSAGEINFO Message; IMessageStore *pStore; IMessageFolder *pFolder; CoCreateInstance(CLSID_MessageStore, NULL, CLSCTX_INPROC_SERVER, IID_IMessageStore, (LPVOID *)&pStore); pStore->Initialize("d:\\storetest"); pStore->OpenSpecialFolder(FOLDERID_LOCAL_STORE, FOLDER_INBOX, &pFolder); pFolder->CreateRowset(IINDEX_SUBJECT, 0, &hRowset); while(S_OK == pFolder->QueryRowset(hRowset, 1, (LPVOID *)&Message, NULL)) { dw = FDTF_DEFAULT; SHFormatDateTimeA(&Message.ftReceived, &dw, szDate, 255); if (Message.pszNormalSubj) printf("%05d: %s, %s, %d\n", i, Message.pszNormalSubj, szDate, Message.idMessage); else printf("%05d: , %s, %d\n", i, szDate, Message.idMessage); pFolder->FreeRecord(&Message); i++; } pFolder->CloseRowset(&hRowset); pFolder->Release(); pStore->Release(); exit(1); */