|
|
// --------------------------------------------------------------------------------
// Binxhex.h
// Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
// Steven J. Bailey
//
// Copied from \\tdsrc\src1911\mapi\src\imail2\decoder.cpp
// Copied from \\tdsrc\src1911\mapi\src\imail2\encoder.cpp
// Copied from \\tdsrc\src1911\mapi\src\imail2\_encoder.h
// --------------------------------------------------------------------------------
#include "pch.hxx"
#include "binhex.h"
#include <shlwapi.h>
// --------------------------------------------------------------------------------
// Module data
// --------------------------------------------------------------------------------
#ifdef MAC
const CHAR szBINHEXHDRLINE[] = "(This file must be converted with BinHex 4.0)\n\r\n\r"; #else // !MAC
const CHAR szBINHEXHDRLINE[] = "(This file must be converted with BinHex 4.0)\r\n\r\n"; #endif // MAC
const ULONG cbBINHEXHDRLINE = lstrlen( szBINHEXHDRLINE ); static BOOL g_bCreatorTypeInit = FALSE; // TRUE ->array initialized
sCreatorType * g_lpCreatorTypes = NULL; // ptr.to Creator-Type pairs
static int g_cCreatorTypes = 0; // # of Creator-Type pairs
// --------------------------------------------------------------------------------
// Prototypes
// --------------------------------------------------------------------------------
void CalcCRC16(LPBYTE lpbBuff, ULONG cBuff, WORD * wCRC); BOOL bIsMacFile(DWORD dwCreator, DWORD dwType); VOID ReadCreatorTypes(void);
//-----------------------------------------------------------------------------
// Name: CBinhexEncoder::CBinhexEncoder
//
// Description:
// Ctor
//
// Parameters:
// Returns:
// Effects:
// Notes:
// Revision:
// Initial:9/5/1996
//-----------------------------------------------------------------------------
CBinhexEncoder::CBinhexEncoder(void) { m_fConfigured = FALSE; m_cbLineLength = cbLineLengthUnlimited; m_cbLeftOnLastLine = m_cbLineLength; m_cMaxLines = 0; m_cLines = 0; }
//-----------------------------------------------------------------------------
// Name: CBinhexEncoder::~CBinhexEncoder
// Description:
//
// Parameters:
// Returns:
// Effects:
// Notes:
// Revision:
// Initial:9/5/1996
//-----------------------------------------------------------------------------
CBinhexEncoder::~CBinhexEncoder( void ) { #if defined (DEBUG) && defined (BINHEX_TRACE)
if ( m_lpstreamEncodeRLE ) { m_lpstreamEncodeRLE->Commit( 0 ); m_lpstreamEncodeRLE->Release(); }
if ( m_lpstreamEncodeRAW ) { m_lpstreamEncodeRAW->Commit( 0 ); m_lpstreamEncodeRAW->Release(); } #endif
}
//-----------------------------------------------------------------------------
// Name: CBinhexEncoder::HrConfig
// Description:
//
// Parameters:
// Returns:
// Effects:
// Notes:
// Revision:
// Initial:9/5/1996
//-----------------------------------------------------------------------------
HRESULT CBinhexEncoder::HrConfig( IN CB cbLineLength, IN C cMaxLines, IN void * pvParms ) { // Is this a repeat call?
if (m_fConfigured) { return ERROR_ALREADY_INITIALIZED; }
// Objects of this class may have pvParms point to a various additional
// configuration values to consider when encoding.
if ( pvParms == NULL) { return ERROR_INVALID_PARAMETER; }
m_cbLineLength = cbLineLength; m_lpmacbinHdr = (LPMACBINARY)pvParms; m_ulAccum = 0; m_cAccum = 0; m_cbRepeat = 0; m_bRepeat = BINHEX_INVALID; m_wCRC = 0; m_cbFork = 0; m_cbLeftInFork = 0; m_eBinHexStateEnc = sHEADER; m_cbProduced = 0; m_cbConsumed = 0; m_pbWrite = NULL; m_cbLeftInOutputBuffer = 0; m_cbLeftInInputBuffer = 0; m_bPrev = BINHEX_INVALID; m_cbWrite = 0; m_cbLine = 0; m_fHandledx90 = FALSE; m_cbPad = 0;
#if defined (DEBUG) && defined (BINHEX_TRACE)
{ CHAR szFilePath[MAX_PATH]; CHAR szPath[MAX_PATH]; ULONG ulDirLen = 0; HRESULT hr = hrSuccess;
ulDirLen = GetPrivateProfileString( "IMAIL2 ITP", "InboundFilePath", "", (LPSTR) szFilePath, sizeof( szFilePath ), "mapidbg.ini");
if ( ulDirLen == 0 ) { // Default to %TEMP%\IMAIL
ulDirLen = GetTempPath( sizeof( szFilePath ), szFilePath );
AssertSz( ulDirLen < sizeof( szFilePath), "Temp directory name too long" );
StrCatBuff(szFilePath, "imail", ARRAYSIZE(szFilePath)); ulDirLen = lstrlen(szFilePath); }
// Open stream on file for input file
StrCatBuff(szFilePath, "\\", ARRAYSIZE(szFilePath)); StrCpyN( szPath, szFilePath, ARRAYSIZE(szPath)); StrCatBuff( szFilePath, "enc_rle.rpt", ARRAYSIZE(szFilePath));
hr = OpenStreamOnFile( MAPIAllocateBuffer, MAPIFreeBuffer, STGM_READWRITE | STGM_CREATE, szFilePath, NULL, &m_lpstreamEncodeRLE );
if ( hr ) AssertSz( FALSE, "Debug encode stream failed to initialize\n" );
StrCpyN (szFilePath, szPath, ARRAYSIZE(szFilePath)); StrCatBuff(szFilePath, "enc_raw.rpt", ARRAYSIZE(szFilePath));
hr = OpenStreamOnFile( MAPIAllocateBuffer, MAPIFreeBuffer, STGM_READWRITE | STGM_CREATE, szFilePath, NULL, &m_lpstreamEncodeRAW );
if ( hr ) AssertSz( FALSE, "Debug encode stream failed to initialize\n" ); } #endif
m_fConfigured = fTrue;
return ERROR_SUCCESS; }
//-----------------------------------------------------------------------------
// Name: CBinhexEncoder::HrEmit
// Description:
//
// Parameters:
// Returns:
// Effects:
//
// Notes:
// Handle Data Fork
// Resource fork.
//
// Revision:
// Initial:9/5/1996
//-----------------------------------------------------------------------------
HRESULT CBinhexEncoder::HrEmit( IN PB pbRead, IN OUT CB * pcbRead, OUT PB pbWrite, IN OUT CB * pcbWrite ) { HRESULT hr = ERROR_SUCCESS; CB cbHeader = 0; CB cbToProcess; CB cbInputCheckPoint = 0; CB cbOut; CB cb; BYTE rgbHeader[ cbMIN_BINHEX_HEADER_SIZE + 64 ];
m_cbConsumed = 0; m_cbProduced = 0; m_cbLeftInOutputBuffer = 0; m_cbLeftInInputBuffer = 0;
// Have to be initialized first
if ( !m_fConfigured ) { return ERROR_BAD_COMMAND; }
// Handle common 'bad parameter' errors
if ( !pbRead || !pbWrite || !pcbRead || !pcbWrite ) { return ERROR_INVALID_PARAMETER; }
// Repeated calls after maximum number of output lines were generated
// will not go through
if ( FMaxLinesReached() ) { *pcbRead = *pcbWrite = 0; return ERROR_SUCCESS; }
// If line length is unlimited, set m_cbLeftOnLastLine to be equal to
// the length of the input buffer
if ( !FLineLengthLimited() ) { m_cbLeftOnLastLine = *pcbWrite; }
m_pbWrite = pbWrite; m_cbWrite = *pcbWrite;
while ( TRUE ) { m_cbLeftInInputBuffer = *pcbRead - m_cbConsumed; m_cbLeftInOutputBuffer = *pcbWrite - m_cbProduced;
// If we have room in the output buffer keep going if in sEnd and no input left
if ( 0 == m_cbLeftInOutputBuffer || (0 == m_cbLeftInInputBuffer && sEND != m_eBinHexStateEnc) ) { goto Cleanup; }
switch ( m_eBinHexStateEnc ) { case sHEADER: { // Output BinHex Header line
CopyMemory( pbWrite, szBINHEXHDRLINE, cbBINHEXHDRLINE ); m_cbProduced += cbBINHEXHDRLINE; m_cLines += 2;
// Output leading ':'
m_pbWrite[m_cbProduced++] = ':'; ++m_cbLine;
// Output MACBIN Header; Header filename length
rgbHeader[cbHeader++] = m_lpmacbinHdr->cchFileName;
// Header filename
CopyMemory( rgbHeader + cbHeader, m_lpmacbinHdr->rgchFileName, m_lpmacbinHdr->cchFileName ); cbHeader += m_lpmacbinHdr->cchFileName;
// Null terminate filename
rgbHeader[cbHeader++] = '\0';
// Macfile TYPE
CopyMemory( rgbHeader + cbHeader, (LPBYTE)&m_lpmacbinHdr->dwType, sizeof(DWORD) ); cbHeader += sizeof(DWORD);
// Macfile CREATOR
CopyMemory( rgbHeader + cbHeader, (LPBYTE)&m_lpmacbinHdr->dwCreator, sizeof(DWORD) ); cbHeader += sizeof(DWORD);
// Macfile FLAGS
rgbHeader[cbHeader++] = m_lpmacbinHdr->bFinderFlags; rgbHeader[cbHeader++] = m_lpmacbinHdr->bFinderFlags2;
// Macfile Fork lengths
CopyMemory( rgbHeader + cbHeader, (LPBYTE)&m_lpmacbinHdr->lcbDataFork, sizeof(DWORD) ); cbHeader += sizeof(DWORD);
CopyMemory( rgbHeader + cbHeader, (LPBYTE)&m_lpmacbinHdr->lcbResourceFork, sizeof(DWORD) ); cbHeader += sizeof(DWORD);
// Calculate the binhex header CRC
CalcCRC16( rgbHeader, cbHeader, &m_wCRC ); CalcCRC16( (LPBYTE)&wZero, sizeof(WORD), &m_wCRC );
rgbHeader[cbHeader++] = HIBYTE( m_wCRC ); rgbHeader[cbHeader++] = LOBYTE( m_wCRC );
// BinHex the header into pbWrite. The initial assumption is that
// the buffer is going to big enough to encode the header.
// Output goes into m_pbWrite.
cbOut = 0; hr = HrBinHexBuffer( rgbHeader, cbHeader, &cbOut );
// setup for the data fork
m_eBinHexStateEnc = sDATA; m_cbFork = NATIVE_LONG_FROM_BIG( (LPBYTE)&m_lpmacbinHdr->lcbDataFork ); m_cbLeftInFork = m_cbFork; m_wCRC = 0; }
break;
case sDATA: { // determine how much we can process
cbToProcess = m_cbLeftInFork < m_cbLeftInInputBuffer ? m_cbLeftInFork : m_cbLeftInInputBuffer; cbInputCheckPoint = m_cbConsumed;
hr = HrBinHexBuffer( pbRead + cbInputCheckPoint, cbToProcess, &m_cbConsumed );
CalcCRC16( pbRead + cbInputCheckPoint, m_cbConsumed - cbInputCheckPoint, &m_wCRC );
m_cbLeftInFork -= m_cbConsumed - cbInputCheckPoint;
// flush output buffer
if ( hr ) goto Cleanup;
if ( !m_cbLeftInFork ) { // write out the last CRC
CalcCRC16( (LPBYTE)&wZero, sizeof(WORD), &m_wCRC );
cbHeader = 0;
rgbHeader[cbHeader++] = HIBYTE( m_wCRC ); rgbHeader[cbHeader++] = LOBYTE( m_wCRC );
cbOut = 0; hr = HrBinHexBuffer( rgbHeader, 2, &cbOut );
// discard padding
if ( m_cbFork % 128 ) { cb = 128 - ( m_cbFork % 128 );
if ( *pcbRead - m_cbConsumed < cb ) { DebugTrace( "Note: Support refilling input buffer to remove padding for Data\n" );
// need to pull in more data
m_cbPad = cb - (*pcbRead - m_cbConsumed); m_cbConsumed -= (*pcbRead - m_cbConsumed); } else { m_cbConsumed = cb; } }
// Set up for resource for if there is one and reset counters
m_cbFork = NATIVE_LONG_FROM_BIG( (LPBYTE)&m_lpmacbinHdr->lcbResourceFork ); m_cbLeftInFork = m_cbFork;
if ( !m_cbFork ) { // handle 0 byte resource fork
m_eBinHexStateEnc = sEND;
// write out crc for 0 length
cbOut = 0; hr = HrBinHexBuffer( (LPBYTE)&wZero, sizeof(WORD), &cbOut ); } else { m_eBinHexStateEnc = sRESOURCE; }
m_wCRC = 0; } } break;
case sRESOURCE: { if ( m_cbPad ) { m_cbConsumed -= m_cbPad; m_cbPad = 0; }
// determine how much we can process
cbToProcess = m_cbLeftInFork < m_cbLeftInInputBuffer ? m_cbLeftInFork : m_cbLeftInInputBuffer; cbInputCheckPoint = m_cbConsumed;
hr = HrBinHexBuffer( pbRead + cbInputCheckPoint, cbToProcess, &m_cbConsumed );
CalcCRC16( pbRead + cbInputCheckPoint, m_cbConsumed - cbInputCheckPoint, &m_wCRC );
m_cbLeftInFork -= m_cbConsumed - cbInputCheckPoint;
// flush output buffer
if ( hr ) goto Cleanup;
if ( !m_cbLeftInFork ) { // write out the last CRC
CalcCRC16( (LPBYTE)&wZero, sizeof(WORD), &m_wCRC );
cbHeader = 0;
rgbHeader[cbHeader++] = HIBYTE( m_wCRC ); rgbHeader[cbHeader++] = LOBYTE( m_wCRC );
cbOut = 0; hr = HrBinHexBuffer( rgbHeader, 2, &cbOut );
// discard padding
if ( m_cbFork % 128 ) { cb = 128 - ( m_cbFork % 128 );
if ( *pcbRead - m_cbConsumed < cb ) { DebugTrace( "Note: Support refilling input buffer to remove padding for Resource\n" );
// need to pull in more data
m_cbPad = cb - (*pcbRead - m_cbConsumed); m_cbConsumed -= (*pcbRead - m_cbConsumed); } else { m_cbConsumed = cb; } }
// set up to terminate
m_eBinHexStateEnc = sEND; } } break;
case sEND: { if ( m_cbPad ) { m_cbConsumed -= m_cbPad; m_cbPad = 0; }
if ( (*pcbWrite - m_cbProduced) == 0 ) break;
// flush out any repeated chars
if ( m_cbRepeat ) { if ( m_cbRepeat > 1 ) { // bump up the repeat count so it reflects actual number of chars to repeat.
m_cbRepeat++;
// encode the repeat code char
// note that we've already emitted the char that we're supplying
// the repeat info for.
hr = HrBinHexByte( BINHEX_REPEAT ); m_bPrev = BINHEX_REPEAT;
Assert( m_cbRepeat <= 255 );
// encode repeat count
hr = HrBinHexByte( (BYTE)(m_cbRepeat) ); m_bPrev = (BYTE)(m_cbRepeat); } else { hr = HrBinHexByte( m_bRepeat ); m_bPrev = m_bRepeat; } }
// check to see if we have bits in the accumulator
if ( m_cAccum ) { switch( m_cAccum ) { case 1: m_pbWrite[m_cbProduced++] = g_rgchBinHex8to6[((m_bPrev & 0x03) << 4)]; break;
case 2: m_pbWrite[m_cbProduced++] = g_rgchBinHex8to6[((m_bPrev & 0x0f) << 2)]; break;
case 3: m_pbWrite[m_cbProduced++] = g_rgchBinHex8to6[m_bCurr & 0x3f]; break;
default: AssertSz( FALSE, "HrBinHexByte: bad shift state\n" ); hr = ERROR_INVALID_PARAMETER; goto Cleanup; } }
// tack on terminating ':'
m_pbWrite[m_cbProduced++] = ':'; m_cbConsumed = *pcbRead;
// probably not so we would have to flush the
// bits out.
goto Cleanup; } } }
Cleanup:
if (hr == ERROR_SUCCESS || hr == ERROR_MORE_DATA) { // Check that at least some processing was done.
// Also this error is returned if we've exhausted the output
// buffer.
if ( (m_cbProduced == 0) || (m_cbLeftInInputBuffer > m_cbLeftInOutputBuffer) || (0 == m_cbLeftInOutputBuffer && sEND == m_eBinHexStateEnc) ) { hr = ERROR_INSUFFICIENT_BUFFER; } else if ( m_cbConsumed < *pcbRead ) { // Was all input processed?
// Note that it is okay to encode only part of the input buffer
// if maximum number of output lines was exceeded.
hr = ERROR_MORE_DATA; } }
// Report the new sizes to the caller.
Assert( m_cbConsumed <= *pcbRead ); Assert( m_cbProduced <= *pcbWrite );
*pcbRead = m_cbConsumed; *pcbWrite = m_cbProduced;
return hr; }
//-----------------------------------------------------------------------------
// Name: CBinhexEncoder::HrBinHexBuffer
//
// Description:
// Output goes into m_pbWrite
//
// Parameters:
// Returns:
// Effects:
// Notes:
//
// Revision:
// Initial:9/5/1996
//-----------------------------------------------------------------------------
HRESULT CBinhexEncoder::HrBinHexBuffer( IN LPBYTE lpbIn, IN CB cbIn, CB * lpcbConsumed ) { HRESULT hr = ERROR_SUCCESS; BOOL fEndRepeat = FALSE; CB cbInUsed = 0;
#if defined (DEBUG) && defined (BINHEX_TRACE)
CB cbOrigCbIn = cbIn; #endif
while ( cbIn && m_cbProduced + 5 < m_cbWrite ) { // process the next char in input buffer
m_bCurr = lpbIn[cbInUsed++]; --cbIn;
// check to see if we've seen this char before. Don't repeat
// if we just added a literal 0x90.
if ( m_bCurr == m_bPrev && !m_fHandledx90 ) { // m_cbRepeat is the count of repeat chars after the initial char.
// e.g., if there are two repeating chars, m_cbRepeat will be 1.
// Note that we've already emitted the char after which to add the repeat
// code and count.
if ( m_cbRepeat < 254 ) { m_cbRepeat++; m_bRepeat = m_bCurr; continue; } }
m_fHandledx90 = FALSE;
// we were counting repeating characters and the run stopped.
if ( m_cbRepeat > 1 ) { // set up to emit the run length encoding
fEndRepeat = TRUE; }
// Are we in repeat mode...
if ( m_cbRepeat > 1 && fEndRepeat == TRUE ) { // bump up the repeat count so it reflects actual number of chars to repeat.
m_cbRepeat++;
// if we're repeating 0x90 tack on the trailing 0x00
if ( m_bRepeat == BINHEX_REPEAT ) { hr = HrBinHexByte( '\0' ); }
// encode the repeat code char
// note that we've already emitted the char that we're supplying
// the repeat info for.
hr = HrBinHexByte( BINHEX_REPEAT );
Assert( m_cbRepeat <= 255 );
// encode repeat count
hr = HrBinHexByte( (BYTE)(m_cbRepeat) );
fEndRepeat = FALSE; m_cbRepeat = 0; } else if ( m_cbRepeat ) // check if we've got two chars to encode.
{ // encode the one char since we've already emitted
// the first one.
hr = HrBinHexByte( m_bRepeat );
if ( m_bRepeat == BINHEX_REPEAT ) { hr = HrBinHexByte( '\0' ); }
m_cbRepeat = 0; }
// special handling for 0x90 chars in stream but 0x90 can repeat
if ( m_bCurr == BINHEX_REPEAT && m_bPrev != BINHEX_REPEAT ) { hr = HrBinHexByte( BINHEX_REPEAT );
hr = HrBinHexByte( '\0' );
m_fHandledx90 = TRUE;
continue; }
// encode the char
hr = HrBinHexByte( m_bCurr );
if ( hr ) goto exit; }
// Check if we filled the output buffer
if ( cbIn && m_cbProduced + 5 >= m_cbWrite ) { hr = ERROR_INSUFFICIENT_BUFFER; }
exit:
#if defined (DEBUG) && defined (BINHEX_TRACE)
m_lpstreamEncodeRAW->Write( lpbIn, cbOrigCbIn - cbIn, NULL ); #endif
*lpcbConsumed += cbInUsed;
return hr; }
//-----------------------------------------------------------------------------
// Name: CBinhexEncoder::HrBinHexByte
// Description:
//
// Parameters:
// Returns:
// Effects:
// Notes:
// Revision:
// Initial:9/5/1996
//-----------------------------------------------------------------------------
HRESULT CBinhexEncoder::HrBinHexByte( IN BYTE b ) { HRESULT hr = ERROR_SUCCESS;
#if defined (DEBUG) & defined (BINHEX_TRACE)
hr = m_lpstreamEncodeRLE->Write( &b, 1, NULL ); #endif
switch( m_cAccum++ ) { case 0: m_pbWrite[m_cbProduced++] = g_rgchBinHex8to6[b >> 2]; ++m_cbLine; break;
case 1: m_pbWrite[m_cbProduced++] = g_rgchBinHex8to6[((m_bPrev & 0x03) << 4) | (b >> 4)]; ++m_cbLine; break;
case 2: m_pbWrite[m_cbProduced++] = g_rgchBinHex8to6[((m_bPrev & 0x0f) << 2) | (b >> 6)]; ++m_cbLine;
if ( m_cbLine >= 64 ) { m_pbWrite[m_cbProduced++] = chCR; m_pbWrite[m_cbProduced++] = chLF; m_cbLine = 0; ++m_cLines; }
m_pbWrite[m_cbProduced++] = g_rgchBinHex8to6[b & 0x3f]; ++m_cbLine; m_cAccum = 0; break;
default: AssertSz( FALSE, "HrBinHexByte: bad shift state\n" ); hr = ERROR_INVALID_PARAMETER; goto exit; }
if ( m_cbLine >= 64 ) { m_pbWrite[m_cbProduced++] = chCR; m_pbWrite[m_cbProduced++] = chLF; m_cbLine = 0; ++m_cLines; }
m_bPrev = b;
exit:
return hr; }
//-----------------------------------------------------------------------------
//
// CBinhexDecoder class implementation
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Name: CalcCRC16
// Description:
// Used to calculate a 16 bit CRC using the
// CCITT polynomial 0x1021.
//
// Parameters:
// Returns:
// Effects:
// Notes:
// Revision:
// Initial:7/30/1996
//-----------------------------------------------------------------------------
void CalcCRC16( LPBYTE lpbBuff, ULONG cBuff, WORD * wCRC ) { LPBYTE lpb; BYTE b; WORD uCRC; WORD fWrap; ULONG i;
uCRC = *wCRC;
for ( lpb = lpbBuff; lpb < lpbBuff + cBuff; lpb++ ) { b = *lpb;
for ( i = 0; i < 8; i++ ) { fWrap = uCRC & 0x8000; uCRC = (uCRC << 1) | (b >> 7);
if ( fWrap ) { uCRC = uCRC ^ 0x1021; }
b = b << 1; } }
*wCRC = uCRC; }
//-----------------------------------------------------------------------------
// Name: bIsMacFile
// Description:
//
// Parameters:
// Returns:
// FALSE: if the given dwCreator/dwType matches one of the
// pairs in g_lpCreatorTypes;
//
// TRUE: otherwise
//
// Effects:
// Notes:
// Revision:
// Initial:10/15/1996
//-----------------------------------------------------------------------------
BOOL bIsMacFile(DWORD dwCreator, DWORD dwType) { BOOL bRet = TRUE; int i; char szCreator[5] = { 0 }; char szType[5] = { 0 };
if ( dwType == 0 && dwCreator == 0 ) { bRet = FALSE; goto exit; }
if ( g_bCreatorTypeInit != TRUE ) { ReadCreatorTypes(); }
if ( g_lpCreatorTypes == NULL ) goto exit;
// Convert dwCreator & dwType to strings
CopyMemory( szCreator, &dwCreator, 4 ); CopyMemory( szType, &dwType, 4 );
for ( i = 0; i < g_cCreatorTypes; i ++ ) { if ( g_lpCreatorTypes[i].szCreator[0] == 0 && g_lpCreatorTypes[i].szType[0] == 0 ) { bRet = FALSE; break; } else if ( g_lpCreatorTypes[i].szCreator[0] == 0 && lstrcmpi( g_lpCreatorTypes[i].szType, szType ) == 0 ) { bRet = FALSE; break; } else if( g_lpCreatorTypes[i].szType[0] == 0 && lstrcmpi( g_lpCreatorTypes[i].szCreator, szCreator ) == 0 ) { bRet = FALSE; break; } else if( lstrcmpi( g_lpCreatorTypes[i].szCreator, szCreator ) == 0 && lstrcmpi( g_lpCreatorTypes[i].szType, szType ) == 0 ) { bRet = FALSE; break; } }
exit: return bRet ; }
//-----------------------------------------------------------------------------
// Name: ReadCreatorTypes
//
// Description:
//
// Read "NonMacCreatorTypes" registry key (REG_MULTI_SZ type)
// from the registry & build an array of Creator-Type pairs
//
// Parameters:
// Returns:
// Effects:
// Notes:
// Revision:
// Initial:10/15/1996
//-----------------------------------------------------------------------------
VOID ReadCreatorTypes( VOID ) { #ifdef MAC
g_bCreatorTypeInit = TRUE; #else // !MAC
DWORD dwStatus; DWORD dwType; DWORD cbData; char * lpData = NULL; char * lpCurrent = NULL; char * lpNext = NULL; int i; LONG lRet; HKEY hKey = 0; SCODE sc = S_OK;
g_bCreatorTypeInit = TRUE;
// Open IMC parameter registry
lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\MSExchangeIS\\ParametersSystem\\InternetContent", 0, KEY_READ, &hKey );
if ( lRet != ERROR_SUCCESS ) goto exit;
// read the registry key
dwStatus = RegQueryValueEx( hKey, "NonMacCreatorTypes", 0, &dwType, (LPBYTE)NULL, &cbData );
if ( dwStatus != ERROR_SUCCESS // key missing
|| dwType != REG_MULTI_SZ // wrong type
|| cbData <= 4 ) // invalid size
{ goto exit; }
if (FAILED(HrAlloc((LPVOID *)&lpData, cbData))) goto exit;
ZeroMemory( (LPVOID)lpData, cbData );
dwStatus = RegQueryValueEx( hKey, "NonMacCreatorTypes", NULL, &dwType, (LPBYTE)lpData, &cbData );
if ( dwStatus != ERROR_SUCCESS ) goto exit;
// Determine # of pairs read:
g_cCreatorTypes = 0;
for ( i= 0; i < (LONG)cbData-1; i++ ) { if ( lpData[i] == '\0' ) g_cCreatorTypes ++; }
if (FAILED(HrAlloc((LPVOID *)&g_lpCreatorTypes, sizeof(sCreatorType) * g_cCreatorTypes))) goto exit;
ZeroMemory( (LPVOID)g_lpCreatorTypes, sizeof(sCreatorType) * g_cCreatorTypes );
// Build the Creator-Type array
lpCurrent = lpData;
i = 0; while ( lpCurrent < (lpData + cbData -1) ) { lpNext = StrChr( lpCurrent, ':' );
if( lpNext == NULL ) { //no ':' found; skip to next string
lpCurrent = StrChr( lpCurrent, '\0' ) + 1; continue; }
*lpNext = '\0'; if ( StrChr( lpCurrent, '*' ) == NULL ) CopyMemory( &g_lpCreatorTypes[i].szCreator, lpCurrent, MIN(4, lpNext-lpCurrent) );
lpCurrent = lpNext + 1;
lpNext = StrChr( lpCurrent, '\0' );
if ( lpNext == NULL ) break;
if ( StrChr( lpCurrent, '*' ) == NULL ) { CopyMemory( &g_lpCreatorTypes[i].szType, lpCurrent, MIN( 4, lpNext-lpCurrent) ); }
lpCurrent = lpNext + 1; i++; }
g_cCreatorTypes = i;
exit:
if ( hKey != 0 ) RegCloseKey( hKey );
SafeMemFree(lpData);
if ( g_cCreatorTypes == 0 && g_lpCreatorTypes != NULL ) { SafeMemFree(g_lpCreatorTypes); } #endif // !MAC
}
|