/*++ Copyright (c) 2000 Microsoft Corporation Module Name: Common.cpp Abstract: Common functions for all modules Notes: None History: 12/15/1999 linstev Created 01/10/2000 linstev Format to new style --*/ #include #include "ShimHook.h" #ifdef DBG extern DEBUGLEVEL GetDebugLevel(); #endif /*++ Function Description: Print a formatted string using DebugOutputString. Arguments: IN dwDetail - Detail level above which no print will occur IN pszFmt - Format string Return Value: None History: 11/01/1999 markder Created --*/ #ifdef DBG VOID __cdecl DebugPrintf( DEBUGLEVEL dwDetail, LPSTR pszFmt, ... ) { char szT[1024]; va_list arglist; if (dwDetail <= GetDebugLevel()) { switch (dwDetail) { case eDbgLevelError: OutputDebugStringA ("[FAIL] "); break; case eDbgLevelWarning: OutputDebugStringA ("[WARN] "); break; case eDbgLevelUser: OutputDebugStringA ("[USER] "); break; case eDbgLevelInfo: OutputDebugStringA ("[INFO] "); break; } va_start(arglist, pszFmt); _vsnprintf(szT, 1023, pszFmt, arglist); szT[1023] = 0; va_end(arglist); OutputDebugStringA(szT); } } /*++ Function Description: Assert that prints file and line number. Arguments: IN dwDetail - Detail level above which no print will occur IN pszFmt - Format string Return Value: None History: 11/01/1999 markder Created --*/ VOID DebugAssert( LPSTR szFile, DWORD dwLine, BOOL bAssert, LPSTR szHelpString ) { if (!bAssert ) { int i; for (i=0; i<80; i++) DPF(eDbgLevelError, "+"); DPF(eDbgLevelError, "\n"); DPF(eDbgLevelError, "FILE: %s\n", szFile); DPF(eDbgLevelError, "LINE: %d\n", dwLine); DPF(eDbgLevelError, "ASSERT: %s\n", szHelpString); for (i=0; i<80; i++) DPF(eDbgLevelError, "+"); DPF(eDbgLevelError, "\n"); #ifdef _X86_ __asm int 3; #else #pragma message ("Not implented on IA64") #endif } } #endif /*++ Function Description: Determine if a file resides on a CD Rom drive Arguments: IN wszFileName - Filename including path Return Value: TRUE if file is on CD drive History: 01/10/2000 linstev Updated --*/ BOOL IsOnCDRomA(LPCSTR szFileName) { CHAR szDrive[4]; CHAR *szCurDir = NULL; DWORD dwCurDirSize = 0; if (szFileName[1] == ':') { szDrive[0] = szFileName[0]; szDrive[1] = ':'; szDrive[2] = '\\'; szDrive[3] = '\0'; } else if (!(szFileName[0] == '\\' && szFileName[1] == '\\')) { // Not UNC naming, must be a relative path dwCurDirSize = GetCurrentDirectoryA(0, szCurDir); if (dwCurDirSize) { szCurDir = (PCHAR)LocalAlloc( LPTR, dwCurDirSize * sizeof(CHAR)); dwCurDirSize = GetCurrentDirectoryA( dwCurDirSize, szCurDir); if (dwCurDirSize && !(szCurDir[0] == '\\' && szCurDir[1] == '\\')) { szDrive[0] = szCurDir[0]; szDrive[1] = ':'; szDrive[2] = '\\'; szDrive[3] = '\0'; } LocalFree( szCurDir ); szCurDir = NULL; } } return (GetDriveTypeA(szDrive) == DRIVE_CDROM); } /*++ Function Description: Determine if a file resides on a CD Rom drive Arguments: IN wszFileName - Filename including path Return Value: TRUE if file is on CD drive History: 01/10/2000 linstev Updated --*/ BOOL IsOnCDRomW(IN LPCWSTR wszFileName) { WCHAR wszDrive[4]; WCHAR *wszCurDir = NULL; DWORD dwCurDirSize = 0; if (wszFileName[1] == L':') { wszDrive[0] = wszFileName[0]; wszDrive[1] = L':'; wszDrive[2] = L'\\'; wszDrive[3] = L'\0'; } else if (!(wszFileName[0] == L'\\' && wszFileName[1] == L'\\')) { // Not UNC naming, must be a relative path dwCurDirSize = GetCurrentDirectoryW(0, wszCurDir); if (dwCurDirSize) { wszCurDir = (PWCHAR)LocalAlloc( LPTR, dwCurDirSize * sizeof(WCHAR)); dwCurDirSize = GetCurrentDirectoryW( dwCurDirSize, wszCurDir ); if (dwCurDirSize && !(wszCurDir[0] == L'\\' && wszCurDir[1] == L'\\')) { wszDrive[0] = wszCurDir[0]; wszDrive[1] = L':'; wszDrive[2] = L'\\'; wszDrive[3] = L'\0'; } LocalFree(wszCurDir); wszCurDir = NULL; } } return (GetDriveTypeW(wszDrive) == DRIVE_CDROM); } /*++ Function Description: Removes all "\ " and replaces with "\". Arguments: IN pszOldPath - String to scan OUT pszNewPath - Resultant string Return Value: None History: 01/10/2000 linstev Updated --*/ VOID MassagePathA( LPCSTR pszOldPath, LPSTR pszNewPath ) { PCHAR pszTempBuffer; PCHAR pszPointer; LONG nOldPos, nNewPos, nOldStringLen; BOOL bAtSeparator = TRUE; nOldStringLen = strlen(pszOldPath); pszTempBuffer = (PCHAR) LocalAlloc(LPTR, nOldStringLen + 1); pszPointer = pszTempBuffer; nNewPos = nOldStringLen; for (nOldPos = nOldStringLen - 1; nOldPos >= 0; nOldPos--) { if (pszOldPath[ nOldPos ] == '\\') { bAtSeparator = TRUE; } else { if (pszOldPath[nOldPos] == ' ' && bAtSeparator) { continue; } else { bAtSeparator = FALSE; } } pszPointer[--nNewPos] = pszOldPath[nOldPos]; } pszPointer += nNewPos; strcpy(pszNewPath, pszPointer); LocalFree(pszTempBuffer); } /*++ Function Description: Removes all L"\ " and replaces with L"\". Arguments: IN pwszOldPath - String to scan OUT pwszNewPath - Resultant string Return Value: None History: 01/10/2000 linstev Updated --*/ VOID MassagePathW( LPCWSTR pwszOldPath, LPWSTR pwszNewPath ) { PWCHAR pwszTempBuffer; PWCHAR pwszPointer; LONG nOldPos, nNewPos, nOldStringLen; BOOL bAtSeparator = TRUE; nOldStringLen = wcslen(pwszOldPath); pwszTempBuffer = (PWCHAR) LocalAlloc(LPTR, (nOldStringLen + 1) * sizeof(WCHAR)); pwszPointer = pwszTempBuffer; nNewPos = nOldStringLen; for (nOldPos = nOldStringLen - 1; nOldPos >= 0; nOldPos--) { if (pwszOldPath[ nOldPos ] == L'\\') { bAtSeparator = TRUE; } else { if (pwszOldPath[nOldPos] == L' ' && bAtSeparator) { continue; } else { bAtSeparator = FALSE; } } pwszPointer[--nNewPos] = pwszOldPath[nOldPos]; } pwszPointer += nNewPos; wcscpy(pwszNewPath, pwszPointer); LocalFree(pwszTempBuffer); } /*++ Function Description: Duplicate a string into malloc memory. Arguments: IN strToCopy - String to copy Return Value: String in malloc memory History: 01/10/2000 linstev Updated 02/14/2000 robkenny Converted from VirtualAlloc to malloc --*/ char * StringDuplicateA(const char *strToCopy) { size_t strToCopySize = (strlen(strToCopy) + 1) * sizeof(strToCopy[0]); char * strDuplicate = (char *) malloc(strToCopySize); memcpy(strDuplicate, strToCopy, strToCopySize); return strDuplicate; } /*++ Function Description: Duplicate a string into malloc memory. Arguments: IN wstrToCopy - String to copy Return Value: String in malloc memory History: 01/10/2000 linstev Updated 02/14/2000 robkenny Converted from VirtualAlloc to malloc --*/ wchar_t * StringDuplicateW(const wchar_t *wstrToCopy) { size_t wstrToCopySize = (wcslen(wstrToCopy) + 1) * sizeof(wstrToCopy[0]); wchar_t * wstrDuplicate = (wchar_t *) malloc(wstrToCopySize); memcpy(wstrDuplicate, wstrToCopy, wstrToCopySize); return wstrDuplicate; } /*++ Function Description: Skip leading whitespace Arguments: IN str - String to scan Return Value: None History: 01/10/2000 linstev Updated --*/ VOID SkipBlanksA(const char *& str) { // Skip leading whitespace static const char * WhiteSpaceString = " \t"; str += strspn(str, WhiteSpaceString); } /*++ Function Description: Skip leading whitespace Arguments: IN str - String to scan Return Value: None History: 01/10/2000 linstev Updated --*/ VOID SkipBlanksW(const WCHAR *& str) { // Skip leading whitespace static const WCHAR * WhiteSpaceString = L" \t"; str += wcsspn(str, WhiteSpaceString); } /*++ Function Description: Find the first occurance of strCharSet in string Case insensitive Arguments: IN string - String to search IN strCharSet - String to search for Return Value: First occurance or NULL History: 12/01/1999 robkenny Created 12/15/1999 linstev Reformatted --*/ char* __cdecl stristr( IN const char* string, IN const char* strCharSet ) { char * pszRet = NULL; long nstringLen = strlen(string) + 1; long nstrCharSetLen = strlen(strCharSet) + 1; char * szTemp_string = (char *) malloc(nstringLen); char * szTemp_strCharSet = (char *) malloc(nstrCharSetLen); if ((!szTemp_string) || (!szTemp_strCharSet)) { goto Fail; } strcpy(szTemp_string, string); strcpy(szTemp_strCharSet, strCharSet); _strlwr(szTemp_string); _strlwr(szTemp_strCharSet); pszRet = strstr(szTemp_string, szTemp_strCharSet); if (pszRet) { pszRet = ((char *) string) + (pszRet - szTemp_string); } Fail: if (szTemp_string) { free(szTemp_string); } if (szTemp_strCharSet) { free(szTemp_strCharSet); } return pszRet; } /*++ Function Description: Find the first occurance of strCharSet in string Case insensitive Arguments: IN string - String to search IN strCharSet - String to search for Return Value: First occurance or NULL History: 12/01/1999 robkenny Created 12/15/1999 linstev Reformatted --*/ WCHAR* __cdecl wcsistr( IN const WCHAR* string, IN const WCHAR* strCharSet ) { WCHAR * pszRet = NULL; long nstringLen = wcslen(string) + 1; long nstrCharSetLen = wcslen(strCharSet) + 1; WCHAR * szTemp_string = (WCHAR *) malloc(nstringLen * sizeof(WCHAR)); WCHAR * szTemp_strCharSet = (WCHAR *) malloc(nstrCharSetLen * sizeof(WCHAR)); if ((!szTemp_string) || (!szTemp_strCharSet)) { goto Fail; } wcscpy(szTemp_string, string); wcscpy(szTemp_strCharSet, strCharSet); _wcslwr(szTemp_string); _wcslwr(szTemp_strCharSet); pszRet = wcsstr(szTemp_string, szTemp_strCharSet); if (pszRet) { pszRet = ((WCHAR *) string) + (pszRet - szTemp_string); } Fail: if (szTemp_string) { free(szTemp_string); } if( szTemp_strCharSet ) { free(szTemp_strCharSet); } return pszRet; } /*++ Func: SafeStringCopyA Params: lpDest Destination string nDestSize size in chars of lpDest lpSrc Original string nSrcLen Number of chars to copy Return: int Number of chars copied into lpDest Desc: Copy lpSrc into lpDest without overflowing the buffer --*/ int SafeStringCopyA(char * lpDest, DWORD nDestSize, const char * lpSrc, DWORD nSrcLen) { size_t nCharsToCopy = __min(nSrcLen, nDestSize); if (nCharsToCopy > 0) { strncpy(lpDest, lpSrc, nCharsToCopy); } return nCharsToCopy; } /*++ Func: SafeStringCopyW Params: lpDest Destination string nDestSize size in chars of lpDest lpSrc Original string nSrcLen Number of chars to copy Return: int Number of chars copied into lpDest Desc: Copy lpSrc into lpDest without overflowing the buffer --*/ int SafeStringCopyW(WCHAR * lpDest, DWORD nDestSize, const WCHAR * lpSrc, DWORD nSrcLen) { size_t nCharsToCopy = __min(nSrcLen, nDestSize); if (nCharsToCopy > 0) { wcsncpy(lpDest, lpSrc, nCharsToCopy); } return nCharsToCopy; } typedef WCHAR * (__cdecl * _pfn_StrStrW)( const WCHAR * string, const WCHAR * strCharSet ); typedef char * (__cdecl * _pfn_StrStrA)( const char * string, const char * strCharSet ); /*++ Func: StringSubstituteRoutineA Params: lpOrig Original string lpMatch Sub-string to look for lpSubstitute string to replace lpMatch lpCorrected the corrected string, may be NULL if (dwCorrectedSize == 0) dwCorrectedSize maximum size of lpCorrected. If 0, then routine returns number of chars necessasry for substitution nCorrectedLen Number of chars placed into lpCorrected. If the buffer was large enough, this == (wcslen(lpCorrected) + 1) nCorrectedTotalSize Number of total chars that should have been copied. This == dwCorrectedSize if lpCorrected was large enough. StringSubStringRoutine String comparison routine Return: BOOL Return TRUE if this routine replaced 1 or more matches Desc: Replace the all occurances of lpMatch with lpSubstitute in lpOrig, placing output into lpCorrected This routine is CASE SENSITIVE! --*/ BOOL StringSubstituteRoutineA( const char * lpOrig, const char * lpMatch, const char * lpSubstitute, DWORD dwCorrectedSize, char * lpCorrected, DWORD * nCorrectedLen, DWORD * nCorrectedTotalSize, _pfn_StrStrA StringSubStringRoutine) { BOOL bStringChanged = FALSE; DWORD nCharsShouldHaveCopied = 0; // Size of resulting string (might exceed ) size_t nCharsCopied = 0; char * lpMatchInString = StringSubStringRoutine( lpOrig, lpMatch ); if (lpMatchInString != NULL) { // Replace lpMatch with lpSubstitute. // Make sure we do not overrun the output buffer. size_t nCharsToCopy; // How many chars we can safely copy (always <= nCopyLen) // Copy the unmodified chars at the beginning of the string nCharsToCopy = lpMatchInString - lpOrig; nCharsCopied += SafeStringCopyA(lpCorrected + nCharsShouldHaveCopied, dwCorrectedSize - nCharsCopied, lpOrig, nCharsToCopy); nCharsShouldHaveCopied += nCharsToCopy; // The substitution string nCharsToCopy = strlen(lpSubstitute); nCharsCopied += SafeStringCopyA(lpCorrected + nCharsShouldHaveCopied, dwCorrectedSize - nCharsCopied, lpSubstitute, nCharsToCopy); nCharsShouldHaveCopied += nCharsToCopy; char * lpOrigAfterMatch = lpMatchInString + strlen(lpMatch); // Recursively replace the remainder of the string DWORD nSmallerSize; DWORD nSmallerTotal; StringSubstituteA(lpOrigAfterMatch, lpMatch, lpSubstitute, dwCorrectedSize - nCharsCopied, lpCorrected + nCharsShouldHaveCopied, &nSmallerSize, &nSmallerTotal); nCharsCopied += nSmallerSize; nCharsShouldHaveCopied += nSmallerTotal; bStringChanged = TRUE; // Recusion is cool: the remainder of the string is copied "automatically" for us in the else statement } else { nCharsShouldHaveCopied = strlen(lpOrig) + 1; nCharsCopied = SafeStringCopyA(lpCorrected, dwCorrectedSize, lpOrig, nCharsShouldHaveCopied); } // Make sure we have placed the 0 char at the end of the string if (nCharsCopied != nCharsShouldHaveCopied && nCharsCopied > 0) { lpCorrected[nCharsCopied-1] = 0; } if (nCorrectedLen != NULL) *nCorrectedLen = nCharsCopied; if (nCorrectedTotalSize != NULL) *nCorrectedTotalSize = nCharsShouldHaveCopied; return bStringChanged; } /*++ Func: StringSubstituteW Params: lpOrig Original string lpMatch Sub-string to look for lpSubstitute string to replace lpMatch lpCorrected the corrected string, may be NULL if (dwCorrectedSize == 0) dwCorrectedSize maximum size of lpCorrected. If 0, then routine returns number of chars necessasry for substitution nCorrectedLen Number of chars placed into lpCorrected. If the buffer was large enough, this == (wcslen(lpCorrected) + 1) nCorrectedTotalSize Number of total chars that should have been copied. This == dwCorrectedSize if lpCorrected was large enough. StringSubStringRoutine String comparison routine Return: BOOL Return TRUE if this routine replaced 1 or more matches Desc: Replace the all occurances of lpMatch with lpSubstitute in lpOrig, placing output into lpCorrected. This routine is CASE SENSITIVE! --*/ BOOL StringSubstituteRoutineW( const WCHAR * lpOrig, const WCHAR * lpMatch, const WCHAR * lpSubstitute, WCHAR * lpCorrected, DWORD dwCorrectedSize, DWORD * nCorrectedLen, DWORD * nCorrectedTotalSize, _pfn_StrStrW StringSubStringRoutine) { BOOL bStringChanged = FALSE; DWORD nCharsShouldHaveCopied = 0; // Size of resulting string (might exceed ) size_t nCharsCopied = 0; WCHAR * lpMatchInString = StringSubStringRoutine( lpOrig, lpMatch ); if (lpMatchInString != NULL) { // Replace lpMatch with lpSubstitute. // Make sure we do not overrun the output buffer. size_t nCharsToCopy; // How many chars we can safely copy (always <= nCopyLen) // Copy the unmodified chars at the beginning of the string nCharsToCopy = lpMatchInString - lpOrig; nCharsCopied += SafeStringCopyW(lpCorrected + nCharsShouldHaveCopied, dwCorrectedSize - nCharsCopied, lpOrig, nCharsToCopy); nCharsShouldHaveCopied += nCharsToCopy; // The substitution string nCharsToCopy = wcslen(lpSubstitute); nCharsCopied += SafeStringCopyW(lpCorrected + nCharsShouldHaveCopied, dwCorrectedSize - nCharsCopied, lpSubstitute, nCharsToCopy); nCharsShouldHaveCopied += nCharsToCopy; WCHAR * lpOrigAfterMatch = lpMatchInString + wcslen(lpMatch); // Recursively replace the remainder of the string DWORD nSmallerSize; DWORD nSmallerTotal; StringSubstituteW(lpOrigAfterMatch, lpMatch, lpSubstitute, lpCorrected + nCharsShouldHaveCopied, dwCorrectedSize - nCharsCopied, &nSmallerSize, &nSmallerTotal); nCharsCopied += nSmallerSize; nCharsShouldHaveCopied += nSmallerTotal; bStringChanged = TRUE; // Recursion is cool: the remainder of the string is copied "automatically" for us in the else statement } else { nCharsShouldHaveCopied = wcslen(lpOrig) + 1; nCharsCopied = SafeStringCopyW(lpCorrected, dwCorrectedSize, lpOrig, nCharsShouldHaveCopied); } // Make sure we have placed the 0 char at the end of the string if (nCharsCopied != nCharsShouldHaveCopied && nCharsCopied > 0) { lpCorrected[nCharsCopied-1] = 0; } if (nCorrectedLen != NULL) *nCorrectedLen = nCharsCopied; if (nCorrectedTotalSize != NULL) *nCorrectedTotalSize = nCharsShouldHaveCopied; return bStringChanged; } /*++ Func: StringISubstituteA Params: lpOrig Original string lpMatch Sub-string to look for lpSubstitute string to replace lpMatch lpCorrected the corrected string, may be NULL if (dwCorrectedSize == 0) dwCorrectedSize maximum size of lpCorrected. If 0, then routine returns number of chars necessasry for substitution nCorrectedLen Number of chars placed into lpCorrected. If the buffer was large enough, this == (wcslen(lpCorrected) + 1) nCorrectedTotalSize Number of total chars that should have been copied. This == dwCorrectedSize if lpCorrected was large enough. Return: BOOL Return TRUE if this routine replaced 1 or more matches Desc: Replace the all occurances of lpMatch with lpSubstitute in lpOrig, placing output into lpCorrected This routine is CASE SENSITIVE! --*/ BOOL StringSubstituteA( const char * lpOrig, const char * lpMatch, const char * lpSubstitute, DWORD dwCorrectedSize, char * lpCorrected, DWORD * nCorrectedLen, DWORD * nCorrectedTotalSize) { return StringSubstituteRoutineA( lpOrig, lpMatch, lpSubstitute, dwCorrectedSize, lpCorrected, nCorrectedLen, nCorrectedTotalSize, strstr); } /*++ Func: StringISubstituteA Params: lpOrig Original string lpMatch Sub-string to look for lpSubstitute string to replace lpMatch lpCorrected the corrected string, may be NULL if (dwCorrectedSize == 0) dwCorrectedSize maximum size of lpCorrected. If 0, then routine returns number of chars necessasry for substitution nCorrectedLen Number of chars placed into lpCorrected. If the buffer was large enough, this == (wcslen(lpCorrected) + 1) nCorrectedTotalSize Number of total chars that should have been copied. This == dwCorrectedSize if lpCorrected was large enough. Return: BOOL Return TRUE if this routine replaced 1 or more matches Desc: Replace the all occurances of lpMatch with lpSubstitute in lpOrig, placing output into lpCorrected This routine is CASE SENSITIVE! --*/ BOOL StringISubstituteA( const char * lpOrig, const char * lpMatch, const char * lpSubstitute, DWORD dwCorrectedSize, char * lpCorrected, DWORD * nCorrectedLen, DWORD * nCorrectedTotalSize) { return StringSubstituteRoutineA( lpOrig, lpMatch, lpSubstitute, dwCorrectedSize, lpCorrected, nCorrectedLen, nCorrectedTotalSize, stristr); } /*++ Func: StringSubstituteW Params: lpOrig Original string lpMatch Sub-string to look for lpSubstitute string to replace lpMatch lpCorrected the corrected string, may be NULL if (dwCorrectedSize == 0) dwCorrectedSize maximum size of lpCorrected. If 0, then routine returns number of chars necessasry for substitution nCorrectedLen Number of chars placed into lpCorrected. If the buffer was large enough, this == (wcslen(lpCorrected) + 1) nCorrectedTotalSize Number of total chars that should have been copied. This == dwCorrectedSize if lpCorrected was large enough. Return: BOOL Return TRUE if this routine replaced 1 or more matches Desc: Replace the all occurances of lpMatch with lpSubstitute in lpOrig, placing output into lpCorrected. This routine is CASE IN-SENSITIVE! --*/ BOOL StringSubstituteW( const WCHAR * lpOrig, const WCHAR * lpMatch, const WCHAR * lpSubstitute, WCHAR * lpCorrected, DWORD dwCorrectedSize, DWORD * nCorrectedLen, DWORD * nCorrectedTotalSize) { return StringSubstituteRoutineW( lpOrig, lpMatch, lpSubstitute, lpCorrected, dwCorrectedSize, nCorrectedLen, nCorrectedTotalSize, wcsstr); } /*++ Func: StringISubstituteW Params: lpOrig Original string lpMatch Sub-string to look for lpSubstitute string to replace lpMatch lpCorrected the corrected string, may be NULL if (dwCorrectedSize == 0) dwCorrectedSize maximum size of lpCorrected. If 0, then routine returns number of chars necessasry for substitution nCorrectedLen Number of chars placed into lpCorrected. If the buffer was large enough, this == (wcslen(lpCorrected) + 1) nCorrectedTotalSize Number of total chars that should have been copied. This == dwCorrectedSize if lpCorrected was large enough. Return: BOOL Return TRUE if this routine replaced 1 or more matches Desc: Replace the all occurances of lpMatch with lpSubstitute in lpOrig, placing output into lpCorrected. This routine is CASE IN-SENSITIVE! --*/ BOOL StringISubstituteW( const WCHAR * lpOrig, const WCHAR * lpMatch, const WCHAR * lpSubstitute, WCHAR * lpCorrected, DWORD dwCorrectedSize, DWORD * nCorrectedLen, DWORD * nCorrectedTotalSize) { return StringSubstituteRoutineW( lpOrig, lpMatch, lpSubstitute, lpCorrected, dwCorrectedSize, nCorrectedLen, nCorrectedTotalSize, wcsistr); }