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.
 
 
 
 
 
 

659 lines
15 KiB

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