|
|
// Copyright (c) 1997-2002 Microsoft Corporation
//
// Module:
//
// Network Security Utilities
// nsustring.c
//
// Abstract:
//
// Wrappers for strsafe.h and safe string functions
//
// Author:
//
// RaymondS 1 February-2002
//
// Environment:
//
// User mode
//
// Revision History:
#include <precomp.h>
#include "NsuString.h"
#include "strsafe.h"
// Description:
//
// Copies not more than cchDest characters from pszSrc to pszDest, including the null
// terminator. If the length of pszSrc is more than cchDest, ERROR_INSUFFICIENT_BUFFER
// is returned but cchDest characters from pszSrc are still copied to pszDest.
// Always null terminates pszDest.
//
// Arguments:
//
// pszDest - destination string.
// cchDest - maximum number of characters to copy including null character.
// pszSrc - souce string.
//
// Return Value:
// ERROR_INVALID_PARAMETER - if one of the parameters is invalid. pszDest unchanged.
// ERROR_INSUFFICIENT_BUFFER - if length of pszSrc is greater than cchDest.
// ERROR_SUCCESS
// Other WIN32 errors possible.
//
DWORD NsuStringCopyW( OUT LPWSTR pszDest, IN size_t cchDest, IN LPCWSTR pszSrc ) { HRESULT hr = S_OK;
hr = StringCchCopyW( pszDest, cchDest, pszSrc );
return HRESULT_CODE(hr); }
// Description:
//
// See NsuStringCopyW.
//
DWORD NsuStringCopyA( OUT LPSTR pszDest, IN size_t cchDest, IN LPCSTR pszSrc ) { HRESULT hr = S_OK;
hr = StringCchCopyA( pszDest, cchDest, pszSrc );
return HRESULT_CODE(hr); }
// Description:
//
// Converts pszSrc from MBCS to an Unicode string and pass the result back in *ppszDest.
// *ppszDest is allocated enough space to store the output string.
// Always null terminates *ppszDest.
// Use NsuFree to free the allocate string.
//
// Arguments:
//
// ppszDest - pointer to output string that is returned.
// cchLimit - specifies the maximum size of the output string to allocate including
// the NULL character.
// Pass 0 if no maximum should be enforced. if cchLimit is
// less than the required output string buffer, only cchLimit characters
// are converted, and ERROR_INSUFFICIENT_BUFFER is returned.
//
// Return Value:
//
// ERROR_INVALID_PARAMETER - if one of the parameters is invalid.
// ERROR_INSUFFICIENT_BUFFER - cchLimit is less than required output string lenghth.
// ERROR_SUCCESS
// Other WIN32 errors
//
DWORD NsuStringCopyAtoWAlloc( OUT LPWSTR* ppszDest, IN size_t cchLimit, IN LPCSTR pszSrc ) { DWORD dwError = ERROR_SUCCESS; LPWSTR lpWideCharStr = NULL; int cchWideChar = 0;
cchWideChar = MultiByteToWideChar( CP_ACP, // ANSI Code page
0, // No special options
pszSrc, // string to map
-1, // Assume string is null terminated.
NULL, // wide-character buffer
0 // size of buffer
); if (cchWideChar <= 0) { dwError = GetLastError(); NSU_BAIL_ON_ERROR(dwError); } else if (cchLimit && (size_t) cchWideChar > cchLimit) { cchWideChar = cchLimit; }
lpWideCharStr = NsuAlloc( cchWideChar * sizeof(WCHAR), 0 ); NSU_BAIL_ON_NULL(lpWideCharStr, dwError); cchWideChar = MultiByteToWideChar( CP_ACP, // ANSI Code page
0, // No special options
pszSrc, // string to map
-1, // Assume string is null terminated.
lpWideCharStr, // wide-character buffer
cchWideChar // size of buffer
); if (cchWideChar == 0) { dwError = GetLastError(); // If ERROR_INSUFFICIENT_BUFFER user set limit
// so just null terminate.
if (dwError == ERROR_INSUFFICIENT_BUFFER && cchWideChar) { lpWideCharStr[cchLimit-1] = L'\0'; } else { NSU_BAIL_ON_ERROR(dwError); } }
*ppszDest = lpWideCharStr; return dwError; NSU_CLEANUP: if (lpWideCharStr) { // Don't want to overwrite dwError so ignore NsuFree errors
//
(VOID) NsuFree0(&lpWideCharStr); } *ppszDest = NULL; return dwError; }
// Description:
//
// Converts pszSrc from Unicode string to an MBCS and passes the result in *ppszDest.
// *ppszDest is allocated enough space to store the output string.
// Always null terminates *ppszDest.
// Use NsuFree to free the allocate string.
//
// Arguments:
//
// ppszDest - pointer to output string that is returned.
// cbLimit - specifies the maximum size of the output string to allocate including
// the NULL character.
// Pass 0 if no maximum should be enforced. if cbLimit is
// less than the required output string buffer, only cbLimit bytes
// are converted, and ERROR_INSUFFICIENT_BUFFER is returned.
//
// Return Value:
//
// ERROR_INVALID_PARAMETER - if one of the parameters is invalid. *ppszDest set to NULL.
// ERROR_INSUFFICIENT_BUFFER - cbLimit is less than required output string length.
// ERROR_SUCCESS
// Other WIN32 errors possible. *ppszDest set to NULL.
//
DWORD NsuStringCopyWtoAAlloc( OUT LPSTR* ppszDest, IN size_t cbLimit, IN LPCWSTR pszSrc ) { DWORD dwError = ERROR_SUCCESS; int cbMultiByte = 0; LPSTR lpMultiByteStr = NULL; cbMultiByte = WideCharToMultiByte( CP_ACP, // code page
0, // performance and mapping flags
pszSrc, // string to map
-1, // assume null termination
NULL, // buffer for new string
0, // find out size of buffer
NULL, // default for unmappable chars
NULL // set when default char used
); if (cbMultiByte <= 0) { dwError = GetLastError(); NSU_BAIL_ON_ERROR(dwError); } else if (cbLimit && (size_t) cbMultiByte > cbLimit) { cbMultiByte = cbLimit; }
lpMultiByteStr = NsuAlloc( cbMultiByte, 0 ); NSU_BAIL_ON_NULL(lpMultiByteStr, dwError);
cbMultiByte = WideCharToMultiByte( CP_ACP, // code page
0, // performance and mapping flags
pszSrc, // string to map
-1, // assume null termination
lpMultiByteStr, // buffer for new string
cbMultiByte, // size of buffer
NULL, // default for unmappable chars
NULL // set when default char used
); if (cbMultiByte == 0) { dwError = GetLastError(); // If ERROR_INSUFFICIENT_BUFFER user set limit
// so just null terminate.
if (dwError == ERROR_INSUFFICIENT_BUFFER && cbLimit) { lpMultiByteStr[cbLimit-1] = '\0'; } else { NSU_BAIL_ON_ERROR(dwError); }
}
*ppszDest = lpMultiByteStr; return dwError; NSU_CLEANUP: if (lpMultiByteStr) { // Don't want to overwrite dwError so ignore NsuFree errors
//
(VOID) NsuFree0(&lpMultiByteStr); } *ppszDest = NULL; return dwError; }
// Description:
//
// Converts pszSrc from MBCS to an Unicode string and pass the result back in pszDest.
// Always null terminates pszDest.
// Use NsuFree to free the allocated string.
//
// Arguments:
//
// ppszDest - pointer to output string that is returned.
// cchDest - maximum number of characters to place in pszDest including null character.
// If cchDest is less than the required output string buffer, only cchDest bytes
// are converted, and ERROR_INSUFFICIENT_BUFFER is returned.
// pszSrc � source string.
//
// Return Value:
//
// ERROR_INVALID_PARAMETER - if one of the parameters is invalid.
// ERROR_INSUFFICIENT_BUFFER - cchLimit is less than required output string lenghth.
// ERROR_SUCCESS
// Other WIN32 errors
//
DWORD NsuStringCopyAtoW( OUT LPWSTR pszDest, IN size_t cchDest, IN LPCSTR pszSrc ) { DWORD dwError = ERROR_SUCCESS; int cchWideChar = 0;
cchWideChar = MultiByteToWideChar( CP_ACP, // ANSI Code page
0, // No special options
pszSrc, // string to map
-1, // Assume string is null terminated.
pszDest, // wide-character buffer
cchDest // size of buffer
); if (cchWideChar == 0) { dwError = GetLastError(); // If ERROR_INSUFFICIENT_BUFFER just null terminate.
if (dwError == ERROR_INSUFFICIENT_BUFFER && cchDest) { pszDest[cchDest-1] = L'\0'; } }
return dwError; }
// Description:
//
// Converts pszSrc from Unicode string to an MBCS and puts the result in pszDest.
// Always null terminates pszDest.
//
// Arguments:
//
//
// pszDest - destination string.
// cchDest - maximum number of characters to place in pszDest including null character.
// If cchDest is less than the required output string buffer, only cchDest bytes
// are converted, and ERROR_INSUFFICIENT_BUFFER is returned.
// pszSrc � source string.
//
// Return Value:
//
// ERROR_INVALID_PARAMETER - if one of the parameters is invalid. *ppszDest set to NULL.
// ERROR_INSUFFICIENT_BUFFER - cchDest is less than required output string length.
// ERROR_SUCCESS
// Other WIN32 errors possible.
//
DWORD NsuStringCopyWtoA( OUT LPSTR pszDest, IN size_t cbDest, IN LPCWSTR pszSrc ) { DWORD dwError = ERROR_SUCCESS; int cbMultiByte = 0;
cbMultiByte = WideCharToMultiByte( CP_ACP, // code page
0, // performance and mapping flags
pszSrc, // string to map
-1, // assume null termination
pszDest, // buffer for new string
cbDest, // size of buffer
NULL, // default for unmappable chars
NULL // set when default char used
); if (cbMultiByte == 0) { dwError = GetLastError(); // If ERROR_INSUFFICIENT_BUFFER just null terminate.
if (dwError == ERROR_INSUFFICIENT_BUFFER && cbDest) { pszDest[cbDest-1] = '\0'; }
}
return dwError; }
// Description:
//
// Makes a duplicate deep memory copy of pszSrc and returns the result in *ppszDest.
// *ppszDest is allocated enough space to store the output string.
// Always null terminates *ppszDest.
// Use NsuFree to free the allocate string.
//
// Arguments:
//
// ppszDest - pointer to output string that is returned.
// cchLimit - specifies the maximum size of the output string to allocate including
// the NULL character.
// Pass 0 if no maximum should be enforced. if cchLimit is
// less than the required output string buffer, only cchLimit characters
// are duplicated, and ERROR_INSUFFICIENT_BUFFER is returned.
//
// Return Value:
//
// ERROR_INVALID_PARAMETER - if one of the parameters is invalid. pszDest unchanged.
// ERROR_INSUFFICIENT_BUFFER - cchLimit is less than required output string length.
// ERROR_SUCCESS
// Other WIN32 errors possible.
//
DWORD NsuStringDupW( OUT LPWSTR* ppszDest, IN size_t cchLimit, IN LPCWSTR pszSrc ) { DWORD dwError = ERROR_SUCCESS; size_t cchToCopy = 0; LPWSTR pszDest = NULL;
dwError = NsuStringLenW( pszSrc, &cchToCopy ); NSU_BAIL_ON_ERROR(dwError);
cchToCopy++; if (cchLimit && cchToCopy >= cchLimit) { cchToCopy = cchLimit; }
pszDest = NsuAlloc( cchToCopy * sizeof(WCHAR), 0 ); NSU_BAIL_ON_NULL(pszDest, dwError); dwError = NsuStringCopyW( pszDest, cchToCopy, pszSrc ); // ERROR_INSUFFICIENT_BUFFER is expected if user
// set a limit on the length of duplicate.
//
if (dwError != ERROR_INSUFFICIENT_BUFFER) { NSU_BAIL_ON_ERROR(dwError); }
*ppszDest = pszDest; return dwError; NSU_CLEANUP: if (pszDest) { // Don't want to overwrite dwError so ignore NsuFree errors
//
(VOID) NsuFree0( &pszDest ); }
*ppszDest = NULL; return dwError; }
// Description:
//
// See NsuStringDupW
//
DWORD WINAPI NsuStringDupA( OUT LPSTR* ppszDest, IN size_t cchLimit, IN LPCSTR pszSrc ) { DWORD dwError = ERROR_SUCCESS; size_t cchToCopy = 0; LPSTR pszDest = NULL;
dwError = NsuStringLenA( pszSrc, &cchToCopy ); NSU_BAIL_ON_ERROR(dwError);
cchToCopy++; if (cchLimit && cchToCopy >= cchLimit) { cchToCopy = cchLimit; }
pszDest = NsuAlloc( cchToCopy, 0 ); NSU_BAIL_ON_NULL(pszDest, dwError); dwError = NsuStringCopyA( pszDest, cchToCopy, pszSrc ); // ERROR_INSUFFICIENT_BUFFER is expected if user
// set a limit on the length of duplicate.
//
if (dwError != ERROR_INSUFFICIENT_BUFFER) { NSU_BAIL_ON_ERROR(dwError); } *ppszDest = pszDest; return dwError; NSU_CLEANUP: if (pszDest) {
// Ignoring errors from NsuFree because want to return
// original cause of bailing out.
//
(VOID) NsuFree0( &pszDest ); }
*ppszDest = NULL; return dwError; }
// Description:
//
// Concatenates characters from pszSrc to pszDest and makes sure that the
// the resulting is not longer than cchDest characters, including
// the NULL character.
// If not enough space was available in pszDest to concatanenate the whole of pszSrc,
// ERROR_INSUFFICIENT_BUFFER is returned but as much as the space that was available in pszDest
// is filled with characters from pszSrc.
// Always null terminates pszDest.
//
// Arguments:
//
// pszDest - destination string.
// cchDest - maximum number length allowed for resulting string including null character.
// pszSrc - souce string.
//
// Return Value:
// ERROR_INVALID_PARAMETER - if one of the parameters is invalid.
// ERROR_INSUFFICIENT_BUFFER - if not enough space in pszDest to cat the whole of pszSrc.
// ERROR_SUCCESS
// Other WIN32 errors possible.
//
DWORD NsuStringCatW( OUT LPWSTR pszDest, IN size_t cchDest, IN LPCWSTR pszSrc ) { HRESULT hr = S_OK;
hr = StringCchCatW( pszDest, cchDest, pszSrc ); return HRESULT_CODE(hr); }
// Description:
//
// See NsuStringCatW
//
DWORD NsuStringCatA( OUT LPSTR pszDest, IN size_t cchDest, IN LPCSTR pszSrc ) { HRESULT hr = S_OK;
hr = StringCchCatA( pszDest, cchDest, pszSrc ); return HRESULT_CODE(hr); }
// Description:
//
// Safe version of sprintf. Formats and writes a string to pszDest
// sure that the result is not longer than cchDest characters, including
// the NULL character.
// If more space is required than cchDest characteters, ERROR_INSUFFICIENT_BUFFER
// is returned but cchDest characters are always written to pszDest.
// Always null terminates pszDest.
//
// Arguments:
//
// pszDest - destination string.
// cchDest - maximum number length allowed for resulting string including null character.
// pszFormat - printf-style format string.
// Optional arguments to format and write to pszDest.
//
// Return Value:
// ERROR_INVALID_PARAMETER - if one of the parameters is invalid.
// ERROR_INSUFFICIENT_BUFFER - if length of the is greater than cchDest.
// ERROR_SUCCESS
// Other WIN32 errors possible.
//
DWORD NsuStringSprintW( OUT LPWSTR pszDest, IN size_t cchDest, IN LPCWSTR pszFormat, ... ) { HRESULT hr = S_OK; va_list pArguments = NULL;
va_start(pArguments, pszFormat);
hr = StringCchVPrintfW( pszDest, cchDest, pszFormat, pArguments ); va_end(pArguments);
return HRESULT_CODE(hr); }
// Description:
//
// See NsuStringPrintA
//
DWORD NsuStringSprintA( OUT LPSTR pszDest, IN size_t cchDest, IN LPCSTR pszFormat, ... ) { HRESULT hr = S_OK; va_list pArguments = NULL;
va_start(pArguments, pszFormat);
hr = StringCchVPrintfA( pszDest, cchDest, pszFormat, pArguments ); va_end(pArguments);
return HRESULT_CODE(hr);
}
// Description:
//
// Fail Safe version of NsuStringSprint. Formats and writes a string to pszDest
// sure that the result is not longer than cchDest characters, including
// the NULL character.
// If more space is required than cchDest characteters, no error
// is returned but cchDest characters are always written to pszDest.
// Always null terminates pszDest.
// This function differs from the normal NsuStringSprint in that it does not return an error code,
// and if the function fails for some reason, pszDest will be set to an empty string.
//
// Arguments:
//
// pszDest - destination string.
// cchDest - maximum number length allowed for resulting string including null character.
// pszFormat - printf-style format string.
// Optional arguments to format and write to pszDest.
//
// Return Value:
// None
VOID NsuStringSprintFailSafeW( OUT LPWSTR pszDest, IN size_t cchDest, IN LPCWSTR pszFormat, ... ) { HRESULT hr = S_OK; va_list pArguments = NULL;
va_start(pArguments, pszFormat); if (cchDest) { hr = StringCchVPrintfW( pszDest, cchDest, pszFormat, pArguments ); } else { hr = STRSAFE_E_INVALID_PARAMETER; NSU_BAIL_OUT; } va_end(pArguments);
if (hr != STRSAFE_E_INSUFFICIENT_BUFFER && FAILED(hr)) { NSU_BAIL_OUT; } return; NSU_CLEANUP: if (cchDest) { pszDest[0] = L'\0'; } return; }
// Description:
//
// See NsuStringPrintFailSafeA
//
VOID NsuStringSprintFailSafeA( OUT LPSTR pszDest, IN size_t cchDest, IN LPCSTR pszFormat, ... ) { HRESULT hr = S_OK; va_list pArguments = NULL;
va_start(pArguments, pszFormat); if (cchDest) { hr = StringCchVPrintfA( pszDest, cchDest, pszFormat, pArguments ); } else { hr = STRSAFE_E_INVALID_PARAMETER; NSU_BAIL_OUT; } va_end(pArguments);
if (hr != STRSAFE_E_INSUFFICIENT_BUFFER && FAILED(hr)) { NSU_BAIL_OUT; }
return; NSU_CLEANUP: if (cchDest) { pszDest[0] = '\0'; } return; }
// Description:
//
// Fail Safe version of NsuStringSprint that accepts a va_list of arguments.
// Formats and writes a string to pszDest sure that the result is not longer
// than cchDest characters, including the NULL character.
// If more space is required than cchDest characteters, no error
// is returned but cchDest characters are always written to pszDest.
// Always null terminates pszDest.
//
// Arguments:
//
// pszDest - destination string.
// cchDest - maximum number length allowed for resulting string including null character.
// pszFormat - printf-style format string.
// vaArguments - Arguments to format and write to pszDest.
//
// Return Value:
// None
//
VOID NsuStringVSprintFailSafeW( OUT LPWSTR pszDest, IN size_t cchDest, IN LPCWSTR pszFormat, IN va_list vaArguments ) { HRESULT hr = S_OK; if (cchDest) { hr = StringCchVPrintfW( pszDest, cchDest, pszFormat, vaArguments ); } else { hr = STRSAFE_E_INVALID_PARAMETER; NSU_BAIL_OUT; } if (hr != STRSAFE_E_INSUFFICIENT_BUFFER && FAILED(hr)) { NSU_BAIL_OUT; }
return; NSU_CLEANUP: if (cchDest) { pszDest[0] = L'\0'; } return; }
// Description:
//
// See NsuStringVPrintFailSafeW
//
VOID NsuStringVSprintFailSafeA( OUT LPSTR pszDest, IN size_t cchDest, IN LPCSTR pszFormat, IN va_list vaArguments ) { HRESULT hr = S_OK;
if (cchDest) { hr = StringCchVPrintfA( pszDest, cchDest, pszFormat, vaArguments );
} else { hr = STRSAFE_E_INVALID_PARAMETER; NSU_BAIL_OUT; }
if (hr != STRSAFE_E_INSUFFICIENT_BUFFER && FAILED(hr)) { NSU_BAIL_OUT; }
return; NSU_CLEANUP: if (cchDest) { pszDest[0] = '\0'; } return; }
// Description:
//
// Safe version of strlen, that will not Access Violate if
// passed a bad pointer or a non-null terminated string.
// A non-null terminated string is detected by making
// sure we do not read past the string into memory we do not own.
//
//
// Arguments:
//
// pszStr - Input string.
// pcchStrLen - pointer to variable in which to return string length.
//
// Return Value:
// ERROR_INVALID_PARAMETER - if pszStr points to an invalid string.
// ERROR_SUCCESS
//
DWORD NsuStringLenW( IN LPCWSTR pszStr, OUT size_t* pcchStrLen ) { BOOL fBadStr = TRUE; DWORD dwError = ERROR_SUCCESS; size_t cchStrLen = 0;
if (!pszStr) { dwError = ERROR_INVALID_PARAMETER; NSU_BAIL_ON_ERROR(dwError); }
__try { cchStrLen = wcslen(pszStr); } __except(EXCEPTION_EXECUTE_HANDLER) { dwError = ERROR_INVALID_PARAMETER; } NSU_BAIL_ON_ERROR(dwError);
*pcchStrLen = cchStrLen; return dwError;
NSU_CLEANUP: *pcchStrLen = 0; return dwError; }
// Description:
//
// See NsuStringLenW
//
DWORD NsuStringLenA( IN LPCSTR pszStr, OUT size_t* pcbStrLen ) { BOOL fBadStr = TRUE; DWORD dwError = ERROR_SUCCESS; size_t cbStrLen;
if (!pszStr) { dwError = ERROR_INVALID_PARAMETER; NSU_BAIL_ON_ERROR(dwError); } __try { cbStrLen = strlen(pszStr); } __except(EXCEPTION_EXECUTE_HANDLER) { dwError = ERROR_INVALID_PARAMETER; } NSU_BAIL_ON_ERROR(dwError);
*pcbStrLen = cbStrLen; return dwError;
NSU_CLEANUP: *pcbStrLen = 0; return dwError;
}
// Description:
//
// Safe string searching routine that will not Access Violate if
// passed bad pointers or non-null terminated strings.
// pszStartOfMatch is a pointer to the start of the first match
// of the string to search for in the string to search.
//
//
// Arguments:
//
// pszStrToSearch - Input string to search in.
// pszStrToFind - Input string to search for.
// bIsCaseSensitive - if true, perform case sensitive search
// pszStartOfMatch - pointer to first occurrance of pszStrToFind
// within pszStrToSearch
//
// Return Value:
// ERROR_INVALID_PARAMETER - if either input string points to an invalid string.
// ERROR_SUCCESS
//
DWORD WINAPI NsuStringFindW( IN LPCWSTR pszStrToSearch, IN LPCWSTR pszStrToFind, IN BOOL bIsCaseSensitive, OUT LPCWSTR* ppszStartOfMatch ) { DWORD dwError = ERROR_SUCCESS; size_t uiSearchLen; size_t uiFindLen; size_t i;
*ppszStartOfMatch = 0;
NsuStringLenW(pszStrToSearch, &uiSearchLen); NSU_BAIL_ON_ERROR(dwError); NsuStringLenW(pszStrToFind, &uiFindLen); NSU_BAIL_ON_ERROR(dwError);
i = 0; if (bIsCaseSensitive) { while ((*ppszStartOfMatch == 0) && ((uiSearchLen - i) >= uiFindLen)) { if (wcsncmp(&pszStrToSearch[i], pszStrToFind, uiFindLen) == 0) { *ppszStartOfMatch = &pszStrToSearch[i]; } ++i; } } else { while ((*ppszStartOfMatch == 0) && ((uiSearchLen - i) >= uiFindLen)) { if (_wcsnicmp(&pszStrToSearch[i], pszStrToFind, uiFindLen) == 0) { *ppszStartOfMatch = &pszStrToSearch[i]; } ++i; } }
NSU_CLEANUP: return dwError; }
// Description:
//
// See NsuStringFindW
//
DWORD WINAPI NsuStringFindA( IN LPCSTR pszStrToSearch, IN LPCSTR pszStrToFind, IN BOOL bIsCaseSensitive, OUT LPCSTR* ppszStartOfMatch ) { DWORD dwError = ERROR_SUCCESS; size_t uiSearchLen; size_t uiFindLen; size_t i;
*ppszStartOfMatch = 0;
NsuStringLenA(pszStrToSearch, &uiSearchLen); NSU_BAIL_ON_ERROR(dwError); NsuStringLenA(pszStrToFind, &uiFindLen); NSU_BAIL_ON_ERROR(dwError);
i = 0; if (bIsCaseSensitive) { while ((*ppszStartOfMatch == 0) && ((uiSearchLen - i) >= uiFindLen)) { if (strncmp(&pszStrToSearch[i], pszStrToFind, uiFindLen) == 0) { *ppszStartOfMatch = &pszStrToSearch[i]; } ++i; } } else { while ((*ppszStartOfMatch == 0) && ((uiSearchLen - i) >= uiFindLen)) { if (_strnicmp(&pszStrToSearch[i], pszStrToFind, uiFindLen) == 0) { *ppszStartOfMatch = &pszStrToSearch[i]; } ++i; } }
NSU_CLEANUP: return dwError; }
|