//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1996. // // File: tracer.cxx // // Contents: // // Classes: // // Functions: // // Coupling: // // Notes: // // History: 10-28-1996 ericne Created // //---------------------------------------------------------------------------- #include "pch.cxx" #include "tracer.hxx" //+--------------------------------------------------------------------------- // // Member: CTracer::CTracer // // Synopsis: // // Arguments: (none) // // Returns: // // History: 10-28-1996 ericne Created // // Notes: // //---------------------------------------------------------------------------- CTracer::CTracer( ) : m_hTempFile( ), m_hMappedFile( ), m_tcsFileStart( NULL ), m_dwPut( 0 ), m_dwGet( 0 ) { } //CTracer::CTracer //+--------------------------------------------------------------------------- // // Member: CTracer::~CTracer // // Synopsis: // // Arguments: (none) // // Returns: // // History: 10-28-1996 ericne Created // // Notes: // //---------------------------------------------------------------------------- CTracer::~CTracer( ) { if( NULL != m_tcsFileStart ) { if( ! UnmapViewOfFile( (LPCVOID) m_tcsFileStart ) ) _tprintf( _T("Unable to unmap view to the temporary file.\r\n") _T("GetLastError return 0x%08X\r\n"), GetLastError()); } } //CTracer::~CTracer //+--------------------------------------------------------------------------- // // Member: CTracer::Init // // Synopsis: // // Arguments: (none) // // Returns: TRUE if successful, FALSE otherwise // // History: 10-28-1996 ericne Created // // Notes: CAutoHandle is a "smart" handle object that calls CloseHandle // in the destructor // //---------------------------------------------------------------------------- BOOL CTracer::Init( ) { TCHAR szFileName[ L_tmpnam ]; CFileHandle FileHandle; CAutoHandle MapHandle; // Create a temporary file name if( NULL == _ttmpnam( szFileName ) ) { return( FALSE ); } // Open the file FileHandle = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, NULL ); // MAke sure it was opened successfully if( INVALID_HANDLE_VALUE == FileHandle ) { _ftprintf( stderr, _T("Unable to create temporary file\r\n") _T("GetLastError returns 0x%08X\r\n"), GetLastError() ); return( FALSE ); } // Create a file mapping MapHandle = CreateFileMapping( FileHandle.GetHandle(), NULL, PAGE_READWRITE, 0, dwMaxFileSize, NULL ); // Make sure the file was mapped successfully if( NULL == MapHandle ) { _ftprintf( stderr, _T("Unable to create mapped temp file\r\n") _T("GetLastError returns 0x%08X\r\n"), GetLastError() ); return( FALSE ); } // Map a view of the entire file m_tcsFileStart = (LPTSTR) MapViewOfFile( MapHandle.GetHandle(), FILE_MAP_ALL_ACCESS, 0, 0, 0 ); // Map the whole file // Make sure we have a valid view of the file if( NULL == m_tcsFileStart ) { _ftprintf( stderr, _T("Unable to map view of temporary file\r\n") _T("GetLastError returns 0x%08X\r\n"), GetLastError() ); return( FALSE ); } // Make the first character in the file the EndOfEntry character m_tcsFileStart[ m_dwPut++ ] = tcsEndOfEntry; // Copy the file handle (increments the ref count) m_hTempFile = FileHandle; // Copy the map handle (increments the ref count) m_hMappedFile = MapHandle; return( TRUE ); } //CTracer::Init //+--------------------------------------------------------------------------- // // Member: CTracer::Trace // // Synopsis: Enter the message into the trace file // // Arguments: [szFormat] -- the format string // // Returns: (none) // // History: 10-28-1996 ericne Created // // Notes: // //---------------------------------------------------------------------------- void CTracer::Trace( LPCTSTR szFormat, ... ) { va_list va; if( m_dwPut >= dwMaxCharsInFile ) return; va_start( va, szFormat ); m_dwPut += _vsntprintf( &m_tcsFileStart[ m_dwPut ], dwMaxCharsInFile - m_dwPut, szFormat, va ); m_tcsFileStart[ m_dwPut++ ] = tcsEndOfEntry; va_end( va ); } //CTracer::Trace //+--------------------------------------------------------------------------- // // Member: CTracer::Dump // // Synopsis: reads the past cEntries from the trace file and sends them // to pFile // // Arguments: [pFile] -- file stream pointer // [cEntries] -- count of entries to dump // // Returns: (none) // // History: 10-28-1996 ericne Created // // Notes: Passing in a negative number for cEntries dumps all the entries // //---------------------------------------------------------------------------- void CTracer::Dump( FILE* pFile, int cEntries ) { m_dwGet = m_dwPut - 1; // At last tcsEndOfEntry while( cEntries-- && 0 < m_dwGet ) { // This cannot read before beginning of file since first // tchar in file is tcsEndOfEntry while( tcsEndOfEntry != m_tcsFileStart[ --m_dwGet ] ) { } // This uses the fact that the EndOfEntry character is '\0' _ftprintf( pFile, _T("\r\n%s"), &m_tcsFileStart[ m_dwGet + 1 ] ); } } //CTracer::Dump //+--------------------------------------------------------------------------- // // Member: CTracer::Clear // // Synopsis: Flushes the contents of the trace file // // Arguments: (none) // // Returns: (none) // // History: 10-29-1996 ericne Created // // Notes: // //---------------------------------------------------------------------------- void CTracer::Clear( ) { m_dwPut = m_dwGet = 0; m_tcsFileStart[ m_dwPut++ ] = tcsEndOfEntry; } //CTracer::Clear //+--------------------------------------------------------------------------- // // Member: CTracer::Interact // // Synopsis: Enters into an interactive dialog with the user, displays the // previous n entries in the trace file, and optionally sends // them to a user-specified file // // Arguments: (none) // // Returns: (none) // // History: 10-29-1996 ericne Created // // Notes: // //---------------------------------------------------------------------------- void CTracer::Interact( ) { const int nMaxCommentLength = 80; int cEntries = 0; FILE* pFile = NULL; TCHAR tcsComment[ nMaxCommentLength ]; TCHAR tcsFileName[ MAX_PATH ]; TCHAR tcsYesNo = _T('\0'); while( 1 ) { _tprintf( _T("\r\nHow many of the entries would you like see?\r\n") _T("( -1 for all, 0 to quit )\r\n") ); fflush( stdin ); _tscanf( _T("%i"), &cEntries ); if( 0 == cEntries ) break; Dump( stdout, cEntries ); do { _tprintf( _T("\r\nWould you like to send ") _T("this to a file (y/n)? ") ); fflush( stdin ); tcsYesNo = (TCHAR) _totlower( _gettchar() ); } while( _T('n') != tcsYesNo && _T('y') != tcsYesNo ); if( _T('y') == tcsYesNo ) { _tprintf( _T("\r\nEnter the name of the file ") _T("to which to append\r\n") ); fflush( stdin ); _getts( tcsFileName ); pFile = _tfopen( tcsFileName, _T("a+") ); _tprintf( _T("\r\nEnter a comment for this trace ") _T("(max %i chars)\r\n"), nMaxCommentLength ); fflush( stdin ); _getts( tcsComment ); if( NULL != pFile ) { _ftprintf( pFile, _T("\r\n\r\n%s\r\n"), tcsComment ); Dump( pFile, cEntries ); fclose( pFile ); } } } } //CTracer::Interact