Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6585 lines
208 KiB

  1. // --------------------------------------------------------------------------------
  2. // BookBody.cpp
  3. // Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  4. // Steven J. Bailey
  5. // --------------------------------------------------------------------------------
  6. #include "pch.hxx"
  7. #include "bookbody.h"
  8. #include "dllmain.h"
  9. #include "ibdylock.h"
  10. #include "stmlock.h"
  11. #include "ibdystm.h"
  12. #include "resource.h"
  13. #include "smime.h"
  14. #include "objheap.h"
  15. #include "internat.h"
  16. #include "urlmon.h"
  17. #include "symcache.h"
  18. #include "booktree.h"
  19. #include <demand.h>
  20. #include "mimeapi.h"
  21. #include <shlwapi.h>
  22. #include "webdocs.h"
  23. // --------------------------------------------------------------------------------
  24. // ASSERTINIT
  25. // --------------------------------------------------------------------------------
  26. #define ASSERTINIT \
  27. AssertSz(m_pContainer, "Object is being used before a call to InitNew")
  28. // --------------------------------------------------------------------------------
  29. // Default Body Options
  30. // --------------------------------------------------------------------------------
  31. static const BODYOPTIONS g_rDefBodyOptions = {
  32. IET_UNKNOWN, // OID_TRANSMIT_BODY_FORMAT
  33. DEF_CBMAX_BODY_LINE, // OID_CBMAX_BODY_LINE
  34. DEF_WRAP_BODY_TEXT, // OID_WRAP_BODY_TEXT
  35. DEF_BODY_REMOVE_NBSP, // OID_BODY_REMOVE_NBSP
  36. DEF_DBCS_ESCAPE_IS_8BIT, // OID_DBCS_ESCAPE_IS_8BIT
  37. DEF_HIDE_TNEF_ATTACHMENTS, // OID_HIDE_TNEF_ATTACHMENTS
  38. MST_NONE, // OID_SECURITY_TYPE
  39. NULL, // OID_SECURITY_ALG_HASH and OID_SECURITY_ALG_HASH_RG
  40. { 0, NULL }, // OID_SECURITY_ALG_BULK
  41. NULL, // OID_SECURITY_CERT_SIGNING and OID_SECURITY_CERT_SIGNING_RG
  42. 0, // OID_SECURITY_CERT_DECRYPTION
  43. NULL, // OID_SECURITY_HCERTSTORE and OID_SECURITY_HCERTSTORE_RG
  44. { 0, NULL }, // OID_SECURITY_SEARCHSTORES
  45. 0,
  46. NULL, // OID_SECURITY_RG_IASN
  47. #ifdef SMIME_V3
  48. NULL, // OID_SECURITY_AUTHATTR and OID_SECURITY_AUTHATTR_RG
  49. NULL, // OID_SECURITY_UNAUTHATTR and OID_SECURITY_UNAUTHATTR_RG
  50. NULL, // OID_SECURITY_UNPROTECTATTR_RG
  51. #else // !SMIME_V3
  52. NULL, // OID_SECURITY_SYMCAPS and OID_SECURITY_SYMCAPS_RG
  53. NULL, // OID_SECURITY_AUTHATTR and OID_SECURITY_AUTHATTR_RG
  54. NULL, // OID_SECURITY_UNAUTHATTR and OID_SECURITY_UNAUTHATTR_RG
  55. NULL, // OID_SECURITY_SIGNTIME and OID_SECURITY_SIGNTIME_RG
  56. #endif // SMIME_V3
  57. NULL, // OID_SECURITY_USER_VALIDITY and OID_SECURITY_USER_VALIDITY_RG
  58. NULL, // OID_SECURITY_RO_MSG_VALIDITY and OID_SECURITY_RO_MSG_VALIDITY_RG
  59. 0, // OID_SECURITY_HCRYPTPROV
  60. 0, // OID_SECURITY_ENCODE_FLAGS
  61. FALSE, // OID_SECURITY_CERT_INCLUDED
  62. // This is NULL b/c default is generated at runtime
  63. NULL, // OID_SECURITY_HWND_OWNER
  64. // Base64 is the recommended value in the S/MIME spec
  65. IET_BASE64, // OID_SECURITY_REQUESTED_CTE
  66. #ifdef SMIME_V3
  67. NULL, // OID_SECURITY_RECEIPT_RG
  68. NULL, // OID_SECURITY_MESSAGE_HASH_RG
  69. NULL, // OID_SECURITY_KEY_PROMPT
  70. #endif // SMIME_V3
  71. DEF_SHOW_MACBINARY, // OID_SHOW_MACBINARY
  72. DEF_SUPPORT_EXTERNAL_BODY, // OID_SUPPORT_EXTERNAL_BODY
  73. 0, // cSecurityLayers (size of arrays of
  74. // OID_SECURITY_ALG_HASH
  75. // OID_SECURITY_CERT_SIGNING
  76. // OID_SECURITY_HCERTSTORE
  77. // OID_SECURITY_SYMCAPS
  78. // OID_SECURITY_AUTHATTR
  79. // OID_SECURITY_UNAUTHATTR
  80. // OID_SECURITY_SIGNTIME
  81. // OID_SECURITY_USER_VALIDITY
  82. // OID_SECURITY_RO_MSG_VALIDITY)
  83. FALSE, // OID_NOSECURITY_ON_SAVE
  84. #ifdef SMIME_V3
  85. 0, 0, NULL, // cRecipients/rgRecipients
  86. #endif // SMIME_V3
  87. NULL, // OID_SECURITY_ENCRYPT_CERT_BAG
  88. };
  89. static const BLOB blobNULL = {0, NULL};
  90. HRESULT HrCopyBlobArray(LPCBLOB pIn, ULONG cEntries, PROPVARIANT FAR * pvOut);
  91. HRESULT HrCopyDwordArray(LPDWORD pIn, ULONG cEntries, PROPVARIANT FAR * pvOut);
  92. HRESULT HrCopyIntoUlonglongArray(ULARGE_INTEGER * pIn, ULONG cEntries, PROPVARIANT FAR * pvOut);
  93. HRESULT HrCopyFiletimeArray(LPFILETIME pIn, ULONG cEntries, PROPVARIANT FAR * pvOut);
  94. DWORD MergeDWORDFlags(LPDWORD rgdw, ULONG cEntries);
  95. extern HRESULT HrGetLastError(void);
  96. extern BOOL FIsMsasn1Loaded();
  97. // --------------------------------------------------------------------------------
  98. // WebBookContentBody_CreateInstance
  99. // --------------------------------------------------------------------------------
  100. HRESULT WebBookContentBody_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppUnknown)
  101. {
  102. // Invalid Arg
  103. Assert(ppUnknown);
  104. // Initialize
  105. *ppUnknown = NULL;
  106. // Create me
  107. CMessageBody *pNew = new CMessageBody(NULL, pUnkOuter);
  108. if (NULL == pNew)
  109. return TrapError(E_OUTOFMEMORY);
  110. // Return the Innter
  111. *ppUnknown = pNew->GetInner();
  112. // Done
  113. return S_OK;
  114. }
  115. // --------------------------------------------------------------------------------
  116. // CMessageBody::CMessageBody
  117. // --------------------------------------------------------------------------------
  118. CMessageBody::CMessageBody(LPTREENODEINFO pNode, IUnknown *pUnkOuter)
  119. : m_pNode(pNode), CPrivateUnknown(pUnkOuter)
  120. {
  121. DllAddRef();
  122. m_cRef = 1;
  123. m_dwState = 0;
  124. m_pszDisplay = NULL;
  125. m_ietEncoding = IET_BINARY;
  126. m_ietPrevious = IET_UNKNOWN;
  127. m_pCharset = CIntlGlobals::GetDefBodyCset();
  128. m_pCsetTagged = NULL;
  129. m_pContainer = NULL;
  130. m_cbExternal = 0xFFFFFFFF;
  131. ZeroMemory(&m_rStorage, sizeof(BODYSTORAGE));
  132. CopyMemory(&m_rOptions, &g_rDefBodyOptions, sizeof(BODYOPTIONS));
  133. // (t-erikne) need to get this default at run time
  134. m_rOptions.hwndOwner = HWND_DESKTOP;
  135. InitializeCriticalSection(&m_cs);
  136. }
  137. // --------------------------------------------------------------------------------
  138. // CMessageBody::~CMessageBody
  139. // --------------------------------------------------------------------------------
  140. CMessageBody::~CMessageBody(void)
  141. {
  142. SafeRelease(m_pContainer);
  143. SafeMemFree(m_pszDisplay);
  144. SafeRelease(m_rStorage.pUnkRelease);
  145. // Clear out the options
  146. _FreeOptions();
  147. DeleteCriticalSection(&m_cs);
  148. DllRelease();
  149. }
  150. // --------------------------------------------------------------------------------
  151. // CMessageBody::PrivateQueryInterface
  152. // --------------------------------------------------------------------------------
  153. HRESULT CMessageBody::PrivateQueryInterface(REFIID riid, LPVOID *ppv)
  154. {
  155. // check params
  156. if (ppv == NULL)
  157. return TrapError(E_INVALIDARG);
  158. // Init
  159. *ppv = NULL;
  160. // Find IID
  161. if (IID_IMimeBody == riid)
  162. *ppv = (IMimeBody *)this;
  163. else if (IID_IMimeBodyW == riid)
  164. *ppv = (IMimeBodyW *)this;
  165. else if (IID_IMimePropertySet == riid)
  166. *ppv = (IMimePropertySet *)this;
  167. else if (IID_IPersist == riid)
  168. *ppv = (IPersist *)this;
  169. else if (IID_IPersistStreamInit == riid)
  170. *ppv = (IPersistStreamInit *)this;
  171. else if (IID_CMessageBody == riid)
  172. *ppv = (CMessageBody *)this;
  173. #ifdef SMIME_V3
  174. else if (IID_IMimeSecurity2 == riid)
  175. *ppv = (IMimeSecurity2 *) this;
  176. #endif
  177. else
  178. {
  179. *ppv = NULL;
  180. return E_NOINTERFACE;
  181. }
  182. // AddRef It
  183. ((IUnknown *)*ppv)->AddRef();
  184. // Done
  185. return S_OK;
  186. }
  187. // --------------------------------------------------------------------------------
  188. // CMessageBody::RevokeTreeNode
  189. // --------------------------------------------------------------------------------
  190. void CMessageBody::RevokeTreeNode(void)
  191. {
  192. EnterCriticalSection(&m_cs);
  193. m_pNode = NULL;
  194. LeaveCriticalSection(&m_cs);
  195. }
  196. // --------------------------------------------------------------------------------
  197. // CMessageBody::HrBindToTree
  198. // --------------------------------------------------------------------------------
  199. HRESULT CMessageBody::HrBindToTree(CStreamLockBytes *pStmLock, LPTREENODEINFO pNode)
  200. {
  201. // Locals
  202. HRESULT hr=S_OK;
  203. HCHARSET hCharset=NULL;
  204. IStream *pstmBody=NULL;
  205. ASSERTINIT;
  206. // Thread Safety
  207. EnterCriticalSection(&m_cs);
  208. // Invalid Arg
  209. Assert(pNode && NULL == pNode->pLockBytes && pStmLock && m_pNode == pNode);
  210. // Create the body lock bytes
  211. CHECKALLOC(pNode->pLockBytes = new CBodyLockBytes(pStmLock, pNode));
  212. // Just assume it
  213. m_rStorage.riid = IID_ILockBytes;
  214. m_rStorage.pLockBytes = (ILockBytes *)pNode->pLockBytes;
  215. m_rStorage.pUnkRelease = m_rStorage.pLockBytes;
  216. m_rStorage.pUnkRelease->AddRef();
  217. // Test for binhex
  218. if (S_FALSE == m_pContainer->IsPropSet(PIDTOSTR(PID_HDR_CNTXFER)) && m_pContainer->IsContentType(STR_CNT_APPLICATION, STR_SUB_BINHEX) == S_OK)
  219. {
  220. // Locals
  221. PROPVARIANT rVariant;
  222. // Setup the variant
  223. rVariant.vt = VT_LPSTR;
  224. // If there is a filename, lets re-compute the content-type
  225. if (SUCCEEDED(m_pContainer->GetProp(PIDTOSTR(PID_ATT_FILENAME), 0, &rVariant)))
  226. {
  227. // Locals
  228. LPSTR pszCntType;
  229. LPSTR pszSubType;
  230. // Get mime file information
  231. if (SUCCEEDED(MimeOleGetFileInfo(rVariant.pszVal, &pszCntType, &pszSubType, NULL, NULL, NULL)))
  232. {
  233. // ContentType
  234. if (pszCntType && pszSubType)
  235. {
  236. CHECKHR(hr = m_pContainer->SetProp(PIDTOSTR(PID_ATT_PRITYPE), pszCntType));
  237. CHECKHR(hr = m_pContainer->SetProp(PIDTOSTR(PID_ATT_SUBTYPE), pszSubType));
  238. }
  239. // application/octet-stream
  240. else
  241. {
  242. CHECKHR(hr = m_pContainer->SetProp(PIDTOSTR(PID_HDR_CNTTYPE), STR_MIME_APPL_STREAM));
  243. }
  244. // Cleanup
  245. SafeMemFree(pszCntType);
  246. SafeMemFree(pszSubType);
  247. }
  248. // Clenaup
  249. SafeMemFree(rVariant.pszVal);
  250. }
  251. // Set the Content-Transfer-Encoding to binhex
  252. m_pContainer->SetProp(PIDTOSTR(PID_HDR_CNTXFER), STR_ENC_BINHEX40);
  253. // The encoding type better be binhex
  254. Assert(m_pContainer->GetEncodingType() == IET_BINHEX40);
  255. }
  256. // Otherwise, test for message/external-body
  257. else if (m_rOptions.fExternalBody && S_OK == m_pContainer->IsContentType(STR_CNT_MESSAGE, STR_SUB_EXTERNAL))
  258. {
  259. // Bind to External-Body
  260. _BindToExternalBody();
  261. }
  262. // Save The Format
  263. m_ietPrevious = m_ietEncoding = m_pContainer->GetEncodingType();
  264. // Raid 2215: Map a CTE of binary to 8bit so that it gets decoded correctly from the internet character set
  265. if (IET_BINARY == m_ietEncoding)
  266. {
  267. // Switch to 8bit because ibdystm.cpp will not do the charset translation right if the source is binary...
  268. m_ietEncoding = IET_8BIT;
  269. }
  270. // LateTnef Check
  271. if (ISFLAGSET(pNode->dwState, NODESTATE_VERIFYTNEF))
  272. {
  273. // Get the data stream
  274. if (SUCCEEDED(GetData(IET_BINARY, &pstmBody)))
  275. {
  276. // If TNEF, apply content type...
  277. if (MimeOleIsTnefStream(pstmBody) == S_OK)
  278. {
  279. // application/ms-tnef
  280. CHECKHR(hr = m_pContainer->SetProp(SYM_HDR_CNTTYPE, STR_MIME_APPLY_MSTNEF));
  281. }
  282. }
  283. // Clear the flag
  284. FLAGCLEAR(pNode->dwState, NODESTATE_VERIFYTNEF);
  285. }
  286. // If I'm a message with crypto mime types, say I'm "secure"
  287. if (IsSecureContentType(m_pContainer))
  288. {
  289. // TREENODE_SECURE
  290. FLAGSET(m_dwState, BODYSTATE_SECURE);
  291. }
  292. // If the Header was tagged with a charset, use that charset
  293. if (m_pContainer->IsState(COSTATE_CSETTAGGED) == S_OK)
  294. {
  295. // Get Internal Character Set
  296. if (SUCCEEDED(m_pContainer->GetCharset(&hCharset)))
  297. {
  298. // Get Pointer
  299. SideAssert(SUCCEEDED(g_pInternat->HrOpenCharset(hCharset, &m_pCharset)));
  300. // Save this as m_pCsetTagged
  301. m_pCsetTagged = m_pCharset;
  302. }
  303. // I was tagged with a charset
  304. FLAGSET(m_dwState, BODYSTATE_CSETTAGGED);
  305. }
  306. // Bound to tree
  307. FLAGSET(pNode->dwState, NODESTATE_BOUNDTOTREE);
  308. exit:
  309. // Cleanup
  310. SafeRelease(pstmBody);
  311. // Thread Safety
  312. LeaveCriticalSection(&m_cs);
  313. // Done
  314. return hr;
  315. }
  316. // ---------------------------------------------------------------------------
  317. // CMessageBody::_BindToExternalBody
  318. // ---------------------------------------------------------------------------
  319. void CMessageBody::_BindToExternalBody(void)
  320. {
  321. // Locals
  322. HRESULT hr=S_OK;
  323. LPSTR pszAccessType=NULL;
  324. LPSTR pszUrl=NULL;
  325. IStream *pstmBody=NULL;
  326. DWORD cbSize=0xFFFFFFFF;
  327. CMimeWebDocument *pWebDoc=NULL;
  328. // Get par:content-type:access-type
  329. CHECKHR(hr = m_pContainer->GetProp(STR_PAR_ACCESSTYPE, &pszAccessType));
  330. // Handle Access-Types that I know about
  331. if (lstrcmpi(pszAccessType, "X-URL") == 0)
  332. {
  333. // Locals
  334. PROPVARIANT rSize;
  335. // Get par:content-type:xurl
  336. CHECKHR(hr = m_pContainer->GetProp(STR_PAR_XURL, &pszUrl));
  337. // Create the WebDoc
  338. CHECKALLOC(pWebDoc = new CMimeWebDocument);
  339. // Initialize It
  340. CHECKHR(hr = pWebDoc->HrInitialize(NULL, pszUrl));
  341. // Setup Variant
  342. rSize.vt = VT_UI4;
  343. // Get par:content-type:size
  344. if (SUCCEEDED(m_pContainer->GetProp(STR_PAR_SIZE, 0, &rSize)))
  345. cbSize = rSize.ulVal;
  346. }
  347. // If we have a webdocument...
  348. if (pWebDoc)
  349. {
  350. // Get the Body Data
  351. if (SUCCEEDED(GetData(IET_BINARY, &pstmBody)))
  352. {
  353. // Locals
  354. PROPVARIANT rOption;
  355. // Setup the option variant
  356. rOption.vt = VT_UI4;
  357. rOption.ulVal = RELOAD_HEADER_REPLACE;
  358. // Set special option since I'm realoding the header...
  359. CHECKHR(hr = m_pContainer->SetOption(OID_HEADER_RELOAD_TYPE, &rOption));
  360. // Load this body into the container
  361. CHECKHR(hr = m_pContainer->Load(pstmBody));
  362. // Reset the option variant
  363. rOption.vt = VT_UI4;
  364. rOption.ulVal = DEF_HEADER_RELOAD_TYPE_PROPSET;
  365. // Set special option since I'm realoding the header...
  366. CHECKHR(hr = m_pContainer->SetOption(OID_HEADER_RELOAD_TYPE, &rOption));
  367. }
  368. // SetData
  369. CHECKHR(hr = SetData(IET_BINARY, NULL, NULL, IID_IMimeWebDocument, (LPVOID)pWebDoc));
  370. // Create a External Body Info Structure: MUST BE SET AFTER CALL TO SETDATA
  371. FLAGSET(m_dwState, BODYSTATE_EXTERNAL);
  372. // Set Size: MUST BE SET AFTER CALL TO SETDATA
  373. m_cbExternal = cbSize;
  374. }
  375. exit:
  376. // Cleanup
  377. SafeMemFree(pszAccessType);
  378. SafeMemFree(pszUrl);
  379. SafeRelease(pstmBody);
  380. SafeRelease(pWebDoc);
  381. // Done
  382. return;
  383. }
  384. #if 0
  385. // ---------------------------------------------------------------------------
  386. // CMessageBody::UseOriginalCharset
  387. // ---------------------------------------------------------------------------
  388. void CMessageBody::UseOriginalCharset(void)
  389. {
  390. // Thread Safety
  391. EnterCriticalSection(&m_cs);
  392. // We should have m_pCsetTagged
  393. Assert(m_pCsetTagged);
  394. // Set the Charset
  395. if (m_pCsetTagged)
  396. SetCharset(m_pCsetTagged->hCharset, CSET_APPLY_ALL);
  397. // Thread Safety
  398. LeaveCriticalSection(&m_cs);
  399. }
  400. #endif
  401. // ---------------------------------------------------------------------------
  402. // CMessageBody::SetDisplayName
  403. // ---------------------------------------------------------------------------
  404. STDMETHODIMP CMessageBody::SetDisplayName(LPCSTR pszDisplayName)
  405. {
  406. LPWSTR pwszDispName;
  407. HRESULT hr = S_OK;
  408. Assert(pszDisplayName);
  409. IF_NULLEXIT(pwszDispName = PszToUnicode(CP_ACP, pszDisplayName));
  410. hr = SetDisplayNameW(pwszDispName);
  411. exit:
  412. MemFree(pwszDispName);
  413. return hr;
  414. }
  415. #define DisplayMaxLen 64
  416. STDMETHODIMP CMessageBody::SetDisplayNameW(LPCWSTR pszDisplayName)
  417. {
  418. // Locals
  419. HRESULT hr=S_OK;
  420. WCHAR szSize[30],
  421. szScratch[30],
  422. szBuf[MAX_PATH];
  423. ULONG cbSize=0,
  424. cAlloc,
  425. cLen;
  426. ASSERTINIT;
  427. // check params
  428. if (NULL == pszDisplayName)
  429. return TrapError(E_INVALIDARG);
  430. // Thread Safety
  431. EnterCriticalSection(&m_cs);
  432. // Free current display name
  433. SafeMemFree(m_pszDisplay);
  434. // Get Data Size...
  435. GetEstimatedSize(IET_BINARY, &cbSize);
  436. // Format the Size
  437. StrFormatByteSizeW(cbSize, szScratch, ARRAYSIZE(szScratch));
  438. StrCpyNW(szSize, L"(", ARRAYSIZE(szSize));
  439. StrCatBuffW(szSize, szScratch, ARRAYSIZE(szSize));
  440. StrCatBuffW(szSize, L")", ARRAYSIZE(szSize));
  441. cLen = lstrlenW(pszDisplayName);
  442. if (cLen+1 > ARRAYSIZE(szBuf))
  443. cLen = ARRAYSIZE(szBuf) - 1;
  444. StrCpyNW(szBuf, pszDisplayName, cLen+1);
  445. PathStripPathW(szBuf);
  446. cLen = lstrlenW(szBuf);
  447. if (cLen > DisplayMaxLen)
  448. {
  449. WCHAR szBuf2[MAX_PATH];
  450. WCHAR *szExt;
  451. szExt = PathFindExtensionW(szBuf);
  452. if (*szExt)
  453. {
  454. int cExt = lstrlenW(szExt);
  455. if (cExt < DisplayMaxLen-3)
  456. {
  457. WCHAR szExt2[DisplayMaxLen];
  458. StrCpyNW(szExt2, szExt, ARRAYSIZE(szExt2));
  459. PathCompactPathExW(szBuf2, szBuf, DisplayMaxLen-cExt, 0);
  460. StrCatBuffW(szBuf2, szExt2, ARRAYSIZE(szBuf2));
  461. }
  462. else
  463. PathCompactPathExW(szBuf2, szBuf, DisplayMaxLen, 0);
  464. }
  465. else
  466. {
  467. PathCompactPathExW(szBuf2, szBuf, DisplayMaxLen, 0);
  468. }
  469. StrCpyNW(szBuf, szBuf2, ARRAYSIZE(szBuf));
  470. }
  471. // Size to allocate: filename.dat (x)\0
  472. cAlloc = lstrlenW(szBuf) + lstrlenW(szSize) + 2;
  473. // Dup the display name
  474. CHECKALLOC(m_pszDisplay = PszAllocW(cAlloc));
  475. // Format the Display Name
  476. StrCpyNW(m_pszDisplay, szBuf, cAlloc);
  477. StrCatBuffW(m_pszDisplay, L" ", cAlloc);
  478. StrCatBuffW(m_pszDisplay, szSize, cAlloc);
  479. exit:
  480. // Thread Safety
  481. LeaveCriticalSection(&m_cs);
  482. // Done
  483. return hr;
  484. }
  485. // ---------------------------------------------------------------------------
  486. // CMessageBody::GetDisplayName
  487. // ---------------------------------------------------------------------------
  488. STDMETHODIMP CMessageBody::GetDisplayName(LPSTR *ppszDisplayName)
  489. {
  490. LPWSTR pwszDispName = NULL;
  491. HRESULT hr;
  492. Assert(ppszDisplayName);
  493. *ppszDisplayName = NULL;
  494. IF_FAILEXIT(hr = GetDisplayNameW(ppszDisplayName ? &pwszDispName : NULL));
  495. IF_NULLEXIT(*ppszDisplayName = PszToANSI(CP_ACP, pwszDispName));
  496. exit:
  497. MemFree(pwszDispName);
  498. return TraceResult(hr);
  499. }
  500. STDMETHODIMP CMessageBody::GetDisplayNameW(LPWSTR *ppszDisplayName)
  501. {
  502. // Locals
  503. HRESULT hr=S_OK;
  504. ASSERTINIT;
  505. // check params
  506. if (NULL == ppszDisplayName)
  507. return TrapError(E_INVALIDARG);
  508. // Init
  509. *ppszDisplayName = NULL;
  510. // Thread Safety
  511. EnterCriticalSection(&m_cs);
  512. // Do I have an internal displayname ?
  513. if (NULL == m_pszDisplay)
  514. {
  515. LPSTR pszVal = NULL;
  516. LPWSTR pwszVal = NULL;
  517. // Use m_pszURL first
  518. if (IID_IMimeWebDocument == m_rStorage.riid && SUCCEEDED(m_rStorage.pWebDocument->GetURL(&pszVal)))
  519. SetDisplayName(pszVal);
  520. // Raid-38681 - mail:file name is incorrect when attaching renamed saved message
  521. // Raid-18813 - Single Bodies messages can have a filename and a subject.
  522. else if (SUCCEEDED(m_pContainer->GetPropW(SYM_ATT_FILENAME, &pwszVal)) && pwszVal)
  523. SetDisplayNameW(pwszVal);
  524. // If I'm an message/rfc822
  525. else if (m_pContainer->IsContentType(STR_CNT_MESSAGE, STR_SUB_RFC822) == S_OK && FExtractRfc822Subject(&pwszVal))
  526. SetDisplayNameW(pwszVal);
  527. // Parent is multipart/digest
  528. else if (m_pNode && m_pNode->pParent && m_pNode->pParent->pBody && m_pNode->pParent->pBody->IsContentType(STR_CNT_MULTIPART, STR_SUB_DIGEST) == S_OK && FExtractRfc822Subject(&pwszVal))
  529. SetDisplayNameW(pwszVal);
  530. // Use Subject
  531. else if (SUCCEEDED(m_pContainer->GetPropW(SYM_HDR_SUBJECT, &pwszVal)) && pwszVal)
  532. SetDisplayNameW(pwszVal);
  533. // Use Generated File Name...
  534. else if (SUCCEEDED(m_pContainer->GetPropW(SYM_ATT_GENFNAME, &pwszVal)) && pwszVal)
  535. SetDisplayNameW(pwszVal);
  536. // Content Description
  537. else if (SUCCEEDED(m_pContainer->GetPropW(SYM_HDR_CNTDESC, &pwszVal)) && pwszVal)
  538. SetDisplayNameW(pwszVal);
  539. SafeMemFree(pszVal);
  540. SafeMemFree(pwszVal);
  541. }
  542. // If there is a display name now, then dup it.
  543. if (m_pszDisplay)
  544. CHECKALLOC(*ppszDisplayName = PszDupW(m_pszDisplay));
  545. else
  546. hr = MIME_E_NO_DATA;
  547. exit:
  548. // Thread Safety
  549. LeaveCriticalSection(&m_cs);
  550. // Done
  551. return hr;
  552. }
  553. // ---------------------------------------------------------------------------
  554. // CMessageBody::FExtractRfc822Subject
  555. // ---------------------------------------------------------------------------
  556. BOOL CMessageBody::FExtractRfc822Subject(LPWSTR *ppwszVal)
  557. {
  558. // Locals
  559. HRESULT hr=S_OK;
  560. IStream *pstmData=NULL;
  561. IMimePropertySet *pPropertySet=NULL;
  562. PROPVARIANT rSubject;
  563. ASSERTINIT;
  564. // Invalid Arg
  565. Assert(ppwszVal);
  566. // Init
  567. MimeOleVariantInit(&rSubject);
  568. *ppwszVal = NULL;
  569. // Get the data
  570. CHECKHR(hr = GetData(IET_BINARY, &pstmData));
  571. // Lets create a header
  572. CHECKHR(hr = MimeOleCreatePropertySet(NULL, &pPropertySet));
  573. // Parse the header
  574. CHECKHR(hr = pPropertySet->Load(pstmData));
  575. // Init Variant
  576. rSubject.vt = VT_LPWSTR;
  577. // Get the subject and set the display name
  578. CHECKHR(hr = pPropertySet->GetProp(PIDTOSTR(PID_HDR_SUBJECT), 0, &rSubject));
  579. // Raid-38681 - mail:file name is incorrect when attaching renamed saved message
  580. if (FIsEmptyW(rSubject.pwszVal))
  581. {
  582. SafeMemFree(rSubject.pwszVal);
  583. goto exit;
  584. }
  585. // Set this subject on my self so that STR_ATT_GENFNAME works
  586. m_pContainer->SetProp(PIDTOSTR(PID_HDR_CNTDESC), 0, &rSubject);
  587. // Return It
  588. *ppwszVal = rSubject.pwszVal;
  589. exit:
  590. // Cleanup
  591. SafeRelease(pstmData);
  592. SafeRelease(pPropertySet);
  593. // Done
  594. return (NULL == *ppwszVal) ? FALSE : TRUE;
  595. }
  596. // ---------------------------------------------------------------------------
  597. // CMessageBody::SetOption
  598. // ---------------------------------------------------------------------------
  599. STDMETHODIMP CMessageBody::SetOption(const TYPEDID oid, LPCPROPVARIANT pValue)
  600. {
  601. // check params
  602. if (NULL == pValue)
  603. return TrapError(E_INVALIDARG);
  604. return InternalSetOption(oid, pValue, FALSE, FALSE);
  605. }
  606. // ---------------------------------------------------------------------------
  607. // CMessageBody::InternalSetOption
  608. // ---------------------------------------------------------------------------
  609. HRESULT CMessageBody::InternalSetOption(const TYPEDID oid, LPCPROPVARIANT pValue, BOOL fInternal, BOOL fNoDirty)
  610. {
  611. // Locals
  612. #ifdef SMIME_V3
  613. DWORD cb;
  614. #endif // SMIME_V3
  615. HRESULT hr=S_OK;
  616. DWORD i;
  617. ASSERTINIT;
  618. CAPROPVARIANT capv;
  619. CAUL caul;
  620. CAUH cauh;
  621. CAFILETIME cafiletime;
  622. #ifdef SMIME_V3
  623. BYTE rgb[50];
  624. #endif // SMIME_V3
  625. // Thread Safety
  626. EnterCriticalSection(&m_cs);
  627. // Handle Optid
  628. switch(oid)
  629. {
  630. case OID_SUPPORT_EXTERNAL_BODY:
  631. if (m_rOptions.fExternalBody != (pValue->boolVal ? TRUE : FALSE))
  632. {
  633. m_rOptions.fExternalBody = pValue->boolVal ? TRUE : FALSE;
  634. if (!fNoDirty)
  635. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  636. }
  637. break;
  638. case OID_SHOW_MACBINARY:
  639. if (m_rOptions.fShowMacBin != (pValue->boolVal ? TRUE : FALSE))
  640. {
  641. m_rOptions.fShowMacBin = pValue->boolVal ? TRUE : FALSE;
  642. if (!fNoDirty)
  643. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  644. }
  645. break;
  646. case OID_CBMAX_BODY_LINE:
  647. if (pValue->ulVal < MIN_CBMAX_BODY_LINE || pValue->ulVal > MAX_CBMAX_BODY_LINE)
  648. {
  649. hr = TrapError(MIME_E_INVALID_OPTION_VALUE);
  650. goto exit;
  651. }
  652. if (m_rOptions.cbMaxLine != pValue->ulVal)
  653. {
  654. m_rOptions.cbMaxLine = pValue->ulVal;
  655. if (!fNoDirty)
  656. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  657. }
  658. break;
  659. case OID_TRANSMIT_BODY_ENCODING:
  660. if (FALSE == FIsValidBodyEncoding((ENCODINGTYPE)pValue->ulVal))
  661. {
  662. hr = TrapError(MIME_E_INVALID_OPTION_VALUE);
  663. goto exit;
  664. }
  665. if (m_rOptions.ietTransmit != (ENCODINGTYPE)pValue->ulVal)
  666. {
  667. m_rOptions.ietTransmit = (ENCODINGTYPE)pValue->ulVal;
  668. if (!fNoDirty)
  669. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  670. }
  671. break;
  672. case OID_WRAP_BODY_TEXT:
  673. if (m_rOptions.fWrapText != (pValue->boolVal ? TRUE : FALSE))
  674. {
  675. m_rOptions.fWrapText = pValue->boolVal ? TRUE : FALSE;
  676. if (!fNoDirty)
  677. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  678. }
  679. break;
  680. case OID_HIDE_TNEF_ATTACHMENTS:
  681. if (m_rOptions.fHideTNEF != (pValue->boolVal ? TRUE : FALSE))
  682. {
  683. m_rOptions.fHideTNEF = pValue->boolVal ? TRUE : FALSE;
  684. if (!fNoDirty)
  685. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  686. }
  687. break;
  688. case OID_DBCS_ESCAPE_IS_8BIT:
  689. if (m_rOptions.fDBCSEscape8 != (pValue->boolVal ? TRUE : FALSE))
  690. {
  691. m_rOptions.fDBCSEscape8 = pValue->boolVal ? TRUE : FALSE;
  692. if (!fNoDirty)
  693. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  694. }
  695. break;
  696. case OID_SECURITY_TYPE:
  697. if (m_rOptions.ulSecurityType != pValue->ulVal)
  698. {
  699. m_rOptions.ulSecurityType = pValue->ulVal;
  700. if (!fNoDirty)
  701. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  702. }
  703. break;
  704. case OID_SECURITY_ALG_HASH: // innermost signing algorithm
  705. if (FAILED(hr = _HrEnsureBodyOptionLayers(1)))
  706. {
  707. break;
  708. }
  709. if (CompareBlob(&m_rOptions.rgblobHash[0], &pValue->blob))
  710. {
  711. ReleaseMem(m_rOptions.rgblobHash[0].pBlobData);
  712. hr = HrCopyBlob(&pValue->blob, &m_rOptions.rgblobHash[0]);
  713. if (!fNoDirty)
  714. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  715. }
  716. break;
  717. case OID_SECURITY_ALG_HASH_RG: // signing algorithms
  718. if (FAILED(hr = _HrEnsureBodyOptionLayers(pValue)))
  719. {
  720. break;
  721. }
  722. hr = _CompareCopyBlobArray(pValue, &m_rOptions.rgblobHash, fNoDirty);
  723. break;
  724. case OID_SECURITY_ALG_BULK:
  725. if (CompareBlob(&m_rOptions.blobBulk, &pValue->blob))
  726. {
  727. ReleaseMem(m_rOptions.blobBulk.pBlobData);
  728. hr = HrCopyBlob(&pValue->blob, &m_rOptions.blobBulk);
  729. if (!fNoDirty)
  730. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  731. }
  732. break;
  733. #ifndef _WIN64
  734. case OID_SECURITY_CERT_SIGNING:
  735. if (FAILED(hr = _HrEnsureBodyOptionLayers(1)))
  736. {
  737. break;
  738. }
  739. if (m_rOptions.rgpcCertSigning[0] != (PCCERT_CONTEXT)pValue->ulVal)
  740. {
  741. if (m_rOptions.rgpcCertSigning[0])
  742. CertFreeCertificateContext(m_rOptions.rgpcCertSigning[0]);
  743. m_rOptions.rgpcCertSigning[0] = CertDuplicateCertificateContext((PCCERT_CONTEXT)pValue->ulVal);
  744. if (!fNoDirty)
  745. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  746. }
  747. break;
  748. case OID_SECURITY_CERT_SIGNING_RG: // signing algorithms
  749. if (FAILED(hr = _HrEnsureBodyOptionLayers(pValue)))
  750. {
  751. break;
  752. }
  753. caul = pValue->caul;
  754. Assert(caul.cElems == m_rOptions.cSigners || 0 == m_rOptions.cSigners);
  755. if (m_rOptions.cSigners != caul.cElems && 0 != m_rOptions.cSigners)
  756. {
  757. hr = E_INVALIDARG;
  758. }
  759. else
  760. {
  761. for (i = 0; i < caul.cElems; i++) {
  762. if (m_rOptions.rgpcCertSigning[i] != (PCCERT_CONTEXT)caul.pElems[i])
  763. {
  764. if (m_rOptions.rgpcCertSigning[i])
  765. CertFreeCertificateContext(m_rOptions.rgpcCertSigning[i]);
  766. m_rOptions.rgpcCertSigning[i] = CertDuplicateCertificateContext((PCCERT_CONTEXT)caul.pElems[i]);
  767. if (!fNoDirty)
  768. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  769. }
  770. }
  771. }
  772. break;
  773. case OID_SECURITY_CERT_DECRYPTION:
  774. if (m_rOptions.pcCertDecryption != (PCCERT_CONTEXT)pValue->ulVal)
  775. {
  776. if (m_rOptions.pcCertDecryption)
  777. CertFreeCertificateContext(m_rOptions.pcCertDecryption);
  778. m_rOptions.pcCertDecryption = CertDuplicateCertificateContext((PCCERT_CONTEXT)pValue->ulVal);
  779. if (!fNoDirty)
  780. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  781. }
  782. break;
  783. case OID_SECURITY_RG_CERT_ENCRYPT:
  784. #ifdef SMIME_V3
  785. for (i=0; i<pValue->caul.cElems; i++)
  786. {
  787. CMS_RECIPIENT_INFO info = {0};
  788. info.pccert = (PCCERT_CONTEXT) pValue->caul.pElems[i];
  789. hr = AddRecipient((i == 0) ? SMIME_RECIPIENT_REPLACE_ALL : 0, 1, &info);
  790. if (FAILED(hr))
  791. {
  792. break;
  793. }
  794. }
  795. if (SUCCEEDED(hr) && !fNoDirty)
  796. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  797. #else // !SMIME_V3
  798. if (SUCCEEDED(hr = _CAULToCERTARRAY(pValue->caul, &m_rOptions.caEncrypt)))
  799. if (!fNoDirty)
  800. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  801. #endif // !SMIME_V3
  802. break;
  803. case OID_SECURITY_HCERTSTORE:
  804. CertCloseStore(m_rOptions.hCertStore, 0);
  805. if (pValue->ulVal)
  806. m_rOptions.hCertStore = CertDuplicateStore((HCERTSTORE)pValue->ulVal);
  807. else
  808. m_rOptions.hCertStore = NULL;
  809. break;
  810. case OID_SECURITY_ENCRYPT_CERT_BAG:
  811. CertCloseStore(m_rOptions.hstoreEncrypt, 0);
  812. if (pValue->ulVal)
  813. m_rOptions.hstoreEncrypt = CertDuplicateStore((HCERTSTORE) pValue->ulVal);
  814. else
  815. m_rOptions.hstoreEncrypt = NULL;
  816. break;
  817. case OID_SECURITY_RG_CERT_BAG:
  818. if (SUCCEEDED(hr = _CAULToCertStore(pValue->caul, &m_rOptions.hCertStore)))
  819. if (!fNoDirty)
  820. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  821. break;
  822. case OID_SECURITY_SEARCHSTORES:
  823. if (SUCCEEDED(hr = _CAULToSTOREARRAY(pValue->caul, &m_rOptions.saSearchStore)))
  824. if (!fNoDirty)
  825. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  826. break;
  827. case OID_SECURITY_RG_IASN:
  828. //N TODO: OID_SECURITY_RG_IASN
  829. if (fInternal)
  830. {
  831. }
  832. else
  833. {
  834. hr = MIME_E_READ_ONLY;
  835. }
  836. break;
  837. // 2 Key implementation
  838. case OID_SECURITY_2KEY_CERT_BAG:
  839. {
  840. hr = S_OK;
  841. // Create a new store if needed
  842. if (m_rOptions.hCertStore == NULL)
  843. {
  844. m_rOptions.hCertStore = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING,
  845. NULL, 0, NULL);
  846. }
  847. if (m_rOptions.hCertStore == NULL)
  848. {
  849. hr = HrGetLastError();
  850. }
  851. for (i=0; i < (pValue->caul).cElems; i++)
  852. {
  853. if (!CertAddCertificateContextToStore(m_rOptions.hCertStore,
  854. (PCCERT_CONTEXT) IntToPtr((pValue->caul).pElems[i]),
  855. CERT_STORE_ADD_ALWAYS, NULL))
  856. {
  857. hr = HrGetLastError();
  858. }
  859. }
  860. if(hr == S_OK)
  861. {
  862. if (!fNoDirty)
  863. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  864. }
  865. }
  866. break;
  867. case OID_SECURITY_HCRYPTPROV:
  868. if (m_rOptions.hCryptProv != pValue->ulVal)
  869. {
  870. if (m_rOptions.hCryptProv)
  871. CryptReleaseContext(m_rOptions.hCryptProv, 0);
  872. m_rOptions.hCryptProv = pValue->ulVal;
  873. if (!fNoDirty)
  874. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  875. }
  876. break;
  877. #else // _WIN64
  878. case OID_SECURITY_CERT_SIGNING_64:
  879. if (FAILED(hr = _HrEnsureBodyOptionLayers(1)))
  880. {
  881. break;
  882. }
  883. if (m_rOptions.rgpcCertSigning[0] != (PCCERT_CONTEXT)pValue->pulVal)
  884. {
  885. if (m_rOptions.rgpcCertSigning[0])
  886. CertFreeCertificateContext(m_rOptions.rgpcCertSigning[0]);
  887. m_rOptions.rgpcCertSigning[0] = CertDuplicateCertificateContext((PCCERT_CONTEXT)pValue->pulVal);
  888. if (!fNoDirty)
  889. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  890. }
  891. break;
  892. case OID_SECURITY_CERT_SIGNING_RG_64: // signing algorithms
  893. if (FAILED(hr = _HrEnsureBodyOptionLayers(pValue)))
  894. {
  895. break;
  896. }
  897. cauh = pValue->cauh;
  898. Assert(cauh.cElems == m_rOptions.cSigners || 0 == m_rOptions.cSigners);
  899. if (m_rOptions.cSigners != cauh.cElems && 0 != m_rOptions.cSigners)
  900. {
  901. hr = E_INVALIDARG;
  902. } else {
  903. for (i = 0; i < cauh.cElems; i++)
  904. {
  905. PCCERT_CONTEXT pCert = *(PCCERT_CONTEXT *) (&(cauh.pElems[i]));
  906. if (m_rOptions.rgpcCertSigning[i] != (PCCERT_CONTEXT)(pCert))
  907. {
  908. if (m_rOptions.rgpcCertSigning[i])
  909. CertFreeCertificateContext(m_rOptions.rgpcCertSigning[i]);
  910. m_rOptions.rgpcCertSigning[i] = CertDuplicateCertificateContext((PCCERT_CONTEXT)(pCert));
  911. if (!fNoDirty)
  912. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  913. }
  914. }
  915. }
  916. break;
  917. case OID_SECURITY_CERT_DECRYPTION_64:
  918. if (m_rOptions.pcCertDecryption != (PCCERT_CONTEXT)pValue->pulVal)
  919. {
  920. if (m_rOptions.pcCertDecryption)
  921. CertFreeCertificateContext(m_rOptions.pcCertDecryption);
  922. m_rOptions.pcCertDecryption = CertDuplicateCertificateContext((PCCERT_CONTEXT)pValue->pulVal);
  923. if (!fNoDirty)
  924. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  925. }
  926. break;
  927. case OID_SECURITY_RG_CERT_ENCRYPT_64:
  928. #ifdef SMIME_V3
  929. for (i=0; i<pValue->cauh.cElems; i++)
  930. {
  931. CMS_RECIPIENT_INFO info = {0};
  932. info.pccert = *((PCCERT_CONTEXT*) &(pValue->cauh.pElems[i]));
  933. hr = AddRecipient((i == 0) ? SMIME_RECIPIENT_REPLACE_ALL : 0, 1, &info);
  934. if (FAILED(hr))
  935. {
  936. break;
  937. }
  938. }
  939. if (SUCCEEDED(hr) && !fNoDirty)
  940. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  941. #else // !SMIME_V3
  942. if (SUCCEEDED(hr = _CAUHToCERTARRAY(pValue->cauh, &m_rOptions.caEncrypt)))
  943. if (!fNoDirty)
  944. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  945. #endif // !SMIME_V3
  946. break;
  947. case OID_SECURITY_HCERTSTORE_64:
  948. CertCloseStore(m_rOptions.hCertStore, 0);
  949. if (pValue->pulVal)
  950. m_rOptions.hCertStore = CertDuplicateStore((HCERTSTORE)pValue->pulVal);
  951. else
  952. m_rOptions.hCertStore = NULL;
  953. break;
  954. case OID_SECURITY_ENCRYPT_CERT_BAG_64:
  955. CertCloseStore(m_rOptions.hstoreEncrypt, 0);
  956. if (pValue->pulVal)
  957. m_rOptions.hstoreEncrypt = CertDuplicateStore((HCERTSTORE) pValue->pulVal);
  958. else
  959. m_rOptions.hstoreEncrypt = NULL;
  960. break;
  961. case OID_SECURITY_RG_CERT_BAG_64:
  962. if (SUCCEEDED(hr = _CAUHToCertStore(pValue->cauh, &m_rOptions.hCertStore)))
  963. if (!fNoDirty)
  964. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  965. break;
  966. case OID_SECURITY_SEARCHSTORES_64:
  967. if (SUCCEEDED(hr = _CAUHToSTOREARRAY(pValue->cauh, &m_rOptions.saSearchStore)))
  968. if (!fNoDirty)
  969. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  970. break;
  971. case OID_SECURITY_RG_IASN_64:
  972. //N TODO: OID_SECURITY_RG_IASN
  973. if (fInternal)
  974. {
  975. }
  976. else
  977. {
  978. hr = MIME_E_READ_ONLY;
  979. }
  980. break;
  981. // 2 Key implementation
  982. case OID_SECURITY_2KEY_CERT_BAG_64:
  983. {
  984. hr = S_OK;
  985. // Create a new store if needed
  986. if (m_rOptions.hCertStore == NULL)
  987. {
  988. m_rOptions.hCertStore = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING,
  989. NULL, 0, NULL);
  990. }
  991. if (m_rOptions.hCertStore == NULL)
  992. {
  993. hr = HrGetLastError();
  994. }
  995. for (i=0; i < (pValue->cauh).cElems; i++)
  996. {
  997. if (!CertAddCertificateContextToStore(m_rOptions.hCertStore,
  998. *((PCCERT_CONTEXT *) (&((pValue->cauh).pElems[i]))),
  999. CERT_STORE_ADD_ALWAYS, NULL))
  1000. {
  1001. hr = HrGetLastError();
  1002. }
  1003. }
  1004. if(hr == S_OK)
  1005. {
  1006. if (!fNoDirty)
  1007. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1008. }
  1009. }
  1010. break;
  1011. case OID_SECURITY_HCRYPTPROV_64:
  1012. if (m_rOptions.hCryptProv != (((HCRYPTPROV) (pValue->pulVal))))
  1013. {
  1014. if (m_rOptions.hCryptProv)
  1015. CryptReleaseContext(m_rOptions.hCryptProv, 0);
  1016. m_rOptions.hCryptProv = (HCRYPTPROV) pValue->pulVal;
  1017. if (!fNoDirty)
  1018. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1019. }
  1020. break;
  1021. #endif //_WIN64
  1022. case OID_SECURITY_CRL:
  1023. if (m_rOptions.hCertStore == NULL)
  1024. {
  1025. m_rOptions.hCertStore = CertOpenStore(CERT_STORE_PROV_MEMORY,
  1026. X509_ASN_ENCODING,
  1027. NULL, 0, NULL);
  1028. if (m_rOptions.hCertStore == NULL)
  1029. {
  1030. hr = HrGetLastError();
  1031. break;
  1032. }
  1033. }
  1034. if (!CertAddEncodedCRLToStore(m_rOptions.hCertStore, X509_ASN_ENCODING,
  1035. pValue->blob.pBlobData,
  1036. pValue->blob.cbSize,
  1037. CERT_STORE_ADD_ALWAYS, NULL))
  1038. {
  1039. hr = HrGetLastError();
  1040. }
  1041. else if (!fNoDirty)
  1042. {
  1043. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1044. }
  1045. break;
  1046. case OID_SECURITY_SYMCAPS:
  1047. if (FAILED(hr = _HrEnsureBodyOptionLayers(1)))
  1048. {
  1049. break;
  1050. }
  1051. #ifdef SMIME_V3
  1052. hr = _HrSetAttribute(0, &m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED][0],
  1053. szOID_RSA_SMIMECapabilities,
  1054. pValue->blob.cbSize, pValue->blob.pBlobData);
  1055. #else // !SMIME_V3
  1056. if (CompareBlob(&m_rOptions.rgblobSymCaps[0], &pValue->blob))
  1057. {
  1058. ReleaseMem(m_rOptions.rgblobSymCaps[0].pBlobData);
  1059. hr = HrCopyBlob(&pValue->blob, &m_rOptions.rgblobSymCaps[0]);
  1060. if (!fNoDirty)
  1061. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1062. }
  1063. #endif // SMIME_V3
  1064. break;
  1065. case OID_SECURITY_SYMCAPS_RG: // symetric capabilities
  1066. if (FAILED(hr = _HrEnsureBodyOptionLayers(pValue)))
  1067. {
  1068. break;
  1069. }
  1070. #ifdef SMIME_V3
  1071. for (i=0; i<pValue->capropvar.cElems; i++)
  1072. {
  1073. hr = _HrSetAttribute(0, &m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED][i],
  1074. szOID_RSA_SMIMECapabilities,
  1075. pValue->capropvar.pElems[i].blob.cbSize,
  1076. pValue->capropvar.pElems[i].blob.pBlobData);
  1077. if (FAILED(hr))
  1078. break;
  1079. }
  1080. #else // !SMIME_V3
  1081. hr = _CompareCopyBlobArray(pValue, &m_rOptions.rgblobSymCaps, fNoDirty);
  1082. #endif // SMIME_V3
  1083. break;
  1084. case OID_SECURITY_AUTHATTR:
  1085. if (FAILED(hr = _HrEnsureBodyOptionLayers(1)))
  1086. {
  1087. break;
  1088. }
  1089. #ifdef SMIME_V3
  1090. hr = _HrSetAttribute(0, &m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED][0],
  1091. NULL, pValue->blob.cbSize, pValue->blob.pBlobData);
  1092. #else // !SMIME_V3
  1093. if (CompareBlob(&m_rOptions.rgblobAuthAttr[0], &pValue->blob))
  1094. {
  1095. ReleaseMem(m_rOptions.rgblobAuthAttr[0].pBlobData);
  1096. hr = HrCopyBlob(&pValue->blob, &m_rOptions.rgblobAuthAttr[0]);
  1097. if (!fNoDirty)
  1098. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1099. }
  1100. #endif // SMIME_V3
  1101. break;
  1102. case OID_SECURITY_AUTHATTR_RG: // authenticated attributes
  1103. if (FAILED(hr = _HrEnsureBodyOptionLayers(pValue)))
  1104. {
  1105. break;
  1106. }
  1107. #ifdef SMIME_V3
  1108. for (i=0; i<pValue->capropvar.cElems; i++)
  1109. {
  1110. hr = _HrSetAttribute(0, &m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED][i],
  1111. NULL, pValue->capropvar.pElems[i].blob.cbSize,
  1112. pValue->capropvar.pElems[i].blob.pBlobData);
  1113. if (FAILED(hr))
  1114. break;
  1115. }
  1116. #else // !SMIME_V3
  1117. hr = _CompareCopyBlobArray(pValue, &m_rOptions.rgblobAuthAttr, fNoDirty);
  1118. #endif // SMIME_V3
  1119. break;
  1120. case OID_SECURITY_UNAUTHATTR:
  1121. if (FAILED(hr = _HrEnsureBodyOptionLayers(1)))
  1122. {
  1123. break;
  1124. }
  1125. #ifdef SMIME_V3
  1126. hr = _HrSetAttribute(0, &m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_UNSIGNED][0],
  1127. NULL, pValue->blob.cbSize, pValue->blob.pBlobData);
  1128. #else // !SMIME_V3
  1129. if (CompareBlob(&m_rOptions.rgblobUnauthAttr[0], &pValue->blob))
  1130. {
  1131. ReleaseMem(m_rOptions.rgblobUnauthAttr[0].pBlobData);
  1132. hr = HrCopyBlob(&pValue->blob, &m_rOptions.rgblobUnauthAttr[0]);
  1133. if (!fNoDirty)
  1134. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1135. }
  1136. #endif // SMIME_V3
  1137. break;
  1138. case OID_SECURITY_UNAUTHATTR_RG: // unauthenticated attributes
  1139. if (FAILED(hr = _HrEnsureBodyOptionLayers(pValue)))
  1140. {
  1141. break;
  1142. }
  1143. #ifdef SMIME_V3
  1144. for (i=0; i<pValue->capropvar.cElems; i++)
  1145. {
  1146. hr = _HrSetAttribute(0, &m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_UNSIGNED][i],
  1147. NULL, pValue->capropvar.pElems[i].blob.cbSize,
  1148. pValue->capropvar.pElems[i].blob.pBlobData);
  1149. if (FAILED(hr))
  1150. break;
  1151. }
  1152. #else // !SMIME_V3
  1153. hr = _CompareCopyBlobArray(pValue, &m_rOptions.rgblobUnauthAttr, fNoDirty);
  1154. #endif // SMIME_V3
  1155. break;
  1156. case OID_SECURITY_SIGNTIME:
  1157. if (FAILED(hr = _HrEnsureBodyOptionLayers(1)))
  1158. {
  1159. break;
  1160. }
  1161. #ifdef SMIME_V3
  1162. if ((pValue->filetime.dwLowDateTime == 0) &&
  1163. (pValue->filetime.dwHighDateTime == 0))
  1164. {
  1165. hr = DeleteAttribute(0, 0, SMIME_ATTRIBUTE_SET_SIGNED, 0,
  1166. szOID_RSA_signingTime);
  1167. }
  1168. else
  1169. {
  1170. cb = sizeof(rgb);
  1171. if (!CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CHOICE_OF_TIME,
  1172. &pValue->filetime, 0, NULL,
  1173. rgb, &cb))
  1174. {
  1175. hr = HrGetLastError();
  1176. break;
  1177. }
  1178. hr = _HrSetAttribute(0, &m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED][0],
  1179. szOID_RSA_signingTime, cb, rgb);
  1180. }
  1181. #else // !SMIME_V3
  1182. if (CompareFileTime(&m_rOptions.rgftSigning[0], (FILETIME FAR*)&pValue->filetime))
  1183. {
  1184. CopyMemory(&m_rOptions.rgftSigning[0], &pValue->filetime, sizeof(FILETIME));
  1185. if (!fNoDirty)
  1186. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1187. }
  1188. #endif // SMIME_V3
  1189. break;
  1190. case OID_SECURITY_SIGNTIME_RG: // signing times
  1191. if (FAILED(hr = _HrEnsureBodyOptionLayers(pValue)))
  1192. {
  1193. break;
  1194. }
  1195. #ifdef SMIME_V3
  1196. for (i=0; i<pValue->cafiletime.cElems; i++)
  1197. {
  1198. if ((pValue->cafiletime.pElems[i].dwLowDateTime == 0) &&
  1199. (pValue->cafiletime.pElems[i].dwHighDateTime == 0))
  1200. {
  1201. hr = DeleteAttribute(0, 0, SMIME_ATTRIBUTE_SET_SIGNED, 0,
  1202. szOID_RSA_signingTime);
  1203. }
  1204. else
  1205. {
  1206. cb = sizeof(rgb);
  1207. if (!CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CHOICE_OF_TIME,
  1208. &pValue->cafiletime.pElems[i], 0, NULL,
  1209. rgb, &cb))
  1210. {
  1211. hr = HrGetLastError();
  1212. break;
  1213. }
  1214. hr = _HrSetAttribute(0, &m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED][i],
  1215. szOID_RSA_signingTime, cb, rgb);
  1216. }
  1217. }
  1218. #else // !SMIME_V3
  1219. cafiletime = pValue->cafiletime;
  1220. Assert(cafiletime.cElems == m_rOptions.cSigners);
  1221. if (m_rOptions.cSigners != cafiletime.cElems)
  1222. {
  1223. hr = E_INVALIDARG;
  1224. } else {
  1225. for (i = 0; i < cafiletime.cElems; i++)
  1226. {
  1227. if (CompareFileTime(&m_rOptions.rgftSigning[i], (FILETIME FAR*)&cafiletime.pElems[i]))
  1228. {
  1229. CopyMemory(&m_rOptions.rgftSigning[i], &cafiletime.pElems[i], sizeof(FILETIME));
  1230. if (!fNoDirty)
  1231. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1232. }
  1233. }
  1234. }
  1235. #endif // SMIME_V3
  1236. break;
  1237. case OID_SECURITY_USER_VALIDITY:
  1238. if (FAILED(hr = _HrEnsureBodyOptionLayers(1)))
  1239. {
  1240. break;
  1241. }
  1242. if (m_rOptions.rgulUserDef[0] != pValue->ulVal)
  1243. {
  1244. m_rOptions.rgulUserDef[0] = pValue->ulVal;
  1245. if (!fNoDirty)
  1246. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1247. }
  1248. break;
  1249. case OID_SECURITY_USER_VALIDITY_RG: // user validity flags
  1250. if (FAILED(hr = _HrEnsureBodyOptionLayers(pValue)))
  1251. {
  1252. break;
  1253. }
  1254. caul = pValue->caul;
  1255. Assert(caul.cElems == m_rOptions.cSigners || 0 == m_rOptions.cSigners);
  1256. if (m_rOptions.cSigners != caul.cElems && 0 != m_rOptions.cSigners)
  1257. {
  1258. hr = E_INVALIDARG;
  1259. } else {
  1260. for (i = 0; i < caul.cElems; i++)
  1261. {
  1262. if (m_rOptions.rgulUserDef[i] != caul.pElems[i])
  1263. {
  1264. m_rOptions.rgulUserDef[i] = caul.pElems[i];
  1265. if (!fNoDirty)
  1266. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1267. }
  1268. }
  1269. }
  1270. break;
  1271. case OID_SECURITY_RO_MSG_VALIDITY:
  1272. if (FAILED(hr = _HrEnsureBodyOptionLayers(1)))
  1273. {
  1274. break;
  1275. }
  1276. if (fInternal)
  1277. {
  1278. if (m_rOptions.rgulROValid[0] != pValue->ulVal)
  1279. {
  1280. m_rOptions.rgulROValid[0] = pValue->ulVal;
  1281. if (!fNoDirty)
  1282. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1283. }
  1284. }
  1285. else
  1286. {
  1287. hr = MIME_E_READ_ONLY;
  1288. }
  1289. break;
  1290. case OID_SECURITY_RO_MSG_VALIDITY_RG: // message validity flags
  1291. if (FAILED(hr = _HrEnsureBodyOptionLayers(pValue)))
  1292. {
  1293. break;
  1294. }
  1295. caul = pValue->caul;
  1296. Assert(caul.cElems == m_rOptions.cSigners || 0 == m_rOptions.cSigners);
  1297. if (m_rOptions.cSigners != caul.cElems && 0 != m_rOptions.cSigners)
  1298. {
  1299. hr = E_INVALIDARG;
  1300. }
  1301. else
  1302. {
  1303. for (i = 0; i < caul.cElems; i++)
  1304. {
  1305. if (m_rOptions.rgulROValid[i] != caul.pElems[i])
  1306. {
  1307. m_rOptions.rgulROValid[i] = caul.pElems[i];
  1308. if (!fNoDirty)
  1309. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1310. }
  1311. }
  1312. }
  1313. break;
  1314. case OID_SECURITY_ENCODE_FLAGS:
  1315. if (m_rOptions.ulEncodeFlags != pValue->ulVal)
  1316. {
  1317. m_rOptions.ulEncodeFlags = pValue->ulVal;
  1318. if (!fNoDirty)
  1319. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1320. }
  1321. break;
  1322. case OID_SECURITY_CERT_INCLUDED:
  1323. if (fInternal)
  1324. {
  1325. if (m_rOptions.fCertWithMsg != pValue->boolVal)
  1326. {
  1327. m_rOptions.fCertWithMsg = pValue->boolVal;
  1328. if (!fNoDirty)
  1329. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1330. }
  1331. }
  1332. else
  1333. {
  1334. hr = MIME_E_READ_ONLY;
  1335. }
  1336. break;
  1337. #ifndef _WIN64
  1338. case OID_SECURITY_HWND_OWNER:
  1339. m_rOptions.hwndOwner = HWND(pValue->ulVal);
  1340. break;
  1341. #endif
  1342. case OID_SECURITY_REQUESTED_CTE:
  1343. if (m_rOptions.ietRequested != pValue->lVal)
  1344. {
  1345. m_rOptions.ietRequested = ENCODINGTYPE(pValue->lVal);
  1346. if (!fNoDirty)
  1347. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1348. }
  1349. break;
  1350. case OID_SECURITY_SIGNATURE_COUNT:
  1351. // M00BUG - I just found out that if lVal >0 but lVal < m_rOptions.cSigners
  1352. // then we don't do any adjustments to handle this case.
  1353. if (pValue->lVal == 0)
  1354. {
  1355. if (m_rOptions.cSigners)
  1356. {
  1357. // OID_SECURITY_ALG_HASH
  1358. SafeMemFree(m_rOptions.rgblobHash[0].pBlobData);
  1359. // OID_SECURITY_CERT_SIGNING
  1360. for (i = 0; i < m_rOptions.cSigners; i++)
  1361. {
  1362. CertFreeCertificateContext(m_rOptions.rgpcCertSigning[i]);
  1363. #ifdef SMIME_V3
  1364. // Attributes
  1365. SafeMemFree(m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED][i]);
  1366. SafeMemFree(m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_UNSIGNED][i]);
  1367. // OID_SECURITY_RECEIPT_RG
  1368. SafeMemFree(m_rOptions.rgblobReceipt[i].pBlobData);
  1369. // OID_SECURITY_MESSAGE_HASH_RG
  1370. SafeMemFree(m_rOptions.rgblobMsgHash[i].pBlobData);
  1371. // OID_SECURITY_KEY_PROMPT
  1372. SafeMemFree(m_rOptions.pwszKeyPrompt);
  1373. #else // !SMIME_V3
  1374. // OID_SECURITY_SYMCAPS
  1375. SafeMemFree(m_rOptions.rgblobSymCaps[i].pBlobData);
  1376. // OID_SECURITY_AUTHATTR
  1377. SafeMemFree(m_rOptions.rgblobAuthAttr[i].pBlobData);
  1378. // OID_SECURITY_UNAUTHATTR
  1379. SafeMemFree(m_rOptions.rgblobUnauthAttr[i].pBlobData);
  1380. #endif // SMIME_V3
  1381. }
  1382. // OID_SECURITY_HCERTSTORE
  1383. CertCloseStore(m_rOptions.hCertStore, 0);
  1384. m_rOptions.hCertStore = NULL;
  1385. _FreeLayerArrays();
  1386. m_rOptions.cSigners = 0;
  1387. }
  1388. }
  1389. else if (m_rOptions.cSigners <= pValue->ulVal)
  1390. {
  1391. hr = _HrEnsureBodyOptionLayers(pValue);
  1392. }
  1393. break;
  1394. #ifdef SMIME_V3
  1395. case OID_SECURITY_RECEIPT_RG:
  1396. if (fInternal)
  1397. {
  1398. if (FAILED(hr = _HrEnsureBodyOptionLayers(pValue)))
  1399. {
  1400. break;
  1401. }
  1402. hr = _CompareCopyBlobArray(pValue, &m_rOptions.rgblobReceipt, fNoDirty);
  1403. }
  1404. else
  1405. hr = MIME_E_READ_ONLY;
  1406. break;
  1407. case OID_SECURITY_MESSAGE_HASH_RG:
  1408. if (fInternal)
  1409. {
  1410. if (FAILED(hr = _HrEnsureBodyOptionLayers(pValue)))
  1411. {
  1412. break;
  1413. }
  1414. hr = _CompareCopyBlobArray(pValue, &m_rOptions.rgblobMsgHash, fNoDirty);
  1415. }
  1416. else
  1417. hr = MIME_E_READ_ONLY;
  1418. break;
  1419. case OID_SECURITY_KEY_PROMPT:
  1420. if ((m_rOptions.pwszKeyPrompt == NULL) ||
  1421. (pValue->pwszVal == NULL) ||
  1422. (lstrcmpW(m_rOptions.pwszKeyPrompt,pValue->pwszVal) != 0))
  1423. {
  1424. SafeMemFree(m_rOptions.pwszKeyPrompt);
  1425. if (pValue->pwszVal != NULL)
  1426. {
  1427. m_rOptions.pwszKeyPrompt = PszDupW(pValue->pwszVal);
  1428. if (NULL == m_rOptions.pwszKeyPrompt)
  1429. hr = E_OUTOFMEMORY;
  1430. }
  1431. }
  1432. break;
  1433. #endif // SMIME_V3
  1434. case OID_NOSECURITY_ONSAVE:
  1435. m_rOptions.fNoSecurityOnSave = !!pValue->boolVal;
  1436. break;
  1437. #ifdef _WIN65
  1438. // (YST) This was checked in by BriMo at 01/22/99
  1439. case OID_SECURITY_CERT_SIGNING2:
  1440. if (FAILED(hr = _HrEnsureBodyOptionLayers(1)))
  1441. {
  1442. break;
  1443. }
  1444. if (m_rOptions.rgpcCertSigning[0] != *(PCCERT_CONTEXT *)(&(pValue->uhVal)))
  1445. {
  1446. if (m_rOptions.rgpcCertSigning[0])
  1447. CertFreeCertificateContext(m_rOptions.rgpcCertSigning[0]);
  1448. m_rOptions.rgpcCertSigning[0] = CertDuplicateCertificateContext(*(PCCERT_CONTEXT *)(&(pValue->uhVal)));
  1449. if (!fNoDirty)
  1450. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1451. }
  1452. break;
  1453. case OID_SECURITY_CERT_SIGNING_RG2: // signing algorithms
  1454. if (FAILED(hr = _HrEnsureBodyOptionLayers(pValue)))
  1455. {
  1456. break;
  1457. }
  1458. cauh = pValue->cauh;
  1459. Assert(cauh.cElems == m_rOptions.cSigners || 0 == m_rOptions.cSigners);
  1460. if (m_rOptions.cSigners != cauh.cElems && 0 != m_rOptions.cSigners)
  1461. {
  1462. hr = E_INVALIDARG;
  1463. } else {
  1464. for (i = 0; i < cauh.cElems; i++)
  1465. {
  1466. if (m_rOptions.rgpcCertSigning[i] != (PCCERT_CONTEXT)(cauh.pElems[i]))
  1467. {
  1468. if (m_rOptions.rgpcCertSigning[i])
  1469. CertFreeCertificateContext(m_rOptions.rgpcCertSigning[i]);
  1470. m_rOptions.rgpcCertSigning[i] = CertDuplicateCertificateContext((PCCERT_CONTEXT )(cauh.pElems[i]));
  1471. if (!fNoDirty)
  1472. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1473. }
  1474. }
  1475. }
  1476. break;
  1477. case OID_SECURITY_CERT_DECRYPTION2:
  1478. if (m_rOptions.pcCertDecryption != *(PCCERT_CONTEXT *)(&(pValue->uhVal)))
  1479. {
  1480. if (m_rOptions.pcCertDecryption)
  1481. CertFreeCertificateContext(m_rOptions.pcCertDecryption);
  1482. m_rOptions.pcCertDecryption = CertDuplicateCertificateContext(*(PCCERT_CONTEXT *)(&(pValue->uhVal)));
  1483. if (!fNoDirty)
  1484. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1485. }
  1486. break;
  1487. case OID_SECURITY_RG_CERT_ENCRYPT2:
  1488. if (SUCCEEDED(hr = _CAUHToCERTARRAY(pValue->cauh, &m_rOptions.caEncrypt)))
  1489. if (!fNoDirty)
  1490. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1491. break;
  1492. case OID_SECURITY_HCERTSTORE2:
  1493. CertCloseStore(m_rOptions.hCertStore, 0);
  1494. if (pValue->ulVal)
  1495. m_rOptions.hCertStore = CertDuplicateStore(*(HCERTSTORE *)(&(pValue->uhVal)));
  1496. else
  1497. m_rOptions.hCertStore = NULL;
  1498. break;
  1499. case OID_SECURITY_RG_CERT_BAG2:
  1500. if (SUCCEEDED(hr = _CAUHToCertStore(pValue->cauh, &m_rOptions.hCertStore)))
  1501. if (!fNoDirty)
  1502. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1503. break;
  1504. case OID_SECURITY_SEARCHSTORES2:
  1505. if (SUCCEEDED(hr = _CAUHToSTOREARRAY(pValue->cauh, &m_rOptions.saSearchStore)))
  1506. if (!fNoDirty)
  1507. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1508. break;
  1509. case OID_SECURITY_RG_IASN2:
  1510. //N TODO: OID_SECURITY_RG_IASN2
  1511. if (fInternal)
  1512. {
  1513. }
  1514. else
  1515. {
  1516. hr = MIME_E_READ_ONLY;
  1517. }
  1518. break;
  1519. case OID_SECURITY_HCRYPTPROV2:
  1520. if (m_rOptions.hCryptProv != *(HCRYPTPROV *)(&(pValue->uhVal)))
  1521. {
  1522. if (m_rOptions.hCryptProv)
  1523. CryptReleaseContext(m_rOptions.hCryptProv, 0);
  1524. m_rOptions.hCryptProv = *(HCRYPTPROV *)(&(pValue->uhVal));
  1525. if (!fNoDirty)
  1526. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  1527. }
  1528. break;
  1529. // End of BriMo checkin
  1530. #endif // _WIN65
  1531. #ifdef _WIN64
  1532. case OID_SECURITY_HWND_OWNER_64:
  1533. m_rOptions.hwndOwner = (HWND)(pValue->pulVal);
  1534. break;
  1535. #endif // _WIN64
  1536. default:
  1537. hr = m_pContainer->SetOption(oid, pValue);
  1538. break;
  1539. }
  1540. exit:
  1541. // Thread Safety
  1542. LeaveCriticalSection(&m_cs);
  1543. // Done
  1544. return TrapError(hr);
  1545. }
  1546. // ---------------------------------------------------------------------------
  1547. // CMessageBody::GetOption
  1548. // ---------------------------------------------------------------------------
  1549. STDMETHODIMP CMessageBody::GetOption(const TYPEDID oid, LPPROPVARIANT pValue)
  1550. {
  1551. // Locals
  1552. DWORD cb;
  1553. HRESULT hr=S_OK;
  1554. DWORD i;
  1555. LPBYTE pb;
  1556. ASSERTINIT;
  1557. ULONG iLayer;
  1558. #ifdef SMIME_V3
  1559. CRYPT_ATTRIBUTE UNALIGNED *pattr;
  1560. #endif // SMIME_V3
  1561. #ifdef _WIN64
  1562. void UNALIGNED *pv = NULL;
  1563. PCCERT_CONTEXT pTmpCert = NULL;
  1564. PCCERT_CONTEXT pcCert = NULL;
  1565. #endif // _WIN64
  1566. CRYPT_ATTR_BLOB UNALIGNED *pVal = NULL;
  1567. // check params
  1568. if (NULL == pValue)
  1569. return TrapError(E_INVALIDARG);
  1570. pValue->vt = TYPEDID_TYPE(oid);
  1571. // Thread Safety
  1572. EnterCriticalSection(&m_cs);
  1573. // Handle Optid
  1574. switch(oid)
  1575. {
  1576. case OID_SUPPORT_EXTERNAL_BODY:
  1577. pValue->boolVal = (VARIANT_BOOL) !!m_rOptions.fExternalBody;
  1578. break;
  1579. case OID_SHOW_MACBINARY:
  1580. pValue->boolVal = (VARIANT_BOOL) !!m_rOptions.fShowMacBin;
  1581. break;
  1582. case OID_CBMAX_BODY_LINE:
  1583. pValue->ulVal = m_rOptions.cbMaxLine;
  1584. break;
  1585. case OID_TRANSMIT_BODY_ENCODING:
  1586. pValue->ulVal = (ULONG)m_rOptions.ietTransmit;
  1587. break;
  1588. case OID_WRAP_BODY_TEXT:
  1589. pValue->boolVal = (VARIANT_BOOL) !!m_rOptions.fWrapText;
  1590. break;
  1591. case OID_HIDE_TNEF_ATTACHMENTS:
  1592. pValue->boolVal = (VARIANT_BOOL) !!m_rOptions.fHideTNEF;
  1593. break;
  1594. case OID_DBCS_ESCAPE_IS_8BIT:
  1595. pValue->boolVal = (VARIANT_BOOL) !!m_rOptions.fDBCSEscape8;
  1596. break;
  1597. case OID_SECURITY_TYPE:
  1598. pValue->ulVal = m_rOptions.ulSecurityType;
  1599. break;
  1600. case OID_SECURITY_ALG_HASH:
  1601. if (m_rOptions.cSigners)
  1602. {
  1603. hr = HrCopyBlob(&m_rOptions.rgblobHash[0], &pValue->blob);
  1604. }
  1605. else
  1606. {
  1607. hr = HrCopyBlob(&blobNULL, &pValue->blob);
  1608. }
  1609. break;
  1610. case OID_SECURITY_ALG_HASH_RG:
  1611. hr = HrCopyBlobArray(m_rOptions.rgblobHash, m_rOptions.cSigners, pValue);
  1612. break;
  1613. case OID_SECURITY_ALG_BULK:
  1614. hr = HrCopyBlob(&m_rOptions.blobBulk, &pValue->blob);
  1615. break;
  1616. #ifndef _WIN64
  1617. case OID_SECURITY_CERT_SIGNING:
  1618. if (m_rOptions.cSigners)
  1619. pValue->ulVal = (ULONG)CertDuplicateCertificateContext(m_rOptions.rgpcCertSigning[0]);
  1620. else
  1621. pValue->ulVal = 0; // ?
  1622. break;
  1623. case OID_SECURITY_CERT_SIGNING_RG:
  1624. hr = HrCopyDwordArray((ULONG*)m_rOptions.rgpcCertSigning, m_rOptions.cSigners, pValue);
  1625. // Duplicate the certs in place.
  1626. for (iLayer = 0; iLayer < m_rOptions.cSigners; iLayer++)
  1627. {
  1628. pValue->caul.pElems[iLayer] = (ULONG)CertDuplicateCertificateContext((PCCERT_CONTEXT)pValue->caul.pElems[iLayer]);
  1629. }
  1630. break;
  1631. case OID_SECURITY_CERT_DECRYPTION:
  1632. pValue->ulVal = (ULONG)CertDuplicateCertificateContext(m_rOptions.pcCertDecryption);
  1633. break;
  1634. #ifndef SMIME_V3
  1635. case OID_SECURITY_RG_CERT_ENCRYPT:
  1636. hr = _CERTARRAYToCAUL(m_rOptions.caEncrypt, &pValue->caul);
  1637. break;
  1638. #endif // !SMIEM_V3
  1639. case OID_SECURITY_HCERTSTORE:
  1640. pValue->ulVal = 0;
  1641. if (m_rOptions.hCertStore)
  1642. pValue->ulVal = (ULONG)CertDuplicateStore(m_rOptions.hCertStore);
  1643. break;
  1644. case OID_SECURITY_ENCRYPT_CERT_BAG:
  1645. pValue->ulVal = 0;
  1646. if (m_rOptions.hstoreEncrypt != NULL)
  1647. pValue->ulVal = (ULONG) CertDuplicateStore(m_rOptions.hstoreEncrypt);
  1648. break;
  1649. case OID_SECURITY_RG_CERT_BAG:
  1650. hr = _CertStoreToCAUL(m_rOptions.hCertStore, &pValue->caul);
  1651. break;
  1652. case OID_SECURITY_SEARCHSTORES:
  1653. hr = _STOREARRAYToCAUL(m_rOptions.saSearchStore, &pValue->caul);
  1654. break;
  1655. case OID_SECURITY_RG_IASN:
  1656. Assert(FALSE);
  1657. //N TODO: OID_SECURITY_RG_IASN
  1658. break;
  1659. case OID_SECURITY_HCRYPTPROV:
  1660. pValue->ulVal = m_rOptions.hCryptProv;
  1661. m_rOptions.hCryptProv = NULL; // read-once
  1662. break;
  1663. #else //_WIN64
  1664. case OID_SECURITY_CERT_SIGNING_64:
  1665. if (m_rOptions.cSigners)
  1666. pValue->pulVal = (ULONG *)CertDuplicateCertificateContext(m_rOptions.rgpcCertSigning[0]);
  1667. else
  1668. pValue->pulVal = 0; // ?
  1669. break;
  1670. case OID_SECURITY_CERT_SIGNING_RG_64:
  1671. hr = HrCopyIntoUlonglongArray((ULARGE_INTEGER *)m_rOptions.rgpcCertSigning, m_rOptions.cSigners, pValue);
  1672. // Duplicate the certs in place.
  1673. if(m_rOptions.cSigners > 0)
  1674. {
  1675. for (iLayer = 0; iLayer < m_rOptions.cSigners; iLayer++)
  1676. {
  1677. pv = (void*) (&(pValue->cauh.pElems[iLayer]));
  1678. pTmpCert = *((PCCERT_CONTEXT *) pv);
  1679. pcCert = CertDuplicateCertificateContext(pTmpCert);
  1680. pValue->cauh.pElems[iLayer] = *((ULARGE_INTEGER *)(&(pcCert)));
  1681. }
  1682. }
  1683. break;
  1684. case OID_SECURITY_CERT_DECRYPTION_64:
  1685. pValue->pulVal = (ULONG *)CertDuplicateCertificateContext(m_rOptions.pcCertDecryption);
  1686. break;
  1687. #ifndef SMIME_V3
  1688. case OID_SECURITY_RG_CERT_ENCRYPT_64:
  1689. hr = _CERTARRAYToCAUH(m_rOptions.caEncrypt, &pValue->cauh);
  1690. break;
  1691. #endif // !SMIEM_V3
  1692. case OID_SECURITY_HCERTSTORE_64:
  1693. pValue->pulVal = 0;
  1694. if (m_rOptions.hCertStore)
  1695. pValue->pulVal = (ULONG *)CertDuplicateStore(m_rOptions.hCertStore);
  1696. break;
  1697. case OID_SECURITY_ENCRYPT_CERT_BAG_64:
  1698. pValue->pulVal = 0;
  1699. if (m_rOptions.hstoreEncrypt != NULL)
  1700. pValue->pulVal = (ULONG *) CertDuplicateStore(m_rOptions.hstoreEncrypt);
  1701. break;
  1702. case OID_SECURITY_RG_CERT_BAG_64:
  1703. hr = _CertStoreToCAUH(m_rOptions.hCertStore, &pValue->cauh);
  1704. break;
  1705. case OID_SECURITY_SEARCHSTORES_64:
  1706. hr = _STOREARRAYToCAUH(m_rOptions.saSearchStore, &pValue->cauh);
  1707. break;
  1708. case OID_SECURITY_RG_IASN_64:
  1709. Assert(FALSE);
  1710. //N TODO: OID_SECURITY_RG_IASN
  1711. break;
  1712. case OID_SECURITY_HCRYPTPROV_64:
  1713. pValue->pulVal = (ULONG *) (m_rOptions.hCryptProv);
  1714. m_rOptions.hCryptProv = NULL; // read-once
  1715. break;
  1716. #endif //_WIN64
  1717. case OID_SECURITY_CRL:
  1718. // hr = HrCopyBlob(&m_rOptions.blobCRL, &pValue->blob);
  1719. Assert(FALSE);
  1720. // M00BUG -- MUST IMPLEMENT THIS
  1721. break;
  1722. case OID_SECURITY_SYMCAPS:
  1723. #ifdef SMIME_V3
  1724. pattr = _FindAttribute(m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED][0],
  1725. szOID_RSA_SMIMECapabilities, 0);
  1726. if (pattr != NULL)
  1727. {
  1728. pVal = &(pattr->rgValue[0]);
  1729. Assert(pattr->cValue == 1);
  1730. if (!MemAlloc((LPVOID UNALIGNED *) &pValue->blob.pBlobData,
  1731. pVal->cbData))
  1732. {
  1733. hr = E_OUTOFMEMORY;
  1734. break;
  1735. }
  1736. pValue->blob.cbSize = pVal->cbData;
  1737. memcpy(pValue->blob.pBlobData, pVal->pbData,
  1738. pVal->cbData);
  1739. }
  1740. else {
  1741. pValue->blob.cbSize = 0;
  1742. pValue->blob.pBlobData = NULL;
  1743. }
  1744. pValue->vt = VT_BLOB;
  1745. #else // !SMIME_V3
  1746. if (m_rOptions.cSigners)
  1747. {
  1748. hr = HrCopyBlob(&m_rOptions.rgblobSymCaps[0], &pValue->blob);
  1749. } else {
  1750. hr = HrCopyBlob(&blobNULL, &pValue->blob);
  1751. }
  1752. #endif // SMIME_V3
  1753. break;
  1754. case OID_SECURITY_SYMCAPS_RG:
  1755. #ifdef SMIME_V3
  1756. hr = _HrGetAttrs(m_rOptions.cSigners, m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED],
  1757. szOID_RSA_SMIMECapabilities, pValue);
  1758. #else // !SMIME_V3
  1759. hr = HrCopyBlobArray(m_rOptions.rgblobSymCaps, m_rOptions.cSigners, pValue);
  1760. #endif // SMIME_V3
  1761. break;
  1762. case OID_SECURITY_AUTHATTR:
  1763. if (m_rOptions.cSigners)
  1764. {
  1765. #ifdef SMIME_V3
  1766. memset(pValue, 0, sizeof(*pValue));
  1767. pValue->vt = VT_BLOB;
  1768. if ((m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED][0] != NULL) &&
  1769. !CryptEncodeObjectEx(X509_ASN_ENCODING,
  1770. szOID_Microsoft_Attribute_Sequence,
  1771. m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED][0],
  1772. CRYPT_ENCODE_ALLOC_FLAG,
  1773. &CryptEncodeAlloc, &pValue->blob.pBlobData,
  1774. &pValue->blob.cbSize))
  1775. {
  1776. hr = HrGetLastError();
  1777. }
  1778. #else // !SMIME_V3
  1779. hr = HrCopyBlob(&m_rOptions.rgblobAuthAttr[0], &pValue->blob);
  1780. #endif // SMIME_V3
  1781. }
  1782. else
  1783. {
  1784. hr = HrCopyBlob(&blobNULL, &pValue->blob);
  1785. }
  1786. break;
  1787. case OID_SECURITY_AUTHATTR_RG:
  1788. #ifdef SMIME_V3
  1789. hr = _HrGetAttrs(m_rOptions.cSigners, m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED], NULL, pValue);
  1790. #else // !SMIME_V3
  1791. hr = HrCopyBlobArray(m_rOptions.rgblobAuthAttr, m_rOptions.cSigners, pValue);
  1792. #endif // SMIME_V3
  1793. break;
  1794. case OID_SECURITY_UNAUTHATTR:
  1795. if (m_rOptions.cSigners)
  1796. {
  1797. #ifdef SMIME_V3
  1798. memset(pValue, 0, sizeof(*pValue));
  1799. pValue->vt = VT_BLOB;
  1800. if ((m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_UNSIGNED][0] != NULL) &&
  1801. !CryptEncodeObjectEx(X509_ASN_ENCODING,
  1802. szOID_Microsoft_Attribute_Sequence,
  1803. m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_UNSIGNED][0],
  1804. CRYPT_ENCODE_ALLOC_FLAG,
  1805. &CryptEncodeAlloc, &pValue->blob.pBlobData,
  1806. &pValue->blob.cbSize))
  1807. {
  1808. hr = HrGetLastError();
  1809. }
  1810. #else // !SMIME_V3
  1811. hr = HrCopyBlob(&m_rOptions.rgblobUnauthAttr[0], &pValue->blob);
  1812. #endif // SMIME_V3
  1813. } else {
  1814. hr = HrCopyBlob(&blobNULL, &pValue->blob);
  1815. }
  1816. break;
  1817. case OID_SECURITY_UNAUTHATTR_RG:
  1818. #ifdef SMIME_V3
  1819. hr = _HrGetAttrs(m_rOptions.cSigners, m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_UNSIGNED], NULL, pValue);
  1820. #else // !SMIME_V3
  1821. hr = HrCopyBlobArray(m_rOptions.rgblobUnauthAttr, m_rOptions.cSigners, pValue);
  1822. #endif // SMIME_V3
  1823. break;
  1824. case OID_SECURITY_SIGNTIME:
  1825. #ifdef SMIME_V3
  1826. pattr = _FindAttribute(m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED][0], szOID_RSA_signingTime, 0);
  1827. pValue->vt = VT_FILETIME;
  1828. if (pattr == NULL)
  1829. {
  1830. pValue->filetime.dwLowDateTime = 0;
  1831. pValue->filetime.dwHighDateTime = 0;
  1832. }
  1833. else
  1834. {
  1835. cb = sizeof(pValue->filetime);
  1836. Assert(pattr->cValue == 1);
  1837. pVal = &(pattr->rgValue[0]);
  1838. if (!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_CHOICE_OF_TIME,
  1839. pVal->pbData,
  1840. pVal->cbData,
  1841. 0, NULL, &pValue->filetime, &cb))
  1842. {
  1843. hr = HrGetLastError();
  1844. break;
  1845. }
  1846. }
  1847. #else // !SMIME_V3
  1848. if (m_rOptions.cSigners)
  1849. {
  1850. CopyMemory(&pValue->filetime, &m_rOptions.rgftSigning[0], sizeof(FILETIME));
  1851. }
  1852. else
  1853. {
  1854. hr = HrCopyBlob(&blobNULL, &pValue->blob);
  1855. }
  1856. #endif // SMIME_V3
  1857. break;
  1858. case OID_SECURITY_SIGNTIME_RG:
  1859. #ifdef SMIME_V3
  1860. pValue->vt = VT_VECTOR | VT_VARIANT;
  1861. pValue->capropvar.cElems = m_rOptions.cSigners;
  1862. if (m_rOptions.cSigners > 0)
  1863. {
  1864. hr = HrAlloc((LPVOID *) &pValue->capropvar.pElems,
  1865. m_rOptions.cSigners * sizeof(PROPVARIANT));
  1866. if (FAILED(hr))
  1867. {
  1868. break;
  1869. }
  1870. memset(pValue->capropvar.pElems, 0, m_rOptions.cSigners * sizeof(PROPVARIANT));
  1871. for (i=0; i<m_rOptions.cSigners; i++)
  1872. {
  1873. pValue->capropvar.pElems[i].vt = VT_FILETIME;
  1874. pattr = _FindAttribute(m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED][i],
  1875. szOID_RSA_signingTime, 0);
  1876. if (pattr != NULL)
  1877. {
  1878. cb = sizeof(pValue->filetime);
  1879. Assert(pattr->cValue == 1);
  1880. pVal = &(pattr->rgValue[0]);
  1881. if (!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_CHOICE_OF_TIME,
  1882. pVal->pbData,
  1883. pVal->cbData, 0, NULL,
  1884. &pValue->capropvar.pElems[i].filetime,
  1885. &cb))
  1886. {
  1887. hr = HrGetLastError();
  1888. MemFree(pValue->capropvar.pElems);
  1889. pValue->capropvar.pElems = NULL;
  1890. break;
  1891. }
  1892. }
  1893. }
  1894. }
  1895. #else // !SMIME_V3
  1896. hr = HrCopyFiletimeArray(m_rOptions.rgftSigning, m_rOptions.cSigners, pValue);
  1897. #endif // SMIME_V3
  1898. break;
  1899. case OID_SECURITY_USER_VALIDITY:
  1900. if (m_rOptions.cSigners)
  1901. {
  1902. pValue->ulVal = m_rOptions.rgulUserDef[0];
  1903. } else {
  1904. pValue->ulVal = 0;
  1905. }
  1906. break;
  1907. case OID_SECURITY_USER_VALIDITY_RG:
  1908. hr = HrCopyDwordArray(m_rOptions.rgulUserDef, m_rOptions.cSigners, pValue);
  1909. break;
  1910. case OID_SECURITY_RO_MSG_VALIDITY:
  1911. if (m_rOptions.cSigners)
  1912. {
  1913. pValue->ulVal = m_rOptions.rgulROValid[0];
  1914. } else {
  1915. pValue->ulVal = 0;
  1916. }
  1917. break;
  1918. case OID_SECURITY_RO_MSG_VALIDITY_RG:
  1919. hr = HrCopyDwordArray(m_rOptions.rgulROValid, m_rOptions.cSigners, pValue);
  1920. break;
  1921. case OID_SECURITY_ENCODE_FLAGS:
  1922. pValue->ulVal = m_rOptions.ulEncodeFlags;
  1923. break;
  1924. case OID_SECURITY_CERT_INCLUDED:
  1925. pValue->boolVal = (VARIANT_BOOL) !!m_rOptions.fCertWithMsg;
  1926. break;
  1927. #ifndef _WIN64
  1928. case OID_SECURITY_HWND_OWNER:
  1929. pValue->ulVal = ULONG(m_rOptions.hwndOwner);
  1930. break;
  1931. #endif // _WIN64
  1932. case OID_SECURITY_REQUESTED_CTE:
  1933. pValue->lVal = m_rOptions.ietRequested;
  1934. break;
  1935. case OID_SECURITY_SIGNATURE_COUNT:
  1936. pValue->ulVal = ULONG(m_rOptions.cSigners);
  1937. break;
  1938. #ifdef SMIME_V3
  1939. case OID_SECURITY_RECEIPT_RG:
  1940. hr = HrCopyBlobArray(m_rOptions.rgblobReceipt, m_rOptions.cSigners, pValue);
  1941. break;
  1942. case OID_SECURITY_MESSAGE_HASH_RG:
  1943. hr = HrCopyBlobArray(m_rOptions.rgblobMsgHash, m_rOptions.cSigners, pValue);
  1944. break;
  1945. case OID_SECURITY_KEY_PROMPT:
  1946. ZeroMemory(&(pValue->pwszVal), sizeof(pValue->pwszVal));
  1947. if (m_rOptions.pwszKeyPrompt != NULL)
  1948. {
  1949. pValue->pwszVal = PszDupW(m_rOptions.pwszKeyPrompt);
  1950. if (NULL == pValue->pwszVal)
  1951. hr = E_OUTOFMEMORY;
  1952. }
  1953. break;
  1954. #endif // SMIME_V3
  1955. case OID_NOSECURITY_ONSAVE:
  1956. pValue->boolVal = (VARIANT_BOOL) !!m_rOptions.fNoSecurityOnSave;
  1957. break;
  1958. #ifdef _WIN65
  1959. // BriMo checkin at 01/22/99
  1960. case OID_SECURITY_CERT_SIGNING2:
  1961. if (m_rOptions.cSigners)
  1962. {
  1963. PCCERT_CONTEXT pcCert = CertDuplicateCertificateContext(m_rOptions.rgpcCertSigning[0]);
  1964. pValue->uhVal = *(ULARGE_INTEGER *)(&(pcCert));
  1965. } else {
  1966. ZeroMemory(&(pValue->uhVal), sizeof(pValue->uhVal));
  1967. }
  1968. break;
  1969. case OID_SECURITY_CERT_SIGNING_RG2:
  1970. hr = HrCopyIntoUlonglongArray((ULARGE_INTEGER *)m_rOptions.rgpcCertSigning, m_rOptions.cSigners, pValue);
  1971. // Duplicate the certs in place.
  1972. for (iLayer = 0; iLayer < m_rOptions.cSigners; iLayer++)
  1973. {
  1974. PCCERT_CONTEXT pcCert = CertDuplicateCertificateContext((PCCERT_CONTEXT)(pValue->cauh.pElems[iLayer]));
  1975. pValue->cauh.pElems[iLayer] = *(ULARGE_INTEGER *)(&(pcCert));
  1976. }
  1977. break;
  1978. case OID_SECURITY_CERT_DECRYPTION2:
  1979. {
  1980. PCCERT_CONTEXT pcCert = CertDuplicateCertificateContext(m_rOptions.pcCertDecryption);
  1981. pValue->uhVal = *(ULARGE_INTEGER *)(&(pcCert));
  1982. }
  1983. break;
  1984. case OID_SECURITY_RG_CERT_ENCRYPT2:
  1985. hr = _CERTARRAYToCAUH(m_rOptions.caEncrypt, &pValue->cauh);
  1986. break;
  1987. case OID_SECURITY_HCERTSTORE2:
  1988. ZeroMemory(&(pValue->uhVal), sizeof(pValue->uhVal));
  1989. if (m_rOptions.hCertStore)
  1990. {
  1991. HCERTSTORE hCertStore = CertDuplicateStore(m_rOptions.hCertStore);
  1992. pValue->uhVal = *(ULARGE_INTEGER *)(&(hCertStore));
  1993. }
  1994. break;
  1995. case OID_SECURITY_RG_CERT_BAG2:
  1996. hr = _CertStoreToCAUH(m_rOptions.hCertStore, &pValue->cauh);
  1997. break;
  1998. case OID_SECURITY_SEARCHSTORES2:
  1999. hr = _STOREARRAYToCAUH(m_rOptions.saSearchStore, &pValue->cauh);
  2000. break;
  2001. case OID_SECURITY_RG_IASN2:
  2002. Assert(FALSE);
  2003. //N TODO: OID_SECURITY_RG_IASN
  2004. break;
  2005. case OID_SECURITY_HCRYPTPROV2:
  2006. pValue->uhVal = *(ULARGE_INTEGER *)(&(m_rOptions.hCryptProv));
  2007. m_rOptions.hCryptProv = NULL; // read-once
  2008. break;
  2009. // End of BriMo check-in
  2010. #endif // _WIN65
  2011. #ifdef _WIN64
  2012. case OID_SECURITY_HWND_OWNER_64:
  2013. pValue->pulVal = (ULONG *)(m_rOptions.hwndOwner);
  2014. break;
  2015. #endif _WIN64
  2016. default:
  2017. hr = m_pContainer->GetOption(oid, pValue);
  2018. break;
  2019. }
  2020. // Thread Safety
  2021. LeaveCriticalSection(&m_cs);
  2022. // Done
  2023. return hr;
  2024. }
  2025. // --------------------------------------------------------------------------------
  2026. // CMessageBody::InitNew
  2027. // --------------------------------------------------------------------------------
  2028. STDMETHODIMP CMessageBody::InitNew(void)
  2029. {
  2030. // Locals
  2031. HRESULT hr=S_OK;
  2032. // Thread Safety
  2033. EnterCriticalSection(&m_cs);
  2034. // Release Lock Bytes
  2035. EmptyData();
  2036. // These flags are based on the data objects
  2037. m_dwState = 0;
  2038. // Change Size
  2039. m_cbExternal = 0xFFFFFFFF;
  2040. // Have I Created my property set yet ?
  2041. if (NULL == m_pContainer)
  2042. {
  2043. // Create Init
  2044. CHECKALLOC(m_pContainer = new CMimePropertyContainer);
  2045. }
  2046. // Reset the property set
  2047. CHECKHR(hr = m_pContainer->InitNew());
  2048. // Reset m_pCsetTagged
  2049. m_pCsetTagged = NULL;
  2050. // Reset Options
  2051. _FreeOptions();
  2052. // Reset to default options (this is probably a bug)
  2053. CopyMemory(&m_rOptions, &g_rDefBodyOptions, sizeof(BODYOPTIONS));
  2054. // (t-erikne) need to get this default at run time
  2055. m_rOptions.hwndOwner = HWND_DESKTOP;
  2056. // Reset Charset
  2057. m_pCharset = CIntlGlobals::GetDefBodyCset();
  2058. exit:
  2059. // Thread Safety
  2060. LeaveCriticalSection(&m_cs);
  2061. // Done
  2062. return hr;
  2063. }
  2064. // --------------------------------------------------------------------------------
  2065. // CMessageBody::EmptyData
  2066. // --------------------------------------------------------------------------------
  2067. STDMETHODIMP CMessageBody::EmptyData(void)
  2068. {
  2069. // Thread Safety
  2070. EnterCriticalSection(&m_cs);
  2071. // Free current display name
  2072. SafeMemFree(m_pszDisplay);
  2073. // Do I have Data
  2074. SafeRelease(m_rStorage.pUnkRelease);
  2075. // Zero
  2076. ZeroMemory(&m_rStorage, sizeof(BODYSTORAGE));
  2077. // Removed CSETTAGGED state
  2078. FLAGCLEAR(m_dwState, BODYSTATE_CSETTAGGED);
  2079. FLAGCLEAR(m_dwState, BODYSTATE_EXTERNAL);
  2080. // Change Size
  2081. m_cbExternal = 0xFFFFFFFF;
  2082. // Reset Encoding
  2083. m_ietEncoding = IET_7BIT;
  2084. // Thread Safety
  2085. LeaveCriticalSection(&m_cs);
  2086. // Done
  2087. return S_OK;
  2088. }
  2089. // --------------------------------------------------------------------------------
  2090. // CMessageBody::SetState
  2091. // --------------------------------------------------------------------------------
  2092. void CMessageBody::SetState(DWORD dwState)
  2093. {
  2094. EnterCriticalSection(&m_cs);
  2095. FLAGSET(m_dwState, dwState);
  2096. LeaveCriticalSection(&m_cs);
  2097. }
  2098. // --------------------------------------------------------------------------------
  2099. // CMessageBody::ClearState
  2100. // --------------------------------------------------------------------------------
  2101. void CMessageBody::ClearState(DWORD dwState)
  2102. {
  2103. EnterCriticalSection(&m_cs);
  2104. FLAGCLEAR(m_dwState, dwState);
  2105. LeaveCriticalSection(&m_cs);
  2106. }
  2107. // --------------------------------------------------------------------------------
  2108. // CMessageBody::ClearDirty
  2109. // --------------------------------------------------------------------------------
  2110. void CMessageBody::ClearDirty(void)
  2111. {
  2112. ASSERTINIT;
  2113. EnterCriticalSection(&m_cs);
  2114. FLAGCLEAR(m_dwState, BODYSTATE_DIRTY);
  2115. m_pContainer->ClearState(COSTATE_DIRTY);
  2116. LeaveCriticalSection(&m_cs);
  2117. }
  2118. // --------------------------------------------------------------------------------
  2119. // CMessageBody::IsType
  2120. // --------------------------------------------------------------------------------
  2121. STDMETHODIMP CMessageBody::IsType(IMSGBODYTYPE type)
  2122. {
  2123. // Locals
  2124. HRESULT hr;
  2125. STATSTG rStat;
  2126. ASSERTINIT;
  2127. // Thread Safety
  2128. EnterCriticalSection(&m_cs);
  2129. // Handle Type
  2130. if (IBT_SECURE == type)
  2131. {
  2132. // Is Secure Flag Set
  2133. hr = (ISFLAGSET(m_dwState, BODYSTATE_SECURE)) ? S_OK : S_FALSE;
  2134. }
  2135. // Charset Tagged
  2136. else if (IBT_CSETTAGGED == type)
  2137. {
  2138. hr = ISFLAGSET(m_dwState, BODYSTATE_CSETTAGGED) ? S_OK : S_FALSE;
  2139. }
  2140. // Is this an attachment
  2141. else if (IBT_ATTACHMENT == type)
  2142. {
  2143. // If container returns IMF_ATTACHMENTS, it must be an attachment
  2144. DWORD dw = m_pContainer->DwGetMessageFlags(m_rOptions.fHideTNEF);
  2145. hr = (ISFLAGSET(dw, IMF_ATTACHMENTS) || ISFLAGSET(dw, IMF_HASVCARD)) ? S_OK : S_FALSE;
  2146. }
  2147. // Was AUTOATTACH
  2148. else if (IBT_AUTOATTACH == type)
  2149. {
  2150. hr = (m_pNode && ISFLAGSET(m_pNode->dwState, NODESTATE_AUTOATTACH)) ? S_OK : S_FALSE;
  2151. }
  2152. // Is the body empty
  2153. else if (IBT_EMPTY == type)
  2154. {
  2155. // Body is not empty if it is a multipart with children
  2156. if (m_pContainer->IsContentType(STR_CNT_MULTIPART, NULL) == S_OK && m_pNode && m_pNode->cChildren > 0)
  2157. hr = S_FALSE;
  2158. else if (m_rStorage.pUnkRelease)
  2159. hr = S_FALSE;
  2160. else
  2161. hr = S_OK;
  2162. }
  2163. // Error
  2164. else
  2165. {
  2166. hr = TrapError(MIME_E_INVALID_BODYTYPE);
  2167. goto exit;
  2168. }
  2169. exit:
  2170. // Thread Safety
  2171. LeaveCriticalSection(&m_cs);
  2172. // Done
  2173. return hr;
  2174. }
  2175. // --------------------------------------------------------------------------------
  2176. // CMessageBody::IsDirty
  2177. // --------------------------------------------------------------------------------
  2178. STDMETHODIMP CMessageBody::IsDirty(void)
  2179. {
  2180. ASSERTINIT;
  2181. EnterCriticalSection(&m_cs);
  2182. HRESULT hr = (ISFLAGSET(m_dwState, BODYSTATE_DIRTY) || m_pContainer->IsDirty() == S_OK) ? S_OK : S_FALSE;
  2183. LeaveCriticalSection(&m_cs);
  2184. return hr;
  2185. }
  2186. // --------------------------------------------------------------------------------
  2187. // CMessageBody::GetOffsets
  2188. // --------------------------------------------------------------------------------
  2189. STDMETHODIMP CMessageBody::GetOffsets(LPBODYOFFSETS pOffsets)
  2190. {
  2191. // Locals
  2192. HRESULT hr=S_OK;
  2193. ASSERTINIT;
  2194. // Invalid Arg
  2195. if (NULL == pOffsets)
  2196. return TrapError(E_INVALIDARG);
  2197. // Init
  2198. ZeroMemory(pOffsets, sizeof(BODYOFFSETS));
  2199. // Thread Safety
  2200. EnterCriticalSection(&m_cs);
  2201. // Not Bound
  2202. if (NULL == m_pNode || (0 == m_pNode->cbBodyStart && 0 == pOffsets->cbBodyEnd))
  2203. {
  2204. hr = TrapError(MIME_E_NO_DATA);
  2205. goto exit;
  2206. }
  2207. // Get Offset Info
  2208. pOffsets->cbBoundaryStart = m_pNode->cbBoundaryStart;
  2209. pOffsets->cbHeaderStart = m_pNode->cbHeaderStart;
  2210. pOffsets->cbBodyStart = m_pNode->cbBodyStart;
  2211. pOffsets->cbBodyEnd = m_pNode->cbBodyEnd;
  2212. exit:
  2213. // Thread Safety
  2214. LeaveCriticalSection(&m_cs);
  2215. // Done
  2216. return hr;
  2217. }
  2218. // --------------------------------------------------------------------------------
  2219. // CMessageBody::GetEstimatedSize
  2220. // --------------------------------------------------------------------------------
  2221. STDMETHODIMP CMessageBody::GetEstimatedSize(ENCODINGTYPE ietEncoding, ULONG *pcbSize)
  2222. {
  2223. // Locals
  2224. HRESULT hr=S_OK;
  2225. ULONG cbSize=0;
  2226. STATSTG rStat;
  2227. DOCCONVTYPE dctConvert;
  2228. ILockBytes *plb=NULL;
  2229. ASSERTINIT;
  2230. // Parameter Check
  2231. if (NULL == pcbSize)
  2232. return TrapError(E_INVALIDARG);
  2233. if (ietEncoding >= IET_UNKNOWN)
  2234. return TrapError(MIME_E_INVALID_ENCODINGTYPE);
  2235. // Thread Safety
  2236. EnterCriticalSection(&m_cs);
  2237. // If external..
  2238. if (ISFLAGSET(m_dwState, BODYSTATE_EXTERNAL) && TRUE == m_rOptions.fExternalBody && 0xFFFFFFFF != m_cbExternal)
  2239. {
  2240. *pcbSize = m_cbExternal;
  2241. goto exit;
  2242. }
  2243. // No internal lockbytes yet ?
  2244. CHECKHR(hr = HrGetLockBytes(&plb));
  2245. // Query m_pLockBytes Size
  2246. CHECKHR(hr = plb->Stat(&rStat, STATFLAG_NONAME));
  2247. cbSize = (ULONG)rStat.cbSize.QuadPart;
  2248. // Otheriwse
  2249. if (IET_CURRENT != ietEncoding)
  2250. {
  2251. // Compute ietEncoding type...
  2252. dctConvert = g_rgConversionMap[m_pContainer->GetEncodingType()].rgDestType[ietEncoding];
  2253. // Handle Conversion type
  2254. if (DCT_ENCODE == dctConvert)
  2255. cbSize = (ULONG)((cbSize * 4) / 3);
  2256. else if (DCT_DECODE == dctConvert)
  2257. cbSize = (ULONG)((cbSize * 3) / 4);
  2258. }
  2259. // Set Return Size
  2260. *pcbSize = cbSize;
  2261. exit:
  2262. // Cleanup
  2263. SafeRelease(plb);
  2264. // Thread Safety
  2265. LeaveCriticalSection(&m_cs);
  2266. // Done
  2267. return hr;
  2268. }
  2269. // --------------------------------------------------------------------------------
  2270. // CMessageBody::SaveToFile
  2271. // --------------------------------------------------------------------------------
  2272. STDMETHODIMP CMessageBody::SaveToFile(ENCODINGTYPE ietEncoding, LPCSTR pszFilePath)
  2273. {
  2274. // Locals
  2275. HRESULT hr=S_OK;
  2276. LPWSTR pszFilePathW=NULL;
  2277. // Trace
  2278. TraceCall("CMessageBody::SaveToFile");
  2279. // Convert
  2280. IF_NULLEXIT(pszFilePathW = PszToUnicode(CP_ACP, pszFilePath));
  2281. // Do it as unicode
  2282. IF_FAILEXIT(hr = SaveToFileW(ietEncoding, pszFilePathW));
  2283. exit:
  2284. // Cleanup
  2285. MemFree(pszFilePathW);
  2286. // Done
  2287. return(hr);
  2288. }
  2289. // --------------------------------------------------------------------------------
  2290. // CMessageBody::SaveToFileW
  2291. // --------------------------------------------------------------------------------
  2292. STDMETHODIMP CMessageBody::SaveToFileW(ENCODINGTYPE ietEncoding, LPCWSTR pszFilePath)
  2293. {
  2294. // Locals
  2295. HRESULT hr=S_OK;
  2296. HRESULT hrWarnings=S_OK;
  2297. LPSTREAM pstmFile=NULL,
  2298. pstmBody=NULL;
  2299. ASSERTINIT;
  2300. // Parameter Check
  2301. if (NULL == pszFilePath)
  2302. return TrapError(E_INVALIDARG);
  2303. if (ietEncoding >= IET_UNKNOWN)
  2304. return TrapError(MIME_E_INVALID_ENCODINGTYPE);
  2305. // Thread Safety
  2306. EnterCriticalSection(&m_cs);
  2307. // Call Get Data
  2308. CHECKHR(hr = GetData(ietEncoding, &pstmBody));
  2309. // Open File Stream
  2310. CHECKHR(hr = OpenFileStreamW((LPWSTR)pszFilePath, CREATE_ALWAYS, GENERIC_WRITE, &pstmFile));
  2311. // Copy Stream
  2312. CHECKHR(hr = _HrCopyDataStream(pstmBody, pstmFile));
  2313. if (S_OK != hr)
  2314. hrWarnings = TrapError(hr);
  2315. // Commit
  2316. CHECKHR(hr = pstmFile->Commit(STGC_DEFAULT));
  2317. exit:
  2318. // Cleanup
  2319. SafeRelease(pstmFile);
  2320. SafeRelease(pstmBody);
  2321. // Thread Safety
  2322. LeaveCriticalSection(&m_cs);
  2323. // Done
  2324. return (hr == S_OK) ? hrWarnings : hr;
  2325. }
  2326. // --------------------------------------------------------------------------------
  2327. // CMessageBody::GetData
  2328. // --------------------------------------------------------------------------------
  2329. STDMETHODIMP CMessageBody::GetData(ENCODINGTYPE ietEncoding, IStream **ppStream)
  2330. {
  2331. // Locals
  2332. HRESULT hr=S_OK;
  2333. BODYSTREAMINIT rStreamInit;
  2334. CBodyStream *pBodyStream=NULL;
  2335. ASSERTINIT;
  2336. // Parameter Check
  2337. if (NULL == ppStream)
  2338. return TrapError(E_INVALIDARG);
  2339. // Thread Safety
  2340. EnterCriticalSection(&m_cs);
  2341. // Init StreamInit
  2342. ZeroMemory(&rStreamInit, sizeof(BODYSTREAMINIT));
  2343. // Initialzie
  2344. rStreamInit.ietExternal = ietEncoding;
  2345. rStreamInit.ietInternal = m_ietEncoding;
  2346. rStreamInit.fRemoveNBSP = m_rOptions.fRemoveNBSP;
  2347. rStreamInit.pCharset = m_pCharset;
  2348. // Create a new body stream...
  2349. CHECKALLOC(pBodyStream = new CBodyStream());
  2350. // Initialize the body stream
  2351. CHECKHR(hr = pBodyStream->HrInitialize(&rStreamInit, this));
  2352. // Set return
  2353. *ppStream = (IStream *)pBodyStream;
  2354. (*ppStream)->AddRef();
  2355. exit:
  2356. // Cleanup
  2357. SafeRelease(pBodyStream);
  2358. // Thread Safety
  2359. LeaveCriticalSection(&m_cs);
  2360. // Done
  2361. return hr;
  2362. }
  2363. // --------------------------------------------------------------------------------
  2364. // CMessageBody::GetDataHere
  2365. // --------------------------------------------------------------------------------
  2366. STDMETHODIMP CMessageBody::GetDataHere(ENCODINGTYPE ietEncoding, IStream *pStream)
  2367. {
  2368. // Locals
  2369. HRESULT hr=S_OK;
  2370. HRESULT hrWarnings=S_OK;
  2371. IStream *pBodyStream=NULL;
  2372. ASSERTINIT;
  2373. // Parameter Check
  2374. if (NULL == pStream)
  2375. return TrapError(E_INVALIDARG);
  2376. // Thread Safety
  2377. EnterCriticalSection(&m_cs);
  2378. // Get the body stream
  2379. CHECKHR(hr = GetData(ietEncoding, &pBodyStream));
  2380. // Copy Stream
  2381. CHECKHR(hr = _HrCopyDataStream(pBodyStream, pStream));
  2382. if (S_OK != hr)
  2383. hrWarnings = TrapError(hr);
  2384. exit:
  2385. // Cleanup
  2386. SafeRelease(pBodyStream);
  2387. // Thread Safety
  2388. LeaveCriticalSection(&m_cs);
  2389. // Done
  2390. return (hr == S_OK) ? hrWarnings : hr;
  2391. }
  2392. // --------------------------------------------------------------------------------
  2393. // CMessageBody::_HrCopyDataStream
  2394. // --------------------------------------------------------------------------------
  2395. HRESULT CMessageBody::_HrCopyDataStream(IStream *pstmSource, IStream *pstmDest)
  2396. {
  2397. // Locals
  2398. HRESULT hr=S_OK;
  2399. HRESULT hrWarnings=S_OK;
  2400. BYTE rgBuffer[4096];
  2401. ULONG cbRead;
  2402. DWORD cbStream = 0;
  2403. STATSTG statstg;
  2404. // Invalid Arg
  2405. Assert(pstmSource && pstmDest);
  2406. // get the size of the stream
  2407. CHECKHR(pstmSource->Stat(&statstg, STATFLAG_NONAME));
  2408. cbStream = statstg.cbSize.LowPart;
  2409. // Loop for ever
  2410. while(cbStream)
  2411. {
  2412. // Read a buffer
  2413. CHECKHR(hr = pstmSource->Read(rgBuffer, ARRAYSIZE(rgBuffer), &cbRead));
  2414. if (S_OK != hr)
  2415. hrWarnings = TrapError(hr);
  2416. // Done
  2417. if (0 == cbRead)
  2418. break;
  2419. cbStream = cbStream - cbRead;
  2420. // Write It
  2421. CHECKHR(hr = pstmDest->Write(rgBuffer, cbRead, NULL));
  2422. }
  2423. exit:
  2424. // Done
  2425. return (hr == S_OK) ? hrWarnings : hr;
  2426. }
  2427. // --------------------------------------------------------------------------------
  2428. // CMessageBody::HrGetLockBytes
  2429. // --------------------------------------------------------------------------------
  2430. HRESULT CMessageBody::HrGetLockBytes(ILockBytes **ppLockBytes)
  2431. {
  2432. // Locals
  2433. HRESULT hr=S_OK;
  2434. ASSERTINIT;
  2435. // Invalid Arg
  2436. Assert(ppLockBytes);
  2437. // Init
  2438. *ppLockBytes = NULL;
  2439. // Thread Safety
  2440. EnterCriticalSection(&m_cs);
  2441. // No Data
  2442. if (NULL == m_rStorage.pUnkRelease)
  2443. {
  2444. hr = TrapError(MIME_E_NO_DATA);
  2445. goto exit;
  2446. }
  2447. // IID_ILockBytes
  2448. if (IID_ILockBytes == m_rStorage.riid)
  2449. {
  2450. // AddRef It
  2451. *ppLockBytes = m_rStorage.pLockBytes;
  2452. (*ppLockBytes)->AddRef();
  2453. }
  2454. // IID_IMimeWebDocument
  2455. else if (IID_IMimeWebDocument == m_rStorage.riid)
  2456. {
  2457. // BindToStorage
  2458. CHECKHR(hr = m_rStorage.pWebDocument->BindToStorage(IID_ILockBytes, (LPVOID *)ppLockBytes));
  2459. // Lets Cache ppLockBytes
  2460. SafeRelease(m_rStorage.pUnkRelease);
  2461. // Assume the lock bytes
  2462. m_rStorage.pLockBytes = (*ppLockBytes);
  2463. m_rStorage.pLockBytes->AddRef();
  2464. // Set pUnkRelease
  2465. m_rStorage.pUnkRelease = m_rStorage.pLockBytes;
  2466. // Set Storage Id
  2467. m_rStorage.riid = IID_ILockBytes;
  2468. }
  2469. // Big Problem
  2470. else
  2471. Assert(FALSE);
  2472. exit:
  2473. // Thread Safety
  2474. LeaveCriticalSection(&m_cs);
  2475. // Done
  2476. return hr;
  2477. }
  2478. // --------------------------------------------------------------------------------
  2479. // CMessageBody::SetData
  2480. // --------------------------------------------------------------------------------
  2481. STDMETHODIMP CMessageBody::SetData(ENCODINGTYPE ietEncoding, LPCSTR pszPriType, LPCSTR pszSubType,
  2482. REFIID riid, LPVOID pvObject)
  2483. {
  2484. // Locals
  2485. HRESULT hr=S_OK;
  2486. IStream *pStream=NULL;
  2487. ASSERTINIT;
  2488. // Parameter Check
  2489. if (NULL == pvObject || ietEncoding >= IET_UNKNOWN || FALSE == FBODYSETDATAIID(riid))
  2490. return TrapError(E_INVALIDARG);
  2491. // Thread Safety
  2492. EnterCriticalSection(&m_cs);
  2493. // If multipart...
  2494. if (m_pContainer->IsContentType(STR_CNT_MULTIPART, NULL) == S_OK)
  2495. {
  2496. // RAID-29817: Only fail if there are children
  2497. if (m_pNode && m_pNode->cChildren > 0)
  2498. {
  2499. hr = TrapError(MIME_E_MULTIPART_NO_DATA);
  2500. goto exit;
  2501. }
  2502. // Lets adjust the Content-Type to application/octet-stream now so that things don't get confused
  2503. CHECKHR(hr = m_pContainer->SetProp(SYM_HDR_CNTTYPE, STR_MIME_APPL_STREAM));
  2504. }
  2505. // Release current m_pLockBytes
  2506. EmptyData();
  2507. // IID_IStream
  2508. if (IID_IStream == riid)
  2509. {
  2510. // New CBodyLockBytes
  2511. CHECKALLOC(m_rStorage.pLockBytes = new CStreamLockBytes((IStream *)pvObject));
  2512. // Set m_rStorage type
  2513. m_rStorage.riid = IID_ILockBytes;
  2514. m_rStorage.pUnkRelease = m_rStorage.pLockBytes;
  2515. }
  2516. // IID_ILockBytes
  2517. else if (IID_ILockBytes == riid)
  2518. {
  2519. // Just assume it
  2520. m_rStorage.pLockBytes = (ILockBytes *)pvObject;
  2521. m_rStorage.pLockBytes->AddRef();
  2522. // Set m_rStorage type
  2523. m_rStorage.riid = IID_ILockBytes;
  2524. m_rStorage.pUnkRelease = m_rStorage.pLockBytes;
  2525. }
  2526. // IID_IMimeBody
  2527. else if (IID_IMimeBody == riid)
  2528. {
  2529. // CopyTo
  2530. CHECKHR(hr = ((IMimeBody *)pvObject)->CopyTo(this));
  2531. }
  2532. // IID_IMimeMessage
  2533. else if (IID_IMimeMessage == riid)
  2534. {
  2535. // Locals
  2536. IMimePropertySet *pProps;
  2537. IMimeMessage *pMessage=(IMimeMessage *)pvObject;
  2538. // Get the message source
  2539. CHECKHR(hr = pMessage->GetMessageSource(&pStream, 0));
  2540. // New CBodyLockBytes
  2541. CHECKALLOC(m_rStorage.pLockBytes = new CStreamLockBytes(pStream));
  2542. // Set m_rStorage type
  2543. m_rStorage.riid = IID_ILockBytes;
  2544. m_rStorage.pUnkRelease = m_rStorage.pLockBytes;
  2545. // Set Content Type message/rfc822
  2546. CHECKHR(hr = m_pContainer->SetProp(SYM_HDR_CNTTYPE, STR_MIME_MSG_RFC822));
  2547. // Get Root Property Container
  2548. if (SUCCEEDED(pMessage->BindToObject(HBODY_ROOT, IID_IMimePropertySet, (LPVOID *)&pProps)))
  2549. {
  2550. // Locals
  2551. MIMEPROPINFO rPropInfo;
  2552. // I don't actualy want any props, just want to know if its set
  2553. rPropInfo.dwMask = 0;
  2554. // News Message ?
  2555. if (SUCCEEDED(pProps->GetPropInfo(PIDTOSTR(PID_HDR_NEWSGROUPS), &rPropInfo)) ||
  2556. SUCCEEDED(pProps->GetPropInfo(PIDTOSTR(PID_HDR_XNEWSRDR), &rPropInfo)) ||
  2557. SUCCEEDED(pProps->GetPropInfo(PIDTOSTR(PID_HDR_NEWSGROUP), &rPropInfo)))
  2558. m_pContainer->SetState(COSTATE_RFC822NEWS);
  2559. else
  2560. m_pContainer->ClearState(COSTATE_RFC822NEWS);
  2561. // Release
  2562. pProps->Release();
  2563. }
  2564. }
  2565. // IID_IMimeWebDocument
  2566. else if (IID_IMimeWebDocument == riid)
  2567. {
  2568. // Just assume it
  2569. m_rStorage.pWebDocument = (IMimeWebDocument *)pvObject;
  2570. m_rStorage.pWebDocument->AddRef();
  2571. // Set m_rStorage type
  2572. m_rStorage.riid = IID_IMimeWebDocument;
  2573. m_rStorage.pUnkRelease = m_rStorage.pWebDocument;
  2574. }
  2575. // Save The Format
  2576. m_ietEncoding = ietEncoding;
  2577. // Save Format per bert
  2578. if (g_rgEncodingMap[ietEncoding].pszName)
  2579. CHECKHR(hr = m_pContainer->SetProp(SYM_HDR_CNTXFER, g_rgEncodingMap[ietEncoding].pszName));
  2580. // Set PriType
  2581. if (pszPriType)
  2582. CHECKHR(hr = m_pContainer->SetProp(SYM_ATT_PRITYPE, pszPriType));
  2583. // Set SubType
  2584. if (pszSubType)
  2585. CHECKHR(hr = m_pContainer->SetProp(SYM_ATT_SUBTYPE, pszSubType));
  2586. // Assume The User is now controlling the Character Set Properties of this body
  2587. FLAGCLEAR(m_dwState, BODYSTATE_CSETTAGGED);
  2588. // We are now dirty
  2589. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  2590. exit:
  2591. // Cleanup
  2592. SafeRelease(pStream);
  2593. // Thread Safety
  2594. LeaveCriticalSection(&m_cs);
  2595. // Done
  2596. return hr;
  2597. }
  2598. STDMETHODIMP CMessageBody::SetDataW(ENCODINGTYPE ietEncoding, LPCWSTR pwszPriType, LPCWSTR pwszSubType,
  2599. REFIID riid, LPVOID pvObject)
  2600. {
  2601. return TraceResult(E_NOTIMPL);
  2602. }
  2603. // --------------------------------------------------------------------------------
  2604. // CMessageBody::CopyTo
  2605. // --------------------------------------------------------------------------------
  2606. STDMETHODIMP CMessageBody::CopyTo(IMimeBody *pBodyIn)
  2607. {
  2608. // Locals
  2609. HRESULT hr=S_OK;
  2610. LPMESSAGEBODY pBody=NULL;
  2611. LPCONTAINER pContainer=NULL;
  2612. // Invalid Arg
  2613. if (NULL == pBodyIn)
  2614. return TrapError(E_INVALIDARG);
  2615. // Thread Safety
  2616. EnterCriticalSection(&m_cs);
  2617. // QI for Private CMessageBody
  2618. CHECKHR(hr = pBodyIn->QueryInterface(IID_CMessageBody, (LPVOID *)&pBody));
  2619. // Thread Safety
  2620. EnterCriticalSection(&pBody->m_cs);
  2621. // Copy Data Over
  2622. pBody->m_dwState = m_dwState;
  2623. // Release Current Data
  2624. pBody->EmptyData();
  2625. // Copy body props
  2626. CHECKHR(hr = m_pContainer->Clone(&pContainer));
  2627. // Release the Bodies' Current Container
  2628. SafeRelease(pBody->m_pContainer);
  2629. // Reset the Container
  2630. pBody->m_pContainer = pContainer;
  2631. pBody->m_pContainer->AddRef();
  2632. // Assume new container in pNode
  2633. if (pBody->m_pNode)
  2634. {
  2635. SafeRelease(pBody->m_pNode->pContainer);
  2636. pBody->m_pNode->pContainer = pContainer;
  2637. pContainer->AddRef();
  2638. }
  2639. // Copy Display Name
  2640. if (m_pszDisplay)
  2641. CHECKALLOC(pBody->m_pszDisplay = PszDupW(m_pszDisplay));
  2642. // Copy Options
  2643. // BUGBUG: This is pretty iffy. BODYOPTIONS contains pointers, each of which should
  2644. // be duplicated. Caller beware!
  2645. CopyMemory(&pBody->m_rOptions, &m_rOptions, sizeof(BODYOPTIONS));
  2646. // Current Encoding
  2647. pBody->m_ietEncoding = m_ietEncoding;
  2648. // Charset
  2649. pBody->m_pCharset = m_pCharset;
  2650. // If we have data
  2651. if (m_rStorage.pUnkRelease)
  2652. {
  2653. // IID_ILockBytes
  2654. if (IID_ILockBytes == m_rStorage.riid)
  2655. {
  2656. pBody->m_rStorage.pLockBytes = m_rStorage.pLockBytes;
  2657. pBody->m_rStorage.pLockBytes->AddRef();
  2658. pBody->m_rStorage.pUnkRelease = pBody->m_rStorage.pLockBytes;
  2659. pBody->m_rStorage.riid = IID_ILockBytes;
  2660. }
  2661. // IID_IMimeWebDocument
  2662. else if (IID_IMimeWebDocument == m_rStorage.riid)
  2663. {
  2664. pBody->m_rStorage.pWebDocument = m_rStorage.pWebDocument;
  2665. pBody->m_rStorage.pWebDocument->AddRef();
  2666. pBody->m_rStorage.pUnkRelease = pBody->m_rStorage.pWebDocument;
  2667. pBody->m_rStorage.riid = IID_IMimeWebDocument;
  2668. }
  2669. // Big Problem
  2670. else
  2671. Assert(FALSE);
  2672. }
  2673. exit:
  2674. // Release Thread Safety
  2675. if (pBody)
  2676. LeaveCriticalSection(&pBody->m_cs);
  2677. // Cleanup
  2678. SafeRelease(pBody);
  2679. SafeRelease(pContainer);
  2680. // Thread Safety
  2681. LeaveCriticalSection(&m_cs);
  2682. // Done
  2683. return hr;
  2684. }
  2685. // --------------------------------------------------------------------------------
  2686. // CMessageBody::SetCurrentEncoding
  2687. // --------------------------------------------------------------------------------
  2688. STDMETHODIMP CMessageBody::SetCurrentEncoding(ENCODINGTYPE ietEncoding)
  2689. {
  2690. // Parameter Check
  2691. if (ietEncoding >= IET_UNKNOWN)
  2692. return TrapError(E_INVALIDARG);
  2693. // Thread Safety
  2694. EnterCriticalSection(&m_cs);
  2695. // Set the current encoding
  2696. m_ietEncoding = ietEncoding;
  2697. // Thread Safety
  2698. LeaveCriticalSection(&m_cs);
  2699. // Done
  2700. return S_OK;
  2701. }
  2702. // --------------------------------------------------------------------------------
  2703. // CMessageBody::GetCurrentEncoding
  2704. // --------------------------------------------------------------------------------
  2705. STDMETHODIMP CMessageBody::GetCurrentEncoding(ENCODINGTYPE *pietEncoding)
  2706. {
  2707. // Invalid Arg
  2708. if (NULL == pietEncoding)
  2709. return TrapError(E_INVALIDARG);
  2710. // Thread Safety
  2711. EnterCriticalSection(&m_cs);
  2712. // Set Return
  2713. *pietEncoding = m_ietEncoding;
  2714. // Thread Safety
  2715. LeaveCriticalSection(&m_cs);
  2716. // Done
  2717. return S_OK;
  2718. }
  2719. // --------------------------------------------------------------------------------
  2720. // CMessageBody::GetTransmitInfo
  2721. // --------------------------------------------------------------------------------
  2722. STDMETHODIMP CMessageBody::GetTransmitInfo(LPTRANSMITINFO pTransmit)
  2723. {
  2724. // Locals
  2725. HRESULT hr=S_OK;
  2726. HRESULT hrWarnings=S_OK;
  2727. ULONG cbRead,
  2728. cbLine=0,
  2729. cEscapeChars=0,
  2730. i;
  2731. BYTE rgBuffer[4096];
  2732. LPSTREAM pStream=NULL;
  2733. BYTE bPrev='\0';
  2734. BOOL fBadEOL=FALSE;
  2735. DWORD cbStream = 0;
  2736. STATSTG statstg;
  2737. ASSERTINIT;
  2738. // Parmaeters
  2739. if (NULL == pTransmit)
  2740. return TrapError(E_INVALIDARG);
  2741. // Thread Safety
  2742. EnterCriticalSection(&m_cs);
  2743. // Init
  2744. ZeroMemory(pTransmit, sizeof(TRANSMITINFO));
  2745. // Set the current code page
  2746. pTransmit->ietCurrent = m_ietEncoding;
  2747. // Init Format
  2748. pTransmit->ietXmitMime = IET_7BIT;
  2749. pTransmit->ietXmit822 = IET_7BIT;
  2750. // Don't call for multipart types...
  2751. if (m_pContainer->IsContentType(STR_CNT_MULTIPART, NULL) == S_OK)
  2752. {
  2753. Assert(FALSE);
  2754. hr = TrapError(MIME_E_MULTIPART_NO_DATA);
  2755. goto exit;
  2756. }
  2757. // Lets a binary stream of the data
  2758. CHECKHR(hr = GetData(IET_INETCSET, &pStream));
  2759. // get the size of the stream
  2760. CHECKHR(pStream->Stat(&statstg, STATFLAG_NONAME));
  2761. cbStream = statstg.cbSize.LowPart;
  2762. // Scan It
  2763. while(cbStream)
  2764. {
  2765. // Read a buffer
  2766. CHECKHR(hr = pStream->Read(rgBuffer, sizeof(rgBuffer), &cbRead));
  2767. if (S_OK != hr)
  2768. hrWarnings = TrapError(hr);
  2769. // Done
  2770. if (0 == cbRead)
  2771. break;
  2772. cbStream = cbStream - cbRead;
  2773. // Scan the buffer
  2774. for (i=0; i<cbRead; i++, cbLine++)
  2775. {
  2776. // If End of line, reset line length
  2777. if (chLF == rgBuffer[i])
  2778. {
  2779. // Count lines
  2780. pTransmit->cLines++;
  2781. cbLine = 0;
  2782. // Raid-41839: x-bitmap images are not correctly transferred via Schotzie
  2783. // Don't write out lines that end with only a \n, not legal
  2784. if (chCR != bPrev)
  2785. fBadEOL = TRUE;
  2786. }
  2787. // Line too long
  2788. if (cbLine > pTransmit->cbLongestLine)
  2789. pTransmit->cbLongestLine++;
  2790. // Tests for extended and control characters
  2791. if (IS_EXTENDED(rgBuffer[i]))
  2792. {
  2793. // Count Extneded
  2794. pTransmit->cExtended++;
  2795. // Count Escape Characters
  2796. if (0x1B == rgBuffer[i])
  2797. cEscapeChars++;
  2798. }
  2799. // Save Previous
  2800. bPrev = rgBuffer[i];
  2801. }
  2802. // Increment Total
  2803. pTransmit->cbSize += cbRead;
  2804. }
  2805. // No Data ?
  2806. if (0 == pTransmit->cbSize)
  2807. {
  2808. pTransmit->ulPercentExt = 0;
  2809. goto exit;
  2810. }
  2811. // RAID-22542: FE-J:Athena:mail:sending mail with text/plain has Content-transfer-encording:8bit
  2812. if (FALSE == m_rOptions.fDBCSEscape8 && cEscapeChars > 0 && m_pCharset && g_pInternat->IsDBCSCharset(m_pCharset->hCharset) == S_OK)
  2813. {
  2814. // Subtract the Number of EscapeChars off of the number of extended chars
  2815. Assert(cEscapeChars <= pTransmit->cExtended);
  2816. pTransmit->cExtended -= cEscapeChars;
  2817. }
  2818. if (IET_UNKNOWN == m_rOptions.ietTransmit)
  2819. {
  2820. // More than 25% extended characters
  2821. pTransmit->ulPercentExt = ((pTransmit->cExtended * 100) / pTransmit->cbSize);
  2822. // Raid-41839: x-bitmap images are not correctly transferred via Schotzie
  2823. // More than 17 percent extended
  2824. if (pTransmit->ulPercentExt > 17)
  2825. {
  2826. pTransmit->ietXmitMime = IET_BASE64;
  2827. pTransmit->ietXmit822 = IET_UUENCODE;
  2828. }
  2829. // Some Extended Characters or line longer than max
  2830. else if (pTransmit->cExtended || pTransmit->cbLongestLine > m_rOptions.cbMaxLine || TRUE == fBadEOL)
  2831. {
  2832. pTransmit->ietXmitMime = IET_QP;
  2833. pTransmit->ietXmit822 = IET_7BIT;
  2834. }
  2835. // Otherwise, 7bit
  2836. else
  2837. {
  2838. pTransmit->ietXmitMime = IET_7BIT;
  2839. pTransmit->ietXmit822 = IET_7BIT;
  2840. }
  2841. }
  2842. else
  2843. {
  2844. // the client specifically set this option, so honor it
  2845. pTransmit->ietXmitMime = m_rOptions.ietTransmit;
  2846. // we may need to fixup ietXmit822 if the XmitMime
  2847. // option does not make sense for it
  2848. switch (m_rOptions.ietTransmit)
  2849. {
  2850. case IET_BASE64:
  2851. pTransmit->ietXmit822 = IET_UUENCODE;
  2852. break;
  2853. case IET_QP:
  2854. pTransmit->ietXmit822 = IET_7BIT;
  2855. break;
  2856. default:
  2857. pTransmit->ietXmit822 = m_rOptions.ietTransmit;
  2858. break;
  2859. }
  2860. }
  2861. exit:
  2862. // Cleanup
  2863. SafeRelease(pStream);
  2864. // Thread Safety
  2865. LeaveCriticalSection(&m_cs);
  2866. // Done
  2867. return (hr == S_OK) ? hrWarnings : hr;
  2868. }
  2869. // --------------------------------------------------------------------------------
  2870. // CMessageBody::SwitchContainers
  2871. // --------------------------------------------------------------------------------
  2872. void CMessageBody::SwitchContainers(CMessageBody *pBody)
  2873. {
  2874. // Thread Safety
  2875. EnterCriticalSection(&m_cs);
  2876. EnterCriticalSection(&pBody->m_cs);
  2877. // Invalid Arg
  2878. Assert(pBody && pBody->m_pContainer && m_pContainer && m_pNode && pBody->m_pNode);
  2879. // Simple Varialbe Swap
  2880. LPCONTAINER pTemp = m_pContainer;
  2881. m_pNode->pContainer = m_pContainer = pBody->m_pContainer;
  2882. pBody->m_pNode->pContainer = pBody->m_pContainer = pTemp;
  2883. // Thread Safety
  2884. LeaveCriticalSection(&pBody->m_cs);
  2885. LeaveCriticalSection(&m_cs);
  2886. }
  2887. // --------------------------------------------------------------------------------
  2888. // CMessageBody::GetHandle
  2889. // --------------------------------------------------------------------------------
  2890. STDMETHODIMP CMessageBody::GetHandle(LPHBODY phBody)
  2891. {
  2892. // Local
  2893. HRESULT hr=S_OK;
  2894. ASSERTINIT;
  2895. // Invalid Arg
  2896. if (NULL == phBody)
  2897. return TrapError(E_INVALIDARG);
  2898. // Thread Safety
  2899. EnterCriticalSection(&m_cs);
  2900. // Init
  2901. *phBody = NULL;
  2902. // Not Bound...
  2903. if (NULL == m_pNode || NULL == m_pNode->hBody)
  2904. {
  2905. hr = MIME_E_NO_DATA;
  2906. goto exit;
  2907. }
  2908. // Set Handle
  2909. *phBody = m_pNode->hBody;
  2910. exit:
  2911. // Thread Safety
  2912. LeaveCriticalSection(&m_cs);
  2913. // Done
  2914. return hr;
  2915. }
  2916. // --------------------------------------------------------------------------------
  2917. // CMessageBody::GetClassID
  2918. // --------------------------------------------------------------------------------
  2919. STDMETHODIMP CMessageBody::GetClassID(CLSID *pClassID)
  2920. {
  2921. ASSERTINIT;
  2922. // Parmaeters
  2923. if (NULL == pClassID)
  2924. return TrapError(E_INVALIDARG);
  2925. // Copy Class Id
  2926. CopyMemory(pClassID, &IID_IMimeBody, sizeof(CLSID));
  2927. // Done
  2928. return S_OK;
  2929. }
  2930. // --------------------------------------------------------------------------------
  2931. // CMessageBody::GetSizeMax
  2932. // --------------------------------------------------------------------------------
  2933. STDMETHODIMP CMessageBody::GetSizeMax(ULARGE_INTEGER* pcbSize)
  2934. {
  2935. // Locals
  2936. HRESULT hr=S_OK;
  2937. ULONG cbSize;
  2938. ASSERTINIT;
  2939. // Get The Size
  2940. CHECKHR(hr = GetEstimatedSize(IET_BINARY, &cbSize));
  2941. // Return the Size
  2942. pcbSize->QuadPart = cbSize;
  2943. exit:
  2944. // Done
  2945. return hr;
  2946. }
  2947. // --------------------------------------------------------------------------------
  2948. // CMessageBody::Load
  2949. // --------------------------------------------------------------------------------
  2950. STDMETHODIMP CMessageBody::Load(LPSTREAM pStream)
  2951. {
  2952. ASSERTINIT;
  2953. return TrapError(m_pContainer->Load(pStream));
  2954. }
  2955. // ---------------------------------------------------------------------------
  2956. // CMessageBody::Load
  2957. // ---------------------------------------------------------------------------
  2958. HRESULT CMessageBody::Load(CInternetStream *pInternet)
  2959. {
  2960. ASSERTINIT;
  2961. return TrapError(m_pContainer->Load(pInternet));
  2962. }
  2963. // --------------------------------------------------------------------------------
  2964. // CMessageBody::Save
  2965. // --------------------------------------------------------------------------------
  2966. STDMETHODIMP CMessageBody::Save(LPSTREAM pStream, BOOL fClearDirty)
  2967. {
  2968. ASSERTINIT;
  2969. return TrapError(m_pContainer->Save(pStream, fClearDirty));
  2970. }
  2971. // --------------------------------------------------------------------------------
  2972. // CMessageBody::IsContentType
  2973. // --------------------------------------------------------------------------------
  2974. STDMETHODIMP CMessageBody::IsContentType(LPCSTR pszPriType, LPCSTR pszSubType)
  2975. {
  2976. ASSERTINIT;
  2977. return TrapError(m_pContainer->IsContentType(pszPriType, pszSubType));
  2978. }
  2979. // --------------------------------------------------------------------------------
  2980. // CMessageBody::GetCharset
  2981. // --------------------------------------------------------------------------------
  2982. STDMETHODIMP CMessageBody::GetCharset(LPHCHARSET phCharset)
  2983. {
  2984. ASSERTINIT;
  2985. return TrapError(m_pContainer->GetCharset(phCharset));
  2986. }
  2987. // --------------------------------------------------------------------------------
  2988. // CMessageBody::SetCharset
  2989. // --------------------------------------------------------------------------------
  2990. STDMETHODIMP CMessageBody::SetCharset(HCHARSET hCharset, CSETAPPLYTYPE applytype)
  2991. {
  2992. // Locals
  2993. HRESULT hr=S_OK;
  2994. ASSERTINIT;
  2995. // Invalid Arg
  2996. if (NULL == hCharset)
  2997. return TrapError(E_INVALIDARG);
  2998. // Thread Safety
  2999. EnterCriticalSection(&m_cs);
  3000. // Lookiup Charset Info
  3001. if (FALSE == g_pInternat->FIsValidHandle(hCharset))
  3002. {
  3003. hr = TrapError(MIME_E_INVALID_HANDLE);
  3004. goto exit;
  3005. }
  3006. // If I'm already tagged with a charset, and applytype is CSET_APPLY_UNTAGGED, then leave
  3007. if (ISFLAGSET(m_dwState, BODYSTATE_SKIPCSET) == TRUE && CSET_APPLY_UNTAGGED == applytype)
  3008. goto exit;
  3009. // Pass it into the property set
  3010. CHECKHR(hr = m_pContainer->SetCharset(hCharset, applytype));
  3011. // If I'm already tagged with a charset, and applytype is CSET_APPLY_UNTAGGED, then leave
  3012. if (ISFLAGSET(m_dwState, BODYSTATE_CSETTAGGED) == TRUE && CSET_APPLY_UNTAGGED == applytype)
  3013. goto exit;
  3014. // Save the character set...
  3015. SideAssert(SUCCEEDED(g_pInternat->HrOpenCharset(hCharset, &m_pCharset)));
  3016. // Mark as Tagged
  3017. if (CSET_APPLY_TAG_ALL == applytype)
  3018. {
  3019. // Mark the body as being tagged with a charset
  3020. // Get Internal Character Set
  3021. if (SUCCEEDED(m_pContainer->GetCharset(&hCharset)))
  3022. {
  3023. // Get Pointer
  3024. SideAssert(SUCCEEDED(g_pInternat->HrOpenCharset(hCharset, &m_pCharset)));
  3025. // Save this as m_pCsetTagged
  3026. m_pCsetTagged = m_pCharset;
  3027. }
  3028. // I was tagged with a charset
  3029. FLAGSET(m_dwState, BODYSTATE_CSETTAGGED);
  3030. // Mark the charset as explicitly set
  3031. FLAGSET(m_dwState, BODYSTATE_SKIPCSET);
  3032. }
  3033. exit:
  3034. // Thread Safety
  3035. LeaveCriticalSection(&m_cs);
  3036. // Done
  3037. return hr;
  3038. }
  3039. // --------------------------------------------------------------------------------
  3040. // CMessageBody::GetProp
  3041. // --------------------------------------------------------------------------------
  3042. STDMETHODIMP CMessageBody::GetProp(LPCSTR pszName, DWORD dwFlags, LPPROPVARIANT pValue)
  3043. {
  3044. ASSERTINIT;
  3045. return TrapError(m_pContainer->GetProp(pszName, dwFlags, pValue));
  3046. }
  3047. // ---------------------------------------------------------------------------
  3048. // CMessageBody::AppendProp
  3049. // ---------------------------------------------------------------------------
  3050. STDMETHODIMP CMessageBody::AppendProp(LPCSTR pszName, DWORD dwFlags, LPPROPVARIANT pValue)
  3051. {
  3052. ASSERTINIT;
  3053. return TrapError(m_pContainer->AppendProp(pszName, dwFlags, pValue));
  3054. }
  3055. // --------------------------------------------------------------------------------
  3056. // CMessageBody::SetProp
  3057. // --------------------------------------------------------------------------------
  3058. STDMETHODIMP CMessageBody::SetProp(LPCSTR pszName, DWORD dwFlags, LPCPROPVARIANT pValue)
  3059. {
  3060. ASSERTINIT;
  3061. return TrapError(m_pContainer->SetProp(pszName, dwFlags, pValue));
  3062. }
  3063. // --------------------------------------------------------------------------------
  3064. // CMessageBody::DeleteProp
  3065. // --------------------------------------------------------------------------------
  3066. STDMETHODIMP CMessageBody::DeleteProp(LPCSTR pszName)
  3067. {
  3068. ASSERTINIT;
  3069. return TrapError(m_pContainer->DeleteProp(pszName));
  3070. }
  3071. // ---------------------------------------------------------------------------
  3072. // CMessageBody::QueryProp
  3073. // ---------------------------------------------------------------------------
  3074. STDMETHODIMP CMessageBody::QueryProp(LPCSTR pszName, LPCSTR pszCriteria, boolean fSubString, boolean fCaseSensitive)
  3075. {
  3076. ASSERTINIT;
  3077. return TrapError(m_pContainer->QueryProp(pszName, pszCriteria, fSubString, fCaseSensitive));
  3078. }
  3079. // --------------------------------------------------------------------------------
  3080. // CMessageBody::Clone
  3081. // --------------------------------------------------------------------------------
  3082. STDMETHODIMP CMessageBody::Clone(IMimePropertySet **ppPropertySet)
  3083. {
  3084. ASSERTINIT;
  3085. return TrapError(m_pContainer->Clone(ppPropertySet));
  3086. }
  3087. // --------------------------------------------------------------------------------
  3088. // CMessageBody::BindToObject
  3089. // --------------------------------------------------------------------------------
  3090. STDMETHODIMP CMessageBody::BindToObject(REFIID riid, void **ppvObject)
  3091. {
  3092. // Locals
  3093. HRESULT hr=S_OK;
  3094. ASSERTINIT;
  3095. // Thread Safety
  3096. EnterCriticalSection(&m_cs);
  3097. // IID_IStream
  3098. if (IID_IStream == riid)
  3099. {
  3100. // Get Data...
  3101. CHECKHR(hr = GetData(IET_INETCSET, (IStream **)ppvObject));
  3102. }
  3103. // IID_IUnicodeStream
  3104. else if (IID_IUnicodeStream == riid)
  3105. {
  3106. // Get Data...
  3107. CHECKHR(hr = GetData(IET_UNICODE, (IStream **)ppvObject));
  3108. }
  3109. // IID_IMimeMessage... (returns message/rfc822 or message/partial bodies)
  3110. else if (IID_IMimeMessage == riid)
  3111. {
  3112. // Better be message/rfc822 or message/partial...
  3113. if (m_pContainer->IsContentType(STR_CNT_MESSAGE, STR_SUB_RFC822) == S_OK ||
  3114. m_pContainer->IsContentType(STR_CNT_MESSAGE, STR_SUB_PARTIAL) == S_OK)
  3115. {
  3116. // Locals
  3117. LPSTREAM pstmMsg=NULL;
  3118. IMimeMessage *pMessage=NULL;
  3119. // Create a message object
  3120. CHECKHR(hr = MimeOleCreateMessage(NULL, &pMessage));
  3121. // Get the body stream...
  3122. hr = GetData(IET_BINARY, &pstmMsg);
  3123. if (FAILED(hr))
  3124. {
  3125. pMessage->Release();
  3126. TrapError(hr);
  3127. goto exit;
  3128. }
  3129. // Load the message...
  3130. hr = pMessage->Load(pstmMsg);
  3131. if (FAILED(hr))
  3132. {
  3133. pstmMsg->Release();
  3134. pMessage->Release();
  3135. TrapError(hr);
  3136. goto exit;
  3137. }
  3138. // Return the message
  3139. *ppvObject = pMessage;
  3140. ((IUnknown *)*ppvObject)->AddRef();
  3141. // Cleanup
  3142. SafeRelease(pstmMsg);
  3143. SafeRelease(pMessage);
  3144. }
  3145. // Otherwise, fail
  3146. else
  3147. {
  3148. hr = TrapError(E_FAIL);
  3149. goto exit;
  3150. }
  3151. }
  3152. // Otheriwse, do a normal QI of the body/property set
  3153. else if (SUCCEEDED(QueryInterface(riid, ppvObject)))
  3154. goto exit;
  3155. // Otherwise, try to do a bindtoobject on the container
  3156. else if (SUCCEEDED(m_pContainer->BindToObject(riid, ppvObject)))
  3157. goto exit;
  3158. // Not Found
  3159. else
  3160. hr = TrapError(MIME_E_NOT_FOUND);
  3161. exit:
  3162. // Thread Safety
  3163. LeaveCriticalSection(&m_cs);
  3164. // Done
  3165. return hr;
  3166. }
  3167. // --------------------------------------------------------------------------------
  3168. // CMessageBody::DeleteExcept
  3169. // --------------------------------------------------------------------------------
  3170. STDMETHODIMP CMessageBody::DeleteExcept(ULONG cNames, LPCSTR *prgszName)
  3171. {
  3172. ASSERTINIT;
  3173. return TrapError(m_pContainer->DeleteExcept(cNames, prgszName));
  3174. }
  3175. // ---------------------------------------------------------------------------
  3176. // CMessageBody::GetParameters
  3177. // ---------------------------------------------------------------------------
  3178. STDMETHODIMP CMessageBody::GetParameters(LPCSTR pszName, ULONG *pcParams, LPMIMEPARAMINFO *pprgParam)
  3179. {
  3180. ASSERTINIT;
  3181. return TrapError(m_pContainer->GetParameters(pszName, pcParams, pprgParam));
  3182. }
  3183. // --------------------------------------------------------------------------------
  3184. // CMessageBody::CopyProps
  3185. // --------------------------------------------------------------------------------
  3186. STDMETHODIMP CMessageBody::CopyProps(ULONG cNames, LPCSTR *prgszName, IMimePropertySet *pPropSet)
  3187. {
  3188. ASSERTINIT;
  3189. return TrapError(m_pContainer->CopyProps(cNames, prgszName, pPropSet));
  3190. }
  3191. // --------------------------------------------------------------------------------
  3192. // CMessageBody::MoveProps
  3193. // --------------------------------------------------------------------------------
  3194. STDMETHODIMP CMessageBody::MoveProps(ULONG cNames, LPCSTR *prgszName, IMimePropertySet *pPropSet)
  3195. {
  3196. ASSERTINIT;
  3197. return TrapError(m_pContainer->MoveProps(cNames, prgszName, pPropSet));
  3198. }
  3199. // --------------------------------------------------------------------------------
  3200. // CMessageBody::GetPropInfo
  3201. // --------------------------------------------------------------------------------
  3202. STDMETHODIMP CMessageBody::GetPropInfo(LPCSTR pszName, LPMIMEPROPINFO pInfo)
  3203. {
  3204. ASSERTINIT;
  3205. return TrapError(m_pContainer->GetPropInfo(pszName, pInfo));
  3206. }
  3207. // --------------------------------------------------------------------------------
  3208. // CMessageBody::SetPropInfo
  3209. // --------------------------------------------------------------------------------
  3210. STDMETHODIMP CMessageBody::SetPropInfo(LPCSTR pszName, LPCMIMEPROPINFO pInfo)
  3211. {
  3212. ASSERTINIT;
  3213. return TrapError(m_pContainer->SetPropInfo(pszName, pInfo));
  3214. }
  3215. // --------------------------------------------------------------------------------
  3216. // CMessageBody::EnumProps
  3217. // --------------------------------------------------------------------------------
  3218. STDMETHODIMP CMessageBody::EnumProps(DWORD dwFlags, IMimeEnumProperties **ppEnum)
  3219. {
  3220. ASSERTINIT;
  3221. return TrapError(m_pContainer->EnumProps(dwFlags, ppEnum));
  3222. }
  3223. // --------------------------------------------------------------------------------
  3224. // CMessageBody::DwGetFlags
  3225. // --------------------------------------------------------------------------------
  3226. DWORD CMessageBody::DwGetFlags(BOOL fHideTnef)
  3227. {
  3228. DWORD dwFlags = 0;
  3229. ASSERTINIT;
  3230. dwFlags |= m_pContainer->DwGetMessageFlags(fHideTnef);
  3231. // if it isn't x-pkcs7-mime, we already know the flags, so no need for the call
  3232. // check the flag first b/c it is cheap
  3233. if (dwFlags & IMF_SECURE &&
  3234. (S_OK == m_pContainer->IsContentType(STR_CNT_APPLICATION, STR_SUB_XPKCS7MIME) ||
  3235. S_OK == m_pContainer->IsContentType(STR_CNT_APPLICATION, STR_SUB_PKCS7MIME)))
  3236. dwFlags |= _GetSecureTypeFlags();
  3237. return dwFlags;
  3238. }
  3239. // --------------------------------------------------------------------------------
  3240. // CMessageBody::_GetSecureTypeFlags
  3241. // --------------------------------------------------------------------------------
  3242. DWORD CMessageBody::_GetSecureTypeFlags()
  3243. {
  3244. DWORD dwSecType;
  3245. DWORD dwFlags;
  3246. // if the data isn't ASN.1, then this call should fail
  3247. if (SUCCEEDED(TrapError(CSMime::StaticGetMessageType(m_rOptions.hwndOwner,
  3248. (IMimeBody *)this, &dwSecType))))
  3249. {
  3250. dwFlags = IMF_SECURE;
  3251. if (MST_THIS_SIGN & dwSecType)
  3252. dwFlags |= IMF_SIGNED;
  3253. if (MST_THIS_ENCRYPT & dwSecType)
  3254. dwFlags |= IMF_ENCRYPTED;
  3255. }
  3256. else
  3257. dwFlags = 0;
  3258. return dwFlags;
  3259. }
  3260. // --------------------------------------------------------------------------------
  3261. // CMessageBody::CopyOptionsTo
  3262. // --------------------------------------------------------------------------------
  3263. void CMessageBody::CopyOptionsTo(CMessageBody *pBody, BOOL fNewOnwer /*=FALSE*/)
  3264. {
  3265. // Locals
  3266. ENCODINGTYPE ietTransmit;
  3267. ASSERTINIT;
  3268. // Valid State
  3269. Assert(pBody);
  3270. // critsec both bodies since we are using information on both
  3271. EnterCriticalSection(&m_cs);
  3272. EnterCriticalSection(&pBody->m_cs);
  3273. // Copy Body Options
  3274. pBody->m_rOptions = m_rOptions;
  3275. // Raid 33207 - Preserve transmit body encoding
  3276. ietTransmit = m_rOptions.ietTransmit;
  3277. // If pBody->m_rOptions is the new owner, then clear my structure
  3278. CopyMemory(&m_rOptions, &g_rDefBodyOptions, sizeof(BODYOPTIONS));
  3279. // Raid 33207 - Restore transmit body encoding
  3280. m_rOptions.ietTransmit = ietTransmit;
  3281. LeaveCriticalSection(&pBody->m_cs);
  3282. LeaveCriticalSection(&m_cs);
  3283. }
  3284. #ifndef _WIN64
  3285. // -----------------------------------------------------------------------------
  3286. // CMessageBody::_CAULToCertStore
  3287. // -----------------------------------------------------------------------------
  3288. HRESULT CMessageBody::_CAULToCertStore(const CAUL caul, HCERTSTORE * phcertstor)
  3289. {
  3290. DWORD i;
  3291. // Release the old store -- we don't want it anymore
  3292. if (*phcertstor != NULL)
  3293. {
  3294. CertCloseStore(*phcertstor, 0);
  3295. *phcertstor = NULL;
  3296. }
  3297. // Create a new store if needed
  3298. if (*phcertstor == NULL)
  3299. {
  3300. *phcertstor = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING,
  3301. NULL, 0, NULL);
  3302. }
  3303. if (*phcertstor == NULL)
  3304. {
  3305. return HrGetLastError();
  3306. }
  3307. for (i=0; i<caul.cElems; i++)
  3308. {
  3309. if (!CertAddCertificateContextToStore(*phcertstor,
  3310. (PCCERT_CONTEXT) caul.pElems[i],
  3311. CERT_STORE_ADD_ALWAYS, NULL))
  3312. {
  3313. return HrGetLastError();
  3314. }
  3315. }
  3316. return S_OK;
  3317. }
  3318. #endif // _WIN64
  3319. // -----------------------------------------------------------------------------
  3320. // CMessageBody::_CertStoreToCAUL
  3321. // -----------------------------------------------------------------------------
  3322. HRESULT CMessageBody::_CertStoreToCAUL(const HCERTSTORE hcertstor, CAUL * pcaul)
  3323. {
  3324. DWORD cCerts = 0;
  3325. PCCERT_CONTEXT pccert = NULL;
  3326. PCCERT_CONTEXT * rgpccert;
  3327. if (hcertstor != NULL)
  3328. {
  3329. while ((pccert = CertEnumCertificatesInStore(hcertstor, pccert)) != NULL)
  3330. {
  3331. cCerts += 1;
  3332. }
  3333. }
  3334. if (cCerts == 0)
  3335. {
  3336. pcaul->pElems = NULL;
  3337. pcaul->cElems = 0;
  3338. return S_OK;
  3339. }
  3340. pcaul->pElems = (ULONG *) g_pMalloc->Alloc(cCerts*sizeof(PCCERT_CONTEXT *));
  3341. if (pcaul->pElems == NULL)
  3342. {
  3343. return TrapError(E_OUTOFMEMORY);
  3344. }
  3345. rgpccert = (PCCERT_CONTEXT *) pcaul->pElems;
  3346. while ((pccert = CertEnumCertificatesInStore(hcertstor, pccert)) != NULL)
  3347. {
  3348. *rgpccert = CertDuplicateCertificateContext(pccert);
  3349. rgpccert++;
  3350. }
  3351. pcaul->cElems = cCerts;
  3352. return S_OK;
  3353. }
  3354. #ifndef SMIME_V3
  3355. // --------------------------------------------------------------------------------
  3356. // CMessageBody::_CAULToCERTARRAY
  3357. // --------------------------------------------------------------------------------
  3358. HRESULT CMessageBody::_CAULToCERTARRAY(const CAUL caul, CERTARRAY *pca)
  3359. {
  3360. // Locals
  3361. HRESULT hr;
  3362. register DWORD i;
  3363. if (SUCCEEDED(hr = HrRealloc((void**)&pca->rgpCerts, caul.cElems*sizeof(PCCERT_CONTEXT))))
  3364. {
  3365. for (i = 0; i < pca->cCerts; i++)
  3366. CertFreeCertificateContext(pca->rgpCerts[i]);
  3367. pca->cCerts = caul.cElems;
  3368. for (i = 0; i < caul.cElems; i++)
  3369. pca->rgpCerts[i] = CertDuplicateCertificateContext((PCCERT_CONTEXT)caul.pElems[i]);
  3370. }
  3371. // Done
  3372. return hr;
  3373. }
  3374. // --------------------------------------------------------------------------------
  3375. // CMessageBody::_CERTARRAYToCAUL
  3376. // --------------------------------------------------------------------------------
  3377. HRESULT CMessageBody::_CERTARRAYToCAUL(const CERTARRAY ca, CAUL *pcaul)
  3378. {
  3379. // Locals
  3380. HRESULT hr = S_OK;
  3381. register DWORD i;
  3382. if (ca.cCerts)
  3383. {
  3384. if ((pcaul->pElems = (ULONG*)(PCCERT_CONTEXT*)g_pMalloc->Alloc(ca.cCerts*sizeof(PCCERT_CONTEXT))))
  3385. {
  3386. pcaul->cElems = ca.cCerts;
  3387. for (i = 0; i < ca.cCerts; i++)
  3388. pcaul->pElems[i] = (ULONG)CertDuplicateCertificateContext(ca.rgpCerts[i]);
  3389. }
  3390. else
  3391. hr = TrapError(E_OUTOFMEMORY);
  3392. }
  3393. else
  3394. {
  3395. pcaul->pElems = NULL;
  3396. pcaul->cElems = 0;
  3397. }
  3398. // Done
  3399. return hr;
  3400. }
  3401. #endif // !SMIEM_V3
  3402. #ifndef _WIN64
  3403. // --------------------------------------------------------------------------------
  3404. // CMessageBody::_CAULToSTOREARRAY
  3405. // --------------------------------------------------------------------------------
  3406. HRESULT CMessageBody::_CAULToSTOREARRAY(const CAUL caul, STOREARRAY *psa)
  3407. {
  3408. // Locals
  3409. HRESULT hr;
  3410. register DWORD i;
  3411. if (SUCCEEDED(hr = HrRealloc((void**)&psa->rgStores, caul.cElems*sizeof(HCERTSTORE))))
  3412. {
  3413. for (i = 0; i < psa->cStores; i++)
  3414. CertCloseStore(psa->rgStores[i], 0);
  3415. psa->cStores = caul.cElems;
  3416. for (i = 0; i < caul.cElems; i++)
  3417. psa->rgStores[i] = CertDuplicateStore((HCERTSTORE)caul.pElems[i]);
  3418. }
  3419. // Done
  3420. return hr;
  3421. }
  3422. #endif // _WIN64
  3423. #ifndef _WIN64
  3424. // --------------------------------------------------------------------------------
  3425. // CMessageBody::_STOREARRAYToCAUL
  3426. // --------------------------------------------------------------------------------
  3427. HRESULT CMessageBody::_STOREARRAYToCAUL(const STOREARRAY sa, CAUL *pcaul)
  3428. {
  3429. // Locals
  3430. HRESULT hr = S_OK;
  3431. register DWORD i;
  3432. if (sa.cStores)
  3433. {
  3434. if ((pcaul->pElems = (ULONG*)(HCERTSTORE*)g_pMalloc->Alloc(sa.cStores*sizeof(HCERTSTORE))))
  3435. {
  3436. pcaul->cElems = sa.cStores;
  3437. for (i = 0; i < sa.cStores; i++)
  3438. pcaul->pElems[i] = (ULONG)CertDuplicateStore(sa.rgStores[i]);
  3439. }
  3440. else
  3441. hr = TrapError(E_OUTOFMEMORY);
  3442. }
  3443. else
  3444. {
  3445. pcaul->pElems = NULL;
  3446. pcaul->cElems = 0;
  3447. }
  3448. // Done
  3449. return hr;
  3450. }
  3451. #endif // _WIN64
  3452. // -----------------------------------------------------------------------------
  3453. // CMessageBody::_CAUHToCertStore
  3454. // -----------------------------------------------------------------------------
  3455. HRESULT CMessageBody::_CAUHToCertStore(const CAUH cauh, HCERTSTORE * phcertstor)
  3456. {
  3457. DWORD i;
  3458. #ifndef NEED // This prevent us from send 2 certificates.
  3459. // Release the old store -- we don't want it anymore
  3460. if (*phcertstor != NULL)
  3461. {
  3462. CertCloseStore(*phcertstor, 0);
  3463. *phcertstor = NULL;
  3464. }
  3465. #endif
  3466. // Create a new store if needed
  3467. if (*phcertstor == NULL)
  3468. {
  3469. *phcertstor = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING,
  3470. NULL, 0, NULL);
  3471. }
  3472. if (*phcertstor == NULL)
  3473. {
  3474. return HrGetLastError();
  3475. }
  3476. for (i=0; i<cauh.cElems; i++)
  3477. {
  3478. if (!CertAddCertificateContextToStore(*phcertstor,
  3479. *(PCCERT_CONTEXT *) (&(cauh.pElems[i])),
  3480. CERT_STORE_ADD_ALWAYS, NULL))
  3481. {
  3482. return HrGetLastError();
  3483. }
  3484. }
  3485. return S_OK;
  3486. }
  3487. // -----------------------------------------------------------------------------
  3488. // CMessageBody::_CertStoreToCAUH
  3489. // -----------------------------------------------------------------------------
  3490. HRESULT CMessageBody::_CertStoreToCAUH(const HCERTSTORE hcertstor, CAUH * pcauh)
  3491. {
  3492. DWORD cCerts = 0;
  3493. PCCERT_CONTEXT pccert = NULL;
  3494. PCCERT_CONTEXT * rgpccert;
  3495. if (hcertstor != NULL)
  3496. {
  3497. while ((pccert = CertEnumCertificatesInStore(hcertstor, pccert)) != NULL)
  3498. {
  3499. cCerts += 1;
  3500. }
  3501. }
  3502. if (cCerts == 0)
  3503. {
  3504. pcauh->pElems = NULL;
  3505. pcauh->cElems = 0;
  3506. return S_OK;
  3507. }
  3508. pcauh->pElems = (ULARGE_INTEGER *) g_pMalloc->Alloc(cCerts*sizeof(PCCERT_CONTEXT *));
  3509. if (pcauh->pElems == NULL)
  3510. {
  3511. return TrapError(E_OUTOFMEMORY);
  3512. }
  3513. rgpccert = (PCCERT_CONTEXT *) pcauh->pElems;
  3514. while ((pccert = CertEnumCertificatesInStore(hcertstor, pccert)) != NULL)
  3515. {
  3516. *rgpccert = CertDuplicateCertificateContext(pccert);
  3517. rgpccert++;
  3518. }
  3519. pcauh->cElems = cCerts;
  3520. return S_OK;
  3521. }
  3522. #ifdef _WIN65
  3523. // --------------------------------------------------------------------------------
  3524. // CMessageBody::_CAUHToCERTARRAY
  3525. // --------------------------------------------------------------------------------
  3526. HRESULT CMessageBody::_CAUHToCERTARRAY(const CAUH cauh, CERTARRAY *pca)
  3527. {
  3528. // Locals
  3529. HRESULT hr;
  3530. register DWORD i;
  3531. if (SUCCEEDED(hr = HrRealloc((void**)&pca->rgpCerts, cauh.cElems*sizeof(PCCERT_CONTEXT))))
  3532. {
  3533. for (i = 0; i < pca->cCerts; i++)
  3534. CertFreeCertificateContext(pca->rgpCerts[i]);
  3535. pca->cCerts = cauh.cElems;
  3536. for (i = 0; i < cauh.cElems; i++)
  3537. pca->rgpCerts[i] = CertDuplicateCertificateContext(*(PCCERT_CONTEXT *)(&(cauh.pElems[i])));
  3538. }
  3539. // Done
  3540. return hr;
  3541. }
  3542. // --------------------------------------------------------------------------------
  3543. // CMessageBody::_CERTARRAYToCAUH
  3544. // --------------------------------------------------------------------------------
  3545. HRESULT CMessageBody::_CERTARRAYToCAUH(const CERTARRAY ca, CAUH *pcauh)
  3546. {
  3547. // Locals
  3548. HRESULT hr = S_OK;
  3549. register DWORD i;
  3550. PCCERT_CONTEXT * rgpccert = NULL;
  3551. if (ca.cCerts)
  3552. {
  3553. if ((pcauh->pElems = (ULARGE_INTEGER *)g_pMalloc->Alloc(ca.cCerts*sizeof(PCCERT_CONTEXT))))
  3554. {
  3555. pcauh->cElems = ca.cCerts;
  3556. rgpccert = *(PCCERT_CONTEXT **)(&(pcauh->pElems));
  3557. for (i = 0; i < ca.cCerts; i++)
  3558. rgpccert[i] = CertDuplicateCertificateContext(ca.rgpCerts[i]);
  3559. }
  3560. else
  3561. hr = TrapError(E_OUTOFMEMORY);
  3562. }
  3563. else
  3564. {
  3565. pcauh->pElems = NULL;
  3566. pcauh->cElems = 0;
  3567. }
  3568. // Done
  3569. return hr;
  3570. }
  3571. #endif // _WIN65
  3572. // --------------------------------------------------------------------------------
  3573. // CMessageBody::_CAUHToSTOREARRAY
  3574. // --------------------------------------------------------------------------------
  3575. HRESULT CMessageBody::_CAUHToSTOREARRAY(const CAUH cauh, STOREARRAY *psa)
  3576. {
  3577. // Locals
  3578. HRESULT hr;
  3579. register DWORD i;
  3580. if (SUCCEEDED(hr = HrRealloc((void**)&psa->rgStores, cauh.cElems*sizeof(HCERTSTORE))))
  3581. {
  3582. for (i = 0; i < psa->cStores; i++)
  3583. CertCloseStore(psa->rgStores[i], 0);
  3584. psa->cStores = cauh.cElems;
  3585. for (i = 0; i < cauh.cElems; i++)
  3586. psa->rgStores[i] = CertDuplicateStore(*(HCERTSTORE *)(&(cauh.pElems[i])));
  3587. }
  3588. // Done
  3589. return hr;
  3590. }
  3591. // --------------------------------------------------------------------------------
  3592. // CMessageBody::_STOREARRAYToCAUH
  3593. // --------------------------------------------------------------------------------
  3594. HRESULT CMessageBody::_STOREARRAYToCAUH(const STOREARRAY sa, CAUH *pcauh)
  3595. {
  3596. // Locals
  3597. HRESULT hr = S_OK;
  3598. register DWORD i;
  3599. HCERTSTORE * rgStores = NULL;
  3600. if (sa.cStores)
  3601. {
  3602. if ((pcauh->pElems = (ULARGE_INTEGER *)g_pMalloc->Alloc(sa.cStores*sizeof(HCERTSTORE))))
  3603. {
  3604. pcauh->cElems = sa.cStores;
  3605. rgStores = *(HCERTSTORE **)(&(pcauh->pElems));
  3606. for (i = 0; i < sa.cStores; i++)
  3607. rgStores[i] = CertDuplicateStore(sa.rgStores[i]);
  3608. }
  3609. else
  3610. hr = TrapError(E_OUTOFMEMORY);
  3611. }
  3612. else
  3613. {
  3614. pcauh->pElems = NULL;
  3615. pcauh->cElems = 0;
  3616. }
  3617. // Done
  3618. return hr;
  3619. }
  3620. // --------------------------------------------------------------------------------
  3621. // CMessageBody::_FreeOptions
  3622. // --------------------------------------------------------------------------------
  3623. void CMessageBody::_FreeOptions()
  3624. {
  3625. DWORD i;
  3626. if (m_rOptions.cSigners)
  3627. {
  3628. // OID_SECURITY_ALG_HASH
  3629. SafeMemFree(m_rOptions.rgblobHash[0].pBlobData);
  3630. // OID_SECURITY_CERT_SIGNING
  3631. for (i = 0; i < m_rOptions.cSigners; i++)
  3632. {
  3633. CertFreeCertificateContext(m_rOptions.rgpcCertSigning[i]);
  3634. #ifdef SMIME_V3
  3635. // Attributes
  3636. SafeMemFree(m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED][i]);
  3637. SafeMemFree(m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_UNSIGNED][i]);
  3638. // OID_SECURITY_RECEIPT_RG
  3639. SafeMemFree(m_rOptions.rgblobReceipt[i].pBlobData);
  3640. // OID_SECURITY_MESSAGE_HASH_RG
  3641. SafeMemFree(m_rOptions.rgblobMsgHash[i].pBlobData);
  3642. // OID_SECURITY_KEY_PROMPT
  3643. SafeMemFree(m_rOptions.pwszKeyPrompt);
  3644. #else // !SMIME_V3
  3645. // OID_SECURITY_SYMCAPS
  3646. SafeMemFree(m_rOptions.rgblobSymCaps[i].pBlobData);
  3647. // OID_SECURITY_AUTHATTR
  3648. SafeMemFree(m_rOptions.rgblobAuthAttr[i].pBlobData);
  3649. // OID_SECURITY_UNAUTHATTR
  3650. SafeMemFree(m_rOptions.rgblobUnauthAttr[i].pBlobData);
  3651. #endif // SMIME_V3
  3652. }
  3653. // OID_SECURITY_HCERTSTORE
  3654. CertCloseStore(m_rOptions.hCertStore, 0);
  3655. _FreeLayerArrays();
  3656. if (m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_UNPROTECTED] != NULL) {
  3657. SafeMemFree(m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_UNPROTECTED][0]);
  3658. SafeMemFree(m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_UNPROTECTED]);
  3659. }
  3660. }
  3661. // OID_SECURITY_ALG_BULK
  3662. SafeMemFree(m_rOptions.blobBulk.pBlobData);
  3663. // OID_SECURITY_CERT_DECRYPTION
  3664. if (m_rOptions.pcCertDecryption)
  3665. CertFreeCertificateContext(m_rOptions.pcCertDecryption);
  3666. #ifdef SMIME_V3
  3667. if (m_rOptions.rgRecipients != 0)
  3668. {
  3669. for (i=0; i<m_rOptions.cRecipients; i++)
  3670. {
  3671. FreeRecipientInfoContent(&m_rOptions.rgRecipients[i]);
  3672. }
  3673. }
  3674. SafeMemFree(m_rOptions.rgRecipients);
  3675. m_rOptions.cRecipients = 0;
  3676. m_rOptions.cRecipsAllocated = 0;
  3677. #else // SMIME_V3
  3678. // OID_SECURITY_RG_CERT_ENCRYPT
  3679. for (i=0; i<m_rOptions.caEncrypt.cCerts; i++)
  3680. CertFreeCertificateContext(m_rOptions.caEncrypt.rgpCerts[i]);
  3681. SafeMemFree(m_rOptions.caEncrypt.rgpCerts);
  3682. #endif // !SMIEM_V3
  3683. // OID_SECURITY_SEARCHSTORES
  3684. for (i=0; i<m_rOptions.saSearchStore.cStores; i++)
  3685. CertCloseStore(m_rOptions.saSearchStore.rgStores[i], 0);
  3686. SafeMemFree(m_rOptions.saSearchStore.rgStores);
  3687. // OID_SECURITY_RG_IASN
  3688. // nyi
  3689. // OID_SECURITY_HCRYPTPROV
  3690. if (m_rOptions.hCryptProv)
  3691. CryptReleaseContext(m_rOptions.hCryptProv, 0);
  3692. return;
  3693. }
  3694. #ifdef _WIN64
  3695. #define REALLOC_AND_INIT_OPTION(Option) \
  3696. if (FAILED(hr = HrRealloc((void**)&Option, LcbAlignLcb(ulLayers * sizeof(*Option))))) { \
  3697. goto exit; \
  3698. } \
  3699. ZeroMemory(&Option[m_rOptions.cSigners], LcbAlignLcb((ulLayersNew) * sizeof(*Option)));
  3700. #else
  3701. #define REALLOC_AND_INIT_OPTION(Option) \
  3702. if (FAILED(hr = HrRealloc((void**)&Option, ulLayers * sizeof(*Option)))) { \
  3703. goto exit; \
  3704. } \
  3705. ZeroMemory(&Option[m_rOptions.cSigners], (ulLayersNew) * sizeof(*Option));
  3706. #endif //_WIN64
  3707. // --------------------------------------------------------------------------------
  3708. // CMessageBody::_HrEnsureBodyOptionLayers
  3709. // --------------------------------------------------------------------------------
  3710. HRESULT CMessageBody::_HrEnsureBodyOptionLayers(ULONG ulLayers)
  3711. {
  3712. HRESULT hr = S_OK;
  3713. ULONG ulLayersNew = ulLayers - m_rOptions.cSigners;
  3714. if (m_rOptions.cSigners < ulLayers)
  3715. {
  3716. // Time to grow the arrays
  3717. REALLOC_AND_INIT_OPTION(m_rOptions.rgblobHash);
  3718. REALLOC_AND_INIT_OPTION(m_rOptions.rgpcCertSigning);
  3719. #ifdef SMIME_V3
  3720. REALLOC_AND_INIT_OPTION(m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED]);
  3721. REALLOC_AND_INIT_OPTION(m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_UNSIGNED]);
  3722. #else // !SMIME_V3
  3723. REALLOC_AND_INIT_OPTION(m_rOptions.rgblobSymCaps);
  3724. REALLOC_AND_INIT_OPTION(m_rOptions.rgblobAuthAttr);
  3725. REALLOC_AND_INIT_OPTION(m_rOptions.rgblobUnauthAttr);
  3726. REALLOC_AND_INIT_OPTION(m_rOptions.rgftSigning);
  3727. #endif // SMIME_V3
  3728. REALLOC_AND_INIT_OPTION(m_rOptions.rgulUserDef);
  3729. REALLOC_AND_INIT_OPTION(m_rOptions.rgulROValid);
  3730. #ifdef SMIME_V3
  3731. REALLOC_AND_INIT_OPTION(m_rOptions.rgblobReceipt);
  3732. REALLOC_AND_INIT_OPTION(m_rOptions.rgblobMsgHash);
  3733. #endif // SMIME_V3
  3734. m_rOptions.cSigners = ulLayers;
  3735. }
  3736. exit:
  3737. return(hr);
  3738. }
  3739. HRESULT CMessageBody::_HrEnsureBodyOptionLayers(LPCPROPVARIANT ppv)
  3740. {
  3741. CAUL * pcaul = (CAUL *)&ppv->caul;
  3742. return(_HrEnsureBodyOptionLayers(pcaul->cElems));
  3743. }
  3744. // --------------------------------------------------------------------------------
  3745. // CMessageBody::_HrEnsureBodyOptionLayers
  3746. // --------------------------------------------------------------------------------
  3747. void CMessageBody::_FreeLayerArrays(void)
  3748. {
  3749. if (m_rOptions.cSigners)
  3750. {
  3751. SafeMemFree(m_rOptions.rgblobHash);
  3752. SafeMemFree(m_rOptions.rgpcCertSigning);
  3753. #ifdef SMIME_V3
  3754. SafeMemFree(m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED]);
  3755. SafeMemFree(m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_UNSIGNED]);
  3756. #else // !SMIME_V3
  3757. SafeMemFree(m_rOptions.rgblobSymCaps);
  3758. SafeMemFree(m_rOptions.rgblobAuthAttr);
  3759. SafeMemFree(m_rOptions.rgblobUnauthAttr);
  3760. SafeMemFree(m_rOptions.rgftSigning);
  3761. #endif // SMIME_V3
  3762. SafeMemFree(m_rOptions.rgulUserDef);
  3763. SafeMemFree(m_rOptions.rgulROValid);
  3764. #ifdef SMIME_V3
  3765. SafeMemFree(m_rOptions.rgblobReceipt);
  3766. SafeMemFree(m_rOptions.rgblobMsgHash);
  3767. #endif // SMIME_V3
  3768. m_rOptions.cSigners = 0;
  3769. }
  3770. }
  3771. HRESULT CMessageBody::_CompareCopyBlobArray(const PROPVARIANT FAR * pvSource, BLOB FAR * FAR * prgblDestination, BOOL fNoDirty)
  3772. {
  3773. HRESULT hr = S_OK;
  3774. ULONG i;
  3775. BOOL fReplace;
  3776. CAPROPVARIANT capropvar = pvSource->capropvar;
  3777. ULONG ulSize = capropvar.cElems;
  3778. Assert(ulSize == m_rOptions.cSigners);
  3779. Assert(*prgblDestination);
  3780. if (ulSize == m_rOptions.cSigners)
  3781. {
  3782. for (i = 0; i < ulSize; i++)
  3783. {
  3784. if ((*prgblDestination)[i].pBlobData)
  3785. {
  3786. if (fReplace = CompareBlob(&(*prgblDestination)[i], (BLOB FAR *)&capropvar.pElems[i]))
  3787. {
  3788. ReleaseMem((VOID FAR *)(*prgblDestination)[i].pBlobData);
  3789. }
  3790. } else {
  3791. fReplace = TRUE;
  3792. }
  3793. if (fReplace)
  3794. {
  3795. if (FAILED(hr = HrCopyBlob(&(capropvar.pElems[i].blob), &(*prgblDestination)[i])))
  3796. {
  3797. goto exit;
  3798. }
  3799. if (!fNoDirty)
  3800. {
  3801. FLAGSET(m_dwState, BODYSTATE_DIRTY);
  3802. }
  3803. }
  3804. }
  3805. } else {
  3806. hr = E_INVALIDARG;
  3807. }
  3808. exit:
  3809. return(hr);
  3810. }
  3811. // --------------------------------------------------------------------------------
  3812. // HrCopyBlobArray
  3813. //
  3814. // Allocate a new propvariant blob array, copy the original to it.
  3815. // --------------------------------------------------------------------------------
  3816. HRESULT HrCopyBlobArray(LPCBLOB pIn, ULONG cEntries, PROPVARIANT FAR * pvOut)
  3817. {
  3818. // Locals
  3819. HRESULT hr = S_OK;
  3820. CAPROPVARIANT * pcapropvar;
  3821. PROPVARIANT * ppv;
  3822. ULONG i;
  3823. pvOut->vt = VT_VECTOR | VT_VARIANT;
  3824. pcapropvar = &pvOut->capropvar;
  3825. pcapropvar->cElems = cEntries;
  3826. if (cEntries)
  3827. {
  3828. Assert(pIn && pvOut);
  3829. // Allocate the array of VT_BLOB propvariants
  3830. if (FAILED(hr = HrAlloc((LPVOID *)&ppv, cEntries * sizeof(PROPVARIANT))))
  3831. {
  3832. goto exit;
  3833. }
  3834. pcapropvar->pElems = ppv;
  3835. // Fill in the array of BLOBs
  3836. for (i = 0; i < cEntries; i++)
  3837. {
  3838. ppv[i].vt = VT_BLOB;
  3839. // HrCopyBlob allocates memory for the blob data.
  3840. if (FAILED(hr = HrCopyBlob((BLOB FAR *)&pIn[i] , &ppv[i].blob)))
  3841. {
  3842. goto exit;
  3843. }
  3844. }
  3845. } else {
  3846. pcapropvar->pElems = NULL;
  3847. }
  3848. exit:
  3849. // BUGBUG: Should clean up allocations on failure
  3850. return(hr);
  3851. }
  3852. // --------------------------------------------------------------------------------
  3853. // HrCopyArray
  3854. //
  3855. // Allocate a new array, copy the original to it.
  3856. // --------------------------------------------------------------------------------
  3857. HRESULT HrCopyArray(LPBYTE pIn, ULONG cEntries, PROPVARIANT FAR * pvOut, ULONG cbElement)
  3858. {
  3859. // Locals
  3860. HRESULT hr = S_OK;
  3861. BYTE * pb;
  3862. ULONG i;
  3863. ULONG cbArray = cEntries * cbElement;
  3864. CAUL * pcaul = &pvOut->caul;
  3865. pcaul->cElems = cEntries;
  3866. if (cEntries)
  3867. {
  3868. Assert(pIn && pvOut);
  3869. // Allocate the array of VT_BLOB propvariants
  3870. if (FAILED(hr = HrAlloc((LPVOID *)&pb, cbArray)))
  3871. {
  3872. goto exit;
  3873. }
  3874. pcaul->pElems = (PULONG)pb;
  3875. // Fill in the array of BLOBs
  3876. memcpy(pb, pIn, cbArray);
  3877. } else {
  3878. pcaul->pElems = NULL;
  3879. }
  3880. exit:
  3881. // BUGBUG: Should clean up allocations on failure
  3882. return(hr);
  3883. }
  3884. // --------------------------------------------------------------------------------
  3885. // HrCopyDwordArray
  3886. //
  3887. // Allocate a new dword array, copy the original to it.
  3888. // --------------------------------------------------------------------------------
  3889. HRESULT HrCopyDwordArray(LPDWORD pIn, ULONG cEntries, PROPVARIANT FAR * pvOut)
  3890. {
  3891. pvOut->vt = VT_VECTOR | VT_UI4;
  3892. return(HrCopyArray((LPBYTE)pIn, cEntries, pvOut, sizeof(DWORD)));
  3893. }
  3894. // --------------------------------------------------------------------------------
  3895. // HrCopyIntoUlonglongArray
  3896. //
  3897. // Allocate a new Ulonglong array, copy the original to it.
  3898. // --------------------------------------------------------------------------------
  3899. HRESULT HrCopyIntoUlonglongArray(ULARGE_INTEGER *pIn, ULONG cEntries, PROPVARIANT FAR * pvOut)
  3900. {
  3901. // Locals
  3902. HRESULT hr = S_OK;
  3903. ULARGE_INTEGER * pullBuff;
  3904. CAUH * pcauh = &pvOut->cauh;
  3905. pvOut->vt = VT_VECTOR | VT_UI8;
  3906. pcauh->cElems = cEntries;
  3907. if (cEntries)
  3908. {
  3909. Assert(pIn && pvOut);
  3910. // Allocate the array of VT_BLOB propvariants
  3911. if (FAILED(hr = HrAlloc((LPVOID *)&pullBuff, cEntries * sizeof(ULARGE_INTEGER *))))
  3912. {
  3913. goto exit;
  3914. }
  3915. pcauh->pElems = (ULARGE_INTEGER *) pullBuff;
  3916. // Fill in the array of BLOBs
  3917. for (; cEntries > 0; cEntries--, pullBuff++, pIn++)
  3918. {
  3919. *pullBuff = *pIn;
  3920. }
  3921. }
  3922. else
  3923. {
  3924. pcauh->pElems = NULL;
  3925. }
  3926. exit:
  3927. // BUGBUG: Should clean up allocations on failure
  3928. return(hr);
  3929. }
  3930. // --------------------------------------------------------------------------------
  3931. // HrCopyFiletimeArray
  3932. //
  3933. // Allocate a new filetime array, copy the original to it.
  3934. // --------------------------------------------------------------------------------
  3935. HRESULT HrCopyFiletimeArray(LPFILETIME pIn, ULONG cEntries, PROPVARIANT FAR * pvOut)
  3936. {
  3937. pvOut->vt = VT_VECTOR | VT_FILETIME;
  3938. return(HrCopyArray((LPBYTE)pIn, cEntries, pvOut, sizeof(FILETIME)));
  3939. }
  3940. // --------------------------------------------------------------------------------
  3941. // MergeDWORDFlags
  3942. //
  3943. // Merge the flags from an array of DWORDs into one DWORD
  3944. // --------------------------------------------------------------------------------
  3945. DWORD MergeDWORDFlags(LPDWORD rgdw, ULONG cEntries)
  3946. {
  3947. DWORD dwReturn = 0;
  3948. for (ULONG i = 0; i < cEntries; i++)
  3949. {
  3950. dwReturn |= rgdw[i];
  3951. }
  3952. return(dwReturn);
  3953. }
  3954. #ifdef SMIME_V3
  3955. // --------------------------------------------------------------------------------
  3956. // CMessageBody::Encode
  3957. // --------------------------------------------------------------------------------
  3958. HRESULT CMessageBody::Encode(HWND hwnd, DWORD dwFlags)
  3959. {
  3960. return E_FAIL;
  3961. }
  3962. // --------------------------------------------------------------------------------
  3963. // CMessageBody::Decode
  3964. // --------------------------------------------------------------------------------
  3965. HRESULT CMessageBody::Decode(HWND hwnd, DWORD dwFlags, IMimeSecurityCallback * pCallback)
  3966. {
  3967. return E_FAIL;
  3968. }
  3969. // --------------------------------------------------------------------------------
  3970. // CMessageBody::GetRecipientCount
  3971. // --------------------------------------------------------------------------------
  3972. HRESULT CMessageBody::GetRecipientCount(DWORD dwFlags, DWORD * pdwRecipCount)
  3973. {
  3974. Assert(dwFlags == 0);
  3975. if (dwFlags != 0) return E_INVALIDARG;
  3976. *pdwRecipCount = m_rOptions.cRecipients;
  3977. return S_OK;
  3978. }
  3979. // --------------------------------------------------------------------------------
  3980. // CMessageBody::AddRecipient
  3981. // --------------------------------------------------------------------------------
  3982. HRESULT CMessageBody::AddRecipient(DWORD dwFlags, DWORD cRecipData,
  3983. PCMS_RECIPIENT_INFO precipData)
  3984. {
  3985. DWORD cbExtra;
  3986. DWORD dw;
  3987. DWORD dwCaps;
  3988. HRESULT hr;
  3989. DWORD i;
  3990. Assert((dwFlags & ~(SMIME_RECIPIENT_REPLACE_ALL)) == 0);
  3991. if ((dwFlags & (~SMIME_RECIPIENT_REPLACE_ALL)) != 0) return E_INVALIDARG;
  3992. //
  3993. // Query capabilities
  3994. //
  3995. CHECKHR(hr = CapabilitiesSupported(&dwCaps));
  3996. //
  3997. // Start by running the verification code on the structures.
  3998. //
  3999. for (i=0; i<cRecipData; i++)
  4000. {
  4001. switch(precipData[i].dwRecipientType)
  4002. {
  4003. //
  4004. // If you tell use that you don't know whats going on, then you must
  4005. // 1. Give us a certificate
  4006. // 2. If you don't specify an alg, we must recognize the alg in the cert
  4007. //
  4008. case CMS_RECIPIENT_INFO_TYPE_UNKNOWN:
  4009. if (precipData[i].pccert == NULL)
  4010. {
  4011. hr = E_INVALIDARG;
  4012. goto exit;
  4013. }
  4014. if (precipData[i].KeyEncryptionAlgorithm.pszObjId == NULL)
  4015. {
  4016. hr = _HrMapPublicKeyAlg(&precipData[i].pccert->pCertInfo->SubjectPublicKeyInfo,
  4017. &dw, NULL);
  4018. if (FAILED(hr))
  4019. {
  4020. goto exit;
  4021. }
  4022. if (dw == CMS_RECIPIENT_INFO_TYPE_KEYTRANS) {
  4023. ;
  4024. }
  4025. else if (dw == CMS_RECIPIENT_INFO_TYPE_KEYAGREE) {
  4026. if (!(dwCaps & SMIME_SUPPORT_KEY_AGREE)) {
  4027. return MIME_E_SECURITY_NOTIMPLEMENTED;
  4028. }
  4029. }
  4030. else {
  4031. return E_INVALIDARG;
  4032. }
  4033. }
  4034. break;
  4035. //
  4036. // We have no requirements here.
  4037. //
  4038. case CMS_RECIPIENT_INFO_TYPE_KEYTRANS:
  4039. break;
  4040. case CMS_RECIPIENT_INFO_TYPE_KEYAGREE:
  4041. if (!(dwCaps & SMIME_SUPPORT_KEY_AGREE)) {
  4042. return MIME_E_SECURITY_NOTIMPLEMENTED;
  4043. }
  4044. break;
  4045. //
  4046. // If you give use a mail list key, you must also tell us the
  4047. // public key identifier and the mail list key or we are going
  4048. // to fail big time
  4049. //
  4050. case CMS_RECIPIENT_INFO_TYPE_MAIL_LIST:
  4051. if (!(dwCaps & SMIME_SUPPORT_MAILLIST)) {
  4052. return MIME_E_SECURITY_NOTIMPLEMENTED;
  4053. }
  4054. if ((precipData[i].dwU1 != CMS_RECIPIENT_INFO_PUBKEY_PROVIDER) ||
  4055. (precipData[i].dwU3 != CMS_RECIPIENT_INFO_KEYID_KEY_ID))
  4056. {
  4057. hr = E_INVALIDARG;
  4058. goto exit;
  4059. }
  4060. break;
  4061. default:
  4062. Assert(FALSE);
  4063. hr = E_INVALIDARG;
  4064. goto exit;
  4065. }
  4066. }
  4067. //
  4068. //
  4069. if (dwFlags & SMIME_RECIPIENT_REPLACE_ALL)
  4070. {
  4071. for (i=0; i<m_rOptions.cRecipients; i++)
  4072. {
  4073. FreeRecipientInfoContent(&m_rOptions.rgRecipients[i]);
  4074. }
  4075. m_rOptions.cRecipients = 0;
  4076. }
  4077. //
  4078. Assert(m_rOptions.cRecipients <= m_rOptions.cRecipsAllocated);
  4079. if (m_rOptions.cRecipients >= m_rOptions.cRecipsAllocated)
  4080. {
  4081. hr = HrRealloc((LPVOID *) &m_rOptions.rgRecipients,
  4082. (m_rOptions.cRecipsAllocated+cRecipData+5)*sizeof(CMS_RECIPIENT_INFO));
  4083. if (FAILED(hr))
  4084. {
  4085. goto exit;
  4086. }
  4087. m_rOptions.cRecipsAllocated += 5 + cRecipData;
  4088. }
  4089. //
  4090. // Do the actual copy of the data
  4091. //
  4092. CHECKHR(hr = _HrCopyRecipInfos(cRecipData, precipData,
  4093. &m_rOptions.rgRecipients[m_rOptions.cRecipients]));
  4094. m_rOptions.cRecipients += cRecipData;
  4095. hr = S_OK;
  4096. exit:
  4097. return hr;
  4098. }
  4099. // ------------------------------------------------------------------------------
  4100. // CMessageBody::_HrMapPublicKeyAlg
  4101. // ------------------------------------------------------------------------------
  4102. HRESULT CMessageBody::_HrMapPublicKeyAlg(CERT_PUBLIC_KEY_INFO * pkey, DWORD * pdw,
  4103. CRYPT_ALGORITHM_IDENTIFIER ** ppalg)
  4104. {
  4105. HRESULT hr = E_INVALIDARG;
  4106. static CRYPT_ALGORITHM_IDENTIFIER rgAlgs[] = {
  4107. {szOID_RSA_RSA, {0, 0}},
  4108. {szOID_RSA_SMIMEalgESDH, {0, 0}}
  4109. };
  4110. if (lstrcmp(pkey->Algorithm.pszObjId, szOID_RSA_RSA) == 0)
  4111. {
  4112. *pdw = CMS_RECIPIENT_INFO_TYPE_KEYTRANS;
  4113. if (ppalg != NULL)
  4114. {
  4115. *ppalg = &rgAlgs[0];
  4116. }
  4117. hr = S_OK;
  4118. }
  4119. else if (lstrcmp(pkey->Algorithm.pszObjId, szOID_ANSI_X942_DH) == 0)
  4120. {
  4121. *pdw = CMS_RECIPIENT_INFO_TYPE_KEYAGREE;
  4122. if (ppalg != NULL)
  4123. {
  4124. *ppalg = &rgAlgs[1];
  4125. }
  4126. hr = S_OK;
  4127. }
  4128. else {
  4129. *pdw = CMS_RECIPIENT_INFO_TYPE_UNKNOWN;
  4130. }
  4131. return hr;
  4132. }
  4133. // ------------------------------------------------------------------------------
  4134. // CMessageBody::_HrCopyRecipInfos
  4135. // ------------------------------------------------------------------------------
  4136. HRESULT CMessageBody::_HrCopyRecipInfos(DWORD cItems,
  4137. const CMS_RECIPIENT_INFO * precipSrc,
  4138. PCMS_RECIPIENT_INFO precipDst)
  4139. {
  4140. DWORD cb;
  4141. DWORD dw;
  4142. HRESULT hr;
  4143. DWORD i;
  4144. CRYPT_ALGORITHM_IDENTIFIER * palg;
  4145. memset(precipDst, 0, cItems*sizeof(*precipDst));
  4146. for (i=0; i<cItems; i++, precipSrc++, precipDst++)
  4147. {
  4148. //
  4149. // Now copy over the information
  4150. //
  4151. precipDst->dwRecipientType = precipSrc->dwRecipientType;
  4152. if (precipSrc->pccert != NULL)
  4153. {
  4154. precipDst->pccert = CertDuplicateCertificateContext(
  4155. (PCCERT_CONTEXT) precipSrc->pccert);
  4156. }
  4157. // Move over the key encryption alg if it exists
  4158. if (precipSrc->KeyEncryptionAlgorithm.pszObjId != NULL)
  4159. {
  4160. CHECKHR(hr = HrCopyOID(precipSrc->KeyEncryptionAlgorithm.pszObjId,
  4161. &precipDst->KeyEncryptionAlgorithm.pszObjId));
  4162. CHECKHR(hr = HrCopyCryptDataBlob(&precipSrc->KeyEncryptionAlgorithm.Parameters,
  4163. &precipDst->KeyEncryptionAlgorithm.Parameters));
  4164. }
  4165. else {
  4166. //
  4167. // If the data does not exist, then we need to create the data
  4168. // from scratch. We do this by pulling information out of the
  4169. // certificate and create the algorithm information about this.
  4170. //
  4171. // Maps RSA->RSA; DH -> smimeAlgESDH
  4172. //
  4173. Assert(precipSrc->pccert != NULL);
  4174. hr = _HrMapPublicKeyAlg(&precipDst->pccert->pCertInfo->SubjectPublicKeyInfo,
  4175. &dw, &palg);
  4176. Assert(hr == S_OK);
  4177. precipDst->dwRecipientType = dw;
  4178. CHECKHR(hr = HrCopyCryptAlgorithm(palg, &precipDst->KeyEncryptionAlgorithm));
  4179. }
  4180. //
  4181. // Move over the aux encryption info if it exists. The length has already
  4182. // been copied over
  4183. //
  4184. if (precipSrc->cbKeyEncryptionAuxInfo != 0)
  4185. {
  4186. CHECKHR(hr = HrAlloc(&precipDst->pvKeyEncryptionAuxInfo,
  4187. precipSrc->cbKeyEncryptionAuxInfo));
  4188. }
  4189. //
  4190. // Copy over the subject key id information
  4191. //
  4192. precipDst->dwU1 = precipSrc->dwU1;
  4193. switch (precipSrc->dwU1)
  4194. {
  4195. case CMS_RECIPIENT_INFO_PUBKEY_CERTIFICATE:
  4196. if (precipDst->dwRecipientType == CMS_RECIPIENT_INFO_TYPE_KEYTRANS)
  4197. {
  4198. precipDst->dwU1 = CMS_RECIPIENT_INFO_PUBKEY_KEYTRANS;
  4199. CHECKHR(hr = HrCopyCryptBitBlob(
  4200. &precipSrc->pccert->pCertInfo->SubjectPublicKeyInfo.PublicKey,
  4201. &precipDst->u1.SubjectPublicKey));
  4202. }
  4203. else if (precipDst->dwRecipientType == CMS_RECIPIENT_INFO_TYPE_KEYAGREE)
  4204. {
  4205. precipDst->dwU1 = CMS_RECIPIENT_INFO_PUBKEY_EPHEMERAL_KEYAGREE;
  4206. CHECKHR(hr = HrCopyCryptBitBlob(
  4207. &precipSrc->pccert->pCertInfo->SubjectPublicKeyInfo.PublicKey,
  4208. &precipDst->u1.u3.SubjectPublicKey));
  4209. // precipDst->u1.u3.UserKeyingMaterial = NULL;
  4210. CHECKHR(hr = HrCopyCryptAlgorithm(
  4211. &precipSrc->pccert->pCertInfo->SubjectPublicKeyInfo.Algorithm,
  4212. &precipDst->u1.u3.EphemeralAlgorithm));
  4213. }
  4214. else {
  4215. hr = E_INVALIDARG;
  4216. goto exit;
  4217. }
  4218. break;
  4219. case CMS_RECIPIENT_INFO_PUBKEY_KEYTRANS:
  4220. CHECKHR(hr = HrCopyCryptBitBlob(&precipSrc->u1.SubjectPublicKey,
  4221. &precipDst->u1.SubjectPublicKey));
  4222. break;
  4223. case CMS_RECIPIENT_INFO_PUBKEY_EPHEMERAL_KEYAGREE:
  4224. CHECKHR(hr = HrCopyCryptDataBlob(&precipSrc->u1.u3.UserKeyingMaterial,
  4225. &precipDst->u1.u3.UserKeyingMaterial));
  4226. CHECKHR(hr = HrCopyCryptAlgorithm(&precipSrc->u1.u3.EphemeralAlgorithm,
  4227. &precipDst->u1.u3.EphemeralAlgorithm));
  4228. CHECKHR(hr = HrCopyCryptBitBlob(&precipSrc->u1.u3.SubjectPublicKey,
  4229. &precipDst->u1.u3.SubjectPublicKey));
  4230. break;
  4231. case CMS_RECIPIENT_INFO_PUBKEY_STATIC_KEYAGREE:
  4232. CHECKHR(hr = HrCopyCryptDataBlob(&precipSrc->u1.u4.UserKeyingMaterial,
  4233. &precipDst->u1.u4.UserKeyingMaterial));
  4234. if (!CryptContextAddRef(precipSrc->u1.u4.hprov, 0, 0))
  4235. {
  4236. hr = HrGetLastError();
  4237. goto exit;
  4238. }
  4239. precipDst->u1.u4.hprov = precipSrc->u1.u4.hprov;
  4240. precipDst->u1.u4.dwKeySpec = precipSrc->u1.u4.dwKeySpec;
  4241. CHECKHR(hr = HrCopyCertId(&precipSrc->u1.u4.senderCertId,
  4242. &precipDst->u1.u4.senderCertId));
  4243. CHECKHR(hr = HrCopyCryptBitBlob(&precipSrc->u1.u4.SubjectPublicKey,
  4244. &precipDst->u1.u4.SubjectPublicKey));
  4245. break;
  4246. // hprov & hkey are already copied over
  4247. case CMS_RECIPIENT_INFO_PUBKEY_PROVIDER:
  4248. if (!CryptContextAddRef(precipDst->u1.u2.hprov, 0, 0))
  4249. {
  4250. hr = HrGetLastError();
  4251. goto exit;
  4252. }
  4253. precipDst->u1.u2.hprov = precipSrc->u1.u2.hprov;
  4254. if (!CryptDuplicateKey(precipSrc->u1.u2.hkey, 0, 0,
  4255. &precipDst->u1.u2.hkey))
  4256. {
  4257. hr = HrGetLastError();
  4258. goto exit;
  4259. }
  4260. precipDst->u1.u2.hkey = precipSrc->u1.u2.hkey;
  4261. break;
  4262. }
  4263. precipDst->dwU3 = precipSrc->dwU3;
  4264. switch (precipSrc->dwU3)
  4265. {
  4266. case CMS_RECIPIENT_INFO_KEYID_CERTIFICATE:
  4267. precipDst->dwU3 = CMS_RECIPIENT_INFO_KEYID_ISSUERSERIAL;
  4268. CHECKHR(hr = HrCopyCryptDataBlob(&precipSrc->pccert->pCertInfo->Issuer,
  4269. &precipDst->u3.IssuerSerial.Issuer));
  4270. CHECKHR(hr = HrCopyCryptDataBlob(&precipSrc->pccert->pCertInfo->SerialNumber,
  4271. &precipDst->u3.IssuerSerial.SerialNumber));
  4272. break;
  4273. case CMS_RECIPIENT_INFO_KEYID_ISSUERSERIAL:
  4274. CHECKHR(hr = HrCopyCryptDataBlob( &precipSrc->u3.IssuerSerial.Issuer,
  4275. &precipDst->u3.IssuerSerial.Issuer));
  4276. CHECKHR(hr = HrCopyCryptDataBlob( &precipSrc->u3.IssuerSerial.SerialNumber,
  4277. &precipDst->u3.IssuerSerial.SerialNumber));
  4278. break;
  4279. case CMS_RECIPIENT_INFO_KEYID_KEY_ID:
  4280. CHECKHR(hr = HrCopyCryptDataBlob(&precipSrc->u3.KeyId, &precipDst->u3.KeyId));
  4281. break;
  4282. }
  4283. precipDst->filetime = precipSrc->filetime;
  4284. if (precipSrc->pOtherAttr != NULL)
  4285. {
  4286. Assert(FALSE);
  4287. }
  4288. }
  4289. hr = S_OK;
  4290. exit:
  4291. return hr;
  4292. }
  4293. // ------------------------------------------------------------------------------
  4294. // CMessageBody::GetRecipient
  4295. // ------------------------------------------------------------------------------
  4296. HRESULT CMessageBody::GetRecipient(DWORD dwFlags, DWORD iRecipient, DWORD cRecipients, PCMS_RECIPIENT_INFO pRecipData)
  4297. {
  4298. DWORD cbAlloc;
  4299. HRESULT hr;
  4300. LPBYTE pb;
  4301. PCMS_RECIPIENT_INFO precip;
  4302. if (iRecipient+cRecipients > m_rOptions.cRecipients)
  4303. {
  4304. hr = E_INVALIDARG;
  4305. goto exit;
  4306. }
  4307. precip = &m_rOptions.rgRecipients[iRecipient];
  4308. //
  4309. // Copy the buffer
  4310. //
  4311. CHECKHR(hr = _HrCopyRecipInfos(cRecipients, precip, pRecipData));
  4312. hr = S_OK;
  4313. exit:
  4314. return hr;
  4315. }
  4316. // --------------------------------------------------------------------------------
  4317. // CMessageBody::DeleteRecipient
  4318. // --------------------------------------------------------------------------------
  4319. HRESULT CMessageBody::DeleteRecipient(DWORD dwFlags, DWORD iRecipient, DWORD cRecipients)
  4320. {
  4321. return E_FAIL;
  4322. }
  4323. // --------------------------------------------------------------------------------
  4324. // CMessageBody::GetAttribute
  4325. // --------------------------------------------------------------------------------
  4326. HRESULT CMessageBody::GetAttribute(DWORD dwFlags, DWORD iSigner, DWORD iAttribSet,
  4327. DWORD iInstance, LPCSTR pszObjId,
  4328. CRYPT_ATTRIBUTE ** ppattr)
  4329. {
  4330. DWORD cb;
  4331. HRESULT hr;
  4332. DWORD i;
  4333. DWORD i1;
  4334. PCRYPT_ATTRIBUTE pattr = NULL;
  4335. PCRYPT_ATTRIBUTES pattrs;
  4336. PCRYPT_ATTRIBUTE pattrSrc;
  4337. LPBYTE pb;
  4338. LPBLOB pblob;
  4339. //
  4340. // Start with some simple parameter checks
  4341. //
  4342. if ( // (iAttribSet < SMIME_ATTRIBUTE_SET_SIGNED) ||
  4343. (iAttribSet > SMIME_ATTRIBUTE_SET_UNPROTECTED))
  4344. {
  4345. return E_INVALIDARG;
  4346. }
  4347. if (dwFlags & ~(SMIME_RECIPIENT_REPLACE_ALL))
  4348. {
  4349. return E_INVALIDARG;
  4350. }
  4351. if (iAttribSet == SMIME_ATTRIBUTE_SET_UNPROTECTED)
  4352. {
  4353. if ((iSigner != 0) || !g_FSupportV3)
  4354. return E_INVALIDARG;
  4355. if (m_rOptions.rgrgpattrs[iAttribSet] == NULL)
  4356. return S_FALSE;
  4357. }
  4358. else if (iSigner >= m_rOptions.cSigners)
  4359. {
  4360. return E_INVALIDARG;
  4361. }
  4362. //
  4363. // Special case of getting every single attribute on record
  4364. //
  4365. if (pszObjId == NULL) {
  4366. if (!CryptEncodeObjectEx(X509_ASN_ENCODING,
  4367. szOID_Microsoft_Attribute_Sequence,
  4368. m_rOptions.rgrgpattrs[iAttribSet][iSigner],
  4369. 0, NULL, NULL, &cb))
  4370. {
  4371. hr = HrGetLastError();
  4372. goto exit;
  4373. }
  4374. if (!MemAlloc((LPVOID *) &pattr, cb + sizeof(CRYPT_ATTRIBUTE) +
  4375. sizeof(CRYPT_ATTR_BLOB))) {
  4376. hr = E_OUTOFMEMORY;
  4377. goto exit;
  4378. }
  4379. pattr->cValue = 1;
  4380. pattr->rgValue = (PCRYPT_ATTR_BLOB) &pattr[1];
  4381. pb = (LPBYTE) &pattr->rgValue[1];
  4382. pattr->pszObjId = NULL;
  4383. pattr->rgValue[0].pbData = pb;
  4384. pattr->rgValue[0].cbData = cb;
  4385. if (!CryptEncodeObjectEx(X509_ASN_ENCODING,
  4386. szOID_Microsoft_Attribute_Sequence,
  4387. m_rOptions.rgrgpattrs[iAttribSet][iSigner],
  4388. 0, NULL, pb, &cb))
  4389. {
  4390. hr = HrGetLastError();
  4391. goto exit;
  4392. }
  4393. *ppattr = pattr;
  4394. pattr = NULL;
  4395. hr = S_OK;
  4396. goto exit;
  4397. }
  4398. //
  4399. //
  4400. pattrSrc = _FindAttribute(m_rOptions.rgrgpattrs[iAttribSet][iSigner], pszObjId,
  4401. iInstance);
  4402. if (pattrSrc != NULL)
  4403. {
  4404. #ifdef _WIN64
  4405. cb = sizeof(CRYPT_ATTRIBUTE) + LcbAlignLcb(strlen(pszObjId) + 1);
  4406. #else
  4407. cb = sizeof(CRYPT_ATTRIBUTE) + strlen(pszObjId) + 1;
  4408. #endif
  4409. for (i1=0; i1<pattrSrc->cValue; i1++)
  4410. {
  4411. cb += sizeof(CRYPT_ATTR_BLOB);
  4412. #ifdef _WIN64
  4413. cb += LcbAlignLcb(pattrSrc->rgValue[i1].cbData);
  4414. #else
  4415. cb += pattrSrc->rgValue[i1].cbData;
  4416. #endif
  4417. }
  4418. if (!MemAlloc((LPVOID *) &pattr, cb))
  4419. {
  4420. hr = E_OUTOFMEMORY;
  4421. goto exit;
  4422. }
  4423. pattr->cValue = pattrSrc->cValue;
  4424. pattr->rgValue = (PCRYPT_ATTR_BLOB) &pattr[1];
  4425. pb = (LPBYTE) &pattr->rgValue[pattrSrc->cValue];
  4426. pattr->pszObjId = (LPSTR) pb;
  4427. cb = strlen(pszObjId)+1;
  4428. memcpy(pattr->pszObjId, pszObjId, cb);
  4429. #ifdef _WIN64
  4430. pb += LcbAlignLcb(cb);
  4431. #else
  4432. pb += cb;
  4433. #endif //_WIN64
  4434. for (i1=0; i1<pattrSrc->cValue; i1++)
  4435. {
  4436. pattr->rgValue[i1].pbData = pb;
  4437. pattr->rgValue[i1].cbData = pattrSrc->rgValue[i1].cbData;
  4438. memcpy(pb, pattrSrc->rgValue[i1].pbData,
  4439. pattrSrc->rgValue[i1].cbData);
  4440. #ifdef _WIN64
  4441. pb += LcbAlignLcb(pattrSrc->rgValue[i1].cbData);
  4442. #else
  4443. pb += pattrSrc->rgValue[i1].cbData;
  4444. #endif //_WIN64
  4445. }
  4446. *ppattr = pattr;
  4447. pattr = NULL;
  4448. hr = S_OK;
  4449. }
  4450. else {
  4451. hr = S_FALSE;
  4452. }
  4453. exit:
  4454. if (pattr != NULL) MemFree(pattr);
  4455. return hr;
  4456. }
  4457. // --------------------------------------------------------------------------------
  4458. // CMessageBody::SetAttribute
  4459. // --------------------------------------------------------------------------------
  4460. HRESULT CMessageBody::SetAttribute(DWORD dwFlags, DWORD iSigner, DWORD iAttribSet,
  4461. const CRYPT_ATTRIBUTE * pattr)
  4462. {
  4463. HRESULT hr;
  4464. DWORD i;
  4465. //
  4466. // Start with some simple parameter checks
  4467. //
  4468. if (// (iAttribSet < SMIME_ATTRIBUTE_SET_SIGNED) ||
  4469. (iAttribSet > SMIME_ATTRIBUTE_SET_UNPROTECTED))
  4470. {
  4471. return E_INVALIDARG;
  4472. }
  4473. if (dwFlags & ~(SMIME_ATTR_ADD_TO_EXISTING |
  4474. SMIME_ATTR_ADD_IF_NOT_EXISTS))
  4475. {
  4476. return E_INVALIDARG;
  4477. }
  4478. if (iAttribSet == SMIME_ATTRIBUTE_SET_UNPROTECTED) {
  4479. if ((iSigner != 0) || !g_FSupportV3)
  4480. return E_INVALIDARG;
  4481. if (m_rOptions.rgrgpattrs[iAttribSet] == NULL) {
  4482. if (!MemAlloc((LPVOID *) &m_rOptions.rgrgpattrs[iAttribSet],
  4483. sizeof(LPVOID))) {
  4484. return E_OUTOFMEMORY;
  4485. }
  4486. m_rOptions.rgrgpattrs[iAttribSet][0] = NULL;
  4487. }
  4488. }
  4489. else if ((iSigner >= m_rOptions.cSigners) && (iSigner != (DWORD) -1))
  4490. {
  4491. return E_INVALIDARG;
  4492. }
  4493. //
  4494. // Now make the correct utility call to put things right
  4495. //
  4496. Assert(pattr->cValue == 1);
  4497. if (iSigner == (DWORD) -1)
  4498. {
  4499. Assert(iAttribSet != SMIME_ATTRIBUTE_SET_UNPROTECTED);
  4500. for (i=0; i<m_rOptions.cSigners; i++)
  4501. {
  4502. hr = _HrSetAttribute(dwFlags, &m_rOptions.rgrgpattrs[iAttribSet][i],
  4503. pattr->pszObjId, pattr->rgValue[0].cbData,
  4504. pattr->rgValue[0].pbData);
  4505. if (FAILED(hr))
  4506. {
  4507. break;
  4508. }
  4509. }
  4510. }
  4511. else {
  4512. hr = _HrSetAttribute(dwFlags, &m_rOptions.rgrgpattrs[iAttribSet][iSigner],
  4513. pattr->pszObjId, pattr->rgValue[0].cbData,
  4514. pattr->rgValue[0].pbData);
  4515. }
  4516. return hr;
  4517. }
  4518. // --------------------------------------------------------------------------------
  4519. // CMessageBody::DeleteAttribute
  4520. // --------------------------------------------------------------------------------
  4521. HRESULT CMessageBody::DeleteAttribute(DWORD dwFlags, DWORD iSigner,
  4522. DWORD iAttribSet, DWORD iInstance,
  4523. LPCSTR pszObjId)
  4524. {
  4525. UINT i;
  4526. PCRYPT_ATTRIBUTE pattr;
  4527. PCRYPT_ATTRIBUTES pattrs;
  4528. //
  4529. // Start with some simple parameter checks
  4530. //
  4531. if (// (iAttribSet < SMIME_ATTRIBUTE_SET_SIGNED) ||
  4532. (iAttribSet > SMIME_ATTRIBUTE_SET_UNPROTECTED))
  4533. {
  4534. return E_INVALIDARG;
  4535. }
  4536. if (dwFlags & ~(SMIME_RECIPIENT_REPLACE_ALL))
  4537. {
  4538. return E_INVALIDARG;
  4539. }
  4540. if (iAttribSet == SMIME_ATTRIBUTE_SET_UNPROTECTED) {
  4541. if ((iSigner != 0) || !g_FSupportV3)
  4542. return E_INVALIDARG;
  4543. if (m_rOptions.rgrgpattrs[iAttribSet] == NULL)
  4544. return S_OK;
  4545. }
  4546. else if (iSigner >= m_rOptions.cSigners)
  4547. {
  4548. return E_INVALIDARG;
  4549. }
  4550. //
  4551. pattrs = m_rOptions.rgrgpattrs[iAttribSet][iSigner];
  4552. pattr = _FindAttribute(pattrs, pszObjId, iInstance);
  4553. if (pattr != NULL)
  4554. {
  4555. i = (UINT) (pattr - &pattrs->rgAttr[0]);
  4556. Assert( (0 <= ((int) i)) && (((int) i) < pattrs->cAttr));
  4557. memcpy(pattr, pattr+1, (pattrs->cAttr - i - 1) * sizeof(CRYPT_ATTRIBUTE));
  4558. pattrs->cAttr -= 1;
  4559. }
  4560. else {
  4561. return S_FALSE;
  4562. }
  4563. return S_OK;
  4564. }
  4565. HRESULT CMessageBody::_SetNames(ReceiptNames * pnames, DWORD cNames, CERT_NAME_BLOB * rgNames)
  4566. {
  4567. DWORD cb;
  4568. HRESULT hr = S_OK;
  4569. DWORD i;
  4570. LPBYTE pb;
  4571. if (pnames->rgNames != NULL)
  4572. {
  4573. MemFree(pnames->rgNames);
  4574. pnames->rgNames = NULL;
  4575. pnames->cNames = 0;
  4576. }
  4577. for (i=0, cb=cNames*sizeof(CERT_NAME_BLOB); i<cNames; i++)
  4578. #ifdef _WIN64
  4579. cb += LcbAlignLcb(rgNames[i].cbData);
  4580. #else
  4581. cb += rgNames[i].cbData;
  4582. #endif //_WIN64
  4583. CHECKHR(hr = HrAlloc((LPVOID *)&pnames->rgNames, cb));
  4584. pb = (LPBYTE) &pnames->rgNames[cNames];
  4585. for (i=0; i<cNames; i++)
  4586. {
  4587. pnames->rgNames[i].pbData = pb;
  4588. pnames->rgNames[i].cbData = rgNames[i].cbData;
  4589. memcpy(pb, rgNames[i].pbData, rgNames[i].cbData);
  4590. #ifdef _WIN64
  4591. pb += LcbAlignLcb(rgNames[i].cbData);
  4592. #else
  4593. pb += rgNames[i].cbData;
  4594. #endif //_WIN64
  4595. }
  4596. pnames->cNames = cNames;
  4597. exit:
  4598. return hr;
  4599. }
  4600. HRESULT CMessageBody::_MergeNames(ReceiptNames * pnames, DWORD cNames, CERT_NAME_BLOB * rgNames)
  4601. {
  4602. DWORD cb;
  4603. HRESULT hr = S_OK;
  4604. DWORD i;
  4605. DWORD i1;
  4606. LPBYTE pb;
  4607. CERT_NAME_BLOB * p;
  4608. for (i=0, cb=0; i<pnames->cNames; i++)
  4609. #ifdef _WIN64
  4610. cb += LcbAlignLcb(pnames->rgNames[i].cbData);
  4611. #else
  4612. cb += pnames->rgNames[i].cbData;
  4613. #endif //_WIN64
  4614. for (i=0; i<cNames; i++)
  4615. #ifdef _WIN64
  4616. cb += LcbAlignLcb(rgNames[i].cbData);
  4617. #else
  4618. cb += rgNames[i].cbData;
  4619. #endif //_WIN64
  4620. CHECKHR(hr = HrAlloc((LPVOID *)&p, cb + (pnames->cNames + cNames) *
  4621. sizeof(CERT_NAME_BLOB)));
  4622. pb = (LPBYTE) &p[pnames->cNames + cNames];
  4623. for (i=0, i1=0; i<pnames->cNames; i++, i1++)
  4624. {
  4625. p[i1].pbData = pb;
  4626. p[i1].cbData = pnames->rgNames[i].cbData;
  4627. memcpy(pb, pnames->rgNames[i].pbData, pnames->rgNames[i].cbData);
  4628. #ifdef _WIN64
  4629. pb += LcbAlignLcb(pnames->rgNames[i].cbData);
  4630. #else
  4631. pb += pnames->rgNames[i].cbData;
  4632. #endif //_WIN64
  4633. }
  4634. for (i=0; i<pnames->cNames; i++, i1++)
  4635. {
  4636. p[i1].pbData = pb;
  4637. p[i1].cbData = rgNames[i].cbData;
  4638. memcpy(pb, rgNames[i].pbData, rgNames[i].cbData);
  4639. #ifdef _WIN64
  4640. pb += LcbAlignLcb(rgNames[i].cbData);
  4641. #else
  4642. pb += rgNames[i].cbData;
  4643. #endif //_WIN64
  4644. }
  4645. MemFree(pnames->rgNames);
  4646. pnames->rgNames = p;
  4647. pnames->cNames = i1;
  4648. exit:
  4649. return hr;
  4650. }
  4651. /////////////////////////////////////////////////////////////////////////
  4652. //--------------------------------------------------------------------------------
  4653. // CMessageBody::_GetReceiptRequest
  4654. //--------------------------------------------------------------------------------
  4655. HRESULT CMessageBody::_GetReceiptRequest(DWORD dwFlags,
  4656. PSMIME_RECEIPT_REQUEST *ppreq,
  4657. ReceiptNames *pReceiptsTo,
  4658. DWORD *pcbReceipt,
  4659. LPBYTE *ppbReceipt,
  4660. DWORD *pcbMsgHash,
  4661. LPBYTE *ppbMsgHash)
  4662. {
  4663. DWORD cb;
  4664. DWORD cbMLHistory = 0;
  4665. DWORD cbMsgHash = 0;
  4666. DWORD cbReceipt = 0;
  4667. DWORD cSendersList = 0;
  4668. DWORD dwReciptsFrom;
  4669. HRESULT hr = S_OK;
  4670. DWORD i;
  4671. DWORD iAttr;
  4672. DWORD iSigner;
  4673. PCRYPT_ATTRIBUTES pattrs = NULL;
  4674. LPBYTE pb;
  4675. LPBYTE pbMLHistory = NULL;
  4676. LPBYTE pbMsgHash = NULL;
  4677. LPBYTE pbReceipt = NULL;
  4678. PSMIME_RECEIPT_REQUEST preq = NULL;
  4679. ReceiptNames receiptsTo = {0, NULL};
  4680. CERT_NAME_BLOB *rgSendersList = NULL;
  4681. PROPVARIANT var;
  4682. *ppreq = NULL;
  4683. if (pReceiptsTo != NULL)
  4684. {
  4685. pReceiptsTo->cNames = 0;
  4686. pReceiptsTo->rgNames = NULL;
  4687. }
  4688. if (pcbReceipt != NULL) *pcbReceipt = 0;
  4689. if (ppbReceipt != NULL) *ppbReceipt = NULL;
  4690. Assert(((pcbReceipt == NULL) && (ppbReceipt == NULL)) ||
  4691. ((pcbReceipt != NULL) && (ppbReceipt != NULL)));
  4692. if (pcbMsgHash != NULL) *pcbMsgHash = 0;
  4693. if (ppbMsgHash != NULL) *ppbMsgHash = NULL;
  4694. Assert(((pcbMsgHash == NULL) && (ppbMsgHash == NULL)) ||
  4695. ((pcbMsgHash != NULL) && (ppbMsgHash != NULL)));
  4696. //
  4697. // If this is the bottom layer then
  4698. // find and Decode Receipt Request
  4699. // Set ReceiptsTo from the request
  4700. // if not then
  4701. // check lower layers
  4702. // if mlExpansion in this layer? No -- Skip to next layer
  4703. // Receipt for First Tier only? Yes - return S_FALSE
  4704. // Policy override on mlExpansion?
  4705. // None - return S_FALSE
  4706. // return S_OK
  4707. // If this is not the bottom layer then look for MLHistory
  4708. if (IsContentType(STR_CNT_MULTIPART, "y-security") == S_OK)
  4709. {
  4710. Assert(m_pNode->cChildren == 1);
  4711. hr = m_pNode->pChildHead->pBody->_GetReceiptRequest(
  4712. dwFlags,
  4713. &preq,
  4714. (pReceiptsTo) ? &receiptsTo : NULL,
  4715. (pcbReceipt) ? &cbReceipt : NULL,
  4716. (ppbReceipt) ? &pbReceipt : NULL,
  4717. (pcbMsgHash) ? &cbMsgHash : NULL,
  4718. (ppbMsgHash) ? &pbMsgHash : NULL);
  4719. if (hr)
  4720. goto exit;
  4721. //
  4722. // Walk through each signer's authenticated attributes processing the
  4723. // relevant attribute.
  4724. //
  4725. for (iSigner=0; iSigner<m_rOptions.cSigners; iSigner++)
  4726. {
  4727. //
  4728. // Walk through each attribute looking for
  4729. // a Mail List expansion history
  4730. //
  4731. pattrs = m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED][iSigner];
  4732. for (iAttr=0; iAttr<pattrs->cAttr; iAttr++)
  4733. {
  4734. if (lstrcmp(pattrs->rgAttr[iAttr].pszObjId,
  4735. szOID_SMIME_MLExpansion_History) == 0)
  4736. {
  4737. //
  4738. // If receipts are from first tier only and we are at
  4739. // this layer then we are not first tier by definition.
  4740. //
  4741. if (preq->ReceiptsFrom.AllOrFirstTier == SMIME_RECEIPTS_FROM_FIRST_TIER)
  4742. {
  4743. hr = S_FALSE;
  4744. goto exit;
  4745. }
  4746. if (cbMLHistory == 0)
  4747. {
  4748. CHECKHR(hr = HrAlloc((LPVOID *)&pbMLHistory,
  4749. pattrs->rgAttr[iAttr].rgValue[0].cbData));
  4750. memcpy(pbMLHistory,pattrs->rgAttr[iAttr].rgValue[0].pbData,
  4751. pattrs->rgAttr[iAttr].rgValue[0].cbData);
  4752. cbMLHistory = pattrs->rgAttr[iAttr].rgValue[0].cbData;
  4753. }
  4754. else if ((pattrs->rgAttr[iAttr].rgValue[0].cbData != cbMLHistory) ||
  4755. (memcmp(pattrs->rgAttr[iAttr].rgValue[0].pbData,
  4756. pbMLHistory, cbMLHistory)))
  4757. {
  4758. // Hey, all MLHistorys should match
  4759. hr = S_FALSE;
  4760. goto exit;
  4761. }
  4762. break;
  4763. }
  4764. }
  4765. }
  4766. // Decode and respect the MLHistory
  4767. if (cbMLHistory != 0)
  4768. {
  4769. PSMIME_ML_EXPANSION_HISTORY pmlhist = NULL;
  4770. //
  4771. // Crack the attribute
  4772. //
  4773. if (!CryptDecodeObjectEx(X509_ASN_ENCODING,
  4774. szOID_SMIME_MLExpansion_History,
  4775. pbMLHistory,
  4776. cbMLHistory,
  4777. CRYPT_ENCODE_ALLOC_FLAG,
  4778. &CryptDecodeAlloc, &pmlhist, &cb))
  4779. goto GeneralFail;
  4780. PSMIME_MLDATA pMLData = &pmlhist->rgMLData[pmlhist->cMLData-1];
  4781. switch( pMLData->dwPolicy)
  4782. {
  4783. // No receipt is to be returned
  4784. case SMIME_MLPOLICY_NONE:
  4785. hr = S_FALSE;
  4786. SafeMemFree(pmlhist);
  4787. goto exit;
  4788. // Return receipt to a new list
  4789. case SMIME_MLPOLICY_INSTEAD_OF:
  4790. if (pReceiptsTo != NULL)
  4791. _SetNames(&receiptsTo, pMLData->cNames, pMLData->rgNames);
  4792. break;
  4793. case SMIME_MLPOLICY_IN_ADDITION_TO:
  4794. if (pReceiptsTo != NULL)
  4795. _MergeNames(&receiptsTo, pMLData->cNames, pMLData->rgNames);
  4796. break;
  4797. case SMIME_MLPOLICY_NO_CHANGE:
  4798. break;
  4799. default:
  4800. SafeMemFree(pmlhist);
  4801. goto GeneralFail;
  4802. }
  4803. SafeMemFree(pmlhist);
  4804. }
  4805. }
  4806. else
  4807. {
  4808. // Else this is the bottom layer so look for receipt request
  4809. //
  4810. // Walk through each signer's authenticated attributes processing the
  4811. // two relevant attributes.
  4812. //
  4813. for (iSigner=0; iSigner<m_rOptions.cSigners; iSigner++)
  4814. {
  4815. // Check if receipt was created for this signer if not then
  4816. // it's signature must have been bad or it had not request
  4817. if (m_rOptions.rgblobReceipt[iSigner].cbSize == 0)
  4818. continue;
  4819. // if we have a receipt we should also have a message hash
  4820. if (m_rOptions.rgblobMsgHash[iSigner].cbSize == 0)
  4821. {
  4822. Assert(FALSE);
  4823. continue;
  4824. }
  4825. if (m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED][iSigner] == NULL)
  4826. {
  4827. // Hey how did we get a receipt without any attributes
  4828. Assert(FALSE);
  4829. goto GeneralFail;
  4830. }
  4831. pattrs = m_rOptions.rgrgpattrs[SMIME_ATTRIBUTE_SET_SIGNED][iSigner];
  4832. //
  4833. // Walk through each attribute looking for the receipt request
  4834. //
  4835. for (iAttr=0; iAttr<pattrs->cAttr; iAttr++)
  4836. {
  4837. if (lstrcmp(pattrs->rgAttr[iAttr].pszObjId,
  4838. szOID_SMIME_MLExpansion_History) == 0)
  4839. {
  4840. // We are at the bottom so we should not have found a ML History
  4841. hr = S_FALSE;
  4842. goto exit;
  4843. }
  4844. if (lstrcmp(pattrs->rgAttr[iAttr].pszObjId,
  4845. szOID_SMIME_Receipt_Request) == 0)
  4846. {
  4847. //
  4848. // Crack the contents of the receipt request
  4849. //
  4850. if (!CryptDecodeObjectEx(X509_ASN_ENCODING,
  4851. szOID_SMIME_Receipt_Request,
  4852. pattrs->rgAttr[iAttr].rgValue[0].pbData,
  4853. pattrs->rgAttr[iAttr].rgValue[0].cbData,
  4854. CRYPT_DECODE_ALLOC_FLAG,
  4855. &CryptDecodeAlloc, &preq, &cb) ||
  4856. (preq->cReceiptsTo == 0))
  4857. goto GeneralFail;
  4858. //
  4859. // Initialize the ReceiptsTo list
  4860. //
  4861. if (pReceiptsTo != NULL)
  4862. _SetNames(&receiptsTo, preq->cReceiptsTo, preq->rgReceiptsTo);
  4863. if (ppbReceipt != NULL)
  4864. {
  4865. CHECKHR(hr = HrAlloc((LPVOID *)&pbReceipt,
  4866. m_rOptions.rgblobReceipt[iSigner].cbSize));
  4867. memcpy(pbReceipt,m_rOptions.rgblobReceipt[iSigner].pBlobData,
  4868. m_rOptions.rgblobReceipt[iSigner].cbSize);
  4869. }
  4870. if (pcbReceipt != NULL) cbReceipt = m_rOptions.rgblobReceipt[iSigner].cbSize;
  4871. if (ppbMsgHash != NULL)
  4872. {
  4873. CHECKHR(hr = HrAlloc((LPVOID *)&pbMsgHash,
  4874. m_rOptions.rgblobMsgHash[iSigner].cbSize));
  4875. memcpy(pbMsgHash,m_rOptions.rgblobMsgHash[iSigner].pBlobData,
  4876. m_rOptions.rgblobMsgHash[iSigner].cbSize);
  4877. }
  4878. if (pcbMsgHash != NULL) cbMsgHash = m_rOptions.rgblobMsgHash[iSigner].cbSize;
  4879. break;
  4880. }
  4881. }
  4882. }
  4883. if (preq == NULL)
  4884. {
  4885. // We are at the bottom so we should have found a receipt request
  4886. hr = S_FALSE;
  4887. goto exit;
  4888. }
  4889. }
  4890. *ppreq = preq;
  4891. preq = NULL;
  4892. if (pReceiptsTo != NULL)
  4893. {
  4894. pReceiptsTo->cNames = receiptsTo.cNames;
  4895. pReceiptsTo->rgNames = receiptsTo.rgNames;
  4896. receiptsTo.cNames = 0;
  4897. receiptsTo.rgNames = NULL;
  4898. }
  4899. if (pcbReceipt != NULL)
  4900. {
  4901. *pcbReceipt = cbReceipt;
  4902. cbReceipt = 0;
  4903. }
  4904. if (ppbReceipt != NULL)
  4905. {
  4906. *ppbReceipt = pbReceipt;
  4907. pbReceipt = NULL;
  4908. }
  4909. if (pcbMsgHash != NULL)
  4910. {
  4911. *pcbMsgHash = cbMsgHash;
  4912. cbMsgHash = 0;
  4913. }
  4914. if (ppbMsgHash != NULL)
  4915. {
  4916. *ppbMsgHash = pbMsgHash;
  4917. pbMsgHash = NULL;
  4918. }
  4919. exit:
  4920. SafeMemFree(preq);
  4921. SafeMemFree(receiptsTo.rgNames);
  4922. SafeMemFree(pbReceipt);
  4923. SafeMemFree(pbMsgHash);
  4924. SafeMemFree(pbMLHistory);
  4925. return hr;
  4926. GeneralFail:
  4927. hr = E_FAIL;
  4928. goto exit;
  4929. }
  4930. //--------------------------------------------------------------------------------
  4931. // CMessageBody::CreateReceipt
  4932. //--------------------------------------------------------------------------------
  4933. HRESULT CMessageBody::CreateReceipt(DWORD dwFlags, DWORD cbFromNames,
  4934. const BYTE *pbFromNames, DWORD cSignerCertificates,
  4935. PCCERT_CONTEXT *rgSignerCertificates,
  4936. IMimeMessage ** ppMimeMessageReceipt)
  4937. {
  4938. CRYPT_ATTRIBUTE attrMsgHash;
  4939. DWORD cb;
  4940. DWORD cbEncodedMsgHash = 0;
  4941. DWORD cbMsgHash = 0;
  4942. DWORD cbReceipt = 0;
  4943. DWORD cLayers;
  4944. DWORD dwReceiptsFrom;
  4945. BOOL fAddedAddress = FALSE;
  4946. HRESULT hr;
  4947. DWORD i;
  4948. DWORD i1;
  4949. DWORD i2;
  4950. DWORD iLayer;
  4951. LPBYTE pbEncodedMsgHash = NULL;
  4952. LPBYTE pbMsgHash = NULL;
  4953. LPBYTE pbReceipt = NULL;
  4954. IMimeAddressTable * pmatbl = NULL;
  4955. IMimeBody * pmb = NULL;
  4956. IMimeMessage * pmm = NULL;
  4957. IMimeSecurity2 * pms = NULL;
  4958. PSMIME_RECEIPT_REQUEST preq = NULL;
  4959. LPSTREAM pstm = NULL;
  4960. ReceiptNames receiptsTo = {0, NULL};
  4961. PROPVARIANT var;
  4962. CRYPT_ATTR_BLOB valMsgHash;
  4963. hr = _GetReceiptRequest(dwFlags,
  4964. &preq,
  4965. &receiptsTo,
  4966. &cbReceipt,
  4967. &pbReceipt,
  4968. &cbMsgHash,
  4969. &pbMsgHash);
  4970. if (hr)
  4971. goto exit;
  4972. //
  4973. // Am I on the ReceiptsFrom List --
  4974. //
  4975. if (preq->ReceiptsFrom.cNames != 0)
  4976. {
  4977. BOOL fFoundMe = FALSE;
  4978. CERT_ALT_NAME_INFO * pname2 = NULL;
  4979. if (!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_ALTERNATE_NAME,
  4980. pbFromNames,
  4981. cbFromNames,
  4982. CRYPT_ENCODE_ALLOC_FLAG,
  4983. &CryptDecodeAlloc, &pname2, &cb))
  4984. goto GeneralFail;
  4985. for (i=0; !fFoundMe && (i<preq->ReceiptsFrom.cNames); i++)
  4986. {
  4987. CERT_ALT_NAME_INFO * pname = NULL;
  4988. if (!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_ALTERNATE_NAME,
  4989. preq->ReceiptsFrom.rgNames[i].pbData,
  4990. preq->ReceiptsFrom.rgNames[i].cbData,
  4991. CRYPT_ENCODE_ALLOC_FLAG,
  4992. &CryptDecodeAlloc, &pname, &cb))
  4993. goto GeneralFail;
  4994. for (i1=0; i1<pname->cAltEntry; i1++)
  4995. {
  4996. for (i2=0; i2<pname2->cAltEntry; i2++)
  4997. {
  4998. if (pname->rgAltEntry[i1].dwAltNameChoice !=
  4999. pname2->rgAltEntry[i2].dwAltNameChoice)
  5000. continue;
  5001. switch (pname->rgAltEntry[i1].dwAltNameChoice)
  5002. {
  5003. case CERT_ALT_NAME_RFC822_NAME:
  5004. if (lstrcmpiW(pname->rgAltEntry[i1].pwszRfc822Name,
  5005. pname2->rgAltEntry[i2].pwszRfc822Name) == 0)
  5006. {
  5007. fFoundMe = TRUE;
  5008. goto FoundMe;
  5009. }
  5010. }
  5011. }
  5012. }
  5013. FoundMe:
  5014. SafeMemFree(pname);
  5015. }
  5016. SafeMemFree(pname2);
  5017. if (!fFoundMe)
  5018. {
  5019. hr = S_FALSE;
  5020. goto exit;
  5021. }
  5022. }
  5023. // Create a stream object to hold the receipt and put the receipt into the
  5024. // stream -- this supplies the body of the receipt message.
  5025. CHECKHR(hr = MimeOleCreateVirtualStream(&pstm));
  5026. CHECKHR(hr = pstm->Write(pbReceipt, cbReceipt, NULL));
  5027. CHECKHR(hr = MimeOleCreateMessage(NULL, &pmm));
  5028. CHECKHR(hr = pmm->BindToObject(HBODY_ROOT, IID_IMimeBody, (LPVOID *) &pmb));
  5029. CHECKHR(hr = pmb->QueryInterface(IID_IMimeSecurity2, (LPVOID *) &pms));
  5030. CHECKHR(hr = pmb->SetData(IET_BINARY, "OID", szOID_SMIME_ContentType_Receipt,
  5031. IID_IStream, pstm));
  5032. //
  5033. // Address the receipt back to the receipients
  5034. //
  5035. CHECKHR(hr = pmm->GetAddressTable(&pmatbl));
  5036. for (i=0; i<receiptsTo.cNames; i++)
  5037. {
  5038. CERT_ALT_NAME_INFO * pname = NULL;
  5039. if (!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_ALTERNATE_NAME,
  5040. receiptsTo.rgNames[i].pbData,
  5041. receiptsTo.rgNames[i].cbData,
  5042. CRYPT_ENCODE_ALLOC_FLAG,
  5043. &CryptDecodeAlloc, &pname, &cb))
  5044. goto GeneralFail;
  5045. for (i1=0; i1<pname->cAltEntry; i1++)
  5046. {
  5047. int cch;
  5048. TCHAR rgch[256];
  5049. if (pname->rgAltEntry[i1].dwAltNameChoice == CERT_ALT_NAME_RFC822_NAME)
  5050. {
  5051. cch = WideCharToMultiByte(CP_ACP, 0,
  5052. pname->rgAltEntry[i1].pwszRfc822Name,
  5053. -1, rgch, sizeof(rgch), NULL, NULL);
  5054. if (cch > 0)
  5055. {
  5056. CHECKHR(hr = pmatbl->AppendRfc822(IAT_TO, IET_DECODED,
  5057. rgch));
  5058. fAddedAddress = TRUE;
  5059. }
  5060. break;
  5061. }
  5062. }
  5063. SafeMemFree(pname);
  5064. }
  5065. if (!fAddedAddress)
  5066. {
  5067. hr = S_FALSE;
  5068. goto exit;
  5069. }
  5070. var.vt = VT_UI4;
  5071. var.ulVal = MST_CLASS_SMIME_V1 | MST_THIS_BLOBSIGN;
  5072. CHECKHR(hr = pmb->SetOption(OID_SECURITY_TYPE, &var));
  5073. #ifndef _WIN64
  5074. var.vt = (VT_VECTOR | VT_UI4);
  5075. var.caul.cElems = cSignerCertificates;
  5076. var.caul.pElems = (DWORD *) rgSignerCertificates;
  5077. CHECKHR(hr = pmb->SetOption(OID_SECURITY_CERT_SIGNING_RG, &var));
  5078. #else
  5079. var.vt = (VT_VECTOR | VT_UI8);
  5080. var.cauh.cElems = cSignerCertificates;
  5081. var.cauh.pElems = (ULARGE_INTEGER *) rgSignerCertificates;
  5082. CHECKHR(hr = pmb->SetOption(OID_SECURITY_CERT_SIGNING_RG_64, &var));
  5083. #endif
  5084. //
  5085. // Setup the authorized attribute block so that
  5086. // we can get the correct information transfered. At present we
  5087. // are only looking at one item to be included here.
  5088. // 1. The Message Hash of the message requesting the receipt
  5089. valMsgHash.cbData = cbMsgHash;
  5090. valMsgHash.pbData = pbMsgHash;
  5091. if (!CryptEncodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING,
  5092. &valMsgHash, CRYPT_ENCODE_ALLOC_FLAG,
  5093. &CryptEncodeAlloc, &pbEncodedMsgHash, &cbEncodedMsgHash))
  5094. goto GeneralFail;
  5095. attrMsgHash.pszObjId = szOID_SMIME_Msg_Sig_Digest;
  5096. attrMsgHash.cValue = 1;
  5097. attrMsgHash.rgValue = &valMsgHash;
  5098. valMsgHash.cbData = cbEncodedMsgHash;
  5099. valMsgHash.pbData = pbEncodedMsgHash;
  5100. CHECKHR(hr = pms->SetAttribute(0, -1, SMIME_ATTRIBUTE_SET_SIGNED, &attrMsgHash));
  5101. hr = S_OK;
  5102. *ppMimeMessageReceipt = pmm;
  5103. pmm->AddRef();
  5104. exit:
  5105. SafeMemFree(preq);
  5106. SafeMemFree(receiptsTo.rgNames);
  5107. SafeMemFree(pbEncodedMsgHash);
  5108. SafeMemFree(pbMsgHash);
  5109. SafeMemFree(pbReceipt);
  5110. if (pstm != NULL) pstm->Release();
  5111. if (pmatbl != NULL) pmatbl->Release();
  5112. if (pmb != NULL) pmb->Release();
  5113. if (pms != NULL) pms->Release();
  5114. if (pmm != NULL) pmm->Release();
  5115. return hr;
  5116. GeneralFail:
  5117. hr = E_FAIL;
  5118. goto exit;
  5119. }
  5120. //--------------------------------------------------------------------------------
  5121. // CMessageBody::GetReceiptSendersList
  5122. //--------------------------------------------------------------------------------
  5123. HRESULT CMessageBody::GetReceiptSendersList(DWORD dwFlags, DWORD *pcSendersList,
  5124. CERT_NAME_BLOB * *rgSendersList)
  5125. {
  5126. DWORD cb;
  5127. HRESULT hr;
  5128. DWORD i;
  5129. LPBYTE pb;
  5130. PSMIME_RECEIPT_REQUEST preq = NULL;
  5131. hr = _GetReceiptRequest(dwFlags,
  5132. &preq,
  5133. NULL, NULL, NULL, NULL, NULL);
  5134. if (hr)
  5135. goto exit;
  5136. if (preq->ReceiptsFrom.cNames == 0)
  5137. {
  5138. *rgSendersList = NULL;
  5139. *pcSendersList = preq->ReceiptsFrom.cNames;
  5140. goto exit;
  5141. }
  5142. cb = 0;
  5143. for (i =0; i < preq->ReceiptsFrom.cNames; i++)
  5144. #ifdef _WIN64
  5145. cb += sizeof(CERT_NAME_BLOB) + LcbAlignLcb(preq->ReceiptsFrom.rgNames[i].cbData);
  5146. #else
  5147. cb += sizeof(CERT_NAME_BLOB) + preq->ReceiptsFrom.rgNames[i].cbData;
  5148. #endif // _WIN64
  5149. CHECKHR(hr = HrAlloc((LPVOID *)rgSendersList, cb));
  5150. *pcSendersList = preq->ReceiptsFrom.cNames;
  5151. pb = (LPBYTE)*rgSendersList + (sizeof(CERT_NAME_BLOB) * (*pcSendersList));
  5152. for (i =0; i < preq->ReceiptsFrom.cNames; i++)
  5153. {
  5154. (*rgSendersList)[i].cbData = preq->ReceiptsFrom.rgNames[i].cbData;
  5155. (*rgSendersList)[i].pbData = pb;
  5156. memcpy(pb, preq->ReceiptsFrom.rgNames[i].pbData, preq->ReceiptsFrom.rgNames[i].cbData);
  5157. #ifdef _WIN64
  5158. pb += LcbAlignLcb((*rgSendersList)[i].cbData);
  5159. #else
  5160. pb += (*rgSendersList)[i].cbData;
  5161. #endif // _WIN64
  5162. }
  5163. exit:
  5164. SafeMemFree(preq);
  5165. return hr;
  5166. }
  5167. // --------------------------------------------------------------------------------
  5168. // CMessageBody::VerifyReceipt
  5169. //
  5170. // Assumes the passed in pMimeMessageReceipt has been decoded and
  5171. // it's signature verified.
  5172. //
  5173. // This function verifies that the values in the Receipt content are
  5174. // identical to those i the original sigendData signerInfo that
  5175. // requested the receipt and that the message hash of the original message
  5176. // is identical to the msgSigDigest sigend Attribute of the receipt
  5177. //
  5178. // --------------------------------------------------------------------------------
  5179. HRESULT CMessageBody::VerifyReceipt(DWORD dwFlags,
  5180. IMimeMessage * pMimeMessageReceipt)
  5181. {
  5182. PCRYPT_ATTRIBUTE pattrMsgHash = NULL;
  5183. PCRYPT_ATTRIBUTE pattrMsgHash2 = NULL;
  5184. DWORD cb;
  5185. DWORD cbMsgHash = 0;
  5186. DWORD cbData;
  5187. HRESULT hr;
  5188. DWORD iReceiptSigner;
  5189. DWORD iSigner;
  5190. LPBYTE pb;
  5191. LPBYTE pbData = NULL;
  5192. PCRYPT_ATTR_BLOB pblobMsgHash = NULL;
  5193. IMimeBody * pmb = NULL;
  5194. IMimeSecurity2 * pms = NULL;
  5195. PSMIME_RECEIPT_REQUEST preq = NULL;
  5196. PSMIME_RECEIPT pSecReceipt = NULL;
  5197. LPSTREAM pstm = NULL;
  5198. STATSTG statstg;
  5199. PROPVARIANT var;
  5200. // If this is not the bottom layer then ask child to verify receipt
  5201. if (IsContentType(STR_CNT_MULTIPART, "y-security") == S_OK)
  5202. {
  5203. Assert(m_pNode->cChildren == 1);
  5204. hr = m_pNode->pChildHead->pBody->VerifyReceipt(
  5205. dwFlags,
  5206. pMimeMessageReceipt);
  5207. goto exit;
  5208. }
  5209. CHECKHR(hr = pMimeMessageReceipt->BindToObject(HBODY_ROOT, IID_IMimeBody,
  5210. (LPVOID *) &pmb));
  5211. CHECKHR(hr = pmb->QueryInterface(IID_IMimeSecurity2, (LPVOID *) &pms));
  5212. CHECKHR(hr = pmb->GetData(IET_BINARY, &pstm));
  5213. CHECKHR(hr = pstm->Stat(&statstg,STATFLAG_NONAME));
  5214. Assert(statstg.cbSize.HighPart == 0);
  5215. CHECKHR(hr = HrAlloc((LPVOID *)&pbData, statstg.cbSize.LowPart));
  5216. CHECKHR(hr = pstm->Read(pbData, statstg.cbSize.LowPart, &cbData));
  5217. // Check if receipt is the receipt we expect
  5218. for (iSigner=0; iSigner<m_rOptions.cSigners; iSigner++)
  5219. {
  5220. if ((m_rOptions.rgblobReceipt[iSigner].cbSize == cbData) &&
  5221. !memcmp(m_rOptions.rgblobReceipt[iSigner].pBlobData,pbData,cbData))
  5222. break;
  5223. }
  5224. // check if we found a matching receipt
  5225. if (iSigner == m_rOptions.cSigners)
  5226. {
  5227. hr = MIME_E_SECURITY_RECEIPT_NOMATCHINGRECEIPTBODY;
  5228. goto exit;
  5229. }
  5230. if (!CryptDecodeObjectEx(X509_ASN_ENCODING, szOID_SMIME_ContentType_Receipt,
  5231. pbData,
  5232. cbData,
  5233. CRYPT_ENCODE_ALLOC_FLAG, &CryptDecodeAlloc,
  5234. &pSecReceipt, &cb))
  5235. goto GeneralFail;
  5236. //
  5237. // Get the first signatures MsgSigDigest
  5238. //
  5239. CHECKHR(hr = pms->GetAttribute(0, 0, SMIME_ATTRIBUTE_SET_SIGNED,
  5240. 0, szOID_SMIME_Msg_Sig_Digest,
  5241. &pattrMsgHash));
  5242. if ((hr == S_FALSE) ||
  5243. (!CryptDecodeObjectEx(X509_ASN_ENCODING,
  5244. X509_OCTET_STRING,
  5245. pattrMsgHash->rgValue[0].pbData,
  5246. pattrMsgHash->rgValue[0].cbData,
  5247. CRYPT_DECODE_ALLOC_FLAG,
  5248. &CryptDecodeAlloc, &pblobMsgHash, &cbMsgHash)))
  5249. {
  5250. hr = MIME_E_SECURITY_RECEIPT_MSGHASHMISMATCH;
  5251. goto exit;
  5252. }
  5253. if ((m_rOptions.rgblobMsgHash[iSigner].cbSize != pblobMsgHash->cbData) ||
  5254. memcmp(m_rOptions.rgblobMsgHash[iSigner].pBlobData,
  5255. pblobMsgHash->pbData, pblobMsgHash->cbData))
  5256. {
  5257. hr = MIME_E_SECURITY_RECEIPT_MSGHASHMISMATCH;
  5258. goto exit;
  5259. }
  5260. CHECKHR(hr = pmb->GetOption(OID_SECURITY_SIGNATURE_COUNT, &var));
  5261. for (iReceiptSigner = 1; iReceiptSigner < var.ulVal; iReceiptSigner++)
  5262. {
  5263. CHECKHR(hr = pms->GetAttribute(0, iReceiptSigner, SMIME_ATTRIBUTE_SET_SIGNED,
  5264. 0, szOID_SMIME_Msg_Sig_Digest,
  5265. &pattrMsgHash2));
  5266. if ((hr == S_FALSE) ||
  5267. (pattrMsgHash->rgValue[0].cbData != pattrMsgHash2->rgValue[0].cbData) ||
  5268. memcmp(pattrMsgHash->rgValue[0].pbData,
  5269. pattrMsgHash2->rgValue[0].pbData,
  5270. pattrMsgHash->rgValue[0].cbData))
  5271. {
  5272. hr = MIME_E_SECURITY_RECEIPT_MSGHASHMISMATCH;
  5273. goto exit;
  5274. }
  5275. SafeMemFree(pattrMsgHash2);
  5276. }
  5277. exit:
  5278. SafeMemFree(pblobMsgHash);
  5279. SafeMemFree(pbData);
  5280. SafeMemFree(pSecReceipt);
  5281. SafeMemFree(pattrMsgHash);
  5282. SafeMemFree(pattrMsgHash2);
  5283. if (pstm != NULL) pstm->Release();
  5284. if (pmb != NULL) pmb->Release();
  5285. if (pms != NULL) pms->Release();
  5286. return hr;
  5287. GeneralFail:
  5288. hr = E_FAIL;
  5289. goto exit;
  5290. }
  5291. // --------------------------------------------------------------------------------
  5292. // CMessageBody::CapabilitiesSupported
  5293. // --------------------------------------------------------------------------------
  5294. HRESULT CMessageBody::CapabilitiesSupported(DWORD * pdwFlags)
  5295. {
  5296. // Assume no capabilities
  5297. *pdwFlags = 0;
  5298. // If we have msasn1.dll on the system, then we can support labels
  5299. if (FIsMsasn1Loaded()) *pdwFlags |= SMIME_SUPPORT_LABELS;
  5300. // If we have a correct crypt32, then we can support receipts & key agreement
  5301. DemandLoadCrypt32();
  5302. if (g_FSupportV3 && FIsMsasn1Loaded())
  5303. *pdwFlags |= SMIME_SUPPORT_RECEIPTS;
  5304. if (g_FSupportV3)
  5305. *pdwFlags |= SMIME_SUPPORT_KEY_AGREE;
  5306. // If we have a correct advapi32, then we can support maillist keys
  5307. DemandLoadAdvApi32();
  5308. if (VAR_CryptContextAddRef != MY_CryptContextAddRef)
  5309. *pdwFlags |= SMIME_SUPPORT_MAILLIST;
  5310. return S_OK;
  5311. }
  5312. // --------------------------------------------------------------------------------
  5313. // CMessage::_HrGetAttrs
  5314. //
  5315. // Utility function to retrieve attributes
  5316. // --------------------------------------------------------------------------------
  5317. HRESULT CMessageBody::_HrGetAttrs(DWORD cSigners, PCRYPT_ATTRIBUTES * rgpattrs,
  5318. LPCSTR pszObjId, PROPVARIANT FAR * pvOut)
  5319. {
  5320. // Locals
  5321. CRYPT_ATTRIBUTES attrs;
  5322. HRESULT hr = S_OK;
  5323. DWORD i;
  5324. DWORD i1;
  5325. CRYPT_ATTRIBUTES UNALIGNED *pattrs;
  5326. CAPROPVARIANT UNALIGNED *pcapropvar;
  5327. PROPVARIANT *ppv = NULL;
  5328. pvOut->vt = VT_VECTOR | VT_VARIANT;
  5329. pcapropvar = &pvOut->capropvar;
  5330. pcapropvar->cElems = cSigners;
  5331. if (cSigners > 0)
  5332. {
  5333. Assert(rgpattrs && pvOut);
  5334. // Allocate the array of VT_BLOB propvariants
  5335. if (FAILED(hr = HrAlloc((LPVOID *)&ppv, cSigners * sizeof(PROPVARIANT))))
  5336. {
  5337. goto exit;
  5338. }
  5339. memset(ppv, 0, cSigners * sizeof(PROPVARIANT));
  5340. pcapropvar->pElems = ppv;
  5341. // Fill in the array of BLOBs
  5342. for (i = 0; i < cSigners; i++)
  5343. {
  5344. ppv[i].vt = VT_BLOB;
  5345. // HrCopyBlob allocates memory for the blob data.
  5346. if (rgpattrs[i] == NULL)
  5347. continue;
  5348. if (pszObjId == NULL)
  5349. {
  5350. pattrs = rgpattrs[i];
  5351. }
  5352. else
  5353. {
  5354. pattrs = NULL;
  5355. for (i1=0; i1<rgpattrs[i]->cAttr; i1++)
  5356. {
  5357. if (lstrcmp(rgpattrs[i]->rgAttr[i1].pszObjId, pszObjId) == NULL)
  5358. {
  5359. pattrs = &attrs;
  5360. attrs.cAttr = 1;
  5361. attrs.rgAttr = &rgpattrs[i]->rgAttr[i1];
  5362. break;
  5363. }
  5364. }
  5365. if (pattrs == NULL)
  5366. continue;
  5367. }
  5368. if (!CryptEncodeObjectEx(X509_ASN_ENCODING,
  5369. szOID_Microsoft_Attribute_Sequence,
  5370. pattrs, CRYPT_ENCODE_ALLOC_FLAG,
  5371. &CryptEncodeAlloc, &ppv[i].blob.pBlobData,
  5372. &ppv[i].blob.cbSize))
  5373. {
  5374. hr = HrGetLastError();
  5375. goto exit;
  5376. }
  5377. }
  5378. } else {
  5379. pcapropvar->pElems = NULL;
  5380. }
  5381. hr = S_OK;
  5382. exit:
  5383. if (FAILED(hr) && (ppv != NULL))
  5384. {
  5385. for (i=0; i<cSigners; i++)
  5386. {
  5387. MemFree(&ppv[i].blob.pBlobData);
  5388. }
  5389. MemFree(ppv);
  5390. }
  5391. return(hr);
  5392. }
  5393. // --------------------------------------------------------------------------------
  5394. // CMessageBody::_FindAttribute
  5395. //
  5396. // Utility function designed to find attributes in an attribute set
  5397. // --------------------------------------------------------------------------------
  5398. PCRYPT_ATTRIBUTE CMessageBody::_FindAttribute(PCRYPT_ATTRIBUTES pattrs,
  5399. LPCSTR pszObjId, DWORD iInstance)
  5400. {
  5401. DWORD i;
  5402. if (pattrs == NULL)
  5403. return NULL;
  5404. for (i=0; i<pattrs->cAttr; i++)
  5405. {
  5406. if (lstrcmp(pattrs->rgAttr[i].pszObjId, pszObjId) == 0)
  5407. {
  5408. if (iInstance == 0)
  5409. {
  5410. return &pattrs->rgAttr[i];
  5411. }
  5412. else
  5413. {
  5414. iInstance -= 1;
  5415. }
  5416. }
  5417. }
  5418. return NULL;
  5419. }
  5420. // --------------------------------------------------------------------------------
  5421. // CMessageBody::_HrSetAttribute
  5422. //
  5423. // Utility function designed to set attributes. Called from set property as well
  5424. // as public interface set attribute function
  5425. // --------------------------------------------------------------------------------
  5426. HRESULT CMessageBody::_HrSetAttribute(DWORD dwFlags, PCRYPT_ATTRIBUTES * ppattrs,
  5427. LPCSTR pszObjId, DWORD cbNew, const BYTE * pbNew)
  5428. {
  5429. DWORD cAttr =0;
  5430. DWORD cb;
  5431. HRESULT hr;
  5432. DWORD i;
  5433. PCRYPT_ATTRIBUTES pattrs = *ppattrs;
  5434. PCRYPT_ATTRIBUTES pattrs2 = NULL;
  5435. LPBYTE pb;
  5436. CRYPT_ATTR_BLOB UNALIGNED *pVal = NULL;
  5437. //
  5438. // We have a special case of pszObjId == NULL, in this case the entire
  5439. // encoded item is passed in
  5440. //
  5441. if (pszObjId == NULL)
  5442. {
  5443. hr = HrDecodeObject(pbNew, cbNew, szOID_Microsoft_Attribute_Sequence, 0,
  5444. &cb, (LPVOID *) &pattrs2);
  5445. if (SUCCEEDED(hr))
  5446. {
  5447. #ifdef _WIN64
  5448. *ppattrs = (PCRYPT_ATTRIBUTES) MyPbAlignPb(*ppattrs);
  5449. #endif //_WIN64
  5450. MemFree(*ppattrs);
  5451. *ppattrs = NULL;
  5452. *ppattrs = pattrs2;
  5453. pattrs2 = NULL;
  5454. }
  5455. goto exit;
  5456. }
  5457. //
  5458. // Compute size of buffer we are going to need to hold the result
  5459. //
  5460. if (pattrs == NULL)
  5461. {
  5462. cb = sizeof(CRYPT_ATTRIBUTES);
  5463. }
  5464. else
  5465. {
  5466. cb = sizeof(CRYPT_ATTRIBUTES);
  5467. for (i=0; i<pattrs->cAttr; i++)
  5468. {
  5469. Assert(pattrs->rgAttr[i].cValue == 1);
  5470. //
  5471. // If we are going to replace something, then set it's oid to NULL
  5472. //
  5473. if ((lstrcmp(pattrs->rgAttr[i].pszObjId, pszObjId) == 0) &&
  5474. !(dwFlags & SMIME_ATTR_ADD_TO_EXISTING))
  5475. {
  5476. if (dwFlags & SMIME_ATTR_ADD_IF_NOT_EXISTS)
  5477. {
  5478. return S_OK;
  5479. }
  5480. pattrs->rgAttr[i].pszObjId = NULL;
  5481. continue;
  5482. }
  5483. pVal = &(pattrs->rgAttr[i].rgValue[0]);
  5484. cb += ((DWORD) (sizeof(CRYPT_ATTRIBUTE) + sizeof(CRYPT_ATTR_BLOB) +
  5485. strlen(pattrs->rgAttr[i].pszObjId) + 1 +
  5486. pVal->cbData));
  5487. #ifdef _WIN64
  5488. cb = LcbAlignLcb(cb);
  5489. #endif // _WIN64
  5490. cAttr += 1;
  5491. }
  5492. }
  5493. //
  5494. // Add room for the one we are about to include
  5495. //
  5496. #ifdef _WIN64
  5497. cb = LcbAlignLcb(cb);
  5498. #endif // _WIN64
  5499. cb += (DWORD)(sizeof(CRYPT_ATTRIBUTE) + sizeof(CRYPT_ATTR_BLOB) +
  5500. #ifdef _WIN64
  5501. LcbAlignLcb(strlen(pszObjId) + 1) + cbNew);
  5502. #else
  5503. strlen(pszObjId) + 1 + cbNew);
  5504. #endif // _WIN64
  5505. cAttr += 1;
  5506. //
  5507. // Allocate Memory to hold the result
  5508. //
  5509. pattrs2 = (PCRYPT_ATTRIBUTES) g_pMalloc->Alloc(cb);
  5510. if (pattrs2 == NULL)
  5511. {
  5512. hr = E_OUTOFMEMORY;
  5513. goto exit;
  5514. }
  5515. //
  5516. // Now copy over the items appending our item at the end
  5517. //
  5518. pattrs2->rgAttr = (PCRYPT_ATTRIBUTE) &pattrs2[1];
  5519. pb = (LPBYTE) &pattrs2->rgAttr[cAttr];
  5520. cAttr = 0;
  5521. if (pattrs != NULL)
  5522. {
  5523. for (i=0; i<pattrs->cAttr; i++)
  5524. {
  5525. if (pattrs->rgAttr[i].pszObjId == NULL) continue;
  5526. pattrs2->rgAttr[cAttr].pszObjId = (LPSTR) pb;
  5527. #ifdef _WIN64
  5528. cb = LcbAlignLcb(strlen(pattrs->rgAttr[i].pszObjId) + 1);
  5529. #else
  5530. cb = strlen(pattrs->rgAttr[i].pszObjId) + 1;
  5531. #endif // _WIN64
  5532. memcpy(pb, pattrs->rgAttr[i].pszObjId, cb);
  5533. pb += cb;
  5534. pattrs2->rgAttr[cAttr].cValue = 1;
  5535. pattrs2->rgAttr[cAttr].rgValue = (PCRYPT_ATTR_BLOB) pb;
  5536. #ifdef _WIN64
  5537. pb += LcbAlignLcb(sizeof(CRYPT_ATTR_BLOB));
  5538. #else
  5539. pb += sizeof(CRYPT_ATTR_BLOB);
  5540. #endif
  5541. pVal = &(pattrs->rgAttr[i].rgValue[0]);
  5542. cb = ((DWORD) (pVal->cbData));
  5543. #ifdef _WIN64
  5544. // cb = LcbAlignLcb(cb);
  5545. #endif // _WIN64
  5546. pVal = &(pattrs2->rgAttr[cAttr].rgValue[0]);
  5547. pVal->pbData = pb;
  5548. pVal->cbData = cb;
  5549. pVal = &(pattrs->rgAttr[i].rgValue[0]);
  5550. memcpy(pb, pVal->pbData, cb);
  5551. #ifdef _WIN64
  5552. pb += LcbAlignLcb(cb);
  5553. #else
  5554. pb += cb;
  5555. #endif
  5556. cAttr += 1;
  5557. }
  5558. }
  5559. //
  5560. // Append the new one
  5561. //
  5562. #ifdef _WIN64
  5563. cb = LcbAlignLcb(strlen(pszObjId) + 1);
  5564. #else
  5565. cb = strlen(pszObjId) + 1;
  5566. #endif // _WIN64
  5567. pattrs2->rgAttr[cAttr].pszObjId = (LPSTR) pb;
  5568. memcpy(pb, pszObjId, cb);
  5569. pb += cb;
  5570. pattrs2->rgAttr[cAttr].cValue = (DWORD) 1;
  5571. pattrs2->rgAttr[cAttr].rgValue = (PCRYPT_ATTR_BLOB) pb;
  5572. #ifdef _WIN64
  5573. pb += LcbAlignLcb(sizeof(CRYPT_ATTR_BLOB));
  5574. #else
  5575. pb += sizeof(CRYPT_ATTR_BLOB);
  5576. #endif
  5577. pVal = &(pattrs2->rgAttr[cAttr].rgValue[0]);
  5578. pVal->cbData = (DWORD) cbNew;
  5579. pVal->pbData = pb;
  5580. memcpy(pb, pbNew, cbNew);
  5581. #ifdef _WIN64
  5582. pb += LcbAlignLcb(cbNew);
  5583. #else
  5584. pb += cbNew;
  5585. #endif
  5586. pattrs2->cAttr = cAttr + 1;
  5587. MemFree(*ppattrs);
  5588. *ppattrs = NULL;
  5589. *ppattrs = pattrs2;
  5590. pattrs2 = NULL;
  5591. hr = S_OK;
  5592. exit:
  5593. if (pattrs2 != NULL) MemFree(pattrs2);
  5594. return hr;
  5595. }
  5596. #endif // SMIME_V3