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

// --------------------------------------------------------------------------------
// 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
}