1054 lines
26 KiB
C++
1054 lines
26 KiB
C++
/*++
|
|
|
|
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 <stdio.h>
|
|
#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);
|
|
}
|
|
|