/*++ dotstuff.h This header files defines some of the Dot Stuffing helper objects that we have built for the File Handle Cache. --*/ #include "refptr2.h" class IDotManipBase : public CRefCount2 { protected : // // Return the number of bytes in the buffer that should pass // through the IO operation ! // virtual BOOL InternalProcessBuffer( BYTE* lpb, // The users original buffer DWORD cbIn, // Number of bytes to look at in orignal buffer DWORD cbAvailable, // Number of bytes available in the original buffer DWORD &cbRemains, // Number of bytes we left in the original Buffer - can be zero BYTE* &lpbOut, // An output buffer that holds a portion of the string ! DWORD &cbOut, // The amount of stuff in our output buffer int &cBias // Whether we should offset associated IO's to overwrite // previous results ! ) = 0 ; // // This is the number of times the string as appeared in the message - // NOTE : This can be initialized to -1 if we are examining the message // to determine that it needs to be dot stuffed. This is because // the terminating CRLF.CRLF will set occurrences to 0, indicating that // there is no issue. // long m_cOccurrences ; // // Private constructor allows us to initialize m_cOccurrences ! // IDotManipBase( long l ) : m_cOccurrences( l ) { } public : /*++ This class defines a pure virtual API used by our Dot Manipulation classes to define how they interact with other code. --*/ // // Destruction is always virtual ! // virtual ~IDotManipBase() {} // // Publicly exposed API ! // inline BOOL ProcessBuffer( BYTE* lpb, DWORD cbIn, DWORD cbAvailable, DWORD &cbRemains, BYTE* &lpbOut, DWORD &cbOut, int &cBias, BOOL fFinalBuffer = FALSE, BOOL fTerminatorPresent = FALSE ) { // // Validate the callers arguments as much as possible ! // _ASSERT( lpb != 0 ) ; _ASSERT( cbIn != 0 ) ; _ASSERT( cbAvailable >= cbIn ) ; // // Ensure that these are correctly setup ! // cbRemains = 0 ; lpbOut = 0 ; cbOut = 0 ; cBias = 0 ; BOOL fReturn = InternalProcessBuffer( lpb, cbIn, cbAvailable, cbRemains, lpbOut, cbOut, cBias ) ; // // Do some checking on the results of the call ! // _ASSERT( cBias <= 0 ) ; _ASSERT( (lpbOut == 0 && cbOut == 0) || (lpbOut != 0 && cbOut != 0) ) ; _ASSERT( cbRemains <= cbAvailable ) ; return fReturn ; } // // Return the number of times we saw a pattern matching the // sequence specified when we were constructed ! // long NumberOfOccurrences() { return m_cOccurrences ; } } ; extern BYTE szDot[] ; extern BYTE szDotStuffed[] ; extern BYTE szShrink[] ; extern BYTE szGrow[] ; class CDotScanner : public IDotManipBase { /*++ This class detects messages which have Dot Stuffing issues. We can operate in one of two modes - determine if the message flowing by is dot stuffed, or determine if the message flowing by would need to be dot stuffed. --*/ private : enum { SIGNATURE = 'futs', // should appear as 'stuf' in the debugger ! DEAD_SIGNATURE = 'futx' } ; // // Our signature ! // DWORD m_dwSignature ; // // This is the string we are interested in detecting : // BYTE *m_pchMatch ; // // This is our current match state ! // BYTE *m_pchState ; // // Don't allow copies and stuff so make these private ! // CDotScanner( CDotScanner& ) ; CDotScanner& operator=( CDotScanner& ) ; public : CDotScanner( BOOL fWillGetTerminator = TRUE ) : IDotManipBase( (fWillGetTerminator ? -1 : 0) ), m_dwSignature( SIGNATURE ), m_pchMatch( szDotStuffed ), m_pchState( szDotStuffed ) { m_cRefs = 0 ; // Hack - our base class CRefCount2 doesn't do what we want ! } ~CDotScanner( ) { m_dwSignature = DEAD_SIGNATURE ; } // // See if the user specified pattern occurs in the buffer ! // BOOL InternalProcessBuffer( BYTE* lpb, // The users original buffer DWORD cbIn, // Number of bytes to look at in orignal buffer DWORD cbAvailable, // Number of bytes available in the original buffer DWORD &cbRemains, // Number of bytes we left in the original Buffer - can be zero BYTE* &lpbOut, // An output buffer that holds a portion of the string ! DWORD &cbOut, // The amount of stuff in our output buffer int &cBias // Whether we should offset associated IO's to overwrite // previous results ! ) ; } ; class CDotModifier : public IDotManipBase { /*++ This class is used to detect messages that need to be dot-stuffed or de-dot stuffed. We can either remove or insert dot-stuffing as required on the fly, depending on how we are constructed ! --*/ private : enum { SIGNATURE = 'mtod', // should appear as 'stuf' in the debugger ! DEAD_SIGNATURE = 'mtox' } ; // // Our signature ! // DWORD m_dwSignature ; // // This is the string we are interested in detecting : // BYTE *m_pchMatch ; // // This is our current match state ! // BYTE *m_pchState ; // // This is the string we want to have replace the string we're detecting // BYTE *m_pchReplace ; // // Number of characters in the matching and replacement string. // int m_cchMatch ; int m_cDiff ; // // This is the total offset we've accumulated in the stream ! // long m_cOffsetBytes ; // // Don't allow copies and stuff so make these private ! // CDotModifier( CDotModifier& ) ; CDotModifier& operator=( CDotModifier& ) ; public : // // Initialize our state - cannot fail ! // CDotModifier( BYTE* szMatch = szDotStuffed, BYTE* szReplace = szShrink ) : IDotManipBase( 0 ), m_dwSignature( SIGNATURE ), m_pchMatch( szMatch ), m_pchState( szMatch ), m_pchReplace( szReplace ), m_cchMatch( strlen( (const char*)szMatch) ), m_cDiff( strlen( (const char*)szReplace) - strlen( (const char*)szMatch ) ), m_cOffsetBytes( 0 ) { m_cRefs = 0 ; // HACK - our base class CRefCount2 doesn't do what we want ! } // // Just mark our Signature DWORD - handy for debugging ! // ~CDotModifier() { m_dwSignature = DEAD_SIGNATURE ; } // // Modify dot sequences as they go by ! // BOOL InternalProcessBuffer( BYTE* lpb, // The users original buffer DWORD cbIn, // Number of bytes to look at in orignal buffer DWORD cbAvailable, // Number of bytes available in the original buffer DWORD &cbRemains, // Number of bytes we left in the original Buffer - can be zero BYTE* &lpbOut, // An output buffer that holds a portion of the string ! DWORD &cbOut, // The amount of stuff in our output buffer int &cBias // Whether we should offset associated IO's to overwrite // previous results ! ) ; } ;