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.

1655 lines
49 KiB

  1. // --------------------------------------------------------------------------------
  2. // VariantX.cpp
  3. // Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  4. // --------------------------------------------------------------------------------
  5. #include "pch.hxx"
  6. #include "variantx.h"
  7. #include "wchar.h"
  8. #include "internat.h"
  9. #include "symcache.h"
  10. #include "dllmain.h"
  11. #include "containx.h"
  12. #include <shlwapi.h>
  13. #include "mimeapi.h"
  14. #include "strconst.h"
  15. #include "demand.h"
  16. // --------------------------------------------------------------------------------
  17. // Helper Prototypes
  18. // --------------------------------------------------------------------------------
  19. HRESULT HrWriteHeaderFormatA(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
  20. HRESULT HrWriteHeaderFormatW(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
  21. HRESULT HrWriteNameInDataA(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
  22. HRESULT HrWriteNameInDataW(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
  23. // --------------------------------------------------------------------------------
  24. // International Conversion Prototypes
  25. // --------------------------------------------------------------------------------
  26. HRESULT Internat_StringA_To_StringA(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT, LPSTR *);
  27. HRESULT Internat_StringA_To_StringW(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT, LPWSTR *);
  28. HRESULT Internat_StringW_To_StringW(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT, LPWSTR *);
  29. HRESULT Internat_StringW_To_StringA(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT, LPSTR *);
  30. // --------------------------------------------------------------------------------
  31. // Variant Conversion Function Prototype
  32. // --------------------------------------------------------------------------------
  33. typedef HRESULT (APIENTRY *PFNVARIANTCONVERT)(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
  34. // --------------------------------------------------------------------------------
  35. // Converter Prototypes
  36. // --------------------------------------------------------------------------------
  37. HRESULT StringA_To_StringA(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
  38. HRESULT StringA_To_StringW(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
  39. HRESULT StringA_To_Variant(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
  40. HRESULT StringW_To_StringA(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
  41. HRESULT StringW_To_StringW(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
  42. HRESULT StringW_To_Variant(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
  43. HRESULT Variant_To_StringA(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
  44. HRESULT Variant_To_StringW(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
  45. HRESULT Variant_To_Variant(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
  46. // --------------------------------------------------------------------------------
  47. // VCASSERTARGS - Common Invalid Arg Assert Macro
  48. // --------------------------------------------------------------------------------
  49. #define VCASSERTARGS(_typeSource, _typeDest) \
  50. Assert(pConvert && pSource && pDest && pSource->type == _typeSource); \
  51. if (MVT_STRINGA == _typeDest) \
  52. Assert(MVT_STRINGA == pDest->type || MVT_STREAM == pDest->type); \
  53. else if (MVT_STRINGW == _typeDest) \
  54. Assert(MVT_STRINGW == pDest->type || MVT_STREAM == pDest->type); \
  55. else \
  56. Assert(_typeDest == pDest->type);
  57. // --------------------------------------------------------------------------------
  58. // VARIANTCONVERTMAP
  59. // --------------------------------------------------------------------------------
  60. typedef struct tagVARIANTCONVERTMAP {
  61. PFNVARIANTCONVERT pfnConvertTo[MVT_LAST];
  62. } VARIANTCONVERTMAP;
  63. // --------------------------------------------------------------------------------
  64. // PVC - Cast to PFNVARIANTCONVERT
  65. // --------------------------------------------------------------------------------
  66. #define PVC(_function) ((PFNVARIANTCONVERT)_function)
  67. // --------------------------------------------------------------------------------
  68. // Variant Conversion Map
  69. // --------------------------------------------------------------------------------
  70. static const VARIANTCONVERTMAP g_rgVariantX[MVT_LAST - 1] = {
  71. { NULL, NULL, NULL, NULL, NULL }, // MVT_EMPTY
  72. { NULL, PVC(StringA_To_StringA), PVC(StringA_To_StringW), PVC(StringA_To_Variant), PVC(StringA_To_StringA) }, // MVT_STRINGA / MVT_STREAM
  73. { NULL, PVC(StringW_To_StringA), PVC(StringW_To_StringW), PVC(StringW_To_Variant), PVC(StringW_To_StringA) }, // MVT_STRINGW
  74. { NULL, PVC(Variant_To_StringA), PVC(Variant_To_StringW), PVC(Variant_To_Variant), PVC(Variant_To_StringA) }, // MVT_VARIANT
  75. };
  76. // --------------------------------------------------------------------------------
  77. // _HrConvertVariant - Looks up the correct Variant Conversion function
  78. // --------------------------------------------------------------------------------
  79. #define _HrConvertVariant(_typeSource, _typeDest, _pConvert, _pSource, _pDest) \
  80. (*(g_rgVariantX[_typeSource].pfnConvertTo[_typeDest]))(_pConvert, _pSource, _pDest)
  81. // --------------------------------------------------------------------------------
  82. // HrConvertVariant
  83. // --------------------------------------------------------------------------------
  84. HRESULT HrConvertVariant(
  85. /* in */ LPHEADOPTIONS pOptions,
  86. /* in */ LPPROPSYMBOL pSymbol,
  87. /* in */ LPINETCSETINFO pCharset,
  88. /* in */ ENCODINGTYPE ietSource,
  89. /* in */ DWORD dwFlags,
  90. /* in */ DWORD dwState,
  91. /* in */ LPMIMEVARIANT pSource,
  92. /* in,out */ LPMIMEVARIANT pDest,
  93. /* out,opt */ BOOL *pfRfc1522 /* = NULL */)
  94. {
  95. // Locals
  96. HRESULT hr=S_OK;
  97. VARIANTCONVERT rConvert;
  98. // Invalid Arg
  99. Assert(pOptions && pSymbol && pSource && pDest && pOptions->pDefaultCharset);
  100. Assert(IET_ENCODED == ietSource || IET_DECODED == ietSource);
  101. // Init
  102. if (pfRfc1522)
  103. *pfRfc1522 = FALSE;
  104. // Failure
  105. if (!ISVALIDVARTYPE(pSource->type) || !ISVALIDVARTYPE(pDest->type))
  106. {
  107. AssertSz(FALSE, "An invalid VARTYPE was encountered!");
  108. hr = TraceResult(MIME_E_VARTYPE_NO_CONVERT);
  109. goto exit;
  110. }
  111. // Init pDest
  112. pDest->fCopy = FALSE;
  113. // Init rConvert
  114. ZeroMemory(&rConvert, sizeof(VARIANTCONVERT));
  115. rConvert.pOptions = pOptions;
  116. rConvert.pSymbol = pSymbol;
  117. rConvert.pCharset = pCharset ? pCharset : pOptions->pDefaultCharset;
  118. rConvert.ietSource = ietSource;
  119. rConvert.dwFlags = dwFlags;
  120. rConvert.dwState = dwState;
  121. // Remove PRSTATE_RFC1522
  122. FLAGCLEAR(rConvert.dwState, PRSTATE_RFC1522);
  123. // Valid Charset
  124. Assert(g_rgVariantX[pSource->type].pfnConvertTo[pDest->type]);
  125. // Remove Comments and fixup the source...
  126. if (ISFLAGSET(dwFlags, PDF_NOCOMMENTS) && (MVT_STRINGA == pSource->type || MVT_STRINGW == pSource->type))
  127. {
  128. // Locals
  129. MIMEVARIANT rVariant;
  130. BYTE rgbScratch[256];
  131. // Init
  132. ZeroMemory(&rVariant, sizeof(MIMEVARIANT));
  133. // Strip Comments
  134. if (SUCCEEDED(MimeVariantStripComments(pSource, &rVariant, rgbScratch, sizeof(rgbScratch))))
  135. {
  136. // Change the Source
  137. pSource = &rVariant;
  138. // Remove CF_NOALLOC
  139. FLAGCLEAR(dwFlags, CVF_NOALLOC);
  140. }
  141. // Do the Conversion
  142. hr = _HrConvertVariant(pSource->type, pDest->type, &rConvert, pSource, pDest);
  143. // Free the Variant
  144. MimeVariantFree(&rVariant);
  145. // Failure
  146. if (FAILED(hr))
  147. {
  148. TrapError(hr);
  149. goto exit;
  150. }
  151. }
  152. // Otherwise, normal Conversion
  153. else
  154. {
  155. // Do the Conversion
  156. CHECKHR(hr = _HrConvertVariant(pSource->type, pDest->type, &rConvert, pSource, pDest));
  157. }
  158. // 1522 Encoded ?
  159. if (pfRfc1522 && ISFLAGSET(rConvert.dwState, PRSTATE_RFC1522))
  160. *pfRfc1522 = TRUE;
  161. exit:
  162. // Done
  163. return hr;
  164. }
  165. // --------------------------------------------------------------------------------
  166. // StringA_To_StringA
  167. // --------------------------------------------------------------------------------
  168. HRESULT StringA_To_StringA(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
  169. {
  170. // Locals
  171. HRESULT hr=S_OK;
  172. LPSTR pszFree=NULL;
  173. MIMEVARIANT rVariant;
  174. // Invalid Arg
  175. VCASSERTARGS(MVT_STRINGA, MVT_STRINGA);
  176. // Invalid Arg
  177. if (ISVALIDSTRINGA(&pSource->rStringA) == FALSE)
  178. return TrapError(E_INVALIDARG);
  179. // Init pDest
  180. if (MVT_STRINGA == pDest->type)
  181. {
  182. pDest->rStringA.pszVal = NULL;
  183. pDest->rStringA.cchVal = 0;
  184. }
  185. // Setup rVariant
  186. ZeroMemory(&rVariant, sizeof(MIMEVARIANT));
  187. rVariant.type = MVT_STRINGA;
  188. // Is International Property
  189. CHECKHR(hr = Internat_StringA_To_StringA(pConvert, pSource, &rVariant, &pszFree));
  190. // If Transmit, setup wrapinfo
  191. if (ISFLAGSET(pConvert->dwFlags, PDF_HEADERFORMAT))
  192. {
  193. // WriteHeaderFormatA
  194. CHECKHR(hr = HrWriteHeaderFormatA(pConvert, &rVariant, pDest));
  195. }
  196. // Wanted in a stream
  197. else if (MVT_STREAM == pDest->type)
  198. {
  199. // No Stream...
  200. if (NULL == pDest->pStream)
  201. {
  202. hr = TrapError(E_INVALIDARG);
  203. goto exit;
  204. }
  205. // Write to the stream
  206. CHECKHR(hr = pDest->pStream->Write(rVariant.rStringA.pszVal, rVariant.rStringA.cchVal, NULL));
  207. }
  208. // MVT_STRINGA
  209. else if (MVT_STRINGA == pDest->type)
  210. {
  211. // If Writing Transmit (Write Header Name)
  212. if (ISFLAGSET(pConvert->dwFlags, PDF_NAMEINDATA))
  213. {
  214. // Write Name Into Data
  215. CHECKHR(hr = HrWriteNameInDataA(pConvert, &rVariant, pDest));
  216. }
  217. // No Conversion
  218. else if (rVariant.rStringA.pszVal == pSource->rStringA.pszVal)
  219. {
  220. // Copy
  221. CHECKHR(hr = HrMimeVariantCopy(pConvert->dwFlags, &rVariant, pDest));
  222. }
  223. // Is Equal to pszFree
  224. else if (rVariant.rStringA.pszVal == pszFree)
  225. {
  226. // Just Copy It
  227. CopyMemory(pDest, &rVariant, sizeof(MIMEVARIANT));
  228. // Not a copy
  229. pDest->fCopy = FALSE;
  230. // Don't free pszFree
  231. pszFree = NULL;
  232. }
  233. // Big Problem
  234. else
  235. Assert(FALSE);
  236. }
  237. // Big Problem
  238. else
  239. Assert(FALSE);
  240. exit:
  241. // Cleanup
  242. SafeMemFree(pszFree);
  243. // Done
  244. return hr;
  245. }
  246. // --------------------------------------------------------------------------------
  247. // StringA_To_StringW
  248. // --------------------------------------------------------------------------------
  249. HRESULT StringA_To_StringW(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
  250. {
  251. // Locals
  252. HRESULT hr=S_OK;
  253. LPWSTR pszFree=NULL;
  254. MIMEVARIANT rVariant;
  255. // Invalid Arg
  256. VCASSERTARGS(MVT_STRINGA, MVT_STRINGW);
  257. // Invalid Arg
  258. if (ISVALIDSTRINGA(&pSource->rStringA) == FALSE)
  259. return TrapError(E_INVALIDARG);
  260. // Init pDest
  261. if (MVT_STRINGW == pDest->type)
  262. {
  263. pDest->rStringW.pszVal = NULL;
  264. pDest->rStringW.cchVal = 0;
  265. }
  266. // Setup rVariant
  267. ZeroMemory(&rVariant, sizeof(MIMEVARIANT));
  268. rVariant.type = MVT_STRINGW;
  269. // Internat Conversion
  270. CHECKHR(hr = Internat_StringA_To_StringW(pConvert, pSource, &rVariant, &pszFree));
  271. // If Transmit, setup wrapinfo
  272. if (ISFLAGSET(pConvert->dwFlags, PDF_HEADERFORMAT))
  273. {
  274. // WriteHeaderFormatW
  275. CHECKHR(hr = HrWriteHeaderFormatW(pConvert, &rVariant, pDest));
  276. }
  277. // MVT_STREAM
  278. else if (MVT_STREAM == pDest->type)
  279. {
  280. // No Stream...
  281. if (NULL == pDest->pStream)
  282. {
  283. hr = TrapError(E_INVALIDARG);
  284. goto exit;
  285. }
  286. // Write to the stream
  287. CHECKHR(hr = pDest->pStream->Write(rVariant.rStringW.pszVal, rVariant.rStringW.cchVal, NULL));
  288. }
  289. // MVT_STRINGW
  290. else if (MVT_STRINGW == pDest->type)
  291. {
  292. // If Writing Transmit (Write Header Name)
  293. if (ISFLAGSET(pConvert->dwFlags, PDF_NAMEINDATA))
  294. {
  295. CHECKHR(hr = HrWriteNameInDataW(pConvert, &rVariant, pDest));
  296. }
  297. // Equal to Data that we Allocated
  298. else if (rVariant.rStringW.pszVal == pszFree)
  299. {
  300. // Copy Memory
  301. CopyMemory(pDest, &rVariant, sizeof(MIMEVARIANT));
  302. // Not a copy
  303. pDest->fCopy = FALSE;
  304. // Don't Free pszFree
  305. pszFree = NULL;
  306. }
  307. // Big Problem
  308. else
  309. Assert(FALSE);
  310. }
  311. // Big Problem
  312. else
  313. Assert(FALSE);
  314. exit:
  315. // Cleanup
  316. SafeMemFree(pszFree);
  317. // Done
  318. return hr;
  319. }
  320. // --------------------------------------------------------------------------------
  321. // StringA_To_Variant
  322. // --------------------------------------------------------------------------------
  323. HRESULT StringA_To_Variant(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
  324. {
  325. // Locals
  326. HRESULT hr=S_OK;
  327. LPSTR psz;
  328. MIMEVARIANT rVariant;
  329. BYTE rgbScratch[255];
  330. // Invalid Arg
  331. VCASSERTARGS(MVT_STRINGA, MVT_VARIANT);
  332. Assert(!ISFLAGSET(pConvert->dwFlags, PDF_ENCODED) && !ISFLAGSET(pConvert->dwFlags, PDF_HEADERFORMAT));
  333. // Init
  334. ZeroMemory(&rVariant, sizeof(MIMEVARIANT));
  335. // See If Symbol has a custom Translator...
  336. if (ISTRIGGERED(pConvert->pSymbol, IST_STRINGA_TO_VARIANT))
  337. {
  338. // Call the Translator
  339. CHECKHR(hr = CALLTRIGGER(pConvert->pSymbol, NULL, IST_STRINGA_TO_VARIANT, pConvert->dwFlags, pSource, pDest));
  340. }
  341. // Otherwise, use default converter
  342. else
  343. {
  344. // Handle Variant Type
  345. switch(pDest->rVariant.vt)
  346. {
  347. case VT_UI4:
  348. // Strip Comments
  349. if (SUCCEEDED(MimeVariantStripComments(pSource, &rVariant, rgbScratch, sizeof(rgbScratch))))
  350. pSource = &rVariant;
  351. // Convert to ULONG
  352. pDest->rVariant.ulVal = strtoul(pSource->rStringA.pszVal, &psz, 10);
  353. break;
  354. case VT_I4:
  355. // Strip Comments
  356. if (SUCCEEDED(MimeVariantStripComments(pSource, &rVariant, rgbScratch, sizeof(rgbScratch))))
  357. pSource = &rVariant;
  358. // Convert to Long
  359. pDest->rVariant.lVal = strtol(pSource->rStringA.pszVal, &psz, 10);
  360. break;
  361. case VT_FILETIME:
  362. CHECKHR(hr = MimeOleInetDateToFileTime(pSource->rStringA.pszVal, &pDest->rVariant.filetime));
  363. break;
  364. default:
  365. hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
  366. goto exit;
  367. }
  368. }
  369. exit:
  370. // Cleanup
  371. MimeVariantFree(&rVariant);
  372. // Done
  373. return hr;
  374. }
  375. // --------------------------------------------------------------------------------
  376. // StringW_To_StringA
  377. // --------------------------------------------------------------------------------
  378. HRESULT StringW_To_StringA(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
  379. {
  380. // Locals
  381. HRESULT hr=S_OK;
  382. LPSTR pszFree=NULL;
  383. MIMEVARIANT rVariant;
  384. // Invalid Arg
  385. VCASSERTARGS(MVT_STRINGW, MVT_STRINGA);
  386. // Invalid Arg
  387. if (ISVALIDSTRINGW(&pSource->rStringW) == FALSE)
  388. return TrapError(E_INVALIDARG);
  389. // Init pDest
  390. if (MVT_STRINGA == pDest->type)
  391. {
  392. pDest->rStringA.pszVal = NULL;
  393. pDest->rStringA.cchVal = 0;
  394. }
  395. // Setup rVariant
  396. ZeroMemory(&rVariant, sizeof(MIMEVARIANT));
  397. rVariant.type = MVT_STRINGA;
  398. // Internat Conversion
  399. CHECKHR(hr = Internat_StringW_To_StringA(pConvert, pSource, &rVariant, &pszFree));
  400. // If Transmit, setup wrapinfo
  401. if (ISFLAGSET(pConvert->dwFlags, PDF_HEADERFORMAT))
  402. {
  403. // WriteHeaderFormatA
  404. CHECKHR(hr = HrWriteHeaderFormatA(pConvert, &rVariant, pDest));
  405. }
  406. // Wanted in a stream
  407. else if (MVT_STREAM == pDest->type)
  408. {
  409. // No Stream...
  410. if (NULL == pDest->pStream)
  411. {
  412. hr = TrapError(E_INVALIDARG);
  413. goto exit;
  414. }
  415. // Write to the stream
  416. CHECKHR(hr = pDest->pStream->Write(rVariant.rStringA.pszVal, rVariant.rStringA.cchVal, NULL));
  417. }
  418. // MVT_STRINGA
  419. else if (MVT_STRINGA == pDest->type)
  420. {
  421. // If Writing Transmit (Write Header Name)
  422. if (ISFLAGSET(pConvert->dwFlags, PDF_NAMEINDATA))
  423. {
  424. // Write Name Into Data
  425. CHECKHR(hr = HrWriteNameInDataA(pConvert, &rVariant, pDest));
  426. }
  427. // Is Equal to pszFree
  428. else if (rVariant.rStringA.pszVal == pszFree)
  429. {
  430. // Copy Memory
  431. CopyMemory(pDest, &rVariant, sizeof(MIMEVARIANT));
  432. // Not a Copy
  433. pDest->fCopy = FALSE;
  434. // Don't Free pszFree
  435. pszFree = NULL;
  436. }
  437. // Big Problem
  438. else
  439. Assert(FALSE);
  440. }
  441. // Big Problem
  442. else
  443. Assert(FALSE);
  444. exit:
  445. // Cleanup
  446. SafeMemFree(pszFree);
  447. // Done
  448. return hr;
  449. }
  450. // --------------------------------------------------------------------------------
  451. // StringW_To_StringW
  452. // --------------------------------------------------------------------------------
  453. HRESULT StringW_To_StringW(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
  454. {
  455. // Locals
  456. HRESULT hr=S_OK;
  457. MIMEVARIANT rVariant;
  458. LPWSTR pszFree=NULL;
  459. // Invalid Arg
  460. VCASSERTARGS(MVT_STRINGW, MVT_STRINGW);
  461. // Invalid Arg
  462. if (ISVALIDSTRINGW(&pSource->rStringW) == FALSE)
  463. return TrapError(E_INVALIDARG);
  464. // Init pDest
  465. if (MVT_STRINGW == pDest->type)
  466. {
  467. pDest->rStringW.pszVal = NULL;
  468. pDest->rStringW.cchVal = 0;
  469. }
  470. // Setup rVariant
  471. ZeroMemory(&rVariant, sizeof(MIMEVARIANT));
  472. rVariant.type = MVT_STRINGW;
  473. // Internat Conversion
  474. CHECKHR(hr = Internat_StringW_To_StringW(pConvert, pSource, &rVariant, &pszFree));
  475. // If Transmit, setup wrapinfo
  476. if (ISFLAGSET(pConvert->dwFlags, PDF_HEADERFORMAT))
  477. {
  478. // WriteHeaderFormatW
  479. CHECKHR(hr = HrWriteHeaderFormatW(pConvert, &rVariant, pDest));
  480. }
  481. // Wanted in a stream
  482. else if (MVT_STREAM == pDest->type)
  483. {
  484. // No Stream...
  485. if (NULL == pDest->pStream)
  486. {
  487. hr = TrapError(E_INVALIDARG);
  488. goto exit;
  489. }
  490. // Write to the stream
  491. CHECKHR(hr = pDest->pStream->Write(rVariant.rStringW.pszVal, rVariant.rStringW.cchVal, NULL));
  492. }
  493. // MVT_STRINGW
  494. else if (MVT_STRINGW == pDest->type)
  495. {
  496. // If Writing Transmit (Write Header Name)
  497. if (ISFLAGSET(pConvert->dwFlags, PDF_NAMEINDATA))
  498. {
  499. CHECKHR(hr = HrWriteNameInDataW(pConvert, &rVariant, pDest));
  500. }
  501. // No Change
  502. else if (rVariant.rStringW.pszVal == pSource->rStringW.pszVal)
  503. {
  504. // Copy
  505. CHECKHR(hr = HrMimeVariantCopy(pConvert->dwFlags, &rVariant, pDest));
  506. }
  507. // Is Decoded Data
  508. else if (rVariant.rStringW.pszVal == pszFree)
  509. {
  510. // Copy Memory
  511. CopyMemory(pDest, &rVariant, sizeof(MIMEVARIANT));
  512. // Not a Copy
  513. pDest->fCopy = FALSE;
  514. // Don't Free pszFree
  515. pszFree = NULL;
  516. }
  517. // Problem
  518. else
  519. Assert(FALSE);
  520. }
  521. // Problem
  522. else
  523. Assert(FALSE);
  524. exit:
  525. // Cleanup
  526. SafeMemFree(pszFree);
  527. // Done
  528. return hr;
  529. }
  530. // --------------------------------------------------------------------------------
  531. // StringW_To_Variant
  532. // --------------------------------------------------------------------------------
  533. HRESULT StringW_To_Variant(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
  534. {
  535. // Locals
  536. HRESULT hr=S_OK;
  537. LPWSTR pwsz;
  538. LPSTR pszANSI=NULL;
  539. MIMEVARIANT rVariant;
  540. BYTE rgbScratch[255];
  541. // Invalid Arg
  542. VCASSERTARGS(MVT_STRINGW, MVT_VARIANT);
  543. Assert(!ISFLAGSET(pConvert->dwFlags, PDF_ENCODED) && !ISFLAGSET(pConvert->dwFlags, PDF_HEADERFORMAT));
  544. // Init
  545. ZeroMemory(&rVariant, sizeof(MIMEVARIANT));
  546. // See If Symbol has a custom Translator...
  547. if (ISTRIGGERED(pConvert->pSymbol, IST_STRINGW_TO_VARIANT))
  548. {
  549. // Call the Translator
  550. CHECKHR(hr = CALLTRIGGER(pConvert->pSymbol, NULL, IST_STRINGW_TO_VARIANT, pConvert->dwFlags, pSource, pDest));
  551. }
  552. // Otherwise, use default converter
  553. else
  554. {
  555. // Handle Variant Type
  556. switch(pDest->rVariant.vt)
  557. {
  558. case VT_UI4:
  559. // Strip Comments
  560. if (SUCCEEDED(MimeVariantStripComments(pSource, &rVariant, rgbScratch, sizeof(rgbScratch))))
  561. pSource = &rVariant;
  562. // Convert to ulong
  563. pDest->rVariant.ulVal = StrToUintW(pSource->rStringW.pszVal);
  564. break;
  565. case VT_I4:
  566. // Strip Comments
  567. if (SUCCEEDED(MimeVariantStripComments(pSource, &rVariant, rgbScratch, sizeof(rgbScratch))))
  568. pSource = &rVariant;
  569. // Convert to Long
  570. pDest->rVariant.lVal = StrToIntW(pSource->rStringW.pszVal);
  571. break;
  572. case VT_FILETIME:
  573. // Convert Unicode to ANSI
  574. CHECKALLOC(pszANSI = PszToANSI(CP_ACP, pSource->rStringW.pszVal));
  575. // String to FileTime
  576. CHECKHR(hr = MimeOleInetDateToFileTime(pSource->rStringA.pszVal, &pDest->rVariant.filetime));
  577. break;
  578. default:
  579. hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
  580. goto exit;
  581. }
  582. }
  583. exit:
  584. // Cleanup
  585. SafeMemFree(pszANSI);
  586. MimeVariantFree(&rVariant);
  587. // Done
  588. return hr;
  589. }
  590. // --------------------------------------------------------------------------------
  591. // Variant_To_StringA
  592. // --------------------------------------------------------------------------------
  593. HRESULT Variant_To_StringA(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
  594. {
  595. // Locals
  596. HRESULT hr=S_OK;
  597. CHAR sz[255];
  598. MIMEVARIANT rValue;
  599. // Invalid Arg
  600. VCASSERTARGS(MVT_VARIANT, MVT_STRINGA);
  601. // Init pDest
  602. if (MVT_STRINGA == pDest->type)
  603. {
  604. pDest->rStringA.pszVal = NULL;
  605. pDest->rStringA.cchVal = 0;
  606. }
  607. // Setup rVariant
  608. ZeroMemory(&rValue, sizeof(MIMEVARIANT));
  609. rValue.type = MVT_STRINGA;
  610. // See If Symbol has a custom Translator...
  611. if (ISTRIGGERED(pConvert->pSymbol, IST_VARIANT_TO_STRINGA))
  612. {
  613. // Call the Translator
  614. CHECKHR(hr = CALLTRIGGER(pConvert->pSymbol, NULL, IST_VARIANT_TO_STRINGA, pConvert->dwFlags, pSource, &rValue));
  615. }
  616. // Otherwise, default translator
  617. else
  618. {
  619. // Handle Variant Type
  620. switch(pSource->rVariant.vt)
  621. {
  622. case VT_UI4:
  623. rValue.rStringA.pszVal = sz;
  624. rValue.rStringA.cchVal = wnsprintfA(rValue.rStringA.pszVal, ARRAYSIZE(sz), "%d", pSource->rVariant.ulVal);
  625. break;
  626. case VT_I4:
  627. rValue.rStringA.pszVal = sz;
  628. rValue.rStringA.cchVal = wnsprintfA(rValue.rStringA.pszVal, ARRAYSIZE(sz), "%d", pSource->rVariant.lVal);
  629. break;
  630. case VT_FILETIME:
  631. CHECKHR(hr = MimeOleFileTimeToInetDate(&pSource->rVariant.filetime, sz, sizeof(sz)));
  632. rValue.rStringA.pszVal = sz;
  633. rValue.rStringA.cchVal = lstrlen(sz);
  634. break;
  635. default:
  636. hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
  637. goto exit;
  638. }
  639. }
  640. // VX_StringA_To_StringA
  641. CHECKHR(hr = StringA_To_StringA(pConvert, &rValue, pDest));
  642. exit:
  643. // Done
  644. return hr;
  645. }
  646. // --------------------------------------------------------------------------------
  647. // Variant_To_StringW
  648. // --------------------------------------------------------------------------------
  649. HRESULT Variant_To_StringW(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
  650. {
  651. // Locals
  652. HRESULT hr=S_OK;
  653. LPWSTR pwszVal=NULL;
  654. WCHAR wsz[255];
  655. CHAR szData[CCHMAX_INTERNET_DATE];
  656. MIMEVARIANT rValue;
  657. // Invalid Arg
  658. VCASSERTARGS(MVT_VARIANT, MVT_STRINGW);
  659. // Init pDest
  660. if (MVT_STRINGW == pDest->type)
  661. {
  662. pDest->rStringW.pszVal = NULL;
  663. pDest->rStringW.cchVal = 0;
  664. }
  665. // Setup rVariant
  666. ZeroMemory(&rValue, sizeof(MIMEVARIANT));
  667. rValue.type = MVT_STRINGW;
  668. // See If Symbol has a custom Translator...
  669. if (ISTRIGGERED(pConvert->pSymbol, IST_VARIANT_TO_STRINGW))
  670. {
  671. // Call the Translator
  672. CHECKHR(hr = CALLTRIGGER(pConvert->pSymbol, NULL, IST_VARIANT_TO_STRINGW, pConvert->dwFlags, pSource, &rValue));
  673. }
  674. // Otherwise, use default converter
  675. else
  676. {
  677. // Handle Variant Type
  678. switch(pSource->rVariant.vt)
  679. {
  680. case VT_UI4:
  681. rValue.rStringW.pszVal = wsz;
  682. rValue.rStringW.cchVal = wnsprintfW(rValue.rStringW.pszVal, ARRAYSIZE(wsz), L"%d", pSource->rVariant.ulVal);
  683. break;
  684. case VT_I4:
  685. rValue.rStringW.pszVal = wsz;
  686. rValue.rStringW.cchVal = wnsprintfW(rValue.rStringW.pszVal, ARRAYSIZE(wsz), L"%d", pSource->rVariant.lVal);
  687. break;
  688. case VT_FILETIME:
  689. CHECKHR(hr = MimeOleFileTimeToInetDate(&pSource->rVariant.filetime, szData, sizeof(szData)));
  690. CHECKALLOC(pwszVal = PszToUnicode(CP_ACP, szData));
  691. rValue.rStringW.pszVal = pwszVal;
  692. rValue.rStringW.cchVal = lstrlenW(pwszVal);
  693. break;
  694. default:
  695. hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
  696. goto exit;
  697. }
  698. }
  699. // VX_StringA_To_StringA
  700. CHECKHR(hr = StringW_To_StringW(pConvert, &rValue, pDest));
  701. exit:
  702. // Cleanup
  703. SafeMemFree(pwszVal);
  704. // Done
  705. return hr;
  706. }
  707. // --------------------------------------------------------------------------------
  708. // Variant_To_Variant
  709. // --------------------------------------------------------------------------------
  710. HRESULT Variant_To_Variant(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
  711. {
  712. // Locals
  713. HRESULT hr=S_OK;
  714. // Invalid Arg
  715. VCASSERTARGS(MVT_VARIANT, MVT_VARIANT);
  716. // See If Symbol has a custom Translator...
  717. if (ISTRIGGERED(pConvert->pSymbol, IST_VARIANT_TO_VARIANT))
  718. {
  719. // Call the Translator
  720. CHECKHR(hr = CALLTRIGGER(pConvert->pSymbol, NULL, IST_VARIANT_TO_VARIANT, pConvert->dwFlags, pSource, pDest));
  721. }
  722. // Otherwise, use default converter
  723. else
  724. {
  725. // Handle Variant Type
  726. switch(pSource->rVariant.vt)
  727. {
  728. case VT_UI4:
  729. switch(pDest->rVariant.vt)
  730. {
  731. case VT_UI4:
  732. pDest->rVariant.ulVal = pSource->rVariant.ulVal;
  733. break;
  734. case VT_I4:
  735. pDest->rVariant.lVal = (LONG)pSource->rVariant.ulVal;
  736. break;
  737. default:
  738. hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
  739. goto exit;
  740. }
  741. break;
  742. case VT_I4:
  743. switch(pDest->rVariant.vt)
  744. {
  745. case VT_UI4:
  746. pDest->rVariant.ulVal = (ULONG)pSource->rVariant.lVal;
  747. break;
  748. case VT_I4:
  749. pDest->rVariant.lVal = pSource->rVariant.lVal;
  750. break;
  751. default:
  752. hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
  753. goto exit;
  754. }
  755. break;
  756. case VT_FILETIME:
  757. switch(pDest->rVariant.vt)
  758. {
  759. case VT_FILETIME:
  760. CopyMemory(&pDest->rVariant.filetime, &pSource->rVariant.filetime, sizeof(FILETIME));
  761. break;
  762. default:
  763. hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
  764. goto exit;
  765. }
  766. break;
  767. default:
  768. hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
  769. goto exit;
  770. }
  771. }
  772. exit:
  773. // Done
  774. return hr;
  775. }
  776. // --------------------------------------------------------------------------------
  777. // HrMimeVariantCopy
  778. // --------------------------------------------------------------------------------
  779. HRESULT HrMimeVariantCopy(DWORD dwFlags, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
  780. {
  781. // Locals
  782. HRESULT hr=S_OK;
  783. // Invalid Arg
  784. Assert(pSource && pDest);
  785. // CVF_NOALLOC
  786. if (ISFLAGSET(dwFlags, CVF_NOALLOC))
  787. {
  788. // Just Copy It
  789. CopyMemory(pDest, pSource, sizeof(MIMEVARIANT));
  790. // Set fCopy so we don't free it
  791. pDest->fCopy = TRUE;
  792. }
  793. // Allocate Memory
  794. else
  795. {
  796. // Not a Copy
  797. pDest->fCopy = FALSE;
  798. // MVT_STRINGA
  799. if (MVT_STRINGA == pSource->type)
  800. {
  801. // Validate
  802. Assert(ISVALIDSTRINGA(&pSource->rStringA));
  803. // Set Dest Type
  804. pDest->type = MVT_STRINGA;
  805. // Allocate Memory
  806. CHECKALLOC(pDest->rStringA.pszVal = (LPSTR)g_pMalloc->Alloc(pSource->rStringA.cchVal + 1));
  807. // Copy the memory
  808. CopyMemory(pDest->rStringA.pszVal, pSource->rStringA.pszVal, pSource->rStringA.cchVal + 1);
  809. // Return the Size
  810. pDest->rStringA.cchVal = pSource->rStringA.cchVal;
  811. }
  812. // MVT_STRINGW
  813. else if (MVT_STRINGW == pSource->type)
  814. {
  815. // Validate
  816. Assert(ISVALIDSTRINGW(&pSource->rStringW));
  817. // Set Dest Type
  818. pDest->type = MVT_STRINGW;
  819. // Compute CB
  820. ULONG cb = ((pSource->rStringW.cchVal + 1) * sizeof(WCHAR));
  821. // Allocate Memory
  822. CHECKALLOC(pDest->rStringW.pszVal = (LPWSTR)g_pMalloc->Alloc(cb));
  823. // Copy the memory
  824. CopyMemory(pDest->rStringW.pszVal, pSource->rStringW.pszVal, cb);
  825. // Return the Size
  826. pDest->rStringW.cchVal = pSource->rStringW.cchVal;
  827. }
  828. // MVT_VARIANT
  829. else if (MVT_VARIANT == pSource->type)
  830. {
  831. // Set Dest Type
  832. pDest->type = MVT_VARIANT;
  833. // Copy the Variant
  834. CopyMemory(&pDest->rVariant, &pSource->rVariant, sizeof(PROPVARIANT));
  835. }
  836. }
  837. exit:
  838. // Done
  839. return hr;
  840. }
  841. // --------------------------------------------------------------------------------
  842. // HrWriteNameInDataA
  843. // --------------------------------------------------------------------------------
  844. HRESULT HrWriteNameInDataA(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
  845. {
  846. // Locals
  847. HRESULT hr=S_OK;
  848. // Invalid Arg
  849. VCASSERTARGS(MVT_STRINGA, MVT_STRINGA);
  850. // Generic STuff
  851. pDest->fCopy = FALSE;
  852. // pszNamed
  853. DWORD cchSize = (pSource->rStringA.cchVal + 3 + pConvert->pSymbol->cchName);
  854. CHECKALLOC(pDest->rStringA.pszVal = (LPSTR)g_pMalloc->Alloc(cchSize));
  855. // Write the named header
  856. pDest->rStringA.cchVal = wnsprintf(pDest->rStringA.pszVal, cchSize, "%s: %s", pConvert->pSymbol->pszName, pSource->rStringA.pszVal);
  857. exit:
  858. // Done
  859. return hr;
  860. }
  861. // --------------------------------------------------------------------------------
  862. // HrWriteNameInDataW
  863. // --------------------------------------------------------------------------------
  864. HRESULT HrWriteNameInDataW(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
  865. {
  866. // Locals
  867. HRESULT hr=S_OK;
  868. ULONG cb;
  869. LPWSTR pszName=NULL;
  870. // Invalid Arg
  871. VCASSERTARGS(MVT_STRINGW, MVT_STRINGW);
  872. // Generic STuff
  873. pDest->fCopy = FALSE;
  874. // Convert Name to Unicode
  875. CHECKALLOC(pszName = PszToUnicode(CP_ACP, pConvert->pSymbol->pszName));
  876. // Compute CB
  877. cb = ((pSource->rStringW.cchVal + 3 + lstrlenW(pszName)) * sizeof(WCHAR));
  878. // pszNamed
  879. CHECKALLOC(pDest->rStringW.pszVal = (LPWSTR)g_pMalloc->Alloc(cb));
  880. // Write the named header
  881. pDest->rStringW.cchVal = wnsprintfW(pDest->rStringW.pszVal, (cb/sizeof(WCHAR)), L"%s: %s", pszName, pSource->rStringW.pszVal);
  882. exit:
  883. // Cleanup
  884. SafeMemFree(pszName);
  885. // Done
  886. return hr;
  887. }
  888. // --------------------------------------------------------------------------------
  889. // HrWriteHeaderFormatA
  890. // --------------------------------------------------------------------------------
  891. HRESULT HrWriteHeaderFormatA(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
  892. {
  893. // Locals
  894. HRESULT hr=S_OK;
  895. LPSTREAM pStream;
  896. CByteStream cByteStream;
  897. // Invalid Arg
  898. VCASSERTARGS(MVT_STRINGA, MVT_STRINGA);
  899. // Generic Stuff
  900. pDest->fCopy = FALSE;
  901. // I need a stream to write to...
  902. if (MVT_STREAM == pDest->type)
  903. {
  904. // Validate the stream
  905. if (NULL == pDest->pStream)
  906. {
  907. hr = TrapError(E_INVALIDARG);
  908. goto exit;
  909. }
  910. // Save the Stream
  911. pStream = pDest->pStream;
  912. }
  913. // Otherwise, create my own stream
  914. else
  915. pStream = &cByteStream;
  916. // If Writing Transmit (Write Header Name)
  917. if (ISFLAGSET(pConvert->dwFlags, PDF_NAMEINDATA))
  918. {
  919. // Write the header name
  920. CHECKHR(hr = pStream->Write(pConvert->pSymbol->pszName, pConvert->pSymbol->cchName, NULL));
  921. // Write Colon
  922. CHECKHR(hr = pStream->Write(c_szColonSpace, lstrlen(c_szColonSpace), NULL));
  923. }
  924. // If not rfc1522 Encoded
  925. if (FALSE == ISFLAGSET(pConvert->dwState, PRSTATE_RFC1522))
  926. {
  927. // PID_HDR_CNTID
  928. if (PID_HDR_CNTID == pConvert->pSymbol->dwPropId)
  929. {
  930. // If not a < yet...
  931. if ('<' != pSource->rStringA.pszVal[0])
  932. {
  933. // Write it
  934. CHECKHR(hr = pStream->Write(c_szEmailStart, lstrlen(c_szEmailStart), NULL));
  935. }
  936. // Write the data
  937. CHECKHR(hr = pStream->Write(pSource->rStringA.pszVal, pSource->rStringA.cchVal, NULL));
  938. // >
  939. if ('>' != pSource->rStringA.pszVal[pSource->rStringA.cchVal - 1])
  940. {
  941. // Write it
  942. CHECKHR(hr = pStream->Write(c_szEmailEnd, lstrlen(c_szEmailEnd), NULL));
  943. }
  944. // Write CRLF
  945. CHECKHR(hr = pStream->Write(c_szCRLF, lstrlen(c_szCRLF), NULL));
  946. }
  947. // Do a wrap text
  948. else
  949. {
  950. // Wrap pszData to the stream
  951. CHECKHR(hr = MimeOleWrapHeaderText(CP_USASCII, pConvert->pOptions->cbMaxLine, pSource->rStringA.pszVal, pSource->rStringA.cchVal, pStream));
  952. }
  953. }
  954. // Otherwise
  955. else
  956. {
  957. // Write the data
  958. CHECKHR(hr = pStream->Write(pSource->rStringA.pszVal, pSource->rStringA.cchVal, NULL));
  959. // Write CRLF
  960. CHECKHR(hr = pStream->Write(c_szCRLF, lstrlen(c_szCRLF), NULL));
  961. }
  962. // MVT_STRINGA
  963. if (MVT_STRINGA == pDest->type)
  964. {
  965. // pStream better be the byte stream
  966. Assert(pStream == &cByteStream);
  967. // Get string from stream...
  968. CHECKHR(hr = cByteStream.HrAcquireStringA(&pDest->rStringA.cchVal, &pDest->rStringA.pszVal, ACQ_DISPLACE));
  969. }
  970. else
  971. Assert(MVT_STREAM == pDest->type);
  972. exit:
  973. // Done
  974. return hr;
  975. }
  976. // --------------------------------------------------------------------------------
  977. // HrWriteHeaderFormatW
  978. // --------------------------------------------------------------------------------
  979. HRESULT HrWriteHeaderFormatW(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
  980. {
  981. return TrapError(MIME_E_VARTYPE_NO_CONVERT);
  982. }
  983. // --------------------------------------------------------------------------------
  984. // Internat_StringA_To_StringA
  985. // --------------------------------------------------------------------------------
  986. HRESULT Internat_StringA_To_StringA(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource,
  987. LPMIMEVARIANT pDest, LPSTR *ppszFree)
  988. {
  989. // Locals
  990. HRESULT hr=S_OK;
  991. // Invalid Arg
  992. VCASSERTARGS(MVT_STRINGA, MVT_STRINGA);
  993. // Init
  994. pDest->rStringA.pszVal = NULL;
  995. *ppszFree = NULL;
  996. // Internat
  997. if (ISFLAGSET(pConvert->pSymbol->dwFlags, MPF_INETCSET))
  998. {
  999. // Encoded...
  1000. if (ISFLAGSET(pConvert->dwFlags, PDF_ENCODED))
  1001. {
  1002. // Save no encode
  1003. if (!ISFLAGSET(pConvert->dwState, PRSTATE_SAVENOENCODE))
  1004. {
  1005. // Decode the Property
  1006. if (SUCCEEDED(g_pInternat->HrEncodeProperty(pConvert, pSource, pDest)))
  1007. *ppszFree = pDest->rStringA.pszVal;
  1008. }
  1009. }
  1010. // Decoded
  1011. else if (IET_ENCODED == pConvert->ietSource)
  1012. {
  1013. // Decode Property
  1014. if (SUCCEEDED(g_pInternat->HrDecodeProperty(pConvert, pSource, pDest)))
  1015. *ppszFree = pDest->rStringA.pszVal;
  1016. }
  1017. }
  1018. // Default
  1019. if (NULL == pDest->rStringA.pszVal)
  1020. {
  1021. // Check State
  1022. Assert(NULL == *ppszFree);
  1023. // Copy It
  1024. pDest->rStringA.pszVal = pSource->rStringA.pszVal;
  1025. pDest->rStringA.cchVal = pSource->rStringA.cchVal;
  1026. // pDest is a copy
  1027. pDest->fCopy = TRUE;
  1028. }
  1029. // Done
  1030. return hr;
  1031. }
  1032. // --------------------------------------------------------------------------------
  1033. // Internat_StringW_To_StringW
  1034. // --------------------------------------------------------------------------------
  1035. HRESULT Internat_StringW_To_StringW(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource,
  1036. LPMIMEVARIANT pDest, LPWSTR *ppszFree)
  1037. {
  1038. // Locals
  1039. HRESULT hr=S_OK;
  1040. // Invalid Arg
  1041. VCASSERTARGS(MVT_STRINGW, MVT_STRINGW);
  1042. // Init
  1043. pDest->rStringW.pszVal = NULL;
  1044. *ppszFree = NULL;
  1045. // Internat
  1046. if (ISFLAGSET(pConvert->pSymbol->dwFlags, MPF_INETCSET))
  1047. {
  1048. // Encoded...
  1049. if (ISFLAGSET(pConvert->dwFlags, PDF_ENCODED))
  1050. {
  1051. // Save no encode
  1052. if (!ISFLAGSET(pConvert->dwState, PRSTATE_SAVENOENCODE))
  1053. {
  1054. // Decode the Property
  1055. if (SUCCEEDED(g_pInternat->HrEncodeProperty(pConvert, pSource, pDest)))
  1056. *ppszFree = pDest->rStringW.pszVal;
  1057. }
  1058. }
  1059. // Decoded
  1060. else if (IET_ENCODED == pConvert->ietSource)
  1061. {
  1062. // Decode Property
  1063. if (SUCCEEDED(g_pInternat->HrDecodeProperty(pConvert, pSource, pDest)))
  1064. *ppszFree = pDest->rStringW.pszVal;
  1065. }
  1066. }
  1067. // Default
  1068. if (NULL == pDest->rStringW.pszVal)
  1069. {
  1070. // Check State
  1071. Assert(NULL == *ppszFree);
  1072. // Copy It
  1073. pDest->rStringW.pszVal = pSource->rStringW.pszVal;
  1074. pDest->rStringW.cchVal = pSource->rStringW.cchVal;
  1075. // Its a copy
  1076. pDest->fCopy = TRUE;
  1077. }
  1078. // Done
  1079. return hr;
  1080. }
  1081. // --------------------------------------------------------------------------------
  1082. // Internat_StringA_To_StringW
  1083. // --------------------------------------------------------------------------------
  1084. HRESULT Internat_StringA_To_StringW(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource,
  1085. LPMIMEVARIANT pDest, LPWSTR *ppszFree)
  1086. {
  1087. // Locals
  1088. HRESULT hr=S_OK;
  1089. // Invalid Arg
  1090. VCASSERTARGS(MVT_STRINGA, MVT_STRINGW);
  1091. // Init
  1092. pDest->rStringW.pszVal = NULL;
  1093. *ppszFree = NULL;
  1094. // Internat
  1095. if (ISFLAGSET(pConvert->pSymbol->dwFlags, MPF_INETCSET))
  1096. {
  1097. // Encoded...
  1098. if (ISFLAGSET(pConvert->dwFlags, PDF_ENCODED))
  1099. {
  1100. // Save no encode
  1101. if (!ISFLAGSET(pConvert->dwState, PRSTATE_SAVENOENCODE))
  1102. {
  1103. // Decode the Property
  1104. if (SUCCEEDED(g_pInternat->HrEncodeProperty(pConvert, pSource, pDest)))
  1105. *ppszFree = pDest->rStringW.pszVal;
  1106. }
  1107. }
  1108. // Decoded
  1109. else if (IET_ENCODED == pConvert->ietSource)
  1110. {
  1111. // Decode Property
  1112. if (SUCCEEDED(g_pInternat->HrDecodeProperty(pConvert, pSource, pDest)))
  1113. *ppszFree = pDest->rStringW.pszVal;
  1114. }
  1115. }
  1116. // Simple Conversion to Unicode
  1117. if (NULL == pDest->rStringW.pszVal)
  1118. {
  1119. // Check State
  1120. Assert(NULL == *ppszFree);
  1121. // HrMultiByteToWideChar
  1122. CHECKHR(hr = g_pInternat->HrMultiByteToWideChar(pConvert->pCharset->cpiWindows, &pSource->rStringA, &pDest->rStringW));
  1123. // Save Charset/Encoding
  1124. pDest->fCopy = FALSE;
  1125. // Save pwszWide
  1126. *ppszFree = pDest->rStringW.pszVal;
  1127. }
  1128. exit:
  1129. // Done
  1130. return hr;
  1131. }
  1132. // --------------------------------------------------------------------------------
  1133. // Internat_StringW_To_StringA
  1134. // --------------------------------------------------------------------------------
  1135. HRESULT Internat_StringW_To_StringA(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource,
  1136. LPMIMEVARIANT pDest, LPSTR *ppszFree)
  1137. {
  1138. // Locals
  1139. HRESULT hr=S_OK;
  1140. // Invalid Arg
  1141. VCASSERTARGS(MVT_STRINGW, MVT_STRINGA);
  1142. // Init
  1143. pDest->rStringA.pszVal = NULL;
  1144. *ppszFree = NULL;
  1145. // Internat
  1146. if (ISFLAGSET(pConvert->pSymbol->dwFlags, MPF_INETCSET))
  1147. {
  1148. // Encoded...
  1149. if (ISFLAGSET(pConvert->dwFlags, PDF_ENCODED))
  1150. {
  1151. // Save no encode
  1152. if (!ISFLAGSET(pConvert->dwState, PRSTATE_SAVENOENCODE))
  1153. {
  1154. // Decode the Property
  1155. if (SUCCEEDED(g_pInternat->HrEncodeProperty(pConvert, pSource, pDest)))
  1156. *ppszFree = pDest->rStringA.pszVal;
  1157. }
  1158. }
  1159. // Decoded
  1160. else if (IET_ENCODED == pConvert->ietSource)
  1161. {
  1162. // Decode Property
  1163. if (SUCCEEDED(g_pInternat->HrDecodeProperty(pConvert, pSource, pDest)))
  1164. *ppszFree = pDest->rStringA.pszVal;
  1165. }
  1166. }
  1167. // Simple Conversion to Unicode
  1168. if (NULL == pDest->rStringA.pszVal)
  1169. {
  1170. // Check State
  1171. Assert(NULL == *ppszFree);
  1172. // HrMultiByteToWideChar
  1173. CHECKHR(hr = g_pInternat->HrWideCharToMultiByte(pConvert->pCharset->cpiWindows, &pSource->rStringW, &pDest->rStringA));
  1174. // Save Charset/Encoding
  1175. pDest->fCopy = FALSE;
  1176. // Save pwszWide
  1177. *ppszFree = pDest->rStringA.pszVal;
  1178. }
  1179. exit:
  1180. // Done
  1181. return hr;
  1182. }
  1183. // --------------------------------------------------------------------------------
  1184. // MimeVariantFree
  1185. // --------------------------------------------------------------------------------
  1186. void MimeVariantFree(LPMIMEVARIANT pVariant)
  1187. {
  1188. // Invalid Arg
  1189. Assert(pVariant);
  1190. // If not a copy
  1191. if (FALSE == pVariant->fCopy)
  1192. {
  1193. // MVT_STRINGA
  1194. if (MVT_STRINGA == pVariant->type && NULL != pVariant->rStringA.pszVal)
  1195. g_pMalloc->Free(pVariant->rStringA.pszVal);
  1196. // MVT_STRINGW
  1197. else if (MVT_STRINGW == pVariant->type && NULL != pVariant->rStringW.pszVal)
  1198. g_pMalloc->Free(pVariant->rStringW.pszVal);
  1199. }
  1200. // Zero Out the Structure
  1201. ZeroMemory(pVariant, sizeof(MIMEVARIANT));
  1202. }
  1203. // ---------------------------------------------------------------------------------------
  1204. // MimeVariantCleanupFileName
  1205. // ---------------------------------------------------------------------------------------
  1206. void MimeVariantCleanupFileName(CODEPAGEID codepage, LPMIMEVARIANT pVariant)
  1207. {
  1208. // Locals
  1209. ULONG i=0;
  1210. // MVT_STRINGA
  1211. if (MVT_STRINGA == pVariant->type && ISVALIDSTRINGA(&pVariant->rStringA))
  1212. {
  1213. // Cleanup
  1214. pVariant->rStringA.cchVal = CleanupFileNameInPlaceA(codepage, pVariant->rStringA.pszVal);
  1215. }
  1216. // MVT_STRINGW
  1217. else if (MVT_STRINGW == pVariant->type && ISVALIDSTRINGW(&pVariant->rStringW))
  1218. {
  1219. // Cleanup
  1220. pVariant->rStringW.cchVal = CleanupFileNameInPlaceW(pVariant->rStringW.pszVal);
  1221. }
  1222. // Hmmm....
  1223. else
  1224. Assert(FALSE);
  1225. // Done
  1226. return;
  1227. }
  1228. // ---------------------------------------------------------------------------------------
  1229. // MimeVariantStripComments
  1230. // ---------------------------------------------------------------------------------------
  1231. HRESULT MimeVariantStripComments(LPMIMEVARIANT pSource, LPMIMEVARIANT pDest, LPBYTE pbScratch, ULONG cbScratch)
  1232. {
  1233. // Locals
  1234. HRESULT hr=S_OK;
  1235. ULONG cchVal=0;
  1236. BOOL fInQuoted=FALSE;
  1237. ULONG cNested=0;
  1238. // Init
  1239. ZeroMemory(pDest, sizeof(MIMEVARIANT));
  1240. // MVT_STRINGA
  1241. if (MVT_STRINGA == pSource->type && ISVALIDSTRINGA(&pSource->rStringA))
  1242. {
  1243. // Locals
  1244. LPSTR psz;
  1245. // Setup pDest
  1246. pDest->type = MVT_STRINGA;
  1247. // Dup It
  1248. if (pSource->rStringA.cchVal + 1 <= cbScratch)
  1249. {
  1250. pDest->fCopy = TRUE;
  1251. pDest->rStringA.pszVal = (LPSTR)pbScratch;
  1252. }
  1253. // Otherwise, allocate memory
  1254. else
  1255. {
  1256. // Allocate
  1257. CHECKALLOC(pDest->rStringA.pszVal = (LPSTR)g_pMalloc->Alloc(pSource->rStringA.cchVal + 1));
  1258. }
  1259. // Setup Loop
  1260. psz = pSource->rStringA.pszVal;
  1261. while(*psz)
  1262. {
  1263. // If lead byte, skip it, its leagal
  1264. if (IsDBCSLeadByte(*psz))
  1265. {
  1266. pDest->rStringA.pszVal[cchVal++] = *psz++;
  1267. pDest->rStringA.pszVal[cchVal++] = *psz++;
  1268. }
  1269. // Starting Comment
  1270. else if ('(' == *psz && !fInQuoted)
  1271. {
  1272. cNested++;
  1273. psz++;
  1274. }
  1275. // Ending Comment
  1276. else if (')' == *psz && !fInQuoted)
  1277. {
  1278. cNested--;
  1279. psz++;
  1280. }
  1281. // Otherwise, if not nested, append
  1282. else if (!cNested)
  1283. {
  1284. // Copy the Char
  1285. pDest->rStringA.pszVal[cchVal++] = *psz++;
  1286. // Check for Quote
  1287. if ('\"' == *psz)
  1288. fInQuoted = (fInQuoted) ? FALSE : TRUE;
  1289. }
  1290. // Skip Char
  1291. else
  1292. psz++;
  1293. }
  1294. // No Change
  1295. if (cchVal == pSource->rStringA.cchVal)
  1296. {
  1297. hr = E_FAIL;
  1298. goto exit;
  1299. }
  1300. // Null It
  1301. pDest->rStringA.pszVal[cchVal] = '\0';
  1302. }
  1303. // MVT_STRINGW
  1304. else if (MVT_STRINGW == pSource->type && ISVALIDSTRINGW(&pSource->rStringW))
  1305. {
  1306. // Locals
  1307. LPWSTR pwsz;
  1308. // Setup pDest
  1309. pDest->type = MVT_STRINGW;
  1310. // Dup It
  1311. if ((pSource->rStringW.cchVal + 1) * sizeof(WCHAR) <= cbScratch)
  1312. {
  1313. pDest->fCopy = TRUE;
  1314. pDest->rStringW.pszVal = (LPWSTR)pbScratch;
  1315. }
  1316. // Otherwise, allocate memory
  1317. else
  1318. {
  1319. // Dup It
  1320. CHECKALLOC(pDest->rStringW.pszVal = (LPWSTR)g_pMalloc->Alloc((pSource->rStringW.cchVal + 1) * sizeof(WCHAR)));
  1321. }
  1322. // Setup Loop
  1323. pwsz = pSource->rStringW.pszVal;
  1324. while(*pwsz)
  1325. {
  1326. // Starting Comment
  1327. if (L'(' == *pwsz && !fInQuoted)
  1328. {
  1329. cNested++;
  1330. pwsz++;
  1331. }
  1332. // Ending Comment
  1333. if (L')' == *pwsz && !fInQuoted)
  1334. {
  1335. cNested--;
  1336. pwsz++;
  1337. }
  1338. // Otherwise, if not nested, append
  1339. else if (!cNested)
  1340. {
  1341. // Copy the Character
  1342. pDest->rStringW.pszVal[cchVal++] = *pwsz++;
  1343. // Check for Quote
  1344. if (L'\"' == *pwsz)
  1345. fInQuoted = (fInQuoted) ? FALSE : TRUE;
  1346. }
  1347. // Skip Char
  1348. else
  1349. pwsz++;
  1350. }
  1351. // No Change
  1352. if (cchVal == pSource->rStringW.cchVal)
  1353. {
  1354. hr = E_FAIL;
  1355. goto exit;
  1356. }
  1357. // Null It
  1358. pDest->rStringW.pszVal[cchVal] = L'\0';
  1359. }
  1360. // Hmmm....
  1361. else
  1362. Assert(FALSE);
  1363. exit:
  1364. // Cleanup
  1365. if (FAILED(hr))
  1366. MimeVariantFree(pDest);
  1367. // Done
  1368. return hr;
  1369. }