|
|
//++
//
// Copyright (c) 1999 Microsoft Corporation
//
// File: commonlib.cpp
//
// Contents: Implements functions used across binaries in SFP
//
//
// History: AshishS Created 07/02/99
//
//--
#include "commonlibh.h"
#ifdef THIS_FILE
#undef THIS_FILE
#endif
static char __szTraceSourceFile[] = __FILE__; #define THIS_FILE __szTraceSourceFile
//
// #define TRACEID SFPCOMLIBID
//
#define TRACEID 100
#define TOASCII(str) str
#define USES_CONVERSION
//
// MBCS Char Index Function
//
inline LPTSTR CharIndex(LPTSTR pszStr, DWORD idwIndex) { #ifdef _MBCS
DWORD cdwIndex; for( cdwIndex = 0;cdwIndex < idwIndex; cdwIndex++) { pszStr = _tcsinc( pszStr ); } #else
pszStr = pszStr + idwIndex; #endif
return( pszStr ); }
//
// Calculate the Real size of a MBCS String
//
DWORD StringLengthBytes( LPTSTR pszStr ) { DWORD cdwNumBytes = 0;
#ifdef _MBCS
for( ; *pszStr; pszStr = _tcsinc( pszTemp ) ) { cdwNumBytes += _tclen( pszTemp ) }
//
// Add one for the NULL char
//
cdwNumBytes += sizeof( TCHAR ); #else
//
// Return (length+NULL)*sizeof(TCHAR)
//
cdwNumBytes = (_tcslen( pszStr ) + 1) * sizeof(TCHAR); #endif
return( cdwNumBytes ); }
//
// String Trimming-- this is a quite complicated routine because of all
// the work needed to get around MBCS string manipulation.
//
void TrimString( LPTSTR pszStr ) { WCHAR *pszStart=NULL; WCHAR *pszBufStart = NULL;
LONG cStrLen =0; DWORD cdwOrigSizeBytes;
WCHAR szStrBuf[MAX_BUFFER];
DWORD dwError;
TraceFunctEnter("TrimString");
if( !pszStr ) { ErrorTrace(TRACEID, "NULL String passed to trim string"); goto cleanup; }
//
// Find the original size in bytes so we can convert back
// to MBCS later.
//
cdwOrigSizeBytes = StringLengthBytes( pszStr );
#ifndef _UNICODE
if( !MultiByteToWideChar( GetCurrentCodePage(), 0, pszStr, -1, szStrBuf, MAX_BUFFER ) ) { dwError = GetLastError(); ErrorTrace( TRACEID, "MultiByteToWideChar( ) failed- ec--%d", dwError); goto cleanup; } pszStart = szStrBuf; pszBufStart = szStrBuf; #else
pszStart = pszStr; pszBufStart = pszStr; #endif
//
// get the first non whitespace characters
//
for( ; (*pszStart == L' ' || *pszStart == L'\t' || *pszStart == L'\n' || *pszStart == L'\r'); pszStart++ ) { ; }
cStrLen = wcslen( pszStart );
if( cStrLen == 0 ) { DebugTrace(TRACEID, "Empty string in Trim String.",0); goto cleanup; }
//
// go back before the null char
//
cStrLen--; while( (cStrLen >= 0) && ( (pszStart[cStrLen] == L' ') || (pszStart[cStrLen] == L'\t' ) || (pszStart[cStrLen] == L'\n' ) || (pszStart[cStrLen] == L'\r' ) ) ) { pszStart[cStrLen--] = 0;
//pszStart[cStrLen--] = 0;
}
if( cStrLen == -1 ) { DebugTrace(TRACEID, "Empty string in Trim String.",0); goto cleanup; } //
// Shift the memory back left ( The +2 is because we need to
// move the null and cStrLen is an index value at this point)
//
MoveMemory( (PVOID) pszBufStart, pszStart,(cStrLen + 2)*sizeof(WCHAR) );
//
// Convert back
//
#ifndef _UNICODE
if(!WideCharToMultiByte( GetCurrentCodePage(), // code page
0, // performance and mapping flags
pszBufStart, // address of wide-character string
-1, // number of characters in string
pszStr, // address of buffer for new string
cdwOrigSizeBytes, // size of buffer
NULL, // address of default for unmappable
// characters
NULL) ) // address of flag set when default
{ dwError = GetLastError(); ErrorTrace( TRACEID, "MultiByteToWideChar( ) failed- ec--%d", dwError); goto cleanup; } #endif
cleanup: TraceFunctLeave(); return; }
//
// A buffer safe string copy. The buffer is in characters.
//
BOOL BufStrCpy(LPTSTR pszBuf, LPTSTR pszSrc, LONG lBufSize) { DWORD cdwSrcLen=0; DWORD cdwBytesUsed=0; DWORD cdwNumCharsToCopy;
cdwSrcLen = _tcslen( pszSrc );
if( (unsigned) lBufSize >= StringLengthBytes( pszSrc ) ) { _tcscpy( pszBuf, pszSrc ); return TRUE; }
#ifdef _MBCS
LPTSTR pszTemp; DWORD cdwBufLeft;
//Save room for the NULL char
cdwBufLeft = (lBufSize-1) * sizeof(TCHAR); pszTemp = pszSrc; cdwNumCharsToCopy = 0;
while( (_tcsnextc(pszTemp) != 0) && ( cdwBufLeft > 0 ) ) { cdwBufLeft -= _tclen( pszTemp ); pszTemp = _tcsinc( pszTemp ); if( cdwBufLeft > 0 ) { cdwNumCharsToCopy++; }
} #else
cdwNumCharsToCopy = lBufSize - 1; #endif
_tcsncpy( pszBuf, pszSrc, cdwNumCharsToCopy );
CHARINDEX( pszBuf, cdwNumCharsToCopy ) = 0;
return TRUE; }
//
// Function: GetLine
// Desc : Gets a line from a file stream, ignores empty lines and
// lines starting with '#'- it also trims off whitespace
// and newline (\n) and return (\r) characters from the input.
// Returns: 0 = Failed or end of st stream
// or
// Length of the string read in ( characters )
//
LONG GetLine(FILE *fl, LPTSTR pszBuf, LONG lMaxBuf) { LONG lRead; _ASSERT( fl ); _ASSERT( pszBuf ); if( lMaxBuf <= 0 ) { return( 0 ); }
do { pszBuf[0] = 0; if( _fgetts( pszBuf, lMaxBuf, fl ) == NULL ) { // our buffer might be too small
return( 0 ); }
// trim the buffer, do it this point so # doesn't get missed because of a space
TrimString( pszBuf );
if( _tcsnextc(pszBuf) == 0 ) { continue; }
} while( _tcsnextc(pszBuf) == _TEXT('#') );
lRead = _tcslen( pszBuf ); return( lRead ); }
//
// Function: GetField
// Desc : Gets a field _lNum_ (0 based index) delimited by _chSep_
// from string psmMain and puts it into pszInto. pszInto
// should be >= in size as pszMain since GetField assumes
// there is enough space.
// Returns: 1 -TRUE, 0, FALSE
//
LONG GetField(LPTSTR pszMain, LPTSTR pszInto, LONG lNum, TCHAR chSep) {
WCHAR *pszP; WCHAR *pszI;
LONG ToFind; WCHAR szMainBuf[MAX_BUFFER]; WCHAR szIntoBuf[MAX_BUFFER];
DWORD dwError; BOOL fReturn = FALSE;
TraceFunctEnter("CXMLFileListParser::GetField");
if(!pszMain || !pszInto) { goto cleanup; }
#ifndef _UNICODE
if( !MultiByteToWideChar( CP_OEMCP, 0, pszMain, -1, szMainBuf, MAX_BUFFER ) ) { dwError = GetLastError(); ErrorTrace( TRACEID, "MultiByteToWideChar( ) failed- ec--%d", dwError); goto cleanup; }
pszP = szMainBuf; pszI = szIntoBuf; #else
pszP = pszMain; pszI = pszInto; #endif
ToFind = lNum;
while( *pszP != 0 && ToFind > 0) { if( *pszP == (WCHAR) ((TBYTE) chSep) ) { ToFind--; } pszP++; }
if( *pszP == 0 ) { goto cleanup; }
while(*pszP != 0 && *pszP != (WCHAR) ((TBYTE) chSep) ) { *pszI = *pszP; pszI++; pszP++;
} *pszI = 0;
#ifndef _UNICODE
//
// Even though we know by definition the products is smaller than
// the source, we need to get the exact size or otherwise
// WidCharToMultiByte will blow some bounds.
//
if(!WideCharToMultiByte( CP_OEMCP, // code page
0, // performance and mapping flags
szIntoBuf, // address of wide-character string
-1, // number of characters in string
pszInto, // address of buffer for new string
StringLengthBytes(pszMain), // size of buffer
NULL, // address of default for unmappable char
NULL) ) // address of flag set when default
{ dwError = GetLastError(); ErrorTrace( TRACEID, "MultiByteToWideChar( ) failed- ec--%d", dwError); goto cleanup; }
#endif
fReturn = TRUE;
cleanup:
TraceFunctLeave();
return( fReturn );
}
inline UINT GetCurrentCodePage() { //
// the current code page value
//
static UINT uiLocal;
//
// only query once-- by ANSI standard, should init to 0
//
static BOOL fPrevQuery;
TraceFunctEnter("GetCurrentCodePage");
//
// Only bother with the query stuff once
// Load variables onto the stack only when needed.
//
if( FALSE == fPrevQuery ) { TCHAR *pszCurrent;
// 256 should be able to fit the language name.
TCHAR szBuffer[256];
uiLocal = CP_ACP; pszCurrent = NULL;
#ifndef UNICODE
pszCurrent = setlocale( LC_CTYPE, ""); #else
pszCurrent = _wsetlocale( LC_CTYPE, L""); #endif
if( NULL == pszCurrent ) { ErrorTrace(TRACEID, "Error querying code locale.",0); goto cleanup; }
if( FALSE == GetField( pszCurrent, szBuffer, 1, _TEXT('.')) ) { ErrorTrace(TRACEID, "Error getting code page.",0); goto cleanup; } uiLocal = _ttoi( szBuffer ); // some bugus input
if( uiLocal == 0 ) { // default to the ansi code page
uiLocal = CP_ACP; } fPrevQuery = TRUE; }
cleanup: TraceFunctLeave(); return( uiLocal ); }
#define DIFF( a, b ) (INT)(INT_PTR)( (PBYTE)(a) - (PBYTE)(b) )
BOOL ExpandShortNames( LPTSTR pFileName, DWORD cbFileName, LPTSTR LongName, DWORD cbLongName ) { PTSTR pStart; PTSTR pEnd; PTSTR pCurrent; TCHAR ShortName[MAX_PATH]; DWORD cbShortName = 0, LongNameIndex = 0;
WIN32_FIND_DATA fd;
BOOL bRet = TRUE;
pStart = pFileName; pCurrent = pFileName;
LongNameIndex = 0;
//
// scan the entire string
//
while (*pCurrent) { //
//
// in this example the pointers are like this:
//
// \Device\HarddiskDmVolumes\PhysicalDmVolumes\ // BlockVolume3\Progra~1\office.exe
// ^ ^
// | |
// pStart pEnd
//
// pStart always points to the last seen '\\' .
//
//
// is this a potential start of a path part?
//
if (*pCurrent == L'\\') { DWORD cbElem = DIFF(pCurrent, pStart) + sizeof(TCHAR);
if (LongNameIndex + cbElem > cbLongName ) { bRet = FALSE; goto End; } //
// yes. copy in the dest string and update pStart.
//
RtlCopyMemory( (PBYTE)LongName + LongNameIndex, pStart, cbElem ); // include '\\'
LongNameIndex += cbElem;
pStart = pCurrent; }
//
// does this current path part contain a short version (~)
//
if (*pCurrent == L'~') {
//
// we need to expand this part.
//
//
// find the end
//
while (*pCurrent != L'\\' && *pCurrent != 0) { pCurrent++ ; }
pEnd = pCurrent;
cbShortName = DIFF(pEnd, pFileName);
CopyMemory( ShortName, pFileName, cbShortName );
ShortName[cbShortName/sizeof(TCHAR)] = 0;
if ( FindFirstFile( ShortName, &fd ) ) { DWORD cbElem = (_tcslen(fd.cFileName)+1) * sizeof(TCHAR);
if ((LongNameIndex + cbElem) > cbLongName ) { bRet = FALSE; goto End; } RtlCopyMemory( (PBYTE)LongName + LongNameIndex, fd.cFileName, cbElem ); // include '\\'
LongNameIndex += cbElem;
LongName[(LongNameIndex - sizeof(TCHAR))/sizeof(TCHAR)] = TEXT('\\'); } else { DWORD cbElem = (_tcslen(ShortName) + 1) * sizeof( TCHAR ); if ((LongNameIndex + cbElem) > cbLongName ) { bRet = FALSE; goto End; }
RtlCopyMemory( (PBYTE)LongName + LongNameIndex, pStart, cbElem + sizeof(TCHAR)); // include '\\'
LongNameIndex += cbElem; }
pStart = pEnd + 1;
if ( *pEnd == TEXT('\\') ) { pCurrent = pStart; continue; } else { pCurrent = pEnd; }
} // if (*pCurrent == L'~')
pCurrent++; }
if ( pEnd != pCurrent ) { DWORD cbElem = DIFF( pCurrent, pStart ) + sizeof(TCHAR);
if ((LongNameIndex + cbElem) > cbLongName ) { bRet = FALSE; goto End; }
RtlCopyMemory( (PBYTE)LongName + LongNameIndex, pStart, cbElem); // include '\\'
LongNameIndex += cbElem; }
LongName[(LongNameIndex - sizeof(TCHAR))/sizeof(TCHAR)] = 0;
End: return bRet;
} // SrExpandShortNames
|