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.

1066 lines
30 KiB

  1. // --------------------------------------------------------------------------------
  2. // Binxhex.h
  3. // Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  4. // Steven J. Bailey
  5. //
  6. // Copied from \\tdsrc\src1911\mapi\src\imail2\decoder.cpp
  7. // Copied from \\tdsrc\src1911\mapi\src\imail2\encoder.cpp
  8. // Copied from \\tdsrc\src1911\mapi\src\imail2\_encoder.h
  9. // --------------------------------------------------------------------------------
  10. #include "pch.hxx"
  11. #include "binhex.h"
  12. #include <shlwapi.h>
  13. // --------------------------------------------------------------------------------
  14. // Module data
  15. // --------------------------------------------------------------------------------
  16. #ifdef MAC
  17. const CHAR szBINHEXHDRLINE[] = "(This file must be converted with BinHex 4.0)\n\r\n\r";
  18. #else // !MAC
  19. const CHAR szBINHEXHDRLINE[] = "(This file must be converted with BinHex 4.0)\r\n\r\n";
  20. #endif // MAC
  21. const ULONG cbBINHEXHDRLINE = lstrlen( szBINHEXHDRLINE );
  22. static BOOL g_bCreatorTypeInit = FALSE; // TRUE ->array initialized
  23. sCreatorType * g_lpCreatorTypes = NULL; // ptr.to Creator-Type pairs
  24. static int g_cCreatorTypes = 0; // # of Creator-Type pairs
  25. // --------------------------------------------------------------------------------
  26. // Prototypes
  27. // --------------------------------------------------------------------------------
  28. void CalcCRC16(LPBYTE lpbBuff, ULONG cBuff, WORD * wCRC);
  29. BOOL bIsMacFile(DWORD dwCreator, DWORD dwType);
  30. VOID ReadCreatorTypes(void);
  31. //-----------------------------------------------------------------------------
  32. // Name: CBinhexEncoder::CBinhexEncoder
  33. //
  34. // Description:
  35. // Ctor
  36. //
  37. // Parameters:
  38. // Returns:
  39. // Effects:
  40. // Notes:
  41. // Revision:
  42. // Initial:9/5/1996
  43. //-----------------------------------------------------------------------------
  44. CBinhexEncoder::CBinhexEncoder(void)
  45. {
  46. m_fConfigured = FALSE;
  47. m_cbLineLength = cbLineLengthUnlimited;
  48. m_cbLeftOnLastLine = m_cbLineLength;
  49. m_cMaxLines = 0;
  50. m_cLines = 0;
  51. }
  52. //-----------------------------------------------------------------------------
  53. // Name: CBinhexEncoder::~CBinhexEncoder
  54. // Description:
  55. //
  56. // Parameters:
  57. // Returns:
  58. // Effects:
  59. // Notes:
  60. // Revision:
  61. // Initial:9/5/1996
  62. //-----------------------------------------------------------------------------
  63. CBinhexEncoder::~CBinhexEncoder( void )
  64. {
  65. #if defined (DEBUG) && defined (BINHEX_TRACE)
  66. if ( m_lpstreamEncodeRLE )
  67. {
  68. m_lpstreamEncodeRLE->Commit( 0 );
  69. m_lpstreamEncodeRLE->Release();
  70. }
  71. if ( m_lpstreamEncodeRAW )
  72. {
  73. m_lpstreamEncodeRAW->Commit( 0 );
  74. m_lpstreamEncodeRAW->Release();
  75. }
  76. #endif
  77. }
  78. //-----------------------------------------------------------------------------
  79. // Name: CBinhexEncoder::HrConfig
  80. // Description:
  81. //
  82. // Parameters:
  83. // Returns:
  84. // Effects:
  85. // Notes:
  86. // Revision:
  87. // Initial:9/5/1996
  88. //-----------------------------------------------------------------------------
  89. HRESULT CBinhexEncoder::HrConfig( IN CB cbLineLength, IN C cMaxLines,
  90. IN void * pvParms )
  91. {
  92. // Is this a repeat call?
  93. if (m_fConfigured)
  94. {
  95. return ERROR_ALREADY_INITIALIZED;
  96. }
  97. // Objects of this class may have pvParms point to a various additional
  98. // configuration values to consider when encoding.
  99. if ( pvParms == NULL)
  100. {
  101. return ERROR_INVALID_PARAMETER;
  102. }
  103. m_cbLineLength = cbLineLength;
  104. m_lpmacbinHdr = (LPMACBINARY)pvParms;
  105. m_ulAccum = 0;
  106. m_cAccum = 0;
  107. m_cbRepeat = 0;
  108. m_bRepeat = BINHEX_INVALID;
  109. m_wCRC = 0;
  110. m_cbFork = 0;
  111. m_cbLeftInFork = 0;
  112. m_eBinHexStateEnc = sHEADER;
  113. m_cbProduced = 0;
  114. m_cbConsumed = 0;
  115. m_pbWrite = NULL;
  116. m_cbLeftInOutputBuffer = 0;
  117. m_cbLeftInInputBuffer = 0;
  118. m_bPrev = BINHEX_INVALID;
  119. m_cbWrite = 0;
  120. m_cbLine = 0;
  121. m_fHandledx90 = FALSE;
  122. m_cbPad = 0;
  123. #if defined (DEBUG) && defined (BINHEX_TRACE)
  124. {
  125. CHAR szFilePath[MAX_PATH];
  126. CHAR szPath[MAX_PATH];
  127. ULONG ulDirLen = 0;
  128. HRESULT hr = hrSuccess;
  129. ulDirLen = GetPrivateProfileString( "IMAIL2 ITP",
  130. "InboundFilePath",
  131. "",
  132. (LPSTR) szFilePath,
  133. sizeof( szFilePath ),
  134. "mapidbg.ini");
  135. if ( ulDirLen == 0 )
  136. {
  137. // Default to %TEMP%\IMAIL
  138. ulDirLen = GetTempPath( sizeof( szFilePath ), szFilePath );
  139. AssertSz( ulDirLen < sizeof( szFilePath), "Temp directory name too long" );
  140. StrCatBuff(szFilePath, "imail", ARRAYSIZE(szFilePath));
  141. ulDirLen = lstrlen(szFilePath);
  142. }
  143. // Open stream on file for input file
  144. StrCatBuff(szFilePath, "\\", ARRAYSIZE(szFilePath));
  145. StrCpyN( szPath, szFilePath, ARRAYSIZE(szPath));
  146. StrCatBuff( szFilePath, "enc_rle.rpt", ARRAYSIZE(szFilePath));
  147. hr = OpenStreamOnFile( MAPIAllocateBuffer, MAPIFreeBuffer,
  148. STGM_READWRITE | STGM_CREATE,
  149. szFilePath, NULL, &m_lpstreamEncodeRLE );
  150. if ( hr )
  151. AssertSz( FALSE, "Debug encode stream failed to initialize\n" );
  152. StrCpyN (szFilePath, szPath, ARRAYSIZE(szFilePath));
  153. StrCatBuff(szFilePath, "enc_raw.rpt", ARRAYSIZE(szFilePath));
  154. hr = OpenStreamOnFile( MAPIAllocateBuffer, MAPIFreeBuffer,
  155. STGM_READWRITE | STGM_CREATE,
  156. szFilePath, NULL, &m_lpstreamEncodeRAW );
  157. if ( hr )
  158. AssertSz( FALSE, "Debug encode stream failed to initialize\n" );
  159. }
  160. #endif
  161. m_fConfigured = fTrue;
  162. return ERROR_SUCCESS;
  163. }
  164. //-----------------------------------------------------------------------------
  165. // Name: CBinhexEncoder::HrEmit
  166. // Description:
  167. //
  168. // Parameters:
  169. // Returns:
  170. // Effects:
  171. //
  172. // Notes:
  173. // Handle Data Fork
  174. // Resource fork.
  175. //
  176. // Revision:
  177. // Initial:9/5/1996
  178. //-----------------------------------------------------------------------------
  179. HRESULT CBinhexEncoder::HrEmit( IN PB pbRead, IN OUT CB * pcbRead, OUT PB pbWrite,
  180. IN OUT CB * pcbWrite )
  181. {
  182. HRESULT hr = ERROR_SUCCESS;
  183. CB cbHeader = 0;
  184. CB cbToProcess;
  185. CB cbInputCheckPoint = 0;
  186. CB cbOut;
  187. CB cb;
  188. BYTE rgbHeader[ cbMIN_BINHEX_HEADER_SIZE + 64 ];
  189. m_cbConsumed = 0;
  190. m_cbProduced = 0;
  191. m_cbLeftInOutputBuffer = 0;
  192. m_cbLeftInInputBuffer = 0;
  193. // Have to be initialized first
  194. if ( !m_fConfigured )
  195. {
  196. return ERROR_BAD_COMMAND;
  197. }
  198. // Handle common 'bad parameter' errors
  199. if ( !pbRead || !pbWrite || !pcbRead || !pcbWrite )
  200. {
  201. return ERROR_INVALID_PARAMETER;
  202. }
  203. // Repeated calls after maximum number of output lines were generated
  204. // will not go through
  205. if ( FMaxLinesReached() )
  206. {
  207. *pcbRead = *pcbWrite = 0;
  208. return ERROR_SUCCESS;
  209. }
  210. // If line length is unlimited, set m_cbLeftOnLastLine to be equal to
  211. // the length of the input buffer
  212. if ( !FLineLengthLimited() )
  213. {
  214. m_cbLeftOnLastLine = *pcbWrite;
  215. }
  216. m_pbWrite = pbWrite;
  217. m_cbWrite = *pcbWrite;
  218. while ( TRUE )
  219. {
  220. m_cbLeftInInputBuffer = *pcbRead - m_cbConsumed;
  221. m_cbLeftInOutputBuffer = *pcbWrite - m_cbProduced;
  222. // If we have room in the output buffer keep going if in sEnd and no input left
  223. if ( 0 == m_cbLeftInOutputBuffer || (0 == m_cbLeftInInputBuffer && sEND != m_eBinHexStateEnc) )
  224. {
  225. goto Cleanup;
  226. }
  227. switch ( m_eBinHexStateEnc )
  228. {
  229. case sHEADER:
  230. {
  231. // Output BinHex Header line
  232. CopyMemory( pbWrite, szBINHEXHDRLINE, cbBINHEXHDRLINE );
  233. m_cbProduced += cbBINHEXHDRLINE;
  234. m_cLines += 2;
  235. // Output leading ':'
  236. m_pbWrite[m_cbProduced++] = ':';
  237. ++m_cbLine;
  238. // Output MACBIN Header; Header filename length
  239. rgbHeader[cbHeader++] = m_lpmacbinHdr->cchFileName;
  240. // Header filename
  241. CopyMemory( rgbHeader + cbHeader, m_lpmacbinHdr->rgchFileName, m_lpmacbinHdr->cchFileName );
  242. cbHeader += m_lpmacbinHdr->cchFileName;
  243. // Null terminate filename
  244. rgbHeader[cbHeader++] = '\0';
  245. // Macfile TYPE
  246. CopyMemory( rgbHeader + cbHeader, (LPBYTE)&m_lpmacbinHdr->dwType, sizeof(DWORD) );
  247. cbHeader += sizeof(DWORD);
  248. // Macfile CREATOR
  249. CopyMemory( rgbHeader + cbHeader, (LPBYTE)&m_lpmacbinHdr->dwCreator, sizeof(DWORD) );
  250. cbHeader += sizeof(DWORD);
  251. // Macfile FLAGS
  252. rgbHeader[cbHeader++] = m_lpmacbinHdr->bFinderFlags;
  253. rgbHeader[cbHeader++] = m_lpmacbinHdr->bFinderFlags2;
  254. // Macfile Fork lengths
  255. CopyMemory( rgbHeader + cbHeader, (LPBYTE)&m_lpmacbinHdr->lcbDataFork, sizeof(DWORD) );
  256. cbHeader += sizeof(DWORD);
  257. CopyMemory( rgbHeader + cbHeader, (LPBYTE)&m_lpmacbinHdr->lcbResourceFork, sizeof(DWORD) );
  258. cbHeader += sizeof(DWORD);
  259. // Calculate the binhex header CRC
  260. CalcCRC16( rgbHeader, cbHeader, &m_wCRC );
  261. CalcCRC16( (LPBYTE)&wZero, sizeof(WORD), &m_wCRC );
  262. rgbHeader[cbHeader++] = HIBYTE( m_wCRC );
  263. rgbHeader[cbHeader++] = LOBYTE( m_wCRC );
  264. // BinHex the header into pbWrite. The initial assumption is that
  265. // the buffer is going to big enough to encode the header.
  266. // Output goes into m_pbWrite.
  267. cbOut = 0;
  268. hr = HrBinHexBuffer( rgbHeader, cbHeader, &cbOut );
  269. // setup for the data fork
  270. m_eBinHexStateEnc = sDATA;
  271. m_cbFork = NATIVE_LONG_FROM_BIG( (LPBYTE)&m_lpmacbinHdr->lcbDataFork );
  272. m_cbLeftInFork = m_cbFork;
  273. m_wCRC = 0;
  274. }
  275. break;
  276. case sDATA:
  277. {
  278. // determine how much we can process
  279. cbToProcess = m_cbLeftInFork < m_cbLeftInInputBuffer ? m_cbLeftInFork : m_cbLeftInInputBuffer;
  280. cbInputCheckPoint = m_cbConsumed;
  281. hr = HrBinHexBuffer( pbRead + cbInputCheckPoint, cbToProcess, &m_cbConsumed );
  282. CalcCRC16( pbRead + cbInputCheckPoint, m_cbConsumed - cbInputCheckPoint, &m_wCRC );
  283. m_cbLeftInFork -= m_cbConsumed - cbInputCheckPoint;
  284. // flush output buffer
  285. if ( hr )
  286. goto Cleanup;
  287. if ( !m_cbLeftInFork )
  288. {
  289. // write out the last CRC
  290. CalcCRC16( (LPBYTE)&wZero, sizeof(WORD), &m_wCRC );
  291. cbHeader = 0;
  292. rgbHeader[cbHeader++] = HIBYTE( m_wCRC );
  293. rgbHeader[cbHeader++] = LOBYTE( m_wCRC );
  294. cbOut = 0;
  295. hr = HrBinHexBuffer( rgbHeader, 2, &cbOut );
  296. // discard padding
  297. if ( m_cbFork % 128 )
  298. {
  299. cb = 128 - ( m_cbFork % 128 );
  300. if ( *pcbRead - m_cbConsumed < cb )
  301. {
  302. DebugTrace( "Note: Support refilling input buffer to remove padding for Data\n" );
  303. // need to pull in more data
  304. m_cbPad = cb - (*pcbRead - m_cbConsumed);
  305. m_cbConsumed -= (*pcbRead - m_cbConsumed);
  306. }
  307. else
  308. {
  309. m_cbConsumed = cb;
  310. }
  311. }
  312. // Set up for resource for if there is one and reset counters
  313. m_cbFork = NATIVE_LONG_FROM_BIG( (LPBYTE)&m_lpmacbinHdr->lcbResourceFork );
  314. m_cbLeftInFork = m_cbFork;
  315. if ( !m_cbFork )
  316. {
  317. // handle 0 byte resource fork
  318. m_eBinHexStateEnc = sEND;
  319. // write out crc for 0 length
  320. cbOut = 0;
  321. hr = HrBinHexBuffer( (LPBYTE)&wZero, sizeof(WORD), &cbOut );
  322. }
  323. else
  324. {
  325. m_eBinHexStateEnc = sRESOURCE;
  326. }
  327. m_wCRC = 0;
  328. }
  329. }
  330. break;
  331. case sRESOURCE:
  332. {
  333. if ( m_cbPad )
  334. {
  335. m_cbConsumed -= m_cbPad;
  336. m_cbPad = 0;
  337. }
  338. // determine how much we can process
  339. cbToProcess = m_cbLeftInFork < m_cbLeftInInputBuffer ? m_cbLeftInFork : m_cbLeftInInputBuffer;
  340. cbInputCheckPoint = m_cbConsumed;
  341. hr = HrBinHexBuffer( pbRead + cbInputCheckPoint, cbToProcess, &m_cbConsumed );
  342. CalcCRC16( pbRead + cbInputCheckPoint, m_cbConsumed - cbInputCheckPoint, &m_wCRC );
  343. m_cbLeftInFork -= m_cbConsumed - cbInputCheckPoint;
  344. // flush output buffer
  345. if ( hr )
  346. goto Cleanup;
  347. if ( !m_cbLeftInFork )
  348. {
  349. // write out the last CRC
  350. CalcCRC16( (LPBYTE)&wZero, sizeof(WORD), &m_wCRC );
  351. cbHeader = 0;
  352. rgbHeader[cbHeader++] = HIBYTE( m_wCRC );
  353. rgbHeader[cbHeader++] = LOBYTE( m_wCRC );
  354. cbOut = 0;
  355. hr = HrBinHexBuffer( rgbHeader, 2, &cbOut );
  356. // discard padding
  357. if ( m_cbFork % 128 )
  358. {
  359. cb = 128 - ( m_cbFork % 128 );
  360. if ( *pcbRead - m_cbConsumed < cb )
  361. {
  362. DebugTrace( "Note: Support refilling input buffer to remove padding for Resource\n" );
  363. // need to pull in more data
  364. m_cbPad = cb - (*pcbRead - m_cbConsumed);
  365. m_cbConsumed -= (*pcbRead - m_cbConsumed);
  366. }
  367. else
  368. {
  369. m_cbConsumed = cb;
  370. }
  371. }
  372. // set up to terminate
  373. m_eBinHexStateEnc = sEND;
  374. }
  375. }
  376. break;
  377. case sEND:
  378. {
  379. if ( m_cbPad )
  380. {
  381. m_cbConsumed -= m_cbPad;
  382. m_cbPad = 0;
  383. }
  384. if ( (*pcbWrite - m_cbProduced) == 0 )
  385. break;
  386. // flush out any repeated chars
  387. if ( m_cbRepeat )
  388. {
  389. if ( m_cbRepeat > 1 )
  390. {
  391. // bump up the repeat count so it reflects actual number of chars to repeat.
  392. m_cbRepeat++;
  393. // encode the repeat code char
  394. // note that we've already emitted the char that we're supplying
  395. // the repeat info for.
  396. hr = HrBinHexByte( BINHEX_REPEAT );
  397. m_bPrev = BINHEX_REPEAT;
  398. Assert( m_cbRepeat <= 255 );
  399. // encode repeat count
  400. hr = HrBinHexByte( (BYTE)(m_cbRepeat) );
  401. m_bPrev = (BYTE)(m_cbRepeat);
  402. }
  403. else
  404. {
  405. hr = HrBinHexByte( m_bRepeat );
  406. m_bPrev = m_bRepeat;
  407. }
  408. }
  409. // check to see if we have bits in the accumulator
  410. if ( m_cAccum )
  411. {
  412. switch( m_cAccum )
  413. {
  414. case 1:
  415. m_pbWrite[m_cbProduced++] = g_rgchBinHex8to6[((m_bPrev & 0x03) << 4)];
  416. break;
  417. case 2:
  418. m_pbWrite[m_cbProduced++] = g_rgchBinHex8to6[((m_bPrev & 0x0f) << 2)];
  419. break;
  420. case 3:
  421. m_pbWrite[m_cbProduced++] = g_rgchBinHex8to6[m_bCurr & 0x3f];
  422. break;
  423. default:
  424. AssertSz( FALSE, "HrBinHexByte: bad shift state\n" );
  425. hr = ERROR_INVALID_PARAMETER;
  426. goto Cleanup;
  427. }
  428. }
  429. // tack on terminating ':'
  430. m_pbWrite[m_cbProduced++] = ':';
  431. m_cbConsumed = *pcbRead;
  432. // probably not so we would have to flush the
  433. // bits out.
  434. goto Cleanup;
  435. }
  436. }
  437. }
  438. Cleanup:
  439. if (hr == ERROR_SUCCESS || hr == ERROR_MORE_DATA)
  440. {
  441. // Check that at least some processing was done.
  442. // Also this error is returned if we've exhausted the output
  443. // buffer.
  444. if ( (m_cbProduced == 0) || (m_cbLeftInInputBuffer > m_cbLeftInOutputBuffer)
  445. || (0 == m_cbLeftInOutputBuffer && sEND == m_eBinHexStateEnc) )
  446. {
  447. hr = ERROR_INSUFFICIENT_BUFFER;
  448. }
  449. else if ( m_cbConsumed < *pcbRead )
  450. {
  451. // Was all input processed?
  452. // Note that it is okay to encode only part of the input buffer
  453. // if maximum number of output lines was exceeded.
  454. hr = ERROR_MORE_DATA;
  455. }
  456. }
  457. // Report the new sizes to the caller.
  458. Assert( m_cbConsumed <= *pcbRead );
  459. Assert( m_cbProduced <= *pcbWrite );
  460. *pcbRead = m_cbConsumed;
  461. *pcbWrite = m_cbProduced;
  462. return hr;
  463. }
  464. //-----------------------------------------------------------------------------
  465. // Name: CBinhexEncoder::HrBinHexBuffer
  466. //
  467. // Description:
  468. // Output goes into m_pbWrite
  469. //
  470. // Parameters:
  471. // Returns:
  472. // Effects:
  473. // Notes:
  474. //
  475. // Revision:
  476. // Initial:9/5/1996
  477. //-----------------------------------------------------------------------------
  478. HRESULT CBinhexEncoder::HrBinHexBuffer( IN LPBYTE lpbIn, IN CB cbIn, CB * lpcbConsumed )
  479. {
  480. HRESULT hr = ERROR_SUCCESS;
  481. BOOL fEndRepeat = FALSE;
  482. CB cbInUsed = 0;
  483. #if defined (DEBUG) && defined (BINHEX_TRACE)
  484. CB cbOrigCbIn = cbIn;
  485. #endif
  486. while ( cbIn && m_cbProduced + 5 < m_cbWrite )
  487. {
  488. // process the next char in input buffer
  489. m_bCurr = lpbIn[cbInUsed++];
  490. --cbIn;
  491. // check to see if we've seen this char before. Don't repeat
  492. // if we just added a literal 0x90.
  493. if ( m_bCurr == m_bPrev && !m_fHandledx90 )
  494. {
  495. // m_cbRepeat is the count of repeat chars after the initial char.
  496. // e.g., if there are two repeating chars, m_cbRepeat will be 1.
  497. // Note that we've already emitted the char after which to add the repeat
  498. // code and count.
  499. if ( m_cbRepeat < 254 )
  500. {
  501. m_cbRepeat++;
  502. m_bRepeat = m_bCurr;
  503. continue;
  504. }
  505. }
  506. m_fHandledx90 = FALSE;
  507. // we were counting repeating characters and the run stopped.
  508. if ( m_cbRepeat > 1 )
  509. {
  510. // set up to emit the run length encoding
  511. fEndRepeat = TRUE;
  512. }
  513. // Are we in repeat mode...
  514. if ( m_cbRepeat > 1 && fEndRepeat == TRUE )
  515. {
  516. // bump up the repeat count so it reflects actual number of chars to repeat.
  517. m_cbRepeat++;
  518. // if we're repeating 0x90 tack on the trailing 0x00
  519. if ( m_bRepeat == BINHEX_REPEAT )
  520. {
  521. hr = HrBinHexByte( '\0' );
  522. }
  523. // encode the repeat code char
  524. // note that we've already emitted the char that we're supplying
  525. // the repeat info for.
  526. hr = HrBinHexByte( BINHEX_REPEAT );
  527. Assert( m_cbRepeat <= 255 );
  528. // encode repeat count
  529. hr = HrBinHexByte( (BYTE)(m_cbRepeat) );
  530. fEndRepeat = FALSE;
  531. m_cbRepeat = 0;
  532. }
  533. else if ( m_cbRepeat ) // check if we've got two chars to encode.
  534. {
  535. // encode the one char since we've already emitted
  536. // the first one.
  537. hr = HrBinHexByte( m_bRepeat );
  538. if ( m_bRepeat == BINHEX_REPEAT )
  539. {
  540. hr = HrBinHexByte( '\0' );
  541. }
  542. m_cbRepeat = 0;
  543. }
  544. // special handling for 0x90 chars in stream but 0x90 can repeat
  545. if ( m_bCurr == BINHEX_REPEAT && m_bPrev != BINHEX_REPEAT )
  546. {
  547. hr = HrBinHexByte( BINHEX_REPEAT );
  548. hr = HrBinHexByte( '\0' );
  549. m_fHandledx90 = TRUE;
  550. continue;
  551. }
  552. // encode the char
  553. hr = HrBinHexByte( m_bCurr );
  554. if ( hr )
  555. goto exit;
  556. }
  557. // Check if we filled the output buffer
  558. if ( cbIn && m_cbProduced + 5 >= m_cbWrite )
  559. {
  560. hr = ERROR_INSUFFICIENT_BUFFER;
  561. }
  562. exit:
  563. #if defined (DEBUG) && defined (BINHEX_TRACE)
  564. m_lpstreamEncodeRAW->Write( lpbIn, cbOrigCbIn - cbIn, NULL );
  565. #endif
  566. *lpcbConsumed += cbInUsed;
  567. return hr;
  568. }
  569. //-----------------------------------------------------------------------------
  570. // Name: CBinhexEncoder::HrBinHexByte
  571. // Description:
  572. //
  573. // Parameters:
  574. // Returns:
  575. // Effects:
  576. // Notes:
  577. // Revision:
  578. // Initial:9/5/1996
  579. //-----------------------------------------------------------------------------
  580. HRESULT CBinhexEncoder::HrBinHexByte( IN BYTE b )
  581. {
  582. HRESULT hr = ERROR_SUCCESS;
  583. #if defined (DEBUG) & defined (BINHEX_TRACE)
  584. hr = m_lpstreamEncodeRLE->Write( &b, 1, NULL );
  585. #endif
  586. switch( m_cAccum++ )
  587. {
  588. case 0:
  589. m_pbWrite[m_cbProduced++] = g_rgchBinHex8to6[b >> 2];
  590. ++m_cbLine;
  591. break;
  592. case 1:
  593. m_pbWrite[m_cbProduced++] = g_rgchBinHex8to6[((m_bPrev & 0x03) << 4) | (b >> 4)];
  594. ++m_cbLine;
  595. break;
  596. case 2:
  597. m_pbWrite[m_cbProduced++] = g_rgchBinHex8to6[((m_bPrev & 0x0f) << 2) | (b >> 6)];
  598. ++m_cbLine;
  599. if ( m_cbLine >= 64 )
  600. {
  601. m_pbWrite[m_cbProduced++] = chCR;
  602. m_pbWrite[m_cbProduced++] = chLF;
  603. m_cbLine = 0;
  604. ++m_cLines;
  605. }
  606. m_pbWrite[m_cbProduced++] = g_rgchBinHex8to6[b & 0x3f];
  607. ++m_cbLine;
  608. m_cAccum = 0;
  609. break;
  610. default:
  611. AssertSz( FALSE, "HrBinHexByte: bad shift state\n" );
  612. hr = ERROR_INVALID_PARAMETER;
  613. goto exit;
  614. }
  615. if ( m_cbLine >= 64 )
  616. {
  617. m_pbWrite[m_cbProduced++] = chCR;
  618. m_pbWrite[m_cbProduced++] = chLF;
  619. m_cbLine = 0;
  620. ++m_cLines;
  621. }
  622. m_bPrev = b;
  623. exit:
  624. return hr;
  625. }
  626. //-----------------------------------------------------------------------------
  627. //
  628. // CBinhexDecoder class implementation
  629. //
  630. //-----------------------------------------------------------------------------
  631. //-----------------------------------------------------------------------------
  632. // Name: CalcCRC16
  633. // Description:
  634. // Used to calculate a 16 bit CRC using the
  635. // CCITT polynomial 0x1021.
  636. //
  637. // Parameters:
  638. // Returns:
  639. // Effects:
  640. // Notes:
  641. // Revision:
  642. // Initial:7/30/1996
  643. //-----------------------------------------------------------------------------
  644. void CalcCRC16( LPBYTE lpbBuff, ULONG cBuff, WORD * wCRC )
  645. {
  646. LPBYTE lpb;
  647. BYTE b;
  648. WORD uCRC;
  649. WORD fWrap;
  650. ULONG i;
  651. uCRC = *wCRC;
  652. for ( lpb = lpbBuff; lpb < lpbBuff + cBuff; lpb++ )
  653. {
  654. b = *lpb;
  655. for ( i = 0; i < 8; i++ )
  656. {
  657. fWrap = uCRC & 0x8000;
  658. uCRC = (uCRC << 1) | (b >> 7);
  659. if ( fWrap )
  660. {
  661. uCRC = uCRC ^ 0x1021;
  662. }
  663. b = b << 1;
  664. }
  665. }
  666. *wCRC = uCRC;
  667. }
  668. //-----------------------------------------------------------------------------
  669. // Name: bIsMacFile
  670. // Description:
  671. //
  672. // Parameters:
  673. // Returns:
  674. // FALSE: if the given dwCreator/dwType matches one of the
  675. // pairs in g_lpCreatorTypes;
  676. //
  677. // TRUE: otherwise
  678. //
  679. // Effects:
  680. // Notes:
  681. // Revision:
  682. // Initial:10/15/1996
  683. //-----------------------------------------------------------------------------
  684. BOOL bIsMacFile(DWORD dwCreator, DWORD dwType)
  685. {
  686. BOOL bRet = TRUE;
  687. int i;
  688. char szCreator[5] = { 0 };
  689. char szType[5] = { 0 };
  690. if ( dwType == 0 && dwCreator == 0 )
  691. {
  692. bRet = FALSE;
  693. goto exit;
  694. }
  695. if ( g_bCreatorTypeInit != TRUE )
  696. {
  697. ReadCreatorTypes();
  698. }
  699. if ( g_lpCreatorTypes == NULL )
  700. goto exit;
  701. // Convert dwCreator & dwType to strings
  702. CopyMemory( szCreator, &dwCreator, 4 );
  703. CopyMemory( szType, &dwType, 4 );
  704. for ( i = 0; i < g_cCreatorTypes; i ++ )
  705. {
  706. if ( g_lpCreatorTypes[i].szCreator[0] == 0 && g_lpCreatorTypes[i].szType[0] == 0 )
  707. {
  708. bRet = FALSE;
  709. break;
  710. }
  711. else if ( g_lpCreatorTypes[i].szCreator[0] == 0 && lstrcmpi( g_lpCreatorTypes[i].szType, szType ) == 0 )
  712. {
  713. bRet = FALSE;
  714. break;
  715. }
  716. else if( g_lpCreatorTypes[i].szType[0] == 0 && lstrcmpi( g_lpCreatorTypes[i].szCreator, szCreator ) == 0 )
  717. {
  718. bRet = FALSE;
  719. break;
  720. }
  721. else if( lstrcmpi( g_lpCreatorTypes[i].szCreator, szCreator ) == 0 && lstrcmpi( g_lpCreatorTypes[i].szType, szType ) == 0 )
  722. {
  723. bRet = FALSE;
  724. break;
  725. }
  726. }
  727. exit:
  728. return bRet ;
  729. }
  730. //-----------------------------------------------------------------------------
  731. // Name: ReadCreatorTypes
  732. //
  733. // Description:
  734. //
  735. // Read "NonMacCreatorTypes" registry key (REG_MULTI_SZ type)
  736. // from the registry & build an array of Creator-Type pairs
  737. //
  738. // Parameters:
  739. // Returns:
  740. // Effects:
  741. // Notes:
  742. // Revision:
  743. // Initial:10/15/1996
  744. //-----------------------------------------------------------------------------
  745. VOID ReadCreatorTypes( VOID )
  746. {
  747. #ifdef MAC
  748. g_bCreatorTypeInit = TRUE;
  749. #else // !MAC
  750. DWORD dwStatus;
  751. DWORD dwType;
  752. DWORD cbData;
  753. char * lpData = NULL;
  754. char * lpCurrent = NULL;
  755. char * lpNext = NULL;
  756. int i;
  757. LONG lRet;
  758. HKEY hKey = 0;
  759. SCODE sc = S_OK;
  760. g_bCreatorTypeInit = TRUE;
  761. // Open IMC parameter registry
  762. lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  763. "SYSTEM\\CurrentControlSet\\Services\\MSExchangeIS\\ParametersSystem\\InternetContent",
  764. 0, KEY_READ, &hKey );
  765. if ( lRet != ERROR_SUCCESS )
  766. goto exit;
  767. // read the registry key
  768. dwStatus = RegQueryValueEx( hKey, "NonMacCreatorTypes", 0, &dwType, (LPBYTE)NULL, &cbData );
  769. if ( dwStatus != ERROR_SUCCESS // key missing
  770. || dwType != REG_MULTI_SZ // wrong type
  771. || cbData <= 4 ) // invalid size
  772. {
  773. goto exit;
  774. }
  775. if (FAILED(HrAlloc((LPVOID *)&lpData, cbData)))
  776. goto exit;
  777. ZeroMemory( (LPVOID)lpData, cbData );
  778. dwStatus = RegQueryValueEx( hKey, "NonMacCreatorTypes", NULL, &dwType, (LPBYTE)lpData, &cbData );
  779. if ( dwStatus != ERROR_SUCCESS )
  780. goto exit;
  781. // Determine # of pairs read:
  782. g_cCreatorTypes = 0;
  783. for ( i= 0; i < (LONG)cbData-1; i++ )
  784. {
  785. if ( lpData[i] == '\0' )
  786. g_cCreatorTypes ++;
  787. }
  788. if (FAILED(HrAlloc((LPVOID *)&g_lpCreatorTypes, sizeof(sCreatorType) * g_cCreatorTypes)))
  789. goto exit;
  790. ZeroMemory( (LPVOID)g_lpCreatorTypes, sizeof(sCreatorType) * g_cCreatorTypes );
  791. // Build the Creator-Type array
  792. lpCurrent = lpData;
  793. i = 0;
  794. while ( lpCurrent < (lpData + cbData -1) )
  795. {
  796. lpNext = StrChr( lpCurrent, ':' );
  797. if( lpNext == NULL )
  798. {
  799. //no ':' found; skip to next string
  800. lpCurrent = StrChr( lpCurrent, '\0' ) + 1;
  801. continue;
  802. }
  803. *lpNext = '\0';
  804. if ( StrChr( lpCurrent, '*' ) == NULL )
  805. CopyMemory( &g_lpCreatorTypes[i].szCreator, lpCurrent, MIN(4, lpNext-lpCurrent) );
  806. lpCurrent = lpNext + 1;
  807. lpNext = StrChr( lpCurrent, '\0' );
  808. if ( lpNext == NULL )
  809. break;
  810. if ( StrChr( lpCurrent, '*' ) == NULL )
  811. {
  812. CopyMemory( &g_lpCreatorTypes[i].szType, lpCurrent, MIN( 4, lpNext-lpCurrent) );
  813. }
  814. lpCurrent = lpNext + 1;
  815. i++;
  816. }
  817. g_cCreatorTypes = i;
  818. exit:
  819. if ( hKey != 0 )
  820. RegCloseKey( hKey );
  821. SafeMemFree(lpData);
  822. if ( g_cCreatorTypes == 0 && g_lpCreatorTypes != NULL )
  823. {
  824. SafeMemFree(g_lpCreatorTypes);
  825. }
  826. #endif // !MAC
  827. }